Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

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

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

    KamWo
    New Poster

    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?

    14 REPLIES 14

    BSTRobin
    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*/
    	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;
    }

     

     

    BSTRobin
    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.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist