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

NRF5284 SPIM3 RX buffer empty

Hi All,

I've run into a weird issue where my SPIM rx buffer remains empty (it's not even filled with garbage - just empty). Am I operating the SPI drivers properly? My process is shown below:

When a command comes in over Bluetooth, I have a "master devkit" initiate a SPI transaction with a "slave devkit". The following function occurs in my main loop (so the CPU starts this ... for now).

static void process_commands()
{
  if (strcmp(token,"read") == 0) {
    NRF_LOG_INFO("read reg cmd recieved");
    
    token = strtok(NULL, delimiter);
    NRF_LOG_INFO("read token: %s", token);
    addr = (uint8_t) atoi(token);
    NRF_LOG_INFO("read addr: %d", addr);

    spi_tx_buf[0]   = addr;
    spi_tx_buf[1]   = 0;
    spi_tx_buf[63]  = 0;
    spi_tx_buf[64]  = 0;
    
    spi_cmd_flag = SPI_READ_REG; //spi_cmd_flag = read
    // NRF_LOG_HEXDUMP_DEBUG(spi_tx_buf, spi_length);
    NRF_LOG_INFO("cmd: %d - %d ... %d - %d",spi_tx_buf[0], spi_tx_buf[1], spi_tx_buf[63], spi_tx_buf[64]);

    // shoot off SPI_TRX
    if (spi_xfer_done == true)
    {
      NRF_LOG_INFO("SENDING SPI CMD...");
      spi_xfer_done = false;
      nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(spi_tx_buf, spi_length, spi_rx_buf, spi_length);
      APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
    }
    
  }
  ...
  ...
}

Then I have my spi event handler take whatever was in the rx buffer and send it back to my 'base station' over bluetooth:

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    spi_xfer_done = true;
    NRF_LOG_INFO("SPI TRX COMPLETE");
    
    if (spi_cmd_flag == SPI_READ_REG) {
      NRF_LOG_INFO("READ REG CCOMPLETE");
      spi_cmd_flag = 0;
      while(ble_nus_data_send(&m_nus, spi_rx_buf, &spi_length, m_conn_handle) != NRF_SUCCESS);
    }
    ...
    ...
}


Unfortunately, when I run this nothing is transmitted over bluetooth... If I try a hexdump it shows nothing (and in fact it crashes the devkit too...). I do not have access to a logic analyzer just yet but I'm looking at getting one to confirm that data is indeed being sent over the MISO. I can confirm that data is being shifted into my "slave" device (LEDs are changing when they're supposed to indicate valid SPI shift ins). Am I handling the SPIM TRX properly though? As in am I setting up the nrfx_spim_xfer object properly?

Thank you for all your help! I'm really stuck!

Ryan

Parents Reply Children
  • Hi Jared!

    Nice to see you again.

    The code I initialize the driver with is copied from the nrfx_spim example:

    static void spi_init(void)
    {
        ret_code_t err_code;
    
    
    
        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.dcx_pin        = NRFX_SPIM_PIN_NOT_USED;
        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));
    
    
        APP_ERROR_CHECK(err_code);
    }


    With the default config being:
    #define NRFX_SPIM_DEFAULT_CONFIG                             \
    {                                                            \
        .sck_pin        = NRFX_SPIM_PIN_NOT_USED,                \
        .mosi_pin       = NRFX_SPIM_PIN_NOT_USED,                \
        .miso_pin       = NRFX_SPIM_PIN_NOT_USED,                \
        .ss_pin         = NRFX_SPIM_PIN_NOT_USED,                \
        .ss_active_high = false,                                 \
        .irq_priority   = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
        .orc            = 0xFF,                                  \
        .frequency      = NRF_SPIM_FREQ_4M,                      \
        .mode           = NRF_SPIM_MODE_0,                       \
        .bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST,          \
        NRFX_SPIM_DEFAULT_EXTENDED_CONFIG                        \
    }

    (note that the sck, mosi, miso, and ss pins are all overwritten in the spi_init function)

    As far as the breakpoint, I have placed a breakpoint at the line in the event handler and the code is getting there. How do I check if the rx buffer is being filled?

    EDIT:

    This is sad but it may have just been a faulty jumper cable on MISO. I swapped out the jumper and reverted back to a stripped down version of the code (it's bassically just the nrfx_spim and spis examples now) and I've started getting partial data (still not everything ...). It seems that when I send 00, the recieve buffer just treats it as a null... In other words i'm hoping to send an arbitrary array of 65 bytes (values may end up being 00) so I have set up a dummy array:

    // SPI transfer buffer
    static uint8_t       m_tx_buf[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,1};
    static uint8_t       m_rx_buf[sizeof(m_tx_buf) + 1];        // RX buffer.
    static const uint8_t m_length = sizeof(m_tx_buf);        // Transfer length.
    //static uint16_t      m_length = sizeof(uint8_t)*65;


    With this I *just* recieved 0x80 - which is 128 in decimal. Nothing else though! So I sent the following array:

    // SPI transfer buffer
    static uint8_t       m_tx_buf[] = {128,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,1};


    Hexdump stops at the 0's... 

    Is there a better way to interperet raw bytes that come in over spi?

    Thanks so much for your help.

  • Hi Jared!

    Nice to see you again.

    The code I initialize the driver with is copied from the nrfx_spim example:

    static void spi_init(void)
    {
        ret_code_t err_code;
    
    
    
        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.dcx_pin        = NRFX_SPIM_PIN_NOT_USED;
        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));
    
    
        APP_ERROR_CHECK(err_code);
    }


    With the default config being:
    #define NRFX_SPIM_DEFAULT_CONFIG                             \
    {                                                            \
        .sck_pin        = NRFX_SPIM_PIN_NOT_USED,                \
        .mosi_pin       = NRFX_SPIM_PIN_NOT_USED,                \
        .miso_pin       = NRFX_SPIM_PIN_NOT_USED,                \
        .ss_pin         = NRFX_SPIM_PIN_NOT_USED,                \
        .ss_active_high = false,                                 \
        .irq_priority   = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
        .orc            = 0xFF,                                  \
        .frequency      = NRF_SPIM_FREQ_4M,                      \
        .mode           = NRF_SPIM_MODE_0,                       \
        .bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST,          \
        NRFX_SPIM_DEFAULT_EXTENDED_CONFIG                        \
    }

    (note that the sck, mosi, miso, and ss pins are all overwritten in the spi_init function)

    As far as the breakpoint, I have placed a breakpoint at the line in the event handler and the code is getting there. How do I check if the rx buffer is being filled?

    EDIT:

    This is sad but it may have just been a faulty jumper cable on MISO. I swapped out the jumper and reverted back to a stripped down version of the code (it's bassically just the nrfx_spim and spis examples now) and I've started getting partial data (still not everything ...). It seems that when I send 00, the recieve buffer just treats it as a null... In other words i'm hoping to send an arbitrary array of 65 bytes (values may end up being 00) so I have set up a dummy array:

    // SPI transfer buffer
    static uint8_t       m_tx_buf[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,1};
    static uint8_t       m_rx_buf[sizeof(m_tx_buf) + 1];        // RX buffer.
    static const uint8_t m_length = sizeof(m_tx_buf);        // Transfer length.
    //static uint16_t      m_length = sizeof(uint8_t)*65;


    With this I *just* recieved 0x80 - which is 128 in decimal. Nothing else though! So I sent the following array:

    // SPI transfer buffer
    static uint8_t       m_tx_buf[] = {128,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,1};


    Hexdump stops at the 0's... 

    Is there a better way to interpret raw bytes that come in over spi? Do I need to worry about "00s" coming in over SPI? Or can I be confident that the ble_nus_data_send will send everything I want it to?

    I have a janky solution that guarantees everything will be sent. I iterate over the rx_buff and convert everything to a char:
          char buf[196];
          uint16_t size_of_buff = sizeof(char)*196;
          for (int i = 0 ; i != 65 ; i++) 
          {
            sprintf(buf + (3*i), "%02x ", spi_rx_buf[i]);
          }
          rx_buff_hex[195] = '\0';
          while(ble_nus_data_send(&m_nus, (uint8_t *) buf, &size_of_buff, m_conn_handle) != NRF_SUCCESS);


    But this takes what would be 65 raw bytes and expands it to 196 chars manually - this seems like it will slow things down...

    Thanks so much for your help.

  • Hi there,

    ryerye120 said:
    How do I check if the rx buffer is being filled?

    You right click the rx_buffer and press add variable to watch. The variable will then be added to the watch window in debug mode. For example: 

    Could add the variable to the watch window and see if the 00's are actually received or not.

    regards

    Jared 

  • You right click the rx_buffer and press add variable to watch. The variable will then be added to the watch window in debug mode. For example:

    This was incredibly helpful! In the end, it was being filled up properly. It seems like the root issue really was a faulty MISO jumper wire. After replacing the MISO wire I could see the rx buff being filled up. Then I was able to take the downstream bits and properly interpret them after converting them to chars (with the previously posted loop).

    Thanks for your help, Jared!


    Kindest regards,

    Ryan

Related