简体   繁体   中英

Porting generic C driver with function pointer

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, &reg, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM