Iis2dh

From Wiki at Neela Nurseries
Revision as of 00:15, 15 October 2021 by Ted (talk | contribs) (Zephyr RTOS Tie-In To STMicro IIS2DH Driver API)
Jump to: navigation, search

Notes on STMicro IIS22DH high frequency MEMS accelerometer.

A promising project on Github:


Symbols in the polling code example from STMicroelectronic/iis2dh repo are defined in a sub-part of sdk-nrf modules/hal/ project space:

guest@ubuntu-vm:~/embedded/z3-on-var/modules/hal/st$ grep -nr IIS2DH_2g ./*
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.h:742:  IIS2DH_2g   = 0,
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:636:    case IIS2DH_2g:
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:637:      *val = IIS2DH_2g;
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:649:      *val = IIS2DH_2g;

guest@ubuntu-vm:~/embedded/z3-on-var/modules/hal/st$ grep -nr IIS2DH_ODR_1Hz ./*
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.h:707:  IIS2DH_ODR_1Hz                         = 0x01,
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:402:    case IIS2DH_ODR_1Hz:
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:403:      *val = IIS2DH_ODR_1Hz;

guest@ubuntu-vm:~/embedded/z3-on-var/modules/hal/st$ grep -nr IIS2DH_TEMP_ENABLE ./*
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.h:692:  IIS2DH_TEMP_ENABLE   = 3,
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:285:    case IIS2DH_TEMP_ENABLE:
./sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c:286:      *val = IIS2DH_TEMP_ENABLE;
guest@ubuntu-vm:~/embedded/z3-on-var/modules/hal/st$ grep -nr PROPERTY_ENABLE ./*

And really the above project is pulled in to Nordic's sdk-nrf. Looks to be at a slightly older, or at least different version, but driver header and sources at https://github.com/STMicroelectronics/iis2dh are the same as in the STMicro hal code in Nordic sdk-nrf v1.6.1.


^ IIS2DH Control Registers As C Structures

An excerpt from Nordic sdk-nrf modules/hal/st/sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.h:

#define IIS2DH_CTRL_REG4             0x23U
typedef struct {
#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
  uint8_t sim               : 1;
  uint8_t st                : 2;
  uint8_t hr                : 1;
  uint8_t fs                : 2;
  uint8_t ble               : 1;
  uint8_t bdu               : 1;
#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
  uint8_t bdu               : 1;
  uint8_t ble               : 1;
  uint8_t fs                : 2;
  uint8_t hr                : 1;
  uint8_t st                : 2;
  uint8_t sim               : 1;
#endif /* DRV_BYTE_ORDER */
} iis2dh_ctrl_reg4_t;


^ Possible Zephyr Driver Routines for IIS2DH

Following routines are not obvious nor mentioned anywhere in Zephyr Project documentation found so far, nor are they hinted at by any trace of analogous routines in the build artifacts of Zephyr lis2dh sample app. But may we use these following routines in app level code we want to have talking with STMicro's IIS2DH sensor? . . .

  1 guest@vm:~/projects/zephyr-based/project-stage-1$ grep -nr stmdev_ctx_t ./*
  2 Binary file ./build/zephyr/zephyr.elf matches
  3 Binary file ./build/zephyr/zephyr_prebuilt.elf matches
  4 ./build/zephyr/zephyr.lst:55935:int32_t iis2dh_read_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data,
  5 ./build/zephyr/zephyr.lst:55953:int32_t iis2dh_write_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data,
  6 ./build/zephyr/zephyr.lst:55973:int32_t iis2dh_operating_mode_set(stmdev_ctx_t *ctx, iis2dh_op_md_t val)
  7 ./build/zephyr/zephyr.lst:56065:int32_t iis2dh_data_rate_set(stmdev_ctx_t *ctx, iis2dh_odr_t val)
  8 ./build/zephyr/zephyr.lst:56107:int32_t iis2dh_full_scale_set(stmdev_ctx_t *ctx, iis2dh_fs_t val)
  9 ./build/zephyr/zephyr.lst:56149:int32_t iis2dh_block_data_update_set(stmdev_ctx_t *ctx, uint8_t val)
 10 ./build/zephyr/zephyr.lst:56191:int32_t iis2dh_acceleration_raw_get(stmdev_ctx_t *ctx, int16_t *val)
 11 ./build/zephyr/zephyr.lst:56231:int32_t iis2dh_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff)
 12 Binary file ./build/zephyr/CMakeFiles/zephyr.dir/home/ted/projects/zephyr-based/modules/hal/st/sensor/stmemsc/iis2dh_STdC/driver/iis2dh_reg.c.obj matches
 13 Binary file ./build/zephyr/libzephyr.a matches
 14 Binary file ./build/zephyr/drivers/sensor/iis2dh/CMakeFiles/drivers__sensor__iis2dh.dir/iis2dh_trigger.c.obj matches
 15 Binary file ./build/zephyr/drivers/sensor/iis2dh/CMakeFiles/drivers__sensor__iis2dh.dir/iis2dh_i2c.c.obj matches
 16 Binary file ./build/zephyr/drivers/sensor/iis2dh/CMakeFiles/drivers__sensor__iis2dh.dir/iis2dh.c.obj matches
 17 Binary file ./build/zephyr/drivers/sensor/iis2dh/libdrivers__sensor__iis2dh.a matches
 18 guest@vm:~/projects/zephyr-based/project-stage-1$


Zephyr RTOS Tie-In To STMicro IIS2DH Driver API

File `$ENV{ZEPHYR_BASE}/drivers/sensor/iis2dh/iis2dh.c` end with:ii2

312 struct iis2dh_data iis2dh_data;
313
314 DEVICE_DT_INST_DEFINE(0, iis2dh_init, NULL,
315              &iis2dh_data, &iis2dh_cfg, POST_KERNEL,
316              CONFIG_SENSOR_INIT_PRIORITY, &iis2dh_driver_api);

...Somewhere data member `&iis2dh_data` gets assigned a value. This data member in turn is referenced when the above driver API routines are called. For example in routine `iis2dh_sample_fetch()` there is reference to an stmdev_ctx_t structure that's assigned to the device handle's "data" member:

203 static int iis2dh_sample_fetch(const struct device *dev,
204                                enum sensor_channel chan)
205 {
206         struct iis2dh_data *iis2dh = dev->data;
207         int16_t buf[3];
208
209         /* fetch raw data sample */
210         if (iis2dh_acceleration_raw_get(iis2dh->ctx, buf) < 0) {
211                 LOG_DBG("Failed to fetch raw data sample");
212                 return -EIO;
213         }
214
215         iis2dh->acc[0] = sys_le16_to_cpu(buf[0]);
216         iis2dh->acc[1] = sys_le16_to_cpu(buf[1]);
217         iis2dh->acc[2] = sys_le16_to_cpu(buf[2]);
218
219         return 0;
220 }

The structure `iis2dh_data` is defined in corresponding header file `iis2dh.h` as:

 59 /* sensor data */
 60 struct iis2dh_data {
 61         const struct device *bus;
 62         int16_t acc[3];
 63         uint32_t gain;
 64
 65         stmdev_ctx_t *ctx;
 66 #ifdef CONFIG_IIS2DH_TRIGGER
 67         const struct device *dev;
 68         const struct device *gpio;
 69         uint8_t gpio_pin;
 70         struct gpio_callback gpio_cb;
 71         sensor_trigger_handler_t drdy_handler;
 72 #if defined(CONFIG_IIS2DH_TRIGGER_OWN_THREAD)
 73         K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_IIS2DH_THREAD_STACK_SIZE);
 74         struct k_thread thread;
 75         struct k_sem gpio_sem;
 76 #elif defined(CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD)
 77         struct k_work work;
 78 #endif /* CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD */
 79 #endif /* CONFIG_IIS2DH_TRIGGER */
 80 #if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
 81         struct spi_cs_control cs_ctrl;
 82 #endif
 83 };

So question, where is *ctx assigned a value? Ah, *ctx is assigned a value in the zephyr/drivers/sensor/iis2dh/iis2dh_i2c.c file. This value is a data structure which entails two C function pointers. Code excerpt here:

 19 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
 20
 21 static uint16_t iis2dh_i2c_slave_addr = DT_INST_REG_ADDR(0);
 22
 23 LOG_MODULE_DECLARE(IIS2DH, CONFIG_SENSOR_LOG_LEVEL);
 24
 25 static int iis2dh_i2c_read(struct iis2dh_data *data, uint8_t reg_addr,
 26                            uint8_t *value, uint16_t len)
 27 {
 28         return i2c_burst_read(data->bus, iis2dh_i2c_slave_addr,
 29                               reg_addr | 0x80, value, len);
 30 }
 31
 32 static int iis2dh_i2c_write(struct iis2dh_data *data, uint8_t reg_addr,
 33                             uint8_t *value, uint16_t len)
 34 {
 35         return i2c_burst_write(data->bus, iis2dh_i2c_slave_addr,
 36                                reg_addr | 0x80, value, len);
 37 }
 38
 39 stmdev_ctx_t iis2dh_i2c_ctx = {
 40         .read_reg = (stmdev_read_ptr) iis2dh_i2c_read,
 41         .write_reg = (stmdev_write_ptr) iis2dh_i2c_write,
 42 };
 43
 44 int iis2dh_i2c_init(const struct device *dev)
 45 {
 46         struct iis2dh_data *data = dev->data;
 47
 48         data->ctx = &iis2dh_i2c_ctx;
 49         data->ctx->handle = data;
 50
 51         return 0;
 52 }
 53 #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */


^ Configuration Post from ST Micro Forum

Excerpt on accelerator configurations from this developer: mhackney (Community Member) Edited by ST Community July 21, 2018 at 5:26 PM Posted on January 02, 2017 at 16:21


Ok, I overlooked the data sheet that Low Power mode is 8-bit data output. But that still does not explain why the data is not left aligned?

Also, here is my complete configuration to sanity check:

// setup CTRL_REG1


accelerometer_write(CTRL_REG1, 0b10011100); // ODR 5.376kHz in LPMode [7-4] Low power enable [3] Z enable [2]

// setup CTRL_REG2


accelerometer_write(CTRL_REG2, 0b00110001); //

// setup CTRL_REG3


accelerometer_write(CTRL_REG3, 0b01000000); // AOI (And Or Interrupt) on INT1 en [6]

// setup CTRL_REG6


accelerometer_write(CTRL_REG6, 0b00000000); //

// setup CTRL_REG4


accelerometer_write(CTRL_REG4, 0b00110000); // Full-scale selection 16G [5-4]

// setup CTRL_REG5


accelerometer_write(CTRL_REG5, 0b01001010); // FIFO enable [6] Latch INT1 [3]

// setup INT1_CFG


accelerometer_write(INT1_CFG, 0b00100000); // ZHIE enabled [5]

// setup INT1_THS


accelerometer_write(INT1_THS, Z_PROBE_SENSITIVITY); // 40

// setup INT1_DURATION


accelerometer_write(INT1_DURATION, 0);