03-22-2021 01:55 AM
Hello,
there is one thing that bothers me, the whole API depends on:
#define BMA2x2_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len) bus_read(dev_addr, reg_addr, reg_data, r_len)
and it's the function which must be implemented by the user as it's specific for every MCU.
I use I2C to read every byte in ISR and store it one at a time in a buffer. Reading data in that way does not allow me to use the BMA2x2 driver as is.
My questions are:
Does the BMA2x2_BUS_READ_FUNC function is meant to be synchronous(it looks so)?
Does it have to block the whole program and wait for every byte from a bus (I2C/SPI) with busy waiting and is the whole API designed this way?
Is there a way to use this API easily with interrupts?
Solved! Go to Solution.
03-22-2021 02:59 AM
Hello KamWo,
bus_read() is a SW interface between sensor API and MCU I2C or SPI driver communication.Whether you use polling or interrupt mode, you only need to follow this interface standard.
03-22-2021 10:23 PM
Thanks for your reply BSTRobin, I would like to be more precise in my question.
I would like to confirm that after leaving function "p_bma2x2->BMA2x2_BUS_READ_FUNC" which I've marked with "(A) read from a bus" the "data_u8" has to be filled with all 6 bytes of accelerometer data in order to whole operation of reading accelerometer data from X,Y,Z be successful. That is what I meant when I was asking if the whole API is designed to be used in a synchronous way.
Am I correct or am I missing something obvious?
BMA2x2_RETURN_FUNCTION_TYPE bma2x2_read_accel_xyz(
struct bma2x2_accel_data *accel) {
/* Variable used to return value of
communication routine*/
BMA2x2_RETURN_FUNCTION_TYPE com_rslt = ERROR;
/* Array holding the accel xyz value
data_u8[0] - x->LSB
data_u8[1] - x->MSB
data_u8[2] - y->MSB
data_u8[3] - y->MSB
data_u8[4] - z->MSB
data_u8[5] - z->MSB
*/
u8 data_u8[BMA2x2_ACCEL_XYZ_DATA_SIZE] = {
BMA2x2_INIT_VALUE, BMA2x2_INIT_VALUE,
BMA2x2_INIT_VALUE, BMA2x2_INIT_VALUE,
BMA2x2_INIT_VALUE, BMA2x2_INIT_VALUE };
if (p_bma2x2 == BMA2x2_NULL) {
/* Check the struct p_bma2x2 is empty */
return E_BMA2x2_NULL_PTR;
} else {
switch (V_BMA2x2RESOLUTION_U8) {
(...)
/* This case used for the resolution bit 14*/
case BMA2x2_14_RESOLUTION:
com_rslt = p_bma2x2->BMA2x2_BUS_READ_FUNC( // <--------------------------------------------- (A) read from a bus
p_bma2x2->dev_addr,
BMA2x2_ACCEL_X12_LSB_REG,
data_u8,
BMA2x2_SHIFT_SIX_BITS
);
/* read the x data_u8*/
accel->x =
(s16) ((((s32) ((s8) data_u8[BMA2x2_SENSOR_DATA_XYZ_X_MSB]))
<<
BMA2x2_SHIFT_EIGHT_BITS)
| (data_u8[BMA2x2_SENSOR_DATA_XYZ_X_LSB]
& BMA2x2_14_BIT_SHIFT));
accel->x = accel->x >> BMA2x2_SHIFT_TWO_BITS;
/* read the y data_u8*/
accel->y =
(s16) ((((s32) ((s8) data_u8[BMA2x2_SENSOR_DATA_XYZ_Y_MSB]))
<<
BMA2x2_SHIFT_EIGHT_BITS)
| (data_u8[BMA2x2_SENSOR_DATA_XYZ_Y_LSB]
& BMA2x2_14_BIT_SHIFT));
accel->y = accel->y >> BMA2x2_SHIFT_TWO_BITS;
/* read the z data_u8*/
accel->z =
(s16) ((((s32) ((s8) data_u8[BMA2x2_SENSOR_DATA_XYZ_Z_MSB]))
<<
BMA2x2_SHIFT_EIGHT_BITS)
| (data_u8[BMA2x2_SENSOR_DATA_XYZ_Z_LSB]
& BMA2x2_14_BIT_SHIFT));
accel->z = accel->z >> BMA2x2_SHIFT_TWO_BITS;
break;
default:
break;
}
}
return com_rslt;
}
03-24-2021 07:29 AM
Hello KamWo,
You only need to implement the actual communication function of BMA2x2_RD_FUNC_PTR function, depending on how convenient your hardware platform is, whether polling or interrupt mode is used. When an application calls an API, it only needs to use this interface.
I gave out a example code on STM32, you could refer it.
#define BMA2x2_RD_FUNC_PTR s8(*bus_read)(u8, u8, u8 *, u8)
dev->dev_addr = BMA2x2_I2C_ADDR2,
dev->bus_read = SensorAPI_BMA2X2_I2Cx_Read,
dev->bus_write = SensorAPI_BMA2X2_I2Cx_Write,
dev->delay_msec = HAL_Delay,
uint8_t GTXBuffer[32];
int8_t SensorAPI_BMA2X2_I2Cx_Read(uint8_t slave_address7, uint8_t subaddress, uint8_t *pBuffer, uint8_t ReadNumbr)
{
uint16_t DevAddress = slave_address7 << 1;
// send register address
HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, &subaddress, 1, BUS_TIMEOUT);
HAL_I2C_Master_Receive(&I2C_HANDLE, DevAddress, pBuffer, ReadNumbr, BUS_TIMEOUT);
return 0;
}
int8_t SensorAPI_BMA2X2_I2Cx_Write(uint8_t slave_address7, uint8_t subaddress, uint8_t *pBuffer, uint8_t WriteNumbr)
{
uint16_t DevAddress = slave_address7 << 1;
GTXBuffer[0] = subaddress;
memcpy(>XBuffer[1], pBuffer, WriteNumbr);
// send register address
HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, GTXBuffer, WriteNumbr+1, BUS_TIMEOUT);
return 0;
}
03-25-2021 11:02 PM
Thanks for giving me an example from STM32. Reading the implementation for 'HAL_I2C_Master_Transmit' and 'HAL_I2C_Master_Receive' answered my question.
For all those who are going to read this subject the answer is: Yes, after leaving BMA2x2_BUS_READ_FUNC the complete data has to be in "data_u8" buffer. So the whole API relies on a synchronous interface. No matter if you get data form I2C using pooling or interrupts the BMA2x2_BUS_READ_FUNC function must not return until all data is read.