2023-05-08 3:23 AM
I have verified in my code that writing and reading with I2C works as expected, and registers are configured seemingly correctly. I believe there must be a problem with how I write the configuration file to the BMI270, but I am at a loss as to what error exists in my code.
Here I present the initialization function and starting function for the BMI270:
--------------------------------------------
uint8_t BMI270_init(void)
{
uint8_t address;
uint8_t init_addr0 = 0x5B;
uint8_t init_addr1 = 0x5C;
uint16_t init_val = 0;
uint8_t value, val_lsb, val_msb;
uint8_t buffer[2] = {0};
uint8_t err = 0;
//disable PWR_CONF.adv_power_save (addr=0x7C,val=0x00)
address = 0x7C;
value = 0x00;
//Read address before
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test pwc 1: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
HAL_Delay(1);
//Read address after
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test pwc 2: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//wait for 450 us
HAL_Delay(1);
//set INIT_CTRL to zero (addr=0x59,val=0x00)
address = 0x59;
value = 0x00;
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
//Read address after
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test set 1: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//write bmi270_config_file (addr=0x5E,val=bmi270_config_file)
address = 0x5E;
//Continuously write parts of the configuration file <--- error??
for(uint8_t i = 0; i<32 ; i++)
{
err = I2C_write(&address, &bmi270_config_file[i*255], 255);
if (err != HAL_OK)
{return err;}
init_val=128;
val_msb = (uint8_t)(init_val >> 8);
val_lsb = (uint8_t)init_val;
//Update init_addr0 and init_addr1 (increment with bytes/2)
err = I2C_write(&init_addr0, &val_lsb, 1);
if (err != HAL_OK)
{return err;}
err = I2C_write(&init_addr1, &val_msb, 1);
if (err != HAL_OK)
{return err;}
address+= 256;
}
//set INIT_CTRL to one (addr=0x59,val=0x01)
address = 0x59;
value = 0x01;
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
//Read address after
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test set 2: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
return 0;
}
//end BMI270_initialize
uint8_t BMI270_start(void)
{
uint8_t address;
uint8_t value;
uint8_t err = 0;
uint8_t buffer[2] = {0};
//Write to PWR_CTRL (addr=0x7D,val=0x0E) (enable acc. & gyr.)
address = 0x7D;
value = 0x0E;
//Read address before
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test pwr 1: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//Write value to register
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
//Read address after
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
//Print result
UART_print_char("test pwr 2: ", 12);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//Write to ACC_CONF (addr=0x40,val=0xA8)
address = 0x40;
value = 0xA3;
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
UART_print_char("test acc: ", 10);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//Write to GYR_CONF (addr=0x42,val=0xA9)
address = 0x42;
value = 0xA9;
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
err = I2C_read(&address, buffer, 1);
if (err != HAL_OK)
{return err;}
UART_print_char("test gyr: ", 10);
UART_print(buffer, 2);
UART_print_char("\r\n", 2);
//Write to PWR_CONF (addr=0x7C,val=0x02) (disable adv_power_save)
address = 0x7C;
value = 0x02;
err = I2C_write(&address, &value, 1);
if (err != HAL_OK)
{return err;}
return 0;
}
//end BMI270_start
--------------------------------------------
If the initialization was successful, the INTERNAL_STATUS register should contain the value 0x01, but in my case keeps containing the value 0x02 (init. error). The strangest thing is that at one point this code did work (internal_status = 0x01, gyroscope and accelerometer outputted values), however I can no longer replicate this response.
I included a zip folder containing two screenshots of both the error response and the working response in my serial monitor.
I have been breaking my head over the initialization proces for a while now, and I have a feeling there's just something I am overlooking. Help would be immensely appreciated. I would be eager to provide any further information if desired.
Kind regards,
Daan
2023-07-01 12:38 AM
Hi Dvan.11,
I am facing the same problem. Have you managed to solve the issue? If yes, could you please share the solution.
2023-08-01 3:25 PM
Please use the code pasting tool so these posts are readable.
On the BMI-160 you have to write a handful of registers and START the device. Would suggest finding other working examples, say from Arduino drivers, or a though reading of the salient manuals for the BOSCH device.
If you can read/write the registers on the device you should be able to port examples from other platforms.
2025-03-24 11:33 AM
Hi Dvan .11, I hope you are having a good day. I am interfacing a BMI270 with an stm32f103c8t6, better known as the Bluepill. I am facing the same error as you and I cannot seem to figure out where I am going wrong in the initialization. If your issue has been resolved, could you please help me figure out where I am going wrong, ill attach my code sample below.
Even im receiving the value "0x02" from register "0x21", it stands for Initialization error and I have no clue where i have made an error.
I have not included the config file in the below code as it would be a waste of space.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
uint8_t BMI_config[] = {}; //The config file is too huge to be posted and quite unnecessary
HAL_StatusTypeDef status;
uint8_t buffer[12];
uint8_t check_id;
uint16_t final_address;
uint8_t chip_address;
int error = 0;
int init_complete = 0;
int init_condition = 0;
int address;
int i;
uint16_t config_file_size;
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
uint8_t internal_status = 0;
/* USER CODE BEGIN PFP */
#define BMI270_I2C_ADDR (0x68 << 1) // BMI270 I2C address (adjust if using different I2C variant)
#define BMI270_CONFIG_LOAD_ADDR 0x5E // Config upload address
extern I2C_HandleTypeDef hi2c1; // Ensure you are using the correct I2C handle
/**
* @brief Burst writes the BMI270 firmware/configuration file
* @PAram data: Pointer to the firmware binary
* @PAram length: Length of the binary
* @return HAL Status
*/
HAL_StatusTypeDef BMI270_BurstWrite(uint8_t *data, uint16_t length) {
uint16_t chunkSize = 32; // Recommended max burst size (BMI270 supports up to 32 bytes at a time)
uint16_t bytesWritten = 0;
while (bytesWritten < length) {
uint16_t bytesToWrite = (length - bytesWritten) > chunkSize ? chunkSize : (length - bytesWritten);
status = HAL_I2C_Mem_Write(&hi2c1, BMI270_I2C_ADDR, BMI270_CONFIG_LOAD_ADDR,
I2C_MEMADD_SIZE_8BIT, &data[bytesWritten], bytesToWrite, HAL_MAX_DELAY);
if (status != HAL_OK) {
return status; // Return error if write fails
}
bytesWritten += bytesToWrite;
HAL_Delay(2); // Small delay to avoid overwhelming the sensor
}
return HAL_OK;
}
uint16_t ret_address(){
for(int i = 0; i < 128; i++){
if(HAL_I2C_IsDeviceReady(&hi2c1, i << 1, 1, 100) == HAL_OK){
address = i;
break;
}
}
//status = HAL_I2C_IsDeviceReady(&hi2c1, address << 1, 1, 100);
HAL_I2C_Mem_Read(&hi2c1, address << 1, 0x00, 1, &check_id, 1, 100);
return address;
}
uint8_t ret_chip(){
uint8_t chip_address;
HAL_I2C_Mem_Read(&hi2c1, 0x68 << 1, 0x00, 1, &chip_address, 1, 100);
return chip_address;
}
int init_BMI(){
uint8_t data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x7c, 1, &data, 1, 100);
HAL_Delay(2000);
uint8_t reset_cmd = 0xb6;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x7E, 1, &reset_cmd, 1, 100);
HAL_Delay(2);
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x59, 1, &data, 1, 100);
config_file_size = sizeof(BMI_config);
for(int j = 0; j < config_file_size; j++){
status = HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x5e, 1, &BMI_config[j], 1, 100);
}
//status = BMI270_BurstWrite(BMI_config, config_file_size);
//status = HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x5e, 1, BMI_config, config_file_size, 100);
data = 0x01;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x59, 1, &data, 1, 100);
if(status == HAL_OK){
return 1;
}
else{
return 0;
}
}
int init_check() {
HAL_Delay(300); // Wait before checking initialization status
HAL_I2C_Mem_Read(&hi2c1, address << 1, 0x00, 1, &check_id, 1, 100);
// Read status register (0x21)
status = HAL_I2C_Mem_Read(&hi2c1, final_address << 1, 0x21, 1, &internal_status, 1, 100);
// Check if the read was successful
if (status != HAL_OK) {
return -1; // Indicate failure
}
// Return LSB of the status register
return (internal_status & 0x01);
}
void normal_config(){
uint8_t data;
data = 0x0e;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x7d, 1, &data, 1, 100);
data = 0xa8;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x40, 1, &data, 1, 100);
data = 0xa9;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x42, 1, &data, 1, 100);
data = 0x02;
HAL_I2C_Mem_Write(&hi2c1, final_address << 1, 0x76, 1, &data, 1, 100);
HAL_I2C_Mem_Read(&hi2c1, final_address << 1, 0x0c, 1, buffer, 12, 100);
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
final_address = ret_address();
chip_address = ret_chip();
if(chip_address == 0x24){
error = 0;
}
else{
error = 1;
}
init_complete = init_BMI();
init_condition = init_check();
//normal_config();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//HAL_I2C_Mem_Read(&hi2c1, 104 << 1, 0x12, 1, buffer, 6, 100);
}
/* USER CODE END 3 */
}