SPI CS pin input vs output inactive power consumption

Hi,

I was checking the HAL for SPI in master mode and notice that when pm_device_action_run(<spi_device>, PM_DEVICE_ACTION_SUSPEND); the CS pin isnt changed since it status change after every transmission to output inactive : https://github.com/nrfconnect/sdk-zephyr/blob/v3.5.99-ncs1/drivers/pinctrl/pinctrl_nrf.c#L136

On the other hand, in the spim driver the SS pin is set as input when the pm action is to suspend: https://github.com/nrfconnect/sdk-hal_nordic/blob/8f013ea950f41bf69b18bf688bfb0dd80a3fdc44/nrfx/drivers/src/nrfx_spim.c#L465 . However, the code never reaches this point because the pinctrl is taking care of setting the pins to suspend state.

My question is what is the difference between both, how setting the pin as input differ as setting the pin as ouput inactive.

Thank you!

Parents
  • Hi,

    The SS pin is controlled as a regular GPIO by the driver, not by the SPIM peripheral itself like MISO, MOSI, and CLK. Therefore, it is not the responsibility of the pinctrl module to configure this pin. The driver should probably have reconfigured this pin to its reset state to match the behavior when pinctrl is not enabled.

    My question is what is the difference between both, how setting the pin as input differ as setting the pin as ouput inactive.

    Output inactive corresponds to an active low output, i.e., the SS signal will be driven low.  

    But why do you need to suspend the SPIM peripheral? Are you experiencing high sleep currents between SPIM transactions?

    Best regards,

    Vidar

    Edit: The chip select signal is almost always active low, which means the pin will be driven high when set to inactive. Whether this will lead to any additional current consumption or not depends on the SS input on your SPI slave sensor. 

  • Hi,
    Thanks for the reply. I understand that the SS pin is controlled by pintctrl or as a normal GPIO (like I mentioned in the question and added the sourced code where this is done). But my question is why the SPIM driver puts the SS pin as input while the pinctrl puts it as output inactive. Also, I believe a GPIO pin set as input will consume less energy compared to GPIO set as output low ?
    From the dataseeht there is also this info:
    The input buffer of a GPIO pin can be disconnected from the pin to enable power savings when the pin is
    not used as an input


    So Im kind confused what approach should be the best one to achieve a low power consumption.

    Thank you!

  • Hmm I see, thanks for pointing out!
    But will be a good practice on the uninit to set the SS pin as input for all situations ?
    Thanks again!

  • No problem! Yes, I can't think of any scenario where you would want to keep the SS pin configured as an output after you have uninitialized the driver.

    I have added this as a feature request internally. 

  • Cool! The NRFx SPIM driver already does this with the ss_pin

    when setting it to the default value. Thanks for the support, I will close the ticket for now and if you want I can also open a PR with this changes :)

  • Yes, I can't think of any scenario where you would want to keep the SS pin configured as an output after you have uninitialized the driver.

    After a bit further consideration, disconnecting the SS line may not be a good idea in the typical scenarios where the SPI slave remains powered in a suspended state. I will update the ticket with the feedback I get from the developers.

  • I arrived here because I am using a SPI Flash with active low CS. When the SOC goes to sleep, it sets the CS pin high. My problem is that I am controlling the power domain in which the Flash device sits so that the VCC rail is removed during sleep. Result is that the high on CS is going against the device datasheet requirements (should "track" the VCC during power up  / down). How can I either specify the sleep polarity of the CS pin, or directly access it as a GPIO and drive it myself? 

Reply
  • I arrived here because I am using a SPI Flash with active low CS. When the SOC goes to sleep, it sets the CS pin high. My problem is that I am controlling the power domain in which the Flash device sits so that the VCC rail is removed during sleep. Result is that the high on CS is going against the device datasheet requirements (should "track" the VCC during power up  / down). How can I either specify the sleep polarity of the CS pin, or directly access it as a GPIO and drive it myself? 

Children
  • I don't foresee any problem with toggling the CS pin state from the application as long as there are no SPI transactions taking place while it is being controlled by the app. Normally when using the Zephyr driver you use Power Management suspend task to make the SPI NOR driver command the chip to enter deep power down mode, and similarly wake it up again on when the "resume" request is received. However, if you are powering it off, it seems lik you need to trigger the PM_DEVICE_ACTION_TURN_ON to re-init the SPI flash after powering it on again: https://github.com/nrfconnect/sdk-zephyr/blob/3c80c155dc70f1a3874f365c570c6fd2adce7e2e/drivers/flash/spi_nor.c#L1680 

    #include <zephyr/drivers/spi.h>
    #include <zephyr/drivers/gpio.h>
    	...
    	/* Get CS GPIO pin used for flash device */
    	const struct gpio_dt_spec cs = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(mx25r64));
    	
    	/* Configure pin as input with input buffer disconnected after 
    	 * powering off SPI flash.
     	 */
    	int err = gpio_pin_configure_dt(&cs, GPIO_DISCONNECTED);
    	if (err) {
    	    printk("gpio_pin_configure() failed. (err:%d)\n", err);
    	}
    	

Related