First 4 bits received by SPIM (from SPIS) are always 1?

I'm running into a weird bug where the first 4 bits received by my SPIM are always 1 - the next 64.5 bytes are all correct though...

I've built 3 FWs out of provided examples.

  1. I have a single devkit acting as a spi_slave built off the spis example from SDK 17.1. It waits for a spi transaction and as soon as it occurs it increments a few bytes (including the first one) in a buffer and sets it to be sent out again. Pertinent code, below:
    static uint8_t       m_tx_buf[] = {2,2,2,2,2,3,3,3,3,4,5,5,6,2,2,3,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
                                       19,20,21,22,23,15,15,16,17,18,19,19,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,16,1,1,1};
    static uint8_t       m_rx_buf[sizeof(m_tx_buf) + 1];        // RX buffer.
    ...
    ...
    void spis_event_handler(nrf_drv_spis_event_t event)
    {
        if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
        {
            spis_xfer_done = true;
            bsp_board_led_invert(BSP_BOARD_LED_2);
            NRF_LOG_INFO(" packet_id: %d",m_tx_buf[0]);
            counter = counter + 1;
    
            m_tx_buf[0] = counter;
    
            m_tx_buf[10] = m_tx_buf[10] + 3;
            m_tx_buf[20] = m_tx_buf[20] + 4;
            m_tx_buf[30] = m_tx_buf[30] + 5;
            m_tx_buf[40] = m_tx_buf[40] + 6;
            m_tx_buf[50] = m_tx_buf[50] + 7;
            m_tx_buf[60] = counter + 2;
        }
    }
  2. I have a spi master (built off the ble_app_uart and the nrfx_spim examples from SDK 16). Ultimately it triggers spi transactions based on a timer interrupt and then sends the 65 received bytes over BLE to a central device. Pertinent code below:
    static uint8_t       spi_tx_buf[] = {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,0,16,0,0,0};
    static uint8_t        ble_tx_buff_t[] = {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,0,0,0,0,0};
    static uint8_t       spi_rx_buf[sizeof(spi_tx_buf) + 1];        /**< RX buffer. */
    
    ...
    
    static void trx_timer_handler(void * p_context)
    {
      // update spi_tx_buff to have read data commands
      spi_tx_buf[0]   = read_data_instr[0];
      spi_tx_buf[1]   = read_data_instr[1];
      spi_tx_buf[63]  = read_data_instr[2];
      spi_tx_buf[64]  = read_data_instr[3];
    
      // fire off a SPI transaction
      NRF_LOG_INFO("%s", spi_tx_buf);
      if (spi_xfer_done == true)
      {
        spi_xfer_done = false;
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(spi_tx_buf, spi_length, ble_tx_buff_t, spi_length);
        APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
    
    }
    
    
    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_STREAM) {
    
          // block to convert and send single char packet
          char buf[131];
          uint16_t size_of_buff = sizeof(char)*131;
          for (int i = 0 ; i != 65 ; i++) 
          {
            sprintf(buf + (2*i), "%02x", ble_tx_buff_t[i]);
          }
          NRF_LOG_INFO("packet_id: %d",buf[0]);
          while(ble_nus_data_send(&m_nus, (uint8_t *) buf, &size_of_buff, m_conn_handle) != NRF_SUCCESS);
        }
    }


  3. A central device that I use to send commands to and read data from the spi_master (built on top of ble_usbd_c from SDK 16).

My issues and current debugging steps are below:

  • The slave has the correct data in its tx buff but the received data is 'incorrect' on the SPIM side. It's odd because it's just the first 4 bits - everything else is correct. The ble_tx_buff_t[0] contents will increment from 128 to 255 and then wrap back to 255 instead of 0. I don't have access to an oscope right now but I'm trying to get one to take a look at the MISO line. Dollars to donuts that the problem is somewhere on the master side...
  • When I try running the SPIM at 4M or above all the data gets corrupted. Are the limits to what the spis default pins can handle? Or are there other issues I have to keep in mind for running spi at faster speeds?
  • This is just a question - not an issue - why is the spi_rx_buff +1 element larger than the tx_buff? This is something I copied over from the examples but never understood why. I tried making the buffers the same size and that didn't seem to change anything...

Thank you for your help!

Ryan

  • Hi Kenneth,

    I'm trying this out but it doesn't seem to be changing the time between CS going low and SCK's first clock cycle. I added nrf_delay.h and the delay right before spim_xfer() (my nrfx_spim_xfer function is copied below).

    nrfx_err_t nrfx_spim_xfer(nrfx_spim_t     const * const p_instance,
                              nrfx_spim_xfer_desc_t const * p_xfer_desc,
                              uint32_t                      flags)
    {
        spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
        NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
        NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
        NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
        NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
                                         p_xfer_desc->rx_length,
                                         p_xfer_desc->tx_length));
    
        nrfx_err_t err_code = NRFX_SUCCESS;
    
        if (p_cb->transfer_in_progress)
        {
            err_code = NRFX_ERROR_BUSY;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
        else
        {
            if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
                                            NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
            {
                p_cb->transfer_in_progress = true;
            }
        }
    
        p_cb->evt.xfer_desc = *p_xfer_desc;
    
        if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
        {
    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
            if (!p_cb->use_hw_ss)
    #endif
            {
                if (p_cb->ss_active_high)
                {
                    nrf_gpio_pin_set(p_cb->ss_pin);
                }
                else
                {
                    nrf_gpio_pin_clear(p_cb->ss_pin);
                }
            }
        }
        
        nrf_delay_us(10);
        return spim_xfer(p_instance->p_reg, p_cb,  p_xfer_desc, flags);
    }


    Am I doing something wrong? I tried 10us and 100us of delay and couldn't observe any delay over the oscope. Is there another way to add this delay?

  • Odd that the delay did not have any effect, I suggest to continue debugging to see if you have any new observations. Maybe the delay is somehow optimized away, though you can set a breakpoint there just to confirm you are hitting the line of code. Do you see the same issues when using the nrf5 sdk examples as-is? 

    Kenneth

  • I put a breakpoint at the delay and it is getting hit but I still can't see the delay over an oscilloscope which is weird. 

    What's weirder is that the issue exists with the bare examples too!! I've attached zips of my spis and nrfx_spim firmwares below.  The only changes remaining are a slightly updated test string and the disabling of DCX.

    Rather than sending the expected "nordic123456", the slave device sends out ".ordic123456" where the period is NRF_LOG_HEXDUMP_INFO's attempt at interpreting 'FF' or 'CE'. Am I not supposed to use the spis example firmware with the nrfx_spim? Surely someone must have run into this problem before.

    Also at this point I've tried out multiple physical dev kits to make sure there wasn't some hardware/chip specific/lemon issue.

    4087.nrfx_spim.zip


    6201.spis_chars.zip

    As always, thanks for your help Kenneth. I'm so lost hahaha -

    Ryan

Related