Skip to content

Commit d44fb29

Browse files
authored
Merge pull request ARMmbed#13397 from winneymj/enable_SPIM
Provide enablement of nrf52840 SPIM
2 parents 8493200 + e5f32ff commit d44fb29

File tree

4 files changed

+180
-11
lines changed

4 files changed

+180
-11
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ The tables must be placed in a C compilation file.
9090
1. If an instance is being used exclusively for either I2C or SPI, the objects can safely be called from multiple threads.
9191
1. If an instance is being used for both I2C and SPI, the user must provide thread safety between the objects.
9292

93+
#### SPIM
94+
Description below taken from nRF52840 datasheet.
95+
96+
*The SPI master can communicate with multiple SPI slaves using individual chip select signals for each slave.*
97+
98+
*Listed here are the main features for the SPIM*
99+
100+
- *EasyDMA direct transfer to/from RAM*
101+
- *SPI mode 0-3*
102+
- *Individual selection of I/O pins*
103+
- *Optional D/CX output line for distinguishing between command and data bytes*
104+
105+
SPIM Instance 3 can provide transfer speeds up to 32 Mhz.
106+
107+
##### Configuration
108+
Enabled in the *sdk_config.h* by setting the **NRFX_SPIM_ENABLED** macro
109+
110+
As SPI and SPIM use the same hardware you should disable the SPI configuration at the same time (**NRFX_SPI_ENABLED**)
93111

94112
### Serial
95113

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@
4343
#include "PortNames.h"
4444
#include "PeripheralNames.h"
4545
#include "PinNames.h"
46+
#if NRFX_SPIM_ENABLED && DEVICE_SPI
47+
#include "nrfx_spim.h"
48+
#elif DEVICE_SPI
4649
#include "nrfx_spi.h"
50+
#endif
4751
#include "nrf_twi.h"
4852

4953
#include "nrf_pwm.h"
@@ -90,7 +94,11 @@ struct serial_s {
9094
struct spi_s {
9195
int instance;
9296
PinName cs;
97+
#if NRFX_SPIM_ENABLED && DEVICE_SPI
98+
nrfx_spim_config_t config;
99+
#elif DEVICE_SPI
93100
nrfx_spi_config_t config;
101+
#endif
94102
bool update;
95103

96104
#if DEVICE_SPI_ASYNCH

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/spi_api.c

Lines changed: 154 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,37 @@
4444
#include "pinmap_ex.h"
4545
#include "PeripheralPins.h"
4646

47+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
48+
#include "nrfx_spim.h"
49+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
4750
#include "nrfx_spi.h"
51+
#endif
4852

4953
#if 0
5054
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
5155
#else
5256
#define DEBUG_PRINTF(...)
5357
#endif
5458

59+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
60+
/* Pre-allocate instances and share them globally. */
61+
static const nrfx_spim_t nordic_nrf5_spim_instance[4] = {
62+
NRFX_SPIM_INSTANCE(0),
63+
NRFX_SPIM_INSTANCE(1),
64+
NRFX_SPIM_INSTANCE(2),
65+
NRFX_SPIM_INSTANCE(3)
66+
};
67+
68+
/* Keep track of which instance has been initialized. */
69+
static bool nordic_nrf5_spi_initialized[4] = { false, false, false, false };
70+
71+
/* Forware declare interrupt handler. */
72+
#if DEVICE_SPI_ASYNCH
73+
static void nordic_nrf5_spi_event_handler(nrfx_spim_evt_t const *p_event, void *p_context);
74+
#endif
75+
76+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
77+
5578
/* Pre-allocate instances and share them globally. */
5679
static const nrfx_spi_t nordic_nrf5_spi_instance[3] = {
5780
NRFX_SPI_INSTANCE(0),
@@ -66,6 +89,7 @@ static bool nordic_nrf5_spi_initialized[3] = { false, false, false };
6689
#if DEVICE_SPI_ASYNCH
6790
static void nordic_nrf5_spi_event_handler(nrfx_spi_evt_t const *p_event, void *p_context);
6891
#endif
92+
#endif //NRFX_SPI_ENABLED
6993

7094
/* Forward declaration. These functions are implemented in the driver but not
7195
* set up in the NVIC due to it being relocated.
@@ -74,6 +98,15 @@ void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void);
7498
void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void);
7599
void SPIM2_SPIS2_SPI2_IRQHandler(void);
76100

101+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
102+
103+
/* Forward declaration. These functions are implemented in the driver but not
104+
* set up in the NVIC due to it being relocated.
105+
*/
106+
void SPIM3_IRQHandler(void);
107+
108+
#endif // NRFX_SPIM_ENABLED
109+
77110
/**
78111
* Brief Reconfigure peripheral.
79112
*
@@ -105,19 +138,36 @@ static void spi_configure_driver_instance(spi_t *obj)
105138

106139
/* Clean up and uninitialize peripheral if already initialized. */
107140
if (nordic_nrf5_spi_initialized[instance]) {
141+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
142+
nrfx_spim_uninit(&nordic_nrf5_spim_instance[instance]);
143+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
108144
nrfx_spi_uninit(&nordic_nrf5_spi_instance[instance]);
145+
#endif
109146
}
110147

111148
#if DEVICE_SPI_ASYNCH
112149
/* Set callback handler in asynchronous mode. */
113150
if (spi_inst->handler) {
151+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
152+
nrfx_spim_init(&nordic_nrf5_spim_instance[instance], &(spi_inst->config), nordic_nrf5_spi_event_handler, obj);
153+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
114154
nrfx_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), nordic_nrf5_spi_event_handler, obj);
155+
#endif
115156
} else {
157+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
158+
nrfx_spim_init(&nordic_nrf5_spim_instance[instance], &(spi_inst->config), NULL, NULL);
159+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
116160
nrfx_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), NULL, NULL);
161+
#endif
117162
}
118163
#else
119164
/* Set callback handler to NULL in synchronous mode. */
120-
nrfx_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), NULL, NULL);
165+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
166+
nrfx_spim_init(&nordic_nrf5_spim_instance[instance], &(spi_inst->config), NULL, NULL);
167+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
168+
nrfx_spi_init(&nordic_nrf5_spim_instance[instance], &(spi_inst->config), NULL, NULL);
169+
#endif
170+
121171
#endif
122172

123173
/* Mark instance as initialized. */
@@ -194,7 +244,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
194244

195245
/* Get instance based on requested pins. */
196246
spi_inst->instance = pin_instance_spi(mosi, miso, sclk);
247+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
248+
MBED_ASSERT(spi_inst->instance < NRFX_SPIM_ENABLED_COUNT);
249+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
197250
MBED_ASSERT(spi_inst->instance < NRFX_SPI_ENABLED_COUNT);
251+
#endif
198252

199253
/* Store chip select separately for manual enabling. */
200254
spi_inst->cs = ssel;
@@ -203,14 +257,24 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
203257
spi_inst->config.sck_pin = sclk;
204258
spi_inst->config.mosi_pin = mosi;
205259
spi_inst->config.miso_pin = miso;
260+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
261+
spi_inst->config.ss_pin = NRFX_SPIM_PIN_NOT_USED;
262+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
206263
spi_inst->config.ss_pin = NRFX_SPI_PIN_NOT_USED;
207-
264+
#endif
208265
/* Use the default config. */
209266
spi_inst->config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY;
210267
spi_inst->config.orc = SPI_FILL_CHAR;
268+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
269+
spi_inst->config.frequency = NRF_SPIM_FREQ_4M;
270+
spi_inst->config.mode = NRF_SPIM_MODE_0;
271+
spi_inst->config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
272+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
211273
spi_inst->config.frequency = NRF_SPI_FREQ_4M;
212274
spi_inst->config.mode = NRF_SPI_MODE_0;
213275
spi_inst->config.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST;
276+
#endif
277+
214278

215279
#if DEVICE_SPI_ASYNCH
216280
/* Set default values for asynchronous variables. */
@@ -239,6 +303,9 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
239303
NVIC_SetVector(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, (uint32_t) SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler);
240304
NVIC_SetVector(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, (uint32_t) SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler);
241305
NVIC_SetVector(SPIM2_SPIS2_SPI2_IRQn, (uint32_t) SPIM2_SPIS2_SPI2_IRQHandler);
306+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
307+
NVIC_SetVector(SPIM3_IRQn, (uint32_t) SPIM3_IRQHandler);
308+
#endif
242309
}
243310
}
244311

@@ -263,7 +330,11 @@ void spi_free(spi_t *obj)
263330
int instance = spi_inst->instance;
264331

265332
/* Use driver uninit to free instance. */
333+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
334+
nrfx_spim_uninit(&nordic_nrf5_spim_instance[instance]);
335+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
266336
nrfx_spi_uninit(&nordic_nrf5_spi_instance[instance]);
337+
#endif
267338

268339
/* Mark instance as uninitialized. */
269340
nordic_nrf5_spi_initialized[instance] = false;
@@ -291,6 +362,20 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
291362
struct spi_s *spi_inst = obj;
292363
#endif
293364

365+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
366+
nrf_spim_mode_t new_mode = NRF_SPIM_MODE_0;
367+
368+
/* Convert Mbed HAL mode to Nordic mode. */
369+
if (mode == 0) {
370+
new_mode = NRF_SPIM_MODE_0;
371+
} else if (mode == 1) {
372+
new_mode = NRF_SPIM_MODE_1;
373+
} else if (mode == 2) {
374+
new_mode = NRF_SPIM_MODE_2;
375+
} else if (mode == 3) {
376+
new_mode = NRF_SPIM_MODE_3;
377+
}
378+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
294379
nrf_spi_mode_t new_mode = NRF_SPI_MODE_0;
295380

296381
/* Convert Mbed HAL mode to Nordic mode. */
@@ -303,6 +388,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
303388
} else if (mode == 3) {
304389
new_mode = NRF_SPI_MODE_3;
305390
}
391+
#endif
306392

307393
/* Check if configuration has changed. */
308394
if (spi_inst->config.mode != new_mode) {
@@ -333,6 +419,30 @@ void spi_frequency(spi_t *obj, int hz)
333419
struct spi_s *spi_inst = obj;
334420
#endif
335421

422+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
423+
nrf_spim_frequency_t new_frequency = NRF_SPIM_FREQ_1M;
424+
425+
/* Convert frequency to Nordic enum type. */
426+
if (hz < 250000) {
427+
new_frequency = NRF_SPIM_FREQ_125K;
428+
} else if (hz < 500000) {
429+
new_frequency = NRF_SPIM_FREQ_250K;
430+
} else if (hz < 1000000) {
431+
new_frequency = NRF_SPIM_FREQ_500K;
432+
} else if (hz < 2000000) {
433+
new_frequency = NRF_SPIM_FREQ_1M;
434+
} else if (hz < 4000000) {
435+
new_frequency = NRF_SPIM_FREQ_2M;
436+
} else if (hz < 8000000) {
437+
new_frequency = NRF_SPIM_FREQ_4M;
438+
} else if (hz < 16000000) {
439+
new_frequency = NRF_SPIM_FREQ_8M;
440+
} else if (hz < 32000000) {
441+
new_frequency = NRF_SPIM_FREQ_16M;
442+
} else {
443+
new_frequency = NRF_SPIM_FREQ_32M;
444+
}
445+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
336446
nrf_spi_frequency_t new_frequency = NRF_SPI_FREQ_1M;
337447

338448
/* Convert frequency to Nordic enum type. */
@@ -351,7 +461,7 @@ void spi_frequency(spi_t *obj, int hz)
351461
} else {
352462
new_frequency = NRF_SPI_FREQ_8M;
353463
}
354-
464+
#endif
355465
/* Check if configuration has changed. */
356466
if (spi_inst->config.frequency != new_frequency) {
357467
spi_inst->config.frequency = new_frequency;
@@ -370,7 +480,12 @@ void spi_frequency(spi_t *obj, int hz)
370480
int spi_master_write(spi_t *obj, int value)
371481
{
372482
nrfx_err_t ret;
373-
nrfx_spi_xfer_desc_t desc;
483+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
484+
nrfx_spim_xfer_desc_t desc;
485+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
486+
nrfx_spi_xfer_desc_t desc;
487+
#endif
488+
374489
#if DEVICE_SPI_ASYNCH
375490
struct spi_s *spi_inst = &obj->spi;
376491
#else
@@ -396,7 +511,11 @@ int spi_master_write(spi_t *obj, int value)
396511
desc.p_rx_buffer = &rx_buff;
397512
desc.tx_length = 1;
398513
desc.rx_length = 1;
514+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
515+
ret = nrfx_spim_xfer(&nordic_nrf5_spim_instance[instance], &desc, 0);
516+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
399517
ret = nrfx_spi_xfer(&nordic_nrf5_spi_instance[instance], &desc, 0);
518+
#endif
400519

401520
if (ret != NRFX_SUCCESS) {
402521
DEBUG_PRINTF("%d error returned from nrf_spi_xfer\n\r");
@@ -428,7 +547,12 @@ int spi_master_write(spi_t *obj, int value)
428547
*/
429548
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill)
430549
{
550+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
551+
nrfx_spim_xfer_desc_t desc;
552+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
431553
nrfx_spi_xfer_desc_t desc;
554+
#endif
555+
432556
#if DEVICE_SPI_ASYNCH
433557
struct spi_s *spi_inst = &obj->spi;
434558
#else
@@ -486,9 +610,13 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha
486610
desc.p_rx_buffer = rx_actual_buffer;
487611
desc.tx_length = tx_actual_length;
488612
desc.rx_length = rx_actual_length;
613+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
614+
result = nrfx_spim_xfer(&nordic_nrf5_spim_instance[instance],
615+
&desc, 0);
616+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
489617
result = nrfx_spi_xfer(&nordic_nrf5_spi_instance[instance],
490618
&desc, 0);
491-
619+
#endif
492620
/* Update loop variables. */
493621
tx_length -= tx_actual_length;
494622
tx_offset += tx_actual_length;
@@ -623,7 +751,11 @@ void spi_slave_write(spi_t *obj, int value)
623751

624752
static ret_code_t spi_master_transfer_async_continue(spi_t *obj)
625753
{
754+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
755+
nrfx_spim_xfer_desc_t desc;
756+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
626757
nrfx_spi_xfer_desc_t desc;
758+
#endif
627759
/* Remaining data to be transferred. */
628760
size_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
629761
size_t rx_length = obj->rx_buff.length - obj->rx_buff.pos;
@@ -643,13 +775,20 @@ static ret_code_t spi_master_transfer_async_continue(spi_t *obj)
643775
desc.tx_length = tx_length;
644776
desc.rx_length = rx_length;
645777

646-
ret_code_t result = nrfx_spi_xfer(&nordic_nrf5_spi_instance[obj->spi.instance],
647-
&desc, 0);
778+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
779+
ret_code_t result = nrfx_spim_xfer(&nordic_nrf5_spim_instance[obj->spi.instance], &desc, 0);
780+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
781+
ret_code_t result = nrfx_spi_xfer(&nordic_nrf5_spi_instance[obj->spi.instance], &desc, 0);
782+
#endif
648783
return result;
649784
}
650785

651786
/* Callback function for driver calls. This is called from ISR context. */
787+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
788+
static void nordic_nrf5_spi_event_handler(nrfx_spim_evt_t const *p_event, void *p_context)
789+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
652790
static void nordic_nrf5_spi_event_handler(nrfx_spi_evt_t const *p_event, void *p_context)
791+
#endif
653792
{
654793
// Only safe to use with mbed-printf.
655794
//DEBUG_PRINTF("nordic_nrf5_twi_event_handler: %d %p\r\n", p_event->type, p_context);
@@ -660,7 +799,11 @@ static void nordic_nrf5_spi_event_handler(nrfx_spi_evt_t const *p_event, void *p
660799
spi_t *obj = (spi_t *) p_context;
661800
struct spi_s *spi_inst = &obj->spi;
662801

802+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
803+
if (p_event->type == NRFX_SPIM_EVENT_DONE) {
804+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
663805
if (p_event->type == NRFX_SPI_EVENT_DONE) {
806+
#endif
664807

665808
/* Update buffers with new positions. */
666809
obj->tx_buff.pos += p_event->xfer_desc.tx_length;
@@ -859,12 +1002,14 @@ void spi_abort_asynch(spi_t *obj)
8591002
int instance = obj->spi.instance;
8601003

8611004
/* Abort transfer. */
1005+
#if NRFX_CHECK(NRFX_SPIM_ENABLED)
1006+
nrfx_spim_abort(&nordic_nrf5_spim_instance[instance]);
1007+
#elif NRFX_CHECK(NRFX_SPI_ENABLED)
8621008
nrfx_spi_abort(&nordic_nrf5_spi_instance[instance]);
863-
1009+
#endif
8641010
/* Force reconfiguration. */
8651011
object_owner_spi2c_set(instance, NULL);
8661012
}
8671013

8681014
#endif // DEVICE_SPI_ASYNCH
869-
8701015
#endif // DEVICE_SPI

0 commit comments

Comments
 (0)