6 years, 3 months ago.

I2C Callback: passing arguments

The new I2C API allows us to setup an I2C tranfser and pass in a pointer to a function and an event flag to be called when the process is done executing, but is it possible to also pass in an argument to the callback function?

I'm trying to do this because I create an object that contains an I2C port and an EventFlag for that I2C port. I use that object as a handle and pass it in to each function that operates on it. In order for the correct EventFlag to be used I must initialize the code and assign a local pointer to the EvenFlag. This works fine when I only create one object that calls this code and/or I create more than one object but they use the same I2C port (with the same set of EventFlags). If I were to create two of these objects and assign different I2C ports (and a different set of EventFlags), then my initialization of the local events flag pointer would be overwritten by the second object and my callback would always use the second object's EventFlag.

My code snippet is below. This is written in C style for compatibility (and stubbornness).

EventFlags* ad7150_eventFlags_localPointer;				/* Local pointer used for shared i2c resource */

uint8_t ad7150_init( AD7150_t *_ad7150 , I2cHandle_t *_i2c , DigitalIn *_digitalIn ){
	_ad7150->io.i2c = _i2c;
	_ad7150->io.cap_out = _digitalIn;
	
	ad7150_eventFlags_localPointer = _ad7150->io.i2c->flags;
		
    _ad7150->io.cap_out->mode( PullDown );
	
    return ad7150_write_registers( _ad7150 );
}
void ad7150_i2c_callback( int argument ){
	ad7150_eventFlags_localPointer->set( I2C_DONE_FLAG );
	ad7150_eventFlags_localPointer->clear( I2C_BUSY_FLAG );
} 

void ad7150_i2c_transfer( AD7150_t* _ad7150, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length ){	
	while( I2C_BUSY_FLAG && _ad7150->io.i2c->flags->get() ) { }
	_ad7150->io.i2c->flags->set( I2C_BUSY_FLAG );
	if( I2C_FREQ_100K != _ad7150->io.i2c->frequency ){
		_ad7150->io.i2c->frequency = I2C_FREQ_100K;
		_ad7150->io.i2c->port->frequency( _ad7150->io.i2c->frequency  );
	}
 	while( TRANSFER_STARTED != _ad7150->io.i2c->port->transfer( 	AD7150_I2C_ADDRESS, 
																	tx_buffer, tx_length, 
																	rx_buffer, rx_length, 
																	ad7150_i2c_callback, 
																	I2C_EVENT_TRANSFER_COMPLETE, 
																	I2C_NO_REPEATED_START
																	) ) { wait_ms( I2C_RETRY_DELAY_MS ); };	//	retry transfer after delay
	if( I2C_DONE_FLAG != _ad7150->io.i2c->flags->wait_all( I2C_DONE_FLAG , I2C_EVENT_WAIT_MS , false ) ){
		ad7150_i2c_callback( NULL );
	}
	_ad7150->io.i2c->flags->clear( I2C_DONE_FLAG );
}

Be the first to answer this question.