This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

What is the safe way to implement ready line for SPI?

I want to implement a ready line for SPI and I noticed nordic has similar code in your sdk: components/serialization/common/transport/ser_phy/ser_phy_spi_slave.c.

However the following comment concerns me: "     //toggle - this should go high - but toggle is unsafe"

So I want to do a safe version and I do the following change:

In spi_slave_gpiote_init(), I change the following line

>> nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
to

>> nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_HIGH;
>> config.init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH;

And I also change the lines in set_ready_line()

from:

>> //toggle - this should go high - but toggle is unsafe
>> uint32_t rdy_task = nrf_drv_gpiote_out_task_addr_get(m_spi_slave_raw_config.pin_rdy)

>> *(uint32_t *)rdy_task = 1;

to

>> nrf_gpio_pin_clear(m_spi_slave_raw_config.pin_rdy);

But it doesn't work at all. The ready line keeps high and never becomes low which indicates ready. I don't know what I do wrongly and what is supposed to be the safe way instead of toggle?

Parents
  • Hello,

    You can use the PPI for this, but you would want to split this into two tasks.

    To set the pin HIGH when SPI transfer is done, you can set 

    in spi_slave_gpiote_init(void):

    NRF_GPIOTE->CONFIG[m_spi_slave_raw_config.ppi_rdy_ch]   = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos | 
                                                GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos | 
                                                m_spi_slawe_raw_config.pin_rdy << GPIOTE_CONFIG_PSEL_Pos | 
                                                GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos;

    instead of 

        nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
        (void) nrf_drv_gpiote_out_init(m_spi_slave_raw_config.pin_rdy, &config);
        (void) nrf_drv_gpiote_out_task_enable(m_spi_slave_raw_config.pin_rdy);

    In spi_slave_ppi_init(void), change:

    NRF_PPI->CH[m_spi_slave_raw_config.ppi_rdy_ch].TEP = rdy_task; 

    to

    NRF_PPI->CH[m_spi_slave_raw_config.ppi_rdy_ch].TEP = (uint32_t)&NRF_GPIOTE->TASKS_SET[some free channel_A];

    Then you must set up a task to set the pin to LOW. This should be done everywhere where you see the set_ready_line(); function (below "DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0);  )

    You can e.g. use the task:

    NRF_GPIOTE->TASKS_CLR[some free channel_A] = 1;

    I am sorry, but I have not tested this. I assume you can use the same setup for the gpiote in spi_slave_gpiote_init, and only change the rdy_task to TASKS_SET, and then use TASKS_CLEAR = 1 as described above, in the application where you want to clear the pin. 

    Best regards,

    Edvin

Reply
  • Hello,

    You can use the PPI for this, but you would want to split this into two tasks.

    To set the pin HIGH when SPI transfer is done, you can set 

    in spi_slave_gpiote_init(void):

    NRF_GPIOTE->CONFIG[m_spi_slave_raw_config.ppi_rdy_ch]   = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos | 
                                                GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos | 
                                                m_spi_slawe_raw_config.pin_rdy << GPIOTE_CONFIG_PSEL_Pos | 
                                                GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos;

    instead of 

        nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
        (void) nrf_drv_gpiote_out_init(m_spi_slave_raw_config.pin_rdy, &config);
        (void) nrf_drv_gpiote_out_task_enable(m_spi_slave_raw_config.pin_rdy);

    In spi_slave_ppi_init(void), change:

    NRF_PPI->CH[m_spi_slave_raw_config.ppi_rdy_ch].TEP = rdy_task; 

    to

    NRF_PPI->CH[m_spi_slave_raw_config.ppi_rdy_ch].TEP = (uint32_t)&NRF_GPIOTE->TASKS_SET[some free channel_A];

    Then you must set up a task to set the pin to LOW. This should be done everywhere where you see the set_ready_line(); function (below "DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0);  )

    You can e.g. use the task:

    NRF_GPIOTE->TASKS_CLR[some free channel_A] = 1;

    I am sorry, but I have not tested this. I assume you can use the same setup for the gpiote in spi_slave_gpiote_init, and only change the rdy_task to TASKS_SET, and then use TASKS_CLEAR = 1 as described above, in the application where you want to clear the pin. 

    Best regards,

    Edvin

Children
No Data
Related