2021-04-15 11:29 PM
Hello,
I am writing a code to initialize the BMI055 IMU on my STM32F765. To do so I am using the HAL libraries to enable the SPI connection through DMA and the drivers provided by Bosch: bma2x2 and bmg160.
The two sensors work perfectly when only one of the two is enabled, but together they don't work.
// Init Gyro
int32_t bmg160_sensor_init(void)
{
SPI_routine_gyro();
com_rslt_2 = bmg160_init(&bmg160);
com_rslt_2 += bmg160_set_power_mode(BMG160_MODE_NORMAL);
v_bw_u8 = C_BMG160_BW_230HZ_U8X; /* set gyro bandwidth of 230Hz*/
com_rslt_2 += bmg160_set_bw(v_bw_u8);
/* This API used to read back the written value of bandwidth for gyro*/
com_rslt_2 += bmg160_get_bw(&v_gyro_value_u8);
bmg160_set_intr_output_type(BMG160_INTR1, 0);
// 1. Interrupt on Data is on INT1 or INT2 on register 0x18
com_rslt_2 += bmg160_set_intr_data(0, BMG160_ENABLE);
// ENABLE INTERRUPT
// 2. Set the interrupt mode to new-data on register 0x15
com_rslt_2 += bmg160_set_data_enable(BMG160_ENABLE);
return com_rslt_2;
}
// Init Accelerometer
int32_t bma2x2_sensor_init(void)
{
SPI_routine_acc();
com_rslt = bma2x2_init(&bma2x2);
com_rslt += bma2x2_set_power_mode(BMA2x2_MODE_NORMAL);
/* This API used to read back the written value of bandwidth*/
com_rslt += bma2x2_get_bw(&banwid);
// Set source to new-data
com_rslt += bma2x2_set_source(5, 0x01);
// Set register 0x19 to INT1 in new-data
com_rslt += bma2x2_set_new_data(0, 0x01);
// Enable interrupt for new-data
com_rslt += bma2x2_set_intr_enable(BMA2x2_DATA_ENABLE, 0x01);
return com_rslt;
}
The transmit and receive is similar for the accelerometer (chip select: PG10) and the gyroscope (chip select: PF4):
s8 BMA2x2_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8* reg_data, u8 cnt)
{
s32 iError = BMA2x2_INIT_VALUE;
u8 array[SPI_BUFFER_LEN * 2];
u8 stringpos = BMA2x2_INIT_VALUE;
for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++)
{
array[stringpos * 2] = (reg_addr++) & BMA2x2_SPI_BUS_WRITE_CONTROL_BYTE;
array[stringpos * 2 + BMA2x2_BUS_READ_WRITE_ARRAY_INDEX]
= *(reg_data + stringpos);
}
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, RESET);
iError = HAL_SPI_Transmit_DMA(&hspi1, array, cnt * 2);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
;
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, SET);
return (s8) iError;
}
//--------------------------------------------------------------
s8 BMA2x2_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8* reg_data, u8 cnt)
{
s32 iError = BMA2x2_INIT_VALUE;
u8 array[SPI_BUFFER_LEN] = { 0xFF };
u8 stringpos;
/* For the SPI mode only 7 bits of register addresses are used.
The MSB of register address is declared the bit what functionality it is
read/write (read as 1/write as 0)*/
array[BMA2x2_INIT_VALUE] = reg_addr | BMA2x2_SPI_BUS_READ_CONTROL_BYTE;
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, RESET);
iError = HAL_SPI_Receive_DMA(&hspi1, array, cnt + 1);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
;
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, SET);
for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++)
{
*(reg_data + stringpos)
= array[stringpos + BMA2x2_BUS_READ_WRITE_ARRAY_INDEX];
}
return (s8) iError;
}
For brevity, I'm not writing here also the gpio initialization, the spi etc. However, when only one sensor is enabled, everything works. When together, problems start at the initialization level: I can't read back for example a proper bandwidth for one of the two sensors.
I'm not sure if the problem is at the sensor level (so the way I am initializing the peripherals) or at the microcontroller level (maybe some errors in the spi initialization, etc).
I hope someone can help to find the problem.
NOTE: The code posted shows this series of events:
But I've also tried:
but nothing changed.
Thanks in advance.
Solved! Go to Solution.
2021-04-21 08:42 AM
Hi @FUs.1 ,
good news! (at least partially...)
Our application team tried to reproduce the issue with two of ST sensors, interfacing them via direct SPI to an STM32F7 and using a code similar to yours, and we didn't reproduce it, combining the interrupts in different ways.
If you want, we can send you our adapter with the configuration.
Let us know!
-Eleon
2021-04-16 01:45 AM
Hi @FUs.1 ,
I would first suggest you to ask for help also to Bosch support, since it might be an issue related to their products...
By the way, could you detail a bit more your application at high level? Do you want to read sensors' data simultaneously at a certain ODR (the same for both of them)?
And in which phase of your code are you getting issues? In the configuration/initialization phase, if it is separately performed for the two sensors, so that you cannot properly read/write the registers, or when you start acquiring data, so that the issue is when you receive "overlapping" data-ready interrupts from the two sensors?
If you get any comments from Bosch community, please let us know as well!
-Eleon
2021-04-16 04:05 AM
Thank you very much for the answer. I have actually asked the question on the Bosch forum
https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMI055-interrupts/m-p/23274.
"By the way, could you detail a bit more your application at high level? Do you want to read sensors' data simultaneously at a certain ODR (the same for both of them)?"
I want to read the two sensors (gyroscope (bmg160) and accelerometer (bma2x2) that are in the same chip, the BMI055 IMU) using SPI through the DMA. Furthermore, I want to read these sensors when new data is available, and for this, I enable the new data interrupts on the sensors. Their data ready pins are connected to the PB14 and PB15 of the STM32. Then, to capture these external interrupts, I enable the EXTI on pins PB14 and PB15 (on the STM32765), as shown in the code below:
/*Configure GPIO pin : PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_14 | GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
The EXTI callback looks like this:
// EXTI Line10-15 External Interrupt ISR Handler CallBackFun
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_14)
{
bmg160_read_gyro();
}
if (GPIO_Pin == GPIO_PIN_15)
{
bma2x2_read_acc();
}
}
The IRQ handler is:
* @brief This function handles EXTI line[15:10] interrupts.
*/
void EXTI15_10_IRQHandler(void)
{
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_14) != RESET)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
}
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_15) != RESET)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
}
}
"And in which phase of your code are you getting issues? In the configuration/initialization phase, if it is separately performed for the two sensors, so that you cannot properly read/write the registers, or when you start acquiring data, so that the issue is when you receive "overlapping" data-ready interrupts from the two sensors?"
This is actually a very good question. To give a precise answer let me show you my initialization code.
int main(void)
{
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_RTC_Init();
MX_SPI1_Init();
MX_TIM2_Init();
// Sensor initialization
bmg160_sensor_init();
HAL_Delay(500);
bma2x2_sensor_init();
HAL_Delay(500);
// Enable sensors interrupts
bmg160_enable_intr();
HAL_Delay(500);
// bma2x2_enable_intr();
while (1) {}
}
The problems start already at the initialization level. Actually, if I enable the bma2x2 before the bmg160, I get problems in the bmg160 initialization (E.g. I read, and probably write, an incorrect bandwidth on the sensor's registers).
If I initialize the bmg160 before the bma2x2 (as shown in the code), the two sensors get initialed properly but (assuming I don't enable the bma2x2 interrupt) the EXTI callback on pin 14 (bmg160) is not called anymore after few loops, and the code gets stuck somewhere.
If I enable also the bma2x2 interrupt, the EXTI for the bmg160 never gets called at all, but the bma2x2 callback "tends" to work. An explanation I was trying to give is that the bma2x2 (accelerometer) should have a much higher frequency (both the sensors are now at their maximum bandwidth), but I'm not very sure that this makes a lot of sense.
NOTE: I really want to stress that the two sensors alone work well and this makes me think that the SPI + DMA is properly set up as well as the two sensors. But there might be a problem in the way I manage the EXTI lines, when there is more than one or maybe the DMA where there is more than one chip-select around.
Thank you very much for your help.
2021-04-16 08:33 AM
Hi @FUs.1 ,
thank you for the detailed answer.
I just saw that they replied to you on Bosch community, let's see if they have something more to say.
In the mean time, I added STM32F7 topic for more help from STM32 experts.
-Eleon
2021-04-16 09:12 AM
Unfortunately, the answer I received on the Bosch forum didn't solve the problem. I'm always more convinced that I'm doing something wrong on the STM32 side, maybe in handling the SPI communication.
2021-04-17 07:28 AM
to give more context, the problem is that after a couple of loops the code get stuck on the SPI reading
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
;
2021-04-19 12:39 AM
Hi @FUs.1 ,
ya, I'm currently following the thread on Bosch community.
You could try to add small delays in the interrupt callback functions, if it is actually an issue related to timings in the SPI handler...
But not sure, since you are saying you run a couple of loops an then you get stuck: if it where such an issue, the code would get stuck immediately.
I would first check the runtime error you are getting when the code stuck. Are you using the STM32CubeIDE for debugging and code upload?
-Eleon
2021-04-19 01:07 AM
Hi Eleon,
I basically use VSCode for debugging as well as developing. But I've also checked with the STM32CubeIDE and I get the same result.
The code gets stuck in the while loop, which apparently never ends. It is not easy to understand what is actually happening. Furthermore, the sensors are embedded in the microcontroller and it is rather difficult to access the pins with the scope to check what's going on.
Another observation is that I tried the SPI communication without the DMA and the result is the same.
2021-04-20 01:16 AM
Hi @FUs.1 ,
the fact that both with DMA and direct SPI you get stuck, it could be and indicator that the issue can be in the sensor configuration itself, or an hard(ware) fault coming from the interface with sensors...
If you cannot access, could you debug via printf method? for example inserting a variable inside the interrupt handled functions, and see whether it is updated during the call of the function, and checking its value after you get the error?
I also see they answered to you in the Bosch community, keep me please update about it.
-Eleon
2021-04-21 08:42 AM
Hi @FUs.1 ,
good news! (at least partially...)
Our application team tried to reproduce the issue with two of ST sensors, interfacing them via direct SPI to an STM32F7 and using a code similar to yours, and we didn't reproduce it, combining the interrupts in different ways.
If you want, we can send you our adapter with the configuration.
Let us know!
-Eleon