Hi! I'm experimenting with a bare-metal implementation of SPI connectivity among two nrf51 modules. One of them is master, another is slave.
The problem is, the below code doesn't trigger an interrupt after starting task in send_spi_data. Is it fine? Shall I do something else to enable SPIM1 peripherial?
static uint32_t rx_dword = 0;
static uint32_t tx_dword = 0;
static bool rx_done = false;
static bool tx_done = false;
void send_spi_data(uint32_t data)
{
NRF_SPIM1->RXD.PTR = (uint32_t)&rx_dword;
NRF_SPIM1->TXD.PTR = (uint32_t)&tx_dword;
tx_dword = data;
NRF_GPIO->OUTCLR = 1UL << SPIM_CSN_PIN;
NRF_SPIM1->EVENTS_ENDRX = 0;
NRF_SPIM1->EVENTS_ENDTX = 0;
NRF_SPIM1->EVENTS_STOPPED = 0;
NRF_SPIM1->TASKS_START = 1;
}
void init_spim()
{
NRF_GPIO->OUTCLR = 1UL << SPIM_SCK_PIN;
NRF_GPIO->PIN_CNF[SPIM_SCK_PIN] =
(uint32_t) NRF_GPIO_PIN_DIR_OUTPUT << GPIO_PIN_CNF_DIR_Pos
| (uint32_t) NRF_GPIO_PIN_INPUT_CONNECT << GPIO_PIN_CNF_INPUT_Pos
| (uint32_t) NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos
| (uint32_t) NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos
| (uint32_t) NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos;
NRF_SPIM1->PSEL.SCK = SPIM_SCK_PIN;
NRF_GPIO->OUTCLR = 1UL << SPIM_MOSI_PIN;
NRF_GPIO->PIN_CNF[SPIM_MOSI_PIN] =
(uint32_t) NRF_GPIO_PIN_DIR_OUTPUT << GPIO_PIN_CNF_DIR_Pos
| (uint32_t) NRF_GPIO_PIN_INPUT_DISCONNECT << GPIO_PIN_CNF_INPUT_Pos
| (uint32_t) NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos
| (uint32_t) NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos
| (uint32_t) NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos;
NRF_SPIM1->PSEL.MOSI = SPIM_MOSI_PIN;
NRF_GPIO->PIN_CNF[SPIM_MISO_PIN] =
(uint32_t) NRF_GPIO_PIN_DIR_INPUT << GPIO_PIN_CNF_DIR_Pos
| (uint32_t) NRF_GPIO_PIN_INPUT_CONNECT << GPIO_PIN_CNF_INPUT_Pos
| (uint32_t) NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos
| (uint32_t) NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos
| (uint32_t) NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos;
NRF_SPIM1->PSEL.MISO = SPIM_MISO_PIN;
NRF_GPIO->OUTSET = 1UL << SPIM_CSN_PIN;
NRF_GPIO->PIN_CNF[SPIM_CSN_PIN] =
(uint32_t) NRF_GPIO_PIN_DIR_OUTPUT << GPIO_PIN_CNF_DIR_Pos
| (uint32_t) NRF_GPIO_PIN_INPUT_DISCONNECT << GPIO_PIN_CNF_INPUT_Pos
| (uint32_t) NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos
| (uint32_t) NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos
| (uint32_t) NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos;
NRF_SPIM1->CONFIG = 0; // CPOL = 0 - ActiveHigh, CPHA = 0 - Leading edge, ByteOrder = 0 - MSB
NRF_SPIM1->ORC = 0x55;
NRF_SPIM1->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M4;
NRF_SPIM1->RXD.MAXCNT = sizeof(rx_dword);
NRF_SPIM1->TXD.MAXCNT = sizeof(tx_dword);
NRF_SPIM1->RXD.PTR = (uint32_t)&rx_dword;
NRF_SPIM1->TXD.PTR = (uint32_t)&tx_dword;
NRF_SPIM1->INTENSET =
(SPIM_INTENSET_ENDRX_Set << SPIM_INTENSET_ENDRX_Pos)
| (SPIM_INTENSET_ENDTX_Set << SPIM_INTENSET_ENDTX_Pos)
| (SPIM_INTENSET_STOPPED_Set << SPIM_INTENSET_STOPPED_Pos);
NRF_SPIM1->ENABLE = SPIM_ENABLE_ENABLE_Enabled;
NVIC_SetPriority(SPI1_TWI1_IRQn, 3);
NVIC_ClearPendingIRQ(SPI1_TWI1_IRQn);
NVIC_EnableIRQ(SPI1_TWI1_IRQn);
}
__attribute__((__interrupt__))
void SPI1_TWI1_IRQHandler (void)
{
UART_PRINT(__func__);
if(NRF_SPIM1->EVENTS_STOPPED)
{
NRF_SPIM1->EVENTS_STOPPED = 0;
NRF_GPIO->OUTSET = 1UL << SPIM_CSN_PIN;
rx_done = false;
tx_done = false;
}
else
{
if(NRF_SPIM1->EVENTS_ENDRX)
{
NRF_SPIM1->EVENTS_ENDRX = 0;
rx_done = true;
}
else if (NRF_SPIM1->EVENTS_ENDTX)
{
NRF_SPIM1->EVENTS_ENDTX = 0;
tx_done = true;
}
if(rx_done && tx_done)
{
NRF_SPIM1->TASKS_STOP = 1;
}
}
}