Can't seem to get SPI pinctrl to work (SDK 1.8.0)

This might be a simple one to answer but I'm struggling to find documentation on what to do here since we're still using an ancient SDK on 9160. 

I have a working board file with SPI2 in use: 

&spi2 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	sck-pin = <0>;
	mosi-pin = <28>;
	miso-pin = <27>;
};

I have a problem that appears after my first spi_write / spi_read call where MOSI is held high between transactions. The best way around this seems to be to use pinctrl to configure a sleep state for these pins so I can use pm_device_state_set. I believe I have a well formed devicetree now: 

&pinctrl {
	spi2_default: spi2_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 0)>,
				<NRF_PSEL(SPIM_MOSI, 0, 28)>,
				<NRF_PSEL(SPIM_MISO, 0, 27)>;
		};
	};

	spi2_sleep: spi2_sleep {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 0)>,
				<NRF_PSEL(SPIM_MOSI, 0, 28)>,
				<NRF_PSEL(SPIM_MISO, 0, 27)>;
			low-power-enable;
		};
	};
}; 
 and  
#include "exampleboard-pinctrl.dtsi"

&spi2 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";
};

However, I am getting uninformative syntax errors when opening the project. Looking into the nordic,nrf-spim yaml file in Zephyr, I see it has no knowledge of pinctrl and needs pins to be defined directly. It really seems like SDK 1.8.0 just doesn't support pinctrl, is this correct? There is mention of it back in the old documentation but it wasn't clear. 

If this SDK doesn't support pinctrl, what alternative approach can I use to keep my SPI pins held low (or released as inputs) between transactions? I should mention that I've tried configuring the pin as GPIO and overriding it, among other things, and it seems impossible to take control of the pin back after the first SPI transaction. 

Many thanks. 

Parents
  • Hello,

    The pinctrl is not working in NCS v1.8.0. Only from v2.0.0 and onwards, so that is why you have a hard time to get it working.

    Is the state of the MOSI pin between transactions actually causing any issues? It shouldn't really matter.

    If you do, however want to control this pin, you need to disable the SPI, and then control the pin "normally" when it is no longer being controlled by the SPI.

    Best regards,

    Edvin

  • Thanks for confirming. 

    Yes, we're powering down our peripheral by completely removing the power, so the MOSI line being high means that it's indicentally half-powering the chip and causing a significant current leak. We would like all pins to be low. 

    How do I disable SPI to release these pins like you mention? I've tried using pm but it seems to have no effect without pinctrl in place, and there seems to be no way of uninitialising the SPI driver before I force the pin low with GPIO (it has no effect). I've tried a few other things but cannot seem to override this pin state at all.

    The pins are in a good state after boot until the first SPI transaction happens. Is there a known working way of undoing what my first spi_write is doing to the SPI pins?

    Many thanks

  • Jake said:
    I've tried using pm but it seems to have no effect without pinctrl in place,

    Does that mean you managed to disable the SPI? Or did it print some error to the log?

    When you have done this, how did you try to control the pin? (I am sorry for not providing you a step by step guide, but I didn't start working with NCS much before 2.0.0, so I am not quite sure. I would say that instead of putting it to output low, you should set the pin as a disconnected input pin, which is the default pin state on the chip before it is initialized to do something. 

    You could try:

     gpio_pin_configure(led, LED0_GPIO_PIN, LED0_GPIO_FLAGS);

    (fetched from the ncs\bootloader\mcuboot\zephyr\main.c)

    but obviously change the pin number and LED0_GPIO_FLAGS. Try either setting it to: GPIO_DISCONNECTED or GPIO_INPUT.

    Best regards,

    Edvin

  • Re:pm, I admit I didn't check for errors from pm_device_state_set, but the pin wasn't released for me to use as GPIO. It may have silently complained about no sleep configuration being available. 

    Yes, we have tried precisely gpio_pin_configure as DISCONNECT, INPUT as you suggest, or even OUTPUT followed by being set to 0. None of the options take control of the pin, it remains under control of the SPI driver.

    There is an spi_release function which sounds like it might've helped, but the description in the definition makes clear that it's related to something else. We tried it anyway in comination with the 3 options above, none worked. 

    We just cannot find a way of getting SPI to let go of the pins so we can use simple GPIO!

    Any more ideas?

    Many thanks

  • Are you able to control the pin if you don't use it for SPI first? If so, is it possible to upload your current application, then I can have a look. (Or a strip down version of the application, that replicates the issue).

    Best regards,

    Edvin

Reply Children
  • Hi Edvin, 

    Good question, I haven't tried interacting with the pin before doing SPI, but I do know that it is low until the first transaction. 

    We've discovered a hack that we're going to use until we can get our SDK upgraded: the MOSI pin remains low if the final bit of the last SPI transaction is 0. This didn't work when I tried it previously because we had both CPHA and CPOL set, without those the hack works. We're sending a byte 0 with no CS when we want MOSI to go low now. 

    Many thanks

Related