SPI Slave enable/disable issue

Hi,

I'm working on final project wrapup on a device with an nRF5340 using NCS v1.7.1 where the Nordic part is an SPI slave to another processor.

My customer is getting my code running on his board for the first time and he's seeing SPI init errors - I'm checking with him to see if it's occasional or every time. I think I remember getting this error once or twice, but not normally. (the board is custom - but it's the same model board I've been working with so this isn't the first time this code has run on a board like his)

The way this system works, another processor sends us a signal on a GPIO line that tells me to enable the SPI slave peripheral on the Nordic part and get ready to receive SPI comms. I have about 1 millisecond between when the line tells me to enable SPI and when the data starts coming in.

The customer's request was that I completely disable the SPI peripheral between communications to save power as this system is extremely power sensitive. 

So, I implemented a GPIO interrupt as follows:

   gpio_pin_configure(m_gpio_port_0, SPI_ENABLE_PIN, GPIO_INPUT);
   gpio_init_callback(&spi_disable_callback, hardware_spi_disable_callback_handler, BIT(SPI_ENABLE_PIN));
   gpio_add_callback(m_gpio_port_0, &spi_disable_callback);
   gpio_pin_interrupt_configure(m_gpio_port_0, SPI_ENABLE_PIN, GPIO_INT_EDGE_RISING);

Then when the GPIO line goes high, it calls spi_disable_callback_handler, which calls a function that sets up the peripheral as follows:

void spi_comms_init(void)
{
   int err;

   nrf_spis_disable(spi_slave_instance.p_reg);

   spis_config.orc = 0xFF;    // Over-read character. When the master reads more than what we have to send, this is what will be sent
   err = nrfx_spis_init(&spi_slave_instance, &spis_config, spis_event_handler, NULL);
   if(err != NRFX_SUCCESS)
   {
      printk("SPI Error with init. %d\n", err);
   } else 
   {
      //printk("SPIS started.\n");
   }
 
   spi_comms_send_no_response(); // Start out with a NOIRQ response message ready to go

   IRQ_DIRECT_CONNECT(SPIM0_SPIS0_TWIM0_TWIS0_UARTE0_IRQn, 0, nrfx_spis_0_irq_handler, 0);
   irq_enable(SPIM0_SPIS0_TWIM0_TWIS0_UARTE0_IRQn);
   nrf_spis_enable(spi_slave_instance.p_reg);
   timer_start(TIMER_SPI_DISABLE);              // Kick the timer that keeps SPI enabled
}

So it's not ideal that I'm calling multiple functions and setting up peripherals from an interrupt service handler, but I'm not sure if I have time to set a flag and wait until I get back to the main loop. 

Questions:

1) Do you think that configuring the SPI slave peripheral from a GPIO interrupt could be causing a problem?.

2) How much (if any) power am I saving by using nrfx_spis_init and nrfx_spis_uninit to fully enable and disable the peripheral every time vs just setting it up in my init code and using nrf_spis_enable and nrf_spis_disable to turn it on and off? Would this code be more reliable if I just enabled/disabled vs initializing and uninitializing?

Thanks!

Glen

Parents
  • Hi Glen,

    What kind of SPIS init errors are you and your customer are getting?

    I see that in your handler you first disable spis just before enabling it. Why do you have to disable an already disabled SPIS?

    I do not think that doing this in the interrupt handler is an issue as this seems quick and with no waiting logic.

    2) How much (if any) power am I saving by using nrfx_spis_init and nrfx_spis_uninit to fully enable and disable the peripheral every time vs just setting it up in my init code and using nrf_spis_enable and nrf_spis_disable to turn it on and off? Would this code be more reliable if I just enabled/disabled vs initializing and uninitializing?

    In the sleep state, disabling SPIS releases hfclk if no other peripheral are enabled that uses it. So the power save is considerable. When the chip select is low I think the SPIS when not disable consumes about 1mA power.

  • The error code printed is 195887109 (BAD005 in hex). My customer got back to me and said it's not happening all the time - just occasionally. 

    I call the disable function just to make sure that it's not enabled due to some edge case, because I believe trying to enable and already enabled peripheral causes a crash.

    Regarding power consumption - are you saying that disabling it with nrf_spis_disable is as good as fully uninitializing it with nrfx_spis_uninit?

Reply
  • The error code printed is 195887109 (BAD005 in hex). My customer got back to me and said it's not happening all the time - just occasionally. 

    I call the disable function just to make sure that it's not enabled due to some edge case, because I believe trying to enable and already enabled peripheral causes a crash.

    Regarding power consumption - are you saying that disabling it with nrf_spis_disable is as good as fully uninitializing it with nrfx_spis_uninit?

Children
  • AH - The main problem is that at the end of this project I reworked my .overlay file and I ended up with 

    status = "okay" for my SPI peripheral in the file. That sets up the peripheral to already be in the initialized state, so my init code was throwing the error.
    This solves my main question, but before we mark this solved I would still love a response to my last question in the above message: "Regarding power consumption - are you saying that disabling it with nrf_spis_disable is as good as fully uninitializing it with nrfx_spis_uninit?"
    Thanks!
  • The way  I see it is that powerwise both should be same. nrfx_spis_uninit will additionally disable the interrupt (on an already disabled peripheral, no power consequences) and will also uninitialize the driver. So next time you want to enable spi will need the driver to be re-initialized which has some power consequences (amount of cpu cycles taken to reinitialize the spis driver). 

Related