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.

  • Hi again

    I would really recommend that you try using a driver instead of setting the registers manually.

    You should consider using our nrfx driver, and even if you decide not to use it, at least have a look at how it does things.

    Also, can you please specify how SCLK and GND are short-circuited when LCD power is turned off? This still confuses me.

    I believe SCLK being grounded is the source of a lot of the unwanted behavior you're observing.

    -Einar

  • Do the following test(based on examples/peripheral/nrfx_spim)

    #include "nrfx_spim.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define NRFX_SPIM_SCK_PIN  3
    #define NRFX_SPIM_MOSI_PIN 4
    #define NRFX_SPIM_MISO_PIN 28
    #define NRFX_SPIM_SS_PIN   29
    #define NRFX_SPIM_DCX_PIN  30
    
    #define SPI_INSTANCE  0                                           /**< SPI instance index. */
    static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    #define TEST_STRING "Nordic123456789012345678901234567890"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];  /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);
    
        nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
        spi_config.frequency      = NRF_SPIM_FREQ_1M;
        spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
        spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
        spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
        spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
        //spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
        //spi_config.use_hw_ss      = true;
        spi_config.ss_active_high = false;
        APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));
    
        NRF_LOG_INFO("NRFX SPIM example started.");
    
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
        }
    }

    result

    SCK/MOSI/MISO/SS is open
    LED is blinking.

    MOSI, MISO or SS is connected to GND.
    LED is blinking.

    SCK is connected to GND.
    LED is not blinking.

    So the result is the same.

    It is a big problem if SPIM stalls due to a problem with the slave device.
    Please provide a solution immediately.

  • Hi

    Can you please specify how SCLK and GND are short-circuited when LCD power is turned off?

    Is this a property of the module, or is it a result of your wiring?

    I'm afraid having a grounded SCK might not be covered by the SPI spec, so there might not be a straight forward solution, but I've asked about this internally and I'll let you know what they have to say about the issue.

    If you don't find another way around this, I would suggest adding a timeout to abort your SPI query in the case of stalling. But I believe best practice would be to avoid using SPI while it's not properly initialized.

    -Einar

  • Hi again

    Here is the response I got after asking about this internally:

    The nRF52840 SPIM does not support operation with shorted output pins. As stated in product specification EVENTS_STOPPED event will occur after ongoing transmission/reception of current byte is completed. This will not be possible with the clock pin grounded.

    Clamped output pins (to ground/VDD) on nRF52840 should also be avoided for other reasons as it will make a short if the application drives the output pin to the opposite power rail as the outside clamping. In such case unpredictable device behavior should be expected.

    Best regards,

    Einar

Related