NRF52 config SPIS by register can't work

i want config spis by register, but it can't work, when spi master send data, spis irq handler can,t enter, could you tell me what's wong happen?if i use spis library ,it works successful.

this is my code:

void nrfx_spis_1_irq_handler(void)
{

    if (NRF_SPIS1->EVENTS_ENDRX)

    {
         NRF_SPIS1->EVENTS_ENDRX = 0;
         NRF_LOG_INFO("123123");
    }
}

void spis_init(void)
{
    NRF_SPIS1->CONFIG = NRF_SPIS_BIT_ORDER_MSB_FIRST << 0 | 0 << 1 | 0 << 2;


    NRF_SPIS1->PSEL.CSN = 0x0 << 31 | AP_SPIS_CS_PIN << 0;
    NRF_SPIS1->PSEL.SCK = 0x0 << 31 | AP_SPIS_SCK_PIN << 0;
    NRF_SPIS1->PSEL.MOSI = 0x0 << 31 | AP_SPIS_MOSI_PIN << 0;
    NRF_SPIS1->PSEL.MISO = 0x0 << 31 | AP_SPIS_MISO_PIN << 0;


    nrf_gpio_cfg(AP_SPIS_CS_PIN,
                 NRF_GPIO_PIN_DIR_INPUT,
                 NRF_GPIO_PIN_INPUT_CONNECT,
                 NRF_GPIO_PIN_NOPULL,
                 NRF_GPIO_PIN_S0S1,
                 NRF_GPIO_PIN_NOSENSE);

    nrf_gpio_cfg(AP_SPIS_SCK_PIN,
                 NRF_GPIO_PIN_DIR_INPUT,
                 NRF_GPIO_PIN_INPUT_CONNECT,
                 NRF_GPIO_PIN_NOPULL,
                 NRF_GPIO_PIN_S0S1,
                 NRF_GPIO_PIN_NOSENSE);

    nrf_gpio_cfg(AP_SPIS_MOSI_PIN,
                     NRF_GPIO_PIN_DIR_INPUT,
                     NRF_GPIO_PIN_INPUT_CONNECT,
                     NRF_GPIO_PIN_NOPULL,
                     NRF_GPIO_PIN_S0S1,
                     NRF_GPIO_PIN_NOSENSE);

    nrf_gpio_cfg(AP_SPIS_MISO_PIN,
                     NRF_GPIO_PIN_DIR_INPUT,
                     NRF_GPIO_PIN_INPUT_CONNECT,
                     NRF_GPIO_PIN_NOPULL,
                     NRF_GPIO_PIN_H0H1,
                     NRF_GPIO_PIN_NOSENSE);

    NRF_SPIS1->DEF = 0x00;
    NRF_SPIS1->ORC = 0x00;

    NRF_SPIS1->EVENTS_ACQUIRED = 0;
    NRF_SPIS1->EVENTS_END = 0;
    NRF_SPIS1->EVENTS_ENDRX = 0;

    NRF_SPIS1->TXD.MAXCNT = AP_SPIS_MAX_DATA_LENGTH;
    NRF_SPIS1->TXD.PTR = (uint32_t)m_spis_tx_buf;

    NRF_SPIS1->RXD.MAXCNT = AP_SPIS_MAX_DATA_LENGTH;
    NRF_SPIS1->RXD.PTR = (uint32_t)m_spis_rx_buf;

    NRF_SPIS1->INTENSET |= 0x1 << 4 | 0x1 << 1 | 1 << 10;

    NVIC_SetPriority(SPI1_TWI1_IRQn, 1);
    NVIC_EnableIRQ(SPI1_TWI1_IRQn);

    NRF_SPIS1->ENABLE = 0x02;

}

  • Hi,

    • Have you checked the register values with a debugger, to make sure they are set to the expected values?
    • What pins are defined in 
    • It looks like you have configured the MISO pin as an input, this should be an output for SPIS.
    • SPI1_TWI1_IRQn, which you use with the NVIC functions are for nRF51, the correct for nRF52832 should be SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn. Can you try this? You can also define the IRQ handler as: "void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void)" when not using the NRFX drivers.

    Best regards,
    Jørgen

  • 1、yes, i use debug mode for check my config, it's correct.

    2、i check pin defined, they are correct

    3、though i config miso as input, the master couldn't receive anything,but slave should receive master data

    4、i use SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn and void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void), it can,t works

  • Hi,

    I wanted to ask which pins are defined in AP_SPIS_CS_PIN, AP_SPIS_SCK_PIN, AP_SPIS_MOSI_PIN, and AP_SPIS_MISO_PIN. Some pins can have special functionality (nRESET, NFCT, etc), although they can also be used as GPIOs.

    Please also post a readout of the SPIS registers when you have completed the configuration (from address 0x40004000 to 0x40005000).

    Best regards,
    Jørgen

  • hi jorgen,

    i found the error,

    after i config and enable spis, the SPI semaphore is assigned to cpu, i added spis-Task-release after spis enable , it works succesful!

    i have some questions:

    1.Why not trigger interrupt function when semaphore is allocated to cpu?

    2.When SPIS transmission starts, the CPU attempts to acquire the semaphore at this time. Will it cause SPIS transmission failure without interruption?

    3.I have two threads. One thread produces data and the other is SPIS sends data. The thread of production data and the thread of sending data have their own ticks, so they cannot be aligned.

    My initial method was to fill the newly produced data in the spis interrupt handler (events_end). I succeeded, but this caused a delay in the spi polling interval.

    I hope that when the data is just produced, it will be directly filled into the DMA buffer of Spis, so I try to obtain the semaphore before filling the buffer, and release the semaphore after filling, but this will result in a certain probability that SPIS will not be interrupted. Why? Do you have any good suggestions that I should do?the timing is here:

    thanks!

  • Hi,

    Liny said:
    1.Why not trigger interrupt function when semaphore is allocated to cpu?

    As mentioned in the SPIS documentation:

    "The SPI slave will try to acquire the semaphore when CSN goes low. If the SPI slave does not manage to acquire the semaphore at this point, the transaction will be ignored. This means that all incoming data on MOSI will be discarded, and the DEF (default) character will be clocked out on the MISO line throughout the whole transaction. This will also be the case even if the semaphore is released by the CPU during the transaction.

    Liny said:
    2.When SPIS transmission starts, the CPU attempts to acquire the semaphore at this time. Will it cause SPIS transmission failure without interruption?

    From documentation: "In case of a race condition where the CPU and the SPI slave try to acquire the semaphore at the same time, as illustrated in lifeline item 2 in Figure 2, the semaphore will be granted to the CPU." and "If the CPU tries to acquire the semaphore while it is assigned to the SPI slave, an immediate handover will not be granted. However, the semaphore will be handed over to the CPU as soon as the SPI slave has released the semaphore after the granted transaction is completed."

    Liny said:
    3.I have two threads. One thread produces data and the other is SPIS sends data. The thread of production data and the thread of sending data have their own ticks, so they cannot be aligned.

    Do you need to always have the data in the same buffer? Another approach would be to have two buffers, one assigned to the SPIS, and another buffer being filled by the "data producers", then switch buffer when the data is being sent. Switching the buffer pointer should be much faster than filling the old buffer with the new data.

    Best regards,
    Jørgen

Related