SPIM doesn't stop forever when Peer is PowerDown.

My environment is
nRF52840 + nRF5 SDK 17

I have nRF52840 and LCD module(ER-TFTM101-1) connected using SPIM2.

When LCD power is on, It's fine work.

But,
When LCD power is off, SPIM never STOP.

Follow is simple test code

	/* SCK */
	nrf_gpio_pin_drive_t pin_drive = NRF_GPIO_PIN_S0S1;
	nrf_gpio_pin_write(SPIM_CLK_PIN, 0);
	nrf_gpio_cfg(SPIM_CLK_PIN,
		NRF_GPIO_PIN_DIR_OUTPUT,
		NRF_GPIO_PIN_INPUT_CONNECT,
		NRF_GPIO_PIN_NOPULL,
		pin_drive,
		NRF_GPIO_PIN_NOSENSE);
	/* MOSI */
	nrf_gpio_pin_write(SPIM_MOSI_PIN, 0);
	nrf_gpio_cfg(SPIM_MOSI_PIN,
		NRF_GPIO_PIN_DIR_OUTPUT,
		NRF_GPIO_PIN_INPUT_DISCONNECT,
		NRF_GPIO_PIN_NOPULL,
		pin_drive,
		NRF_GPIO_PIN_NOSENSE);
	/* MISO */
	nrf_gpio_cfg(SPIM_MISO_PIN,
		NRF_GPIO_PIN_DIR_INPUT,
		NRF_GPIO_PIN_INPUT_CONNECT,
		NRF_GPIO_PIN_NOPULL,
		pin_drive,
		NRF_GPIO_PIN_NOSENSE);
	/* SS */
	nrf_gpio_pin_write(SPIM_SS_PIN, 1);
	nrf_gpio_cfg(SPIM_SS_PIN,
		NRF_GPIO_PIN_DIR_OUTPUT,
		NRF_GPIO_PIN_INPUT_DISCONNECT,
		NRF_GPIO_PIN_NOPULL,
		pin_drive,
		NRF_GPIO_PIN_NOSENSE);

	SpimReg.ENABLE = SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos;
	SpimReg.TASKS_STOP = 1;
	SpimReg.PSEL.SCK = SPIM_CLK_PIN;
	SpimReg.PSEL.MOSI = SPIM_MOSI_PIN;
	SpimReg.PSEL.MISO = SPIM_MISO_PIN;
	SpimReg.FREQUENCY = SPIM_FREQ;
	SpimReg.RXD.PTR = uint32_t(m_recv_buff),
	SpimReg.RXD.MAXCNT = 2;
	SpimReg.RXD.LIST = 0;
	SpimReg.TXD.PTR = uint32_t(m_send_buff),
	SpimReg.TXD.MAXCNT = 2;
	SpimReg.TXD.LIST = 0;
	SpimReg.CONFIG = 0; /* active-high / Leading / MsbFirst */
	SpimReg.ORC = 0x00;
	actCS(true); /* assert CS */
	SpimReg.EVENTS_END = 0;
	SpimReg.TASKS_START = 1;

EVENTS_STARTED is 1
EVENTS_STOPPED/EVENTS_ENDRX/EVENTS_END/EVENTS_ENDTX never be 1.

in the above condition,
when LCD power is turned on, EVENTS_STOPPED/EVENTS_ENDRX/EVENTS_END/EVENTS_ENDTX is 1.

after that, when LCD power is turned off,

Again, When TASKS_START set 1, EVENTS_STARTED  and EVENTS_STOPPED/EVENTS_ENDRX/EVENTS_END/EVENTS_ENDTX is 1.

how is this going?

** SPIM returns EVENT_STOP if the SCLK signal line is determined while the LCD is power down.

  • My test code.

    #define	SPIM_SS_PIN			28
    #define	SPIM_CLK_PIN		29
    #define	SPIM_MOSI_PIN		30
    #define	SPIM_MISO_PIN		31
    
    #define	SpimReg				(*NRF_SPIM0)
    
    volatile uint32_t s_counter;
    
    uint8_t m_recv_buff[2];
    uint8_t m_send_buff[2] = { 0xA5, 0x3C };
    
    int main(void)
    {
    	/* SCK */
    	nrf_gpio_pin_drive_t pin_drive = NRF_GPIO_PIN_S0S1;
    	nrf_gpio_pin_write(SPIM_CLK_PIN, 0);
    	nrf_gpio_cfg(SPIM_CLK_PIN,
    		NRF_GPIO_PIN_DIR_OUTPUT,
    		NRF_GPIO_PIN_INPUT_CONNECT,
    		NRF_GPIO_PIN_NOPULL,
    		pin_drive,
    		NRF_GPIO_PIN_NOSENSE);
    	/* MOSI */
    	nrf_gpio_pin_write(SPIM_MOSI_PIN, 0);
    	nrf_gpio_cfg(SPIM_MOSI_PIN,
    		NRF_GPIO_PIN_DIR_OUTPUT,
    		NRF_GPIO_PIN_INPUT_DISCONNECT,
    		NRF_GPIO_PIN_NOPULL,
    		pin_drive,
    		NRF_GPIO_PIN_NOSENSE);
    	/* MISO */
    	nrf_gpio_cfg(SPIM_MISO_PIN,
    		NRF_GPIO_PIN_DIR_INPUT,
    		NRF_GPIO_PIN_INPUT_CONNECT,
    		NRF_GPIO_PIN_NOPULL,
    		pin_drive,
    		NRF_GPIO_PIN_NOSENSE);
    
    	/* SS */
    	nrf_gpio_pin_write(SPIM_SS_PIN, 1);
    	nrf_gpio_cfg(SPIM_SS_PIN,
    		NRF_GPIO_PIN_DIR_OUTPUT,
    		NRF_GPIO_PIN_INPUT_DISCONNECT,
    		NRF_GPIO_PIN_NOPULL,
    		pin_drive,
    		NRF_GPIO_PIN_NOSENSE);
    
    	/**/
    	SpimReg.TASKS_STOP = 1;
    	SpimReg.PSEL.SCK = SPIM_CLK_PIN;
    	SpimReg.PSEL.MOSI = SPIM_MOSI_PIN;
    	SpimReg.PSEL.MISO = SPIM_MISO_PIN;
    	SpimReg.FREQUENCY = SPIM_FREQUENCY_FREQUENCY_K125;
    	SpimReg.RXD.PTR = uint32_t(m_recv_buff),
    	SpimReg.RXD.MAXCNT = 2;
    	SpimReg.RXD.LIST = 0;
    	SpimReg.TXD.PTR = uint32_t(m_send_buff),
    	SpimReg.TXD.MAXCNT = 2;
    	SpimReg.TXD.LIST = 0;
    	SpimReg.CONFIG = 0; /* active-high / Leading / MsbFirst */
    	SpimReg.ORC = 0x00;
    
    	SpimReg.ENABLE = SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos;
    
    	nrf_gpio_pin_clear(SPIM_SS_PIN);
    
    	SpimReg.EVENTS_END = 0;
    	SpimReg.TASKS_START = 1;
    
    	for (;;) {
    		s_counter++;
    	}
    }
    

    When SCLK is open.

    SS and MOSI wave form

    EVENTS

    When write to TASKS_START=1, as soon as, EVENTS_ENDRX/EVENTS_END/EVENTS_ENDTX is '1'.

    When SCLK is connect to GND.

    SS and MOSI wave form(MOSI is not change.)

    EVENTS

    EVENTS_ENDRX/EVENTS_END/EVENTS_ENDTX is never '1'.

    Is this move as expected?

    Even if the SPIM-peer is in such a state, I want the SPIM to always complete. Is there any workaround?

  • Again, have you tried sending messages on the SPI?

    Does it work?

  • Look at the [SCLK is open] waveform.
    0xA5, 0x3C are sent in order.

    No data is sent to MOSI in the [SCLK is connect to GND.] waveform.

  • Well yes, it should not be surprising that no data is sent when SCLK is connected to GND?

    When "LCD power" is turned on and SCLK is open, does SPI work as expected?

  • >When "LCD power" is turned on and SCLK is open, does SPI work as expected?

    Yes.

    The problem is the following two points.
    1. It cannot detect that SPIM is not transmitting. (no error occurs)
    2. Writing 1 to TASKS_STOP never causes EVENTS_STOP.

Related