I am trying to port a generic C driver available for a IMU to my embedded platform based on a nordic module. the most optimal way would be to correctly modify the interface functions to adapt it to my system. So the driver available on github here, has this interface for write/read register:
typedef int32_t (*lsm6dso_write_ptr)(void *, uint8_t, uint8_t*, uint16_t);
typedef int32_t (*lsm6dso_read_ptr) (void *, uint8_t, uint8_t*, uint16_t);
typedef struct {
/** Component mandatory fields **/
lsm6dso_write_ptr write_reg;
lsm6dso_read_ptr read_reg;
/** Customizable optional pointer **/
void *handle;
} lsm6dso_ctx_t;
My read/write register functions are:
void write_i2c_data(nrf_drv_twi_t const *m_twi, uint8_t reg, uint8_t val)
{
uint8_t cmd[2] = {0, 0};
cmd[0] = reg;
cmd[1] = val;
nrf_drv_twi_tx(m_twi, ADDR, cmd, 2, true);
nrf_delay_ms(1);
}
void read_i2c_data(nrf_drv_twi_t const *m_twi, uint8_t reg, uint8_t *val)
{
nrf_drv_twi_tx(m_twi, ADDR, ®, 1, true);
nrf_delay_ms(1);
nrf_drv_twi_rx(m_twi, ADDR, val, 1);
nrf_delay_ms(1);
}
Questions -
1 - I am not sure how to pass along the m_twi
driver instance function along to the lsm6dso_ctx_t
struct. It says the struct is customizable, but I am not sure how to augment it.
2 - The function pointer kind of got me too - how can I point my function to the lsm6dso_write_ptr
pointer. I know will need to modify my function to provide for multiple byte read/write, which I think is doable.
You should implement two functions:
static int32_t your_callback_lsm6dso_read_reg(void *ctx, uint8_t reg, uint8_t* data,
uint16_t len) {
// read from register ret
// len length of data to data pointer
// return 0 on success
// something like: (I have no idea about nrf_* interface)
nrf_drv_twi_t const *m_twi = ctx;
nrf_drv_twi_rx(m_twi, reg, data, len);
return 0;
}
static int32_t your_callback_lsm6dso_write_reg(void *ctx, uint8_t reg, uint8_t* data,
uint16_t len)
// write to register ret len length od data from data pointer
// return 0 on success
// something like: (I have no idea about nrf* interface)
nrf_drv_twi_t const *m_twi = ctx;
nrf_drv_twi_tx(m_twi, reg, data, len);
return 0;
}
Then instantiate the structure:
lsm6dso_ctx_t lsm6dso_ctx = { your_callback_lsm6dso_write_reg, your_callback_lsm6dso_read_reg, m_twi };
and use it like:
lsm6dso_some_function_from_the_library(&lsm6dso_ctx, ...)
The function from the library will call the function pointers from lsm6dso_ctx
with the first argument as the void*
pointer from the structure. The void*
pointer from the structure is used to pass your custom data along. You can then cast the handle from void*
pointer into a custom pointer and call the appropriate functions.
how can I point my function to the lsm6dso_write_ptr pointer.
I think your confusion comes from it, that's it's the other way round. The function pointers inside lsm6dso_ctx_t
should point to your functions.
Then you have just an instance of lsm6dso_ctx_t
structure you use with all functions from the driver. The driver has some logic and it calls your functions as passed with the structure to do input/output operations.