Skip to content

Commit 5203994

Browse files
committed
use legacy SPI for 832, SPIM for 840 due to 832's silicon errata
1 parent 6b61e9a commit 5203994

File tree

4 files changed

+266
-14
lines changed

4 files changed

+266
-14
lines changed

libraries/SPI/SPI.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2020
*/
2121

22+
// Due to nRF52832 Errata with SPIM, we will only use SPIM for 840 variant
23+
// https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev2/ERR/nRF52832/Rev2/latest/anomaly_832_58.html
24+
#ifdef NRF52840_XXAA
25+
2226
#include "SPI.h"
2327
#include <Arduino.h>
2428
#include <wiring_private.h>
@@ -44,9 +48,11 @@ SPIClass::SPIClass(NRF_SPIM_Type *p_spi, uint8_t uc_pinMISO, uint8_t uc_pinSCK,
4448
}
4549
#endif
4650

51+
#if NRFX_SPIM2_ENABLED
4752
if ( NRF_SPIM2 == p_spi ) {
4853
_spim.drv_inst_idx = NRFX_SPIM2_INST_IDX;
4954
}
55+
#endif
5056

5157
#if NRFX_SPIM3_ENABLED
5258
if ( NRF_SPIM3 == p_spi ) {
@@ -226,19 +232,13 @@ void SPIClass::detachInterrupt() {
226232
// Should be disableInterrupt()
227233
}
228234

229-
// SPIM0, SPIM1 are configured as I2C
230-
#ifdef NRF52840_XXAA
231-
#if SPI_INTERFACES_COUNT > 0
232-
// use SPIM3 for nrf52840 for highspeed 32Mhz
233-
SPIClass SPI(NRF_SPIM3, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI);
234-
#endif
235-
236-
#if SPI_INTERFACES_COUNT > 1
237-
SPIClass SPI1(NRF_SPIM2, PIN_SPI1_MISO, PIN_SPI1_SCK, PIN_SPI1_MOSI);
238-
#endif
239-
240-
#else
241-
SPIClass SPI(NRF_SPIM2, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI);
235+
#if SPI_INTERFACES_COUNT > 0
236+
// use SPIM3 for highspeed 32Mhz
237+
SPIClass SPI(NRF_SPIM2, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI);
238+
#endif
242239

240+
#if SPI_INTERFACES_COUNT > 1
241+
SPIClass SPI1(NRF_SPIM2, PIN_SPI1_MISO, PIN_SPI1_SCK, PIN_SPI1_MOSI);
243242
#endif
244243

244+
#endif // NRF52840_XXAA

libraries/SPI/SPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class SPIClass {
8888

8989
private:
9090
nrfx_spim_t _spim;
91+
NRF_SPI_Type *_p_spi;
9192

9293
uint8_t _uc_pinMiso;
9394
uint8_t _uc_pinMosi;

libraries/SPI/SPI_nrf52832.cpp

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
/*
2+
* SPI Master library for nRF5x.
3+
* Copyright (c) 2015 Arduino LLC
4+
* Copyright (c) 2016 Sandeep Mistry All right reserved.
5+
* Copyright (c) 2019 Ha Thach for Adafruit Industries. All right reserved.
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
// Due to nRF52832 Errata with SPIM, we use the legacy SPI for 832 variant
23+
// https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev2/ERR/nRF52832/Rev2/latest/anomaly_832_58.html
24+
#ifdef NRF52832_XXAA
25+
26+
#include "SPI.h"
27+
#include <Arduino.h>
28+
#include <wiring_private.h>
29+
#include <assert.h>
30+
31+
32+
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
33+
34+
SPIClass::SPIClass(NRF_SPIM_Type *p_spi, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI)
35+
{
36+
initialized = false;
37+
assert(p_spi != NULL);
38+
39+
_p_spi = (NRF_SPI_Type*) p_spi;
40+
41+
// not used by 832
42+
// _spim.p_reg = p_spi;
43+
// _spim.drv_inst_idx = 0;
44+
45+
// pins
46+
_uc_pinMiso = g_ADigitalPinMap[uc_pinMISO];
47+
_uc_pinSCK = g_ADigitalPinMap[uc_pinSCK];
48+
_uc_pinMosi = g_ADigitalPinMap[uc_pinMOSI];
49+
50+
_dataMode = SPI_MODE0;
51+
_bitOrder = SPI_CONFIG_ORDER_MsbFirst;
52+
}
53+
54+
void SPIClass::begin()
55+
{
56+
if (initialized) return;
57+
initialized = true;
58+
59+
_p_spi->PSELSCK = _uc_pinSCK;
60+
_p_spi->PSELMOSI = _uc_pinMosi;
61+
_p_spi->PSELMISO = _uc_pinMiso;
62+
63+
beginTransaction(DEFAULT_SPI_SETTINGS);
64+
}
65+
66+
void SPIClass::beginTransaction(SPISettings settings)
67+
{
68+
_p_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
69+
70+
this->_bitOrder = (settings.bitOrder == MSBFIRST ? SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
71+
uint32_t config = this->_bitOrder;
72+
73+
switch (settings.dataMode) {
74+
default:
75+
case SPI_MODE0:
76+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
77+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
78+
break;
79+
80+
case SPI_MODE1:
81+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
82+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
83+
break;
84+
85+
case SPI_MODE2:
86+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
87+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
88+
break;
89+
90+
case SPI_MODE3:
91+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
92+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
93+
break;
94+
}
95+
96+
_p_spi->CONFIG = config;
97+
setClockDivider(F_CPU / settings.clockFreq);
98+
99+
_p_spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
100+
}
101+
102+
void SPIClass::end()
103+
{
104+
_p_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
105+
106+
initialized = false;
107+
}
108+
109+
void SPIClass::usingInterrupt(int /*interruptNumber*/)
110+
{
111+
}
112+
113+
//void SPIClass::beginTransaction(SPISettings settings)
114+
//{
115+
// config(settings);
116+
//}
117+
118+
void SPIClass::endTransaction(void)
119+
{
120+
_p_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
121+
}
122+
123+
void SPIClass::setBitOrder(BitOrder order)
124+
{
125+
this->_bitOrder = (order == MSBFIRST ? SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
126+
127+
uint32_t config = this->_bitOrder;
128+
129+
switch (this->_dataMode) {
130+
default:
131+
case SPI_MODE0:
132+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
133+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
134+
break;
135+
136+
case SPI_MODE1:
137+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
138+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
139+
break;
140+
141+
case SPI_MODE2:
142+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
143+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
144+
break;
145+
146+
case SPI_MODE3:
147+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
148+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
149+
break;
150+
}
151+
152+
_p_spi->CONFIG = config;
153+
}
154+
155+
void SPIClass::setDataMode(uint8_t mode)
156+
{
157+
this->_dataMode = mode;
158+
159+
uint32_t config = this->_bitOrder;
160+
161+
switch (this->_dataMode) {
162+
default:
163+
case SPI_MODE0:
164+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
165+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
166+
break;
167+
168+
case SPI_MODE1:
169+
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
170+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
171+
break;
172+
173+
case SPI_MODE2:
174+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
175+
config |= (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
176+
break;
177+
178+
case SPI_MODE3:
179+
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
180+
config |= (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
181+
break;
182+
}
183+
184+
_p_spi->CONFIG = config;
185+
}
186+
187+
void SPIClass::setClockDivider(uint32_t div)
188+
{
189+
uint32_t clockFreq;
190+
191+
// Adafruit Note: nrf52 run at 64MHz
192+
if (div >= SPI_CLOCK_DIV512) {
193+
clockFreq = SPI_FREQUENCY_FREQUENCY_K125;
194+
} else if (div >= SPI_CLOCK_DIV256) {
195+
clockFreq = SPI_FREQUENCY_FREQUENCY_K250;
196+
} else if (div >= SPI_CLOCK_DIV128) {
197+
clockFreq = SPI_FREQUENCY_FREQUENCY_K500;
198+
} else if (div >= SPI_CLOCK_DIV64) {
199+
clockFreq = SPI_FREQUENCY_FREQUENCY_M1;
200+
} else if (div >= SPI_CLOCK_DIV32) {
201+
clockFreq = SPI_FREQUENCY_FREQUENCY_M2;
202+
} else if (div >= SPI_CLOCK_DIV16) {
203+
clockFreq = SPI_FREQUENCY_FREQUENCY_M4;
204+
} else {
205+
clockFreq = SPI_FREQUENCY_FREQUENCY_M8;
206+
}
207+
208+
_p_spi->FREQUENCY = clockFreq;
209+
}
210+
211+
byte SPIClass::transfer(uint8_t data)
212+
{
213+
_p_spi->TXD = data;
214+
215+
while(!_p_spi->EVENTS_READY);
216+
217+
data = _p_spi->RXD;
218+
219+
_p_spi->EVENTS_READY = 0x0UL;
220+
221+
return data;
222+
}
223+
224+
uint16_t SPIClass::transfer16(uint16_t data) {
225+
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } t;
226+
227+
t.val = data;
228+
229+
if (_bitOrder == SPI_CONFIG_ORDER_LsbFirst) {
230+
t.lsb = transfer(t.lsb);
231+
t.msb = transfer(t.msb);
232+
} else {
233+
t.msb = transfer(t.msb);
234+
t.lsb = transfer(t.lsb);
235+
}
236+
237+
return t.val;
238+
}
239+
240+
void SPIClass::attachInterrupt() {
241+
// Should be enableInterrupt()
242+
}
243+
244+
void SPIClass::detachInterrupt() {
245+
// Should be disableInterrupt()
246+
}
247+
248+
// SPIM0, SPIM1 are configured as I2C
249+
SPIClass SPI(NRF_SPIM2, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI);
250+
251+
#endif // NRF52832_XXAA

variants/feather_nrf52832/variant.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static const uint8_t AREF = PIN_AREF;
100100
#define PIN_SPI_MOSI (13)
101101
#define PIN_SPI_SCK (12)
102102

103-
static const uint8_t SS = 18 ;
103+
static const uint8_t SS = 27 ;
104104
static const uint8_t MOSI = PIN_SPI_MOSI ;
105105
static const uint8_t MISO = PIN_SPI_MISO ;
106106
static const uint8_t SCK = PIN_SPI_SCK ;

0 commit comments

Comments
 (0)