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

Dual-mode for SPI module.

Hi,

I am using nrf52810 and want to use the same SPI module as an SPI slave and master in the same application. Is it possible to change the SPI module role on the fly?

I got SPI slave working.

Now When I tried to configure the SPI as Master I got compilation error.

multiple definition of `SPIM0_SPIS0_SPI0_IRQHandler'; Output/ble_app_nrf52810 Release/Obj/nrfx_spis.o: \modules\nrfx\drivers\src/nrfx_spis.c:487: first defined here

I could not resolve the issue. 

Parents
  • The error tells you you've got multiple definitions - so you need to choose one, and remove the other!

  • I understood the error. I want to make a change so that I can use both master and slave functionality. Right now, SDK does not allow us to do this.

    How is this being formed? Is there any way to change it so I can configure the SPI module on the fly.

  • You are using the same hardware instance for both SPIM and SPIS, in which case both SPIM and SPIS drivers will declare their own interrupt handler, this will likely fail as you experience. It is technically possible to switch dynamically between the two, e.g. have one common interrupt handler that call the corresponding driver handler depending on the "active" role. But it's not designed this way, so I don't expect this to be straight forward. Is there any reason why you can't use different hardware instance (e.g. SPIM0 and SPIS1)?

  • Hi Kenneth,

    The complexity is there in our hardware architecture. We have one shared SPI flash between two micro. Nrf52810 acts as spi slave on the same bus. Most of the time, it is a slave device. But there are some cases where it needs to access the SPI flash device. In this case, another master release the bus and nordic should take over as spi master. 

    Is there any reason why you can't use different hardware instance (e.g. SPIM0 and SPIS1)?-->

    nrf52810 has only one SPI peripheral. So there is only one SPIM0 and SPIS0 instance. 

  • Maybe you can consider using SPIS with interrupt, and then SPIM without interrupt?

    So everytime you want to use SPIM you disable SPIS and use SPIM peripheral directly, and re-enable SPIS afterwards.

    It should be pretty straight forward to use the SPIM without interrupt:
    https://infocenter.nordicsemi.com/topic/ps_nrf52810/spim.html

    E.g. enable SPIM, set the PSEL pins, update pointer to buffers, length field, then set CS pin low, trigger START task, wait for END event, and set CS high again, memcpy rx buffer, disable SPIM.

    Best regards,
    Kenneth

  • Looks like I made some progress after using PRS module. 

    Now there is another issue I am facing. 

    After Power On, I am configuring the SPIS module. It works fine. 

    But when I uninit the module and init it back, it behaves weird. It keeps the MOSI pin low.  I did not configure the module as SPI Master. I just uninit it.

    Attached the code

    void init_spi_slave(void)
    {
        nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
        spis_config.csn_pin               = SPIS_CS_PIN;
        spis_config.miso_pin              = SPI_MISO_PIN;
        spis_config.mosi_pin              = SPI_MOSI_PIN;
        spis_config.sck_pin               = SPI_SCK_PIN;
    
        APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));
        APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, p_spi_tx_buf, spi_buf_len, p_spi_rx_buf, spi_buf_len));
    }
    
    void uninit_spi_slave(void)
    {
        nrf_drv_spis_uninit(&spis);
        //Added this later to fix but did not help
        nrf_gpio_cfg_input(SPIS_MISO_PIN, NRF_GPIO_PIN_NOPULL);
        nrf_gpio_cfg_input(SPIS_MOSI_PIN, NRF_GPIO_PIN_NOPULL);
        nrf_gpio_cfg_input(SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL);
        nrf_gpio_cfg_input(SPIS_CS_PIN, NRF_GPIO_PIN_NOPULL);
    }

    Any idea? 

    I tried to configure all the pins as input and then configure the module but it did not work either.

    It works after reset. So something is causing the issue.

  • Can you try to do a hard reset of the peripheral between re-configuration:

    *(volatile uint32_t *)0x40004FFC = 0;
    *(volatile uint32_t *)0x40004FFC;
    *(volatile uint32_t *)0x40004FFC = 1;
Reply Children
No Data
Related