Skip to content

Commit dc32afe

Browse files
committed
(untested) hardware SPI on nRF52. Needs batch mode to make built-in DMA even remotely useful though
1 parent 86d358b commit dc32afe

File tree

4 files changed

+104
-24
lines changed

4 files changed

+104
-24
lines changed

Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,10 +1432,11 @@ ifdef NRF5X
14321432
INCLUDE += -I$(NRF5X_SDK_PATH)/components/ble/ble_advertising
14331433
INCLUDE += -I$(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler
14341434
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/twi_master
1435+
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/spi_master
14351436
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/ppi
14361437
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_pwm
1437-
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/clock
1438-
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/rng
1438+
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/clock
1439+
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/rng
14391440

14401441
TARGETSOURCES += \
14411442
$(NRF5X_SDK_PATH)/components/libraries/util/app_error.c \
@@ -1454,10 +1455,11 @@ ifdef NRF5X
14541455
$(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler/softdevice_handler.c \
14551456
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_nvmc.c \
14561457
$(NRF5X_SDK_PATH)/components/drivers_nrf/twi_master/nrf_drv_twi.c \
1458+
$(NRF5X_SDK_PATH)/components/drivers_nrf/spi_master/nrf_drv_spi.c \
14571459
$(NRF5X_SDK_PATH)/components/drivers_nrf/ppi/nrf_drv_ppi.c \
1458-
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_adc.c \
1459-
$(NRF5X_SDK_PATH)/components/drivers_nrf/clock/nrf_drv_clock.c \
1460-
$(NRF5X_SDK_PATH)/components/libraries/util/app_util_platform.c
1460+
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_adc.c \
1461+
$(NRF5X_SDK_PATH)/components/drivers_nrf/clock/nrf_drv_clock.c \
1462+
$(NRF5X_SDK_PATH)/components/libraries/util/app_util_platform.c
14611463

14621464
# $(NRF5X_SDK_PATH)/components/libraries/util/nrf_log.c
14631465

targetlibs/nrf5x/nrf51_config/sdk_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@
14831483
// <e> TWI0_ENABLED - Enable TWI0 instance
14841484
//==========================================================
14851485
#ifndef TWI0_ENABLED
1486-
#define TWI0_ENABLED 1
1486+
#define TWI0_ENABLED 0
14871487
#endif
14881488
#if TWI0_ENABLED
14891489
// <q> TWI0_USE_EASY_DMA - Use EasyDMA (if present)

targetlibs/nrf5x/nrf52_config/sdk_config.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@
11851185
// <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver
11861186
//==========================================================
11871187
#ifndef SPI_ENABLED
1188-
#define SPI_ENABLED 0
1188+
#define SPI_ENABLED 1
11891189
#endif
11901190
#if SPI_ENABLED
11911191
// <e> SPI_CONFIG_LOG_ENABLED - Enables logging in the module.
@@ -1261,7 +1261,7 @@
12611261
// <e> SPI0_ENABLED - Enable SPI0 instance
12621262
//==========================================================
12631263
#ifndef SPI0_ENABLED
1264-
#define SPI0_ENABLED 0
1264+
#define SPI0_ENABLED 1
12651265
#endif
12661266
#if SPI0_ENABLED
12671267
// <q> SPI0_USE_EASY_DMA - Use EasyDMA
@@ -1545,7 +1545,7 @@
15451545
// <e> TWI0_ENABLED - Enable TWI0 instance
15461546
//==========================================================
15471547
#ifndef TWI0_ENABLED
1548-
#define TWI0_ENABLED 1
1548+
#define TWI0_ENABLED 0
15491549
#endif
15501550
#if TWI0_ENABLED
15511551
// <q> TWI0_USE_EASY_DMA - Use EasyDMA (if present)

targets/nrf5x/jshardware.c

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "nrf_drv_twi.h"
5151
#include "nrf_drv_gpiote.h"
5252
#include "nrf_drv_ppi.h"
53+
#include "nrf_drv_spi.h"
5354

5455
#include "app_uart.h"
5556

@@ -65,7 +66,9 @@
6566
TIMER0 (32 bit) not usable (softdevice)
6667
TIMER1 (16 bit on nRF51, 32 bit on nRF52) used by jshardware util timer
6768
TIMER2 (16 bit) free
68-
SPI0/1 free
69+
SPI0 / TWI0 -> Espruino's SPI1 (only nRF52 - not enough flash on 51)
70+
SPI1 / TWI1 -> Espruino's I2C1
71+
SPI2 -> free
6972
7073
*/
7174

@@ -81,6 +84,18 @@ unsigned int ticksSinceStart = 0;
8184

8285
JshPinFunction pinStates[JSH_PIN_COUNT];
8386

87+
#if SPI_ENABLED
88+
static const NRF_SPI_Type *spi0 = NRF_DRV_SPI_PERIPHERAL(0);
89+
bool spi0Initialised = false;
90+
#endif
91+
92+
static const nrf_drv_twi_t TWI1 = NRF_DRV_TWI_INSTANCE(1);
93+
bool twi1Initialised = false;
94+
95+
const nrf_drv_twi_t *jshGetTWI(IOEventFlags device) {
96+
if (device == EV_I2C1) return &TWI1;
97+
return 0;
98+
}
8499

85100

86101
/// Called when we have had an event that means we should execute JS
@@ -145,7 +160,17 @@ static NO_INLINE void jshPinSetFunction_int(JshPinFunction func, uint32_t pin) {
145160
}
146161
#endif
147162
case JSH_USART1: if (fInfo==JSH_USART_RX) NRF_UART0->PSELRXD = pin;
148-
else NRF_UART0->PSELTXD = pin; break;
163+
else NRF_UART0->PSELTXD = pin;
164+
break;
165+
#if SPI_ENABLED
166+
case JSH_SPI1: if (fInfo==JSH_SPI_MISO) NRF_SPI0->PSELMISO = pin;
167+
else if (fInfo==JSH_SPI_MOSI) NRF_SPI0->PSELMOSI = pin;
168+
else NRF_SPI0->PSELSCK = pin;
169+
break;
170+
#endif
171+
case JSH_I2C1: if (fInfo==JSH_I2C_SDA) NRF_TWI1->PSELSDA = pin;
172+
else NRF_TWI1->PSELSCL = pin;
173+
break;
149174
default: assert(0);
150175
}
151176
}
@@ -779,44 +804,89 @@ void jshUSARTKick(IOEventFlags device) {
779804
}
780805
}
781806

807+
782808
/** Set up SPI, if pins are -1 they will be guessed */
783809
void jshSPISetup(IOEventFlags device, JshSPIInfo *inf) {
810+
#if SPI_ENABLED
811+
if (device!=EV_SPI1) return;
812+
813+
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
814+
815+
nrf_spi_frequency_t freq;
816+
if (inf->baudRate<((125000+250000)/2))
817+
freq = SPI_FREQUENCY_FREQUENCY_K125;
818+
else if (inf->baudRate<((250000+500000)/2))
819+
freq = SPI_FREQUENCY_FREQUENCY_K250;
820+
else if (inf->baudRate<((500000+1000000)/2))
821+
freq = SPI_FREQUENCY_FREQUENCY_K500;
822+
else if (inf->baudRate<((1000000+2000000)/2))
823+
freq = SPI_FREQUENCY_FREQUENCY_M1;
824+
else if (inf->baudRate<((2000000+4000000)/2))
825+
freq = SPI_FREQUENCY_FREQUENCY_M2;
826+
else if (inf->baudRate<((4000000+8000000)/2))
827+
freq = SPI_FREQUENCY_FREQUENCY_M4;
828+
else
829+
freq = SPI_FREQUENCY_FREQUENCY_M8;
830+
spi_config.frequency = freq;
831+
spi_config.mode = inf->spiMode;
832+
spi_config.bit_order = inf->spiMSB ? NRF_DRV_SPI_BIT_ORDER_MSB_FIRST : NRF_DRV_SPI_BIT_ORDER_LSB_FIRST;
833+
834+
if (jshIsPinValid(inf->pinMISO))
835+
spi_config.miso_pin = (uint32_t)pinInfo[inf->pinMISO].pin;
836+
if (jshIsPinValid(inf->pinMOSI))
837+
spi_config.mosi_pin = (uint32_t)pinInfo[inf->pinMOSI].pin;
838+
if (spi0Initialised) nrf_drv_twi_uninit(&spi0);
839+
spi0Initialised = true;
840+
// No event handler means SPI transfers are blocking
841+
uint32_t err_code = nrf_drv_spi_init(&spi0, &spi_config, NULL);
842+
if (err_code != NRF_SUCCESS)
843+
jsExceptionHere(JSET_INTERNALERROR, "SPI Initialisation Error %d\n", err_code);
784844

845+
// nrf_drv_spi_init will set pins, but this ensures we know so can reset state later
846+
if (jshIsPinValid(inf->pinSCK)) {
847+
jshPinSetFunction(inf->pinSCK, JSH_SPI1|JSH_SPI_SCK);
848+
}
849+
if (jshIsPinValid(inf->pinMOSI)) {
850+
jshPinSetFunction(inf->pinMOSI, JSH_SPI1|JSH_SPI_MOSI);
851+
}
852+
if (jshIsPinValid(inf->pinMISO)) {
853+
jshPinSetFunction(inf->pinMISO, JSH_SPI1|JSH_SPI_MISO);
854+
}
855+
#endif
785856
}
786857

787858
/** Send data through the given SPI device (if data>=0), and return the result
788859
* of the previous send (or -1). If data<0, no data is sent and the function
789860
* waits for data to be returned */
790861
int jshSPISend(IOEventFlags device, int data) {
791-
return -1;
862+
#if SPI_ENABLED
863+
if (device!=EV_SPI1) return -1;
864+
uint8_t tx = (uint8_t)data;
865+
uint8_t rx = 0;
866+
nrf_drv_spi_transfer(&spi0, &tx, 1, &rx, 1);
867+
return rx;
868+
#endif
792869
}
793870

794871
/** Send 16 bit data through the given SPI device. */
795872
void jshSPISend16(IOEventFlags device, int data) {
796-
873+
#if SPI_ENABLED
874+
if (device!=EV_SPI1) return;
875+
uint16_t tx = (uint16_t)data;
876+
nrf_drv_spi_transfer(&spi0, (uint8_t*)&tx, 1, 0, 0);
877+
#endif
797878
}
798879

799880
/** Set whether to send 16 bits or 8 over SPI */
800881
void jshSPISet16(IOEventFlags device, bool is16) {
801-
802882
}
803883

804884
/** Set whether to use the receive interrupt or not */
805885
void jshSPISetReceive(IOEventFlags device, bool isReceive) {
806-
807886
}
808887

809888
/** Wait until SPI send is finished, and flush all received data */
810889
void jshSPIWait(IOEventFlags device) {
811-
812-
}
813-
814-
const nrf_drv_twi_t TWI1 = NRF_DRV_TWI_INSTANCE(1);
815-
bool twi1Initialised = false;
816-
817-
const nrf_drv_twi_t *jshGetTWI(IOEventFlags device) {
818-
if (device == EV_I2C1) return &TWI1;
819-
return 0;
820890
}
821891

822892
/** Set up I2C, if pins are -1 they will be guessed */
@@ -840,6 +910,14 @@ void jshI2CSetup(IOEventFlags device, JshI2CInfo *inf) {
840910
jsExceptionHere(JSET_INTERNALERROR, "I2C Initialisation Error %d\n", err_code);
841911
else
842912
nrf_drv_twi_enable(twi);
913+
914+
// nrf_drv_spi_init will set pins, but this ensures we know so can reset state later
915+
if (jshIsPinValid(inf->pinSCL)) {
916+
jshPinSetFunction(inf->pinSCL, JSH_I2C1|JSH_I2C_SCL);
917+
}
918+
if (jshIsPinValid(inf->pinSDA)) {
919+
jshPinSetFunction(inf->pinSDA, JSH_I2C1|JSH_I2C_SDA);
920+
}
843921
}
844922

845923
/** Addresses are 7 bit - that is, between 0 and 0x7F. sendStop is whether to send a stop bit or not */

0 commit comments

Comments
 (0)