Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPIM Driver not reading correct data from NVM

Hello,

We are using the nrf52840 with the SDK v17.0.2

We are trying to read specific addresses from our external NVM using the SPIM driver. Unfortunately when we examine our receive buffer, the data is not what we expect.

We format our command in the following order:

command = EXT_NVM_READ

uint8_t formatNvmCmd( uint8_t *txBuffer, uint32_t address, uint8_t command ){
*txBuffer = command;
*( ++txBuffer ) = ( address >> 16 ) & 0xFF;
*( ++txBuffer ) = ( address >> 8 )  & 0xFF;
*( ++txBuffer )   = address       & 0xFF;
}

Our tx_buffer and rx_buffer are initialized as below:
#define SPIM_XFER_BUF_LEN             ( 256 )

static uint8_t m_tx_buf[SPIM_XFER_BUF_LEN] = { 0 };
static uint8_t m_rx_buf[SPIM_XFER_BUF_LEN] = { 0 };
We utilize the SDK and its functions as below:

memcpy( m_tx_buf, formattedCmd, cmdLen ); 
nrfx_spim_xfer_desc_t xfer_desc_data_buf = NRFX_SPIM_XFER_TRX( m_tx_buf, cmdLen, m_rx_buf, dataLen );
memset( m_rx_buf, 0, dataLen ); 
retCode = nrfx_spim_xfer( &spiInstance, &xfer_desc_data_buf, 0 );
memcpy(dataBuff, &m_rx_buf[1], dataLen);

When we examine the dataBuff, it does not have the expected values, currently the NVM is completely set, so we expect for a datalen = 5, five 0xFF, but instead we get four 0x00 and one 0xFF.




  • Hi there,

    Does the nRF transmit the expected bytes? Have you used a logical analyzer and compared the data being sent from the slave with the data that is printed and ensured that it's the same? If the input from the nRF to the slave device is correct but the slave device outputs something different than expected than the issue is most probably related to how the slave is configured.

    regards

    Jared 

  • After looking through the logic analyzer and previous console outputs we have figured that the issue is occurring when we try using the NRFX_SPIM_XFER_TRX function.

     

    Our function is initialized as below:

    nrfx_spim_xfer_desc_t xfer_desc_data_buf = NRFX_SPIM_XFER_TRX( m_tx_buf,  cmdLen,        

          m_rx_buf,  dataLen );

     

     

    Input:

    m_tx_buf = {0x03, 0x00, 0x00, 0x64} {CMD, 3 -byte addr}

    cmdLen = 4

    m_rx_buf[dataLen] = {0}

    dataLen = 5

     

     

    Output (Actual):

    m_rx_buf = {0x00, 0x00, 0x00, 0x00, 0xFF}

     

    Output (Expected):

    m_rx_buf = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

     

    Logic Analyzer:

    Input:

    dataLen = 6

     

    Output (Actual):

    m_rx_buf = {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}

     

    Output (Expected):

    m_rx_buf = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

     

    Logic Analyzer:

     

    Input:

    dataLen = 6

     

    Output (Actual):

    m_rx_buf = {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF}

     

    Output (Expected):

    m_rx_buf = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

     

    Logic Analyzer:

    Conclusion:

    We believe that the TRX function is starting to read and fill the rx_buff even when the TX is still ongoing.

     

    The TRX function takes in the 4 bytes of the MOSI line (0x00) when the 4-byte cmd is still being pushed through and then the remaining (dataLen – cmdlen) are picked up from the MISO line.

     

    In the 3 above examples you can see that the Slave(MOSI) line is still remaining high even after the clock has stopped, this indicates the correct length and data being sent back.

     

    We think that the TRX function should only be filling the RX buffer after the TX cmd (cmdlen bytes) have been passed.

     

    Note: We have seen a similar issue when we try and read the device ID of the slave (20 bytes), this is only a 1 byte cmd and the correct data is stored in the rx_buffer because we read 21 bytes total, and ignore the first entry in the rx_buffer. This also highlights the same issue of (dataLen – cmdlen) bytes being read into the rx_buffer before the correct data is stored.

  • devp1310 said:
    We believe that the TRX function is starting to read and fill the rx_buff even when the TX is still ongoing.

    This is as expected with the SPI protocol. There is a shift register on both sides that clocks data out as it receives data. Since the TX data buffer is one byte less than the RX buffer, the SPIM master has to clock out the ORC character, which seems to be 0xFF in your case.

    If the data from the slave is not ready yet when the data is clocked out on MISO, then you can just ignore the first bytes and expand the RX buffer so that you eventually receive the expected data.

    More on SPIM peripheral here.

    regards

    Jared

  • Hey jared,

    Thank you for the reply. Our coding is working now after ignoring the first byte ion the rx_buffer and reading the rest.

Related