Deinitialize SPI

Hi,

i am creating a BLE application based on a NRF52832 with a coustum board.

I have a very small battery and thus need to save power in the best way possible. I already made made sure that I can shut down all my peripherals by GPIOs.

But the problem I have is that the SPI keeps the level of the MOSI line and the CS on a high level.

This leads to the problem that the peripherals are backsourced.

Because of that the peripherals are in an undefined state and therefore the current consumtion is very high during sleepmode (about 2mA).

My question is:

Is there a way to deinit the SPI interface via software to keep it from backsoucing my circuit?

My workaround at the moment is to set the CS pin low like a GPIO and disable the register of the SPI.

The problem with that is, that I need to reset the MCU to reenable the SPI.

Through this I can get into a state where the current consumption drops to 16uA but this is not suitable for a sleepmode that is called constantly in my application.

Parents
  • It should not be problematic to uninit and init the the spi between transactions, e.g. by something like:

    // power off sensor
    // unint spi + lower cs + lower spi pins (e.g. clk, mosi)
    // wait
    // raise cs pin + init spi
    // power on sensor

    I guess how this can be done slightly depends on which sdk + driver api you are using.

    Kenneth

  • Thanks for the quick answer.

    I didin't find the function to uninit and init the SPI. I only found  the function device_is_ready(). Is there any function in zephyr to uninit the SPI?

    I am using the nrf Connect SDK

    in my prj.conf I set the following defines:

    CONFIG_SPI=y
    CONFIG_FLASH_JESD216_API=y
    CONFIG_SPI_NOR=y
  • I was thinking along the lines of if you use CONFIG_PM_DEVICE=y, then you have the option to call for instance pm_device_action_run(spi_dev, PM_DEVICE_ACTION_SUSPEND) and pm_device_action_run(spi_dev, PM_DEVICE_ACTION_RESUME) between transfers. When spi is suspended the pins should fall back to to the sleep state you have configured in dts or overlay file. I can however see now that you are possible having an external flash, which may complicate things but not sure, since I have not looked into it.

    Kenneth

  • Hey Kenneth,

    thanks for the advice. I was able to suspend the SPI and reduce the supply current to 13uA.
    pm_device_action_run(spi_dev, PM_DEVICE_ACTION_SUSPEND)did not work at first and caused a BUS FAULT ERROR and my program crashed.

    It worked when I used PM_DEVICE_ACTION_SUSPEND together with the spi node instead of the spi device device everything worked fine. All I had to do after the suspension was to pull low the CS pins of my two peripherals and set them high again after resumed. 

    So in the end the code I use is:

    CONFIG_PM_DEVICE=y in prj.conf

    Deinit SPI
    :
    const struct device *cons = DEVICE_DT_GET(DT_NODELABEL(spi1));
    pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
    gpio_pin_set_dt(&pin_cs, 1); //CS is active high

    reinit SPI:
    gpio_pin_set_dt(&pin_cs, 0); //CS is active high
    const struct device *cons = DEVICE_DT_GET(DT_NODELABEL(spi1));
    pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);

    Kind Regards Paul

  • Thank you for providing the additional details on how to make this work.

    Kenneth

Reply Children
No Data
Related