BMI160 SPI on RG firmware development

I'm trying to work with BMI160 over SPI ( RG board ).

On nrf_drv_config.h:

/* SPI */
#define SPI0_ENABLED 1

#if (SPI0_ENABLED == 1)
#define SPI0_USE_EASY_DMA 0

#define SPI0_CONFIG_SCK_PIN         0
#define SPI0_CONFIG_MOSI_PIN        7
#define SPI0_CONFIG_MISO_PIN        11


On main.c:

#define SPI_CS_PIN 10
#define SPI_BUFFER_SIZE 16

#define SPI_INSTANCE  0
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  
static volatile bool spi_xfer_done;  

static uint8_t       m_tx_buf[SPI_BUFFER_SIZE];           
static uint8_t       m_rx_buf[SPI_BUFFER_SIZE];    
static const uint8_t m_length = SPI_BUFFER_SIZE;       

void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    spi_xfer_done = true;
void spi_master_init(void)
      nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG(SPI_INSTANCE);
      spi_config.ss_pin            = SPI_CS_PIN;
      spi_config.miso_pin          = SPI0_CONFIG_MISO_PIN;
      spi_config.mosi_pin          = SPI0_CONFIG_MOSI_PIN;
      spi_config.sck_pin           = SPI0_CONFIG_SCK_PIN;
      spi_config.frequency         = NRF_DRV_SPI_FREQ_1M;
      spi_config.mode                 = NRF_DRV_SPI_MODE_3;
      spi_config.irq_priority = SPI0_CONFIG_IRQ_PRIORITY;
      APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));

On main routine:

                m_tx_buf[0] = 0x00  |  0x80 ;  // chip id reg adr | read_mask
                memset(m_rx_buf, 0, SPI_BUFFER_SIZE);
                spi_xfer_done   = false;
                APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 1, m_rx_buf, 1));
                while(spi_xfer_done == false){;}       
After the while loop for spi_xfer_done m_rx_buf[0] is always 0xFF;

The main problem is that I can't use oscilloscope ( no test/pad pin on specifications ).
So, I can't understand what happen (debugging step by step seems good).

I tried to swap MISO and MOSI pin cause pdf spacifications is not so clear.
strange thing is that in specification pdf there is a draw with i2c
BMI160 connection ( Figure 1 Block diagram ) but the "Internal Module
Pin list" says that BMI160 is connected via SPI.

Thank you for any answer.


  • I tried to use spi pins directly by a simple software routine (always usefull for try to understand).
    So, I was using in wrong way the function nrf_drv_spi_transfer. The lengh of buffers was 1, not enought for 16bit clock cycle.
    Thank you for reading.
  • Hi @wsuite, we're glad you figured out what was wrong.  Let us know if you have any other issues!
  • Hi @Matt, I'll be here if I need like this time.
    Thank you.

  • edited August 2016
    Hello, Wsuite.
    I wish to discuss with you about this in more detail.
    I can't understand your comments enoughly.
    Did you realize the correct SPI interface firmware for BMI160?
    If you realize it, did you read the correct CHIP_ID, 0xD1 for BMI160?
    And didn't you use the function <nrf_drv_spi_transfer>?
    I hope that you give the correct answer about this.
    Thanks for your time.
    From Minghui.
  • MinghuiHao,
    Yes SPI is working well by SPI.
    Tell me what's not clear for you.
    ( sofware SPI routine was just for understand the problem )
  • Hi guys,
    have you tried to use the BMI160 FIFO?

    I am trying to access the FIFO with burst reads but without success.
    This is basically what I do:

    #define READ_MASK 0x80
    // Prepare the address - reg_addr = 0x24
    uint16_t packet = reg_addr | READ_MASK;
    spi_txbuf[0] = (uint8_t)(packet & 0xFF);
    spi_txbuf[1] = (uint8_t)(packet >> 0x8);

    // cnt is 1024 to read the entire FIFO
    uint32_t err_code = spi_master_send_recv(SPI_MASTER_1, spi_txbuf, 2, reg_data, cnt);

    The data I get back is wrong, it's always the same and for sure it is not the accelerometer and gyro data.
    I am using SDK 6.1.0 on Metawear RPRO.

    Do you have any advice?

  • edited October 2016
    I solved the problem.
    When you do a burst read keeping the CS pin low from start to end, you need to discard the first byte you receive from the BMI160.

    This is the code to initiate the read:

    #define READ_MASK 0x80
    uint16_t packet = reg_addr | READ_MASK;
    spi_txbuf[0] = (uint8_t)(packet & 0xFF);

    // cnt is 1024 to read the entire FIFO
    uint32_t err_code = spi_master_send_recv(SPI_MASTER_1, spi_txbuf, 1, reg_data, (uint16_t)cnt);

    Then I had to modify spi_master.c to discard the first byte, I modified line 233 in this way:

    if(p_spi_instance->max_length != 1024 || (p_spi_instance->max_length == 1024 &&  p_spi_instance->bytes_count > 1))
    { p_spi_instance->p_rx_buffer[p_spi_instance->rx_index++] = rx_byte;

    It's probably not the best solution but it works for now. :)

This discussion has been closed.