Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

The nrfx_spim driver toggles random pin when chip select pin of the driver is not used.

The nrfx_spim driver has an issue when chip select pin of the driver is not used. 

When nrfx_spim_init is called with a nrfx_spim_config_t whose ss_pin is set to NRFX_SPIM_PIN_NOT_USED the value is not assigned to the ss_pin of the spim_control_block_t in the driver.

This results in a toggle of the ss_pin, which has not been initialized, when nrfx_spim_xfer is called.

This problem is present in nrf-sdk version 15.2 and 15.0. 

  • Hi,

    Can you upload some project files that I can use to recreate this? Or point me to exactly where in the driver the ss pin is being toggled?

    When I test this with the basic SPI example in SDK 15.2.0 the p_cb->ss_pin is set to 0xFF (NRFX_SPIM_PIN_NOT_USED) inside nrfx_spim_init(). Then there is an if-statement inside nrfx_spim_xfer() that checks this and skips the toggling of the ss_pin if it is not used:

    if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
    {
    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
        if (!p_cb->use_hw_ss)
    #endif
        {
            if (p_cb->ss_active_high)
            {
                nrf_gpio_pin_set(p_cb->ss_pin);
            }
            else
            {
                nrf_gpio_pin_clear(p_cb->ss_pin);
            }

  • In the nrfx_spim_init() function the ss_pin of the driver instance in the m_cb array is set if the ss_pin in the config is not NRFX_SPIM_PIN_NOT_USED. If however the p_config->ss_pin is NRFX_SPIM_PIN_NOT_USED the ss_pin of the driver (m_cb[p_instance->drv_inst_idx].ss_pin) instance is not set. The relevant if clause is included below, it starts at line 281 in the driver code.

        if (p_config->ss_pin != NRFX_SPIM_PIN_NOT_USED)
        {
            if (p_config->ss_active_high)
            {
                nrf_gpio_pin_clear(p_config->ss_pin);
            }
            else
            {
                nrf_gpio_pin_set(p_config->ss_pin);
            }
            //nrf_gpio_cfg_output(p_config->ss_pin);
    			 nrf_gpio_cfg(p_config->ss_pin,
    				  NRF_GPIO_PIN_DIR_OUTPUT,
    				  NRF_GPIO_PIN_INPUT_DISCONNECT,
    				  NRF_GPIO_PIN_NOPULL,
    				  NRF_GPIO_PIN_H0H1,
    				  NRF_GPIO_PIN_NOSENSE);
    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
            if (p_config->use_hw_ss)
            {
                m_cb[p_instance->drv_inst_idx].use_hw_ss = p_config->use_hw_ss;
                nrf_spim_csn_configure(p_spim,
                                       p_config->ss_pin,
                                       (p_config->ss_active_high == true ?
                                            NRF_SPIM_CSN_POL_HIGH : NRF_SPIM_CSN_POL_LOW),
                                       p_config->ss_duration);
            }
    #endif
            m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin;
            m_cb[p_instance->drv_inst_idx].ss_active_high = p_config->ss_active_high;
        } 

    When nrfx_spim_xfer() is called, after initializing the spim driver with ss_pin ==NRFX_SPIM_PIN_NOT_USED in the config, the ss_pin of the driver has not been initialized. In the code below p_cb->ss_pin is therefore not NRFX_SPIM_PIN_NOT_USED and the code in the if cluase is executed. I am not using the extended mode so the use_hw_ss flag is not checked.

        if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
        {
    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
            if (!p_cb->use_hw_ss)
    #endif
            {
                if (p_cb->ss_active_high)
                {
                    nrf_gpio_pin_set(p_cb->ss_pin);
                }
                else
                {
                    nrf_gpio_pin_clear(p_cb->ss_pin);
                }
            }
        }

  • This seems to be the same issue as the one reported here: https://devzone.nordicsemi.com/f/nordic-q-a/33246/sdk-15-spi-driver-sttting-with-ss_pin-nrf_drv_spi_pin_not_used

    However, I believe they have fixed it in SDK 15.2.0 where they have added these lines in nrfx_spim_init():

    // 'p_cb->ss_pin' variable is used during transfers to check if SS pin should be toggled,
    // so this field needs to be initialized even if the pin is not used.
    p_cb->ss_pin = p_config->ss_pin;

    p_cb is a pointer to m_cb so the ss_pin is set no matter what.

  • Ok, I've checked the driver in sdk 15.2 and it works as you've noted.

    I tested it on sdk 15.0 and missed this assignment when reviewing sdk 15.2.

    Thanks!

Related