Bosch Sensortec Community

    Showing results for 
    Search instead for 
    Did you mean: 

    Is BMA2x2 driver designed to be used in a synchronous way?

    Is BMA2x2 driver designed to be used in a synchronous way?

    New Poster


    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?

    14 REPLIES 14

    Community Moderator
    Community Moderator

    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.

    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*/
    	/* 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] = {
    	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
    			/* read the x data_u8*/
    			accel->x =
    					(s16) ((((s32) ((s8) data_u8[BMA2x2_SENSOR_DATA_XYZ_X_MSB]))
    							| (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]))
    							| (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]))
    							| (data_u8[BMA2x2_SENSOR_DATA_XYZ_Z_LSB]
    									& BMA2x2_14_BIT_SHIFT));
    			accel->z = accel->z >> BMA2x2_SHIFT_TWO_BITS;
    	return com_rslt;



    Community Moderator
    Community Moderator

    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(&GTXBuffer[1], pBuffer, WriteNumbr);

    // send register address
    HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, GTXBuffer, WriteNumbr+1, BUS_TIMEOUT);
    return 0;

    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.