|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
ST LSM6DSO 6-DoF IMU driver (accel + gyro + temperature). More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_lsm6dso_xyz_t |
| 3-axis raw sample (X, Y, Z as 16-bit two's-complement counts). More... | |
| struct | ra8_lsm6dso_bus_t |
| Transport interface bound at ra8_lsm6dso_init time. More... | |
| struct | ra8_lsm6dso_t |
| Per-instance driver state. More... | |
Typedefs | |
| typedef ra8_err_t(* | ra8_lsm6dso_read_fn_t) (void *ctx, uint8_t reg, uint8_t *buf, uint32_t len) |
| Read len bytes from reg on the target. | |
| typedef ra8_err_t(* | ra8_lsm6dso_write_fn_t) (void *ctx, uint8_t reg, const uint8_t *buf, uint32_t len) |
| Write len bytes starting at reg on the target. | |
Functions | |
| ra8_err_t | ra8_lsm6dso_init (ra8_lsm6dso_t *out_dev, const ra8_lsm6dso_bus_t *bus) |
| Bind a transport to a driver instance. | |
| ra8_err_t | ra8_lsm6dso_who_am_i (ra8_lsm6dso_t *dev, uint8_t *out_id) |
| Read the WHO_AM_I register. | |
| ra8_err_t | ra8_lsm6dso_set_accel_range (ra8_lsm6dso_t *dev, ra8_lsm6dso_xl_fs_t fs) |
| Program the accelerometer full-scale range. | |
| ra8_err_t | ra8_lsm6dso_set_gyro_range (ra8_lsm6dso_t *dev, ra8_lsm6dso_g_fs_t fs) |
| Program the gyroscope full-scale range. | |
| ra8_err_t | ra8_lsm6dso_set_odr (ra8_lsm6dso_t *dev, ra8_lsm6dso_odr_t odr) |
| Program the Output Data Rate for both the accelerometer and the gyroscope. | |
| ra8_err_t | ra8_lsm6dso_read_accel (ra8_lsm6dso_t *dev, ra8_lsm6dso_xyz_t *out) |
| Read one accelerometer sample (raw 16-bit two's-complement). | |
| ra8_err_t | ra8_lsm6dso_read_gyro (ra8_lsm6dso_t *dev, ra8_lsm6dso_xyz_t *out) |
| Read one gyroscope sample (raw 16-bit two's-complement). | |
| ra8_err_t | ra8_lsm6dso_read_temp (ra8_lsm6dso_t *dev, int32_t *out_centi_c) |
| Read the on-die temperature in centi-degrees Celsius. | |
| ra8_err_t | ra8_lsm6dso_read_xl_gyro_fifo (ra8_lsm6dso_t *dev, uint8_t *out_buf, uint32_t max_words, uint32_t *out_words) |
| Drain up to max_samples paired XL+G samples from the embedded FIFO. | |
ST LSM6DSO 6-DoF IMU driver (accel + gyro + temperature).
Public API for a polling, transport-agnostic driver for the STMicroelectronics LSM6DSO 3-axis accelerometer + 3-axis gyroscope. The part is carried by the MikroE 6DOF IMU 12 Click (Digikey 1471-MIKROE-4073-ND); the same silicon ships on several other MEMS-sensor break-out boards as well. All register-level citations point at "LSM6DSO datasheet (ST DS12140 Rev 4)".
Transport abstraction (Dependency Inversion, see CLAUDE.md "SOLID Principles for C"):
Surface (mirrors the deliverables list in the task brief):
The driver carries no global state outside the caller's ra8_lsm6dso_t – multiple LSM6DSO parts on different buses can coexist with one descriptor each.
Definition in file ra8_lsm6dso.h.
| typedef ra8_err_t(* ra8_lsm6dso_read_fn_t) (void *ctx, uint8_t reg, uint8_t *buf, uint32_t len) |
Read len bytes from reg on the target.
Implementations must honor the LSM6DSO auto-increment behaviour (DS12140 sec 6.1.2 "I2C Operation") so that a multi-byte read starting at register N returns bytes from N, N+1, ... – the production I2C and SPI HAL paths do this naturally.
| [in] | ctx | Transport context (e.g. ra8_lsm6dso_i2c_ctx_t or ra8_lsm6dso_spi_ctx_t cast to void*). |
| [in] | reg | First register address. |
| [out] | buf | Destination buffer (non-NULL when len > 0). |
| [in] | len | Byte count. |
| k_ra8_ok | Transfer succeeded. |
| k_ra8_err_nack | Target NACKed (I2C) or returned a hard error (SPI). |
| k_ra8_err_null_ptr | buf is NULL with non-zero len. |
Definition at line 238 of file ra8_lsm6dso.h.
| typedef ra8_err_t(* ra8_lsm6dso_write_fn_t) (void *ctx, uint8_t reg, const uint8_t *buf, uint32_t len) |
Write len bytes starting at reg on the target.
| [in] | ctx | Transport context. |
| [in] | reg | First register address. |
| [in] | buf | Source buffer (non-NULL when len > 0). |
| [in] | len | Byte count. |
Definition at line 251 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_const_t : uint8_t |
Part-level identification + sizing constants.
Per LSM6DSO DS12140 Rev 4 sec 9.11 "WHO_AM_I (0Fh)": the read-only device-identification register returns 0x6C (binary 0b01101100) on a healthy part. Any other value indicates a wrong part, a wired-up wrong address, or a dead bus.
Definition at line 78 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_g_fs_t : uint8_t |
Gyroscope full-scale (FS_G) range codes.
Per DS12140 sec 9.13 "CTRL2_G (11h)" Table 47 "Gyroscope full-scale selection": FS_G[1:0] occupies CTRL2_G bits [3:2], with the FS_125 bit at bit [1] selecting the +-125 dps narrow scale. The driver folds both fields into a single enum.
Sensitivity (mdps/LSB) per FS_G = 4.375 / 8.75 / 17.5 / 35 / 70 for +-125, +-250, +-500, +-1000, +-2000 dps respectively (DS12140 Table 3).
Definition at line 162 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_i2c_addr_t : uint8_t |
Default 7-bit I2C target addresses.
Per DS12140 sec 6.1.1 "I2C operation": the LSM6DSO 7-bit peripheral address is 1101 010x where x is the inverted SDO/SA0 pin level. SDO/SA0 = 0 selects 0x6A; SDO/SA0 = 1 selects 0x6B. The MikroE 6DOF IMU 12 Click ties SA0 high by default (per MikroE schematic rev v100), so the default board address is 0x6B.
| Enumerator | |
|---|---|
| k_lsm6dso_i2c_addr_sa0_low | SDO/SA0 tied low. |
| k_lsm6dso_i2c_addr_sa0_high | SDO/SA0 tied high. |
Definition at line 96 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_odr_t : uint8_t |
Output Data Rate codes (shared between XL and G).
Per DS12140 sec 9.12 "CTRL1_XL (10h)" Table 45 (ODR_XL) and sec 9.13 "CTRL2_G (11h)" Table 48 (ODR_G): the four-bit ODR field occupies bits [7:4] of CTRL1_XL and CTRL2_G respectively. The codes are identical for both peripherals; ra8_lsm6dso_set_odr writes the chosen code into the high nibble of both CTRL1_XL and CTRL2_G.
Definition at line 181 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_reg_t : uint8_t |
Register-map addresses used by this driver.
Subset of the full LSM6DSO register map (DS12140 sec 9 "Register description"). Only registers actually accessed by the driver appear here – adding embedded-functions or pedometer registers is a future extension.
Definition at line 111 of file ra8_lsm6dso.h.
| enum ra8_lsm6dso_xl_fs_t : uint8_t |
Accelerometer full-scale (FS_XL) range codes.
Per DS12140 sec 9.12 "CTRL1_XL (10h)" Table 44 "Accelerometer full-scale selection": FS_XL[1:0] occupies CTRL1_XL bits [3:2]. The numeric values below are the raw bit-field codes for FS_XL.
Sensitivity (LSB/g) per FS_XL = 0.061 / 0.122 / 0.244 / 0.488 mg/LSB for +-2, +-4, +-8, +-16 g respectively (DS12140 Table 3).
Definition at line 141 of file ra8_lsm6dso.h.
|
nodiscard |
Bind a transport to a driver instance.
Copies the supplied bus interface into out_dev and marks the instance initialised. Does not touch the wire – the caller is expected to follow this with ra8_lsm6dso_who_am_i (sanity check) and then ra8_lsm6dso_set_* calls to configure the part.
| [out] | out_dev | Driver state, populated on success. |
| [in] | bus | Transport interface (must have non-NULL read_regs and write_regs). |
| k_ra8_ok | Driver state initialized. |
| k_ra8_err_null_ptr | out_dev or bus is NULL, or one of the callbacks in bus is NULL. |
Definition at line 256 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::accel_fs_code, ra8_lsm6dso_t::bus, ra8_lsm6dso_t::gyro_fs_code, ra8_lsm6dso_t::initialized, k_lsm6dso_g_fs_250dps, k_lsm6dso_odr_off, k_lsm6dso_xl_fs_2g, k_ra8_ok, ra8_lsm6dso_t::odr_code, RA8_CHECK_NULL_PTR, ra8_lsm6dso_bus_t::read_regs, s_lsm6dso_tag, and ra8_lsm6dso_bus_t::write_regs.
Referenced by main().
|
nodiscard |
Read one accelerometer sample (raw 16-bit two's-complement).
Burst-reads 6 bytes starting at OUTX_L_A (0x28) into a 3x16 sample (DS12140 sec 9.35 .. 9.40). The LSM6DSO is little-endian so the bytes are combined as (high << 8) | low.
| [in] | dev | Driver instance. |
| [out] | out | 3-axis raw sample. |
| k_ra8_ok | Sample read. |
| k_ra8_err_null_ptr | dev or out is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 422 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::initialized, internal_lsm6dso_read_xyz(), k_lsm6dso_reg_outx_l_a, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_sample_and_emit().
|
nodiscard |
Read one gyroscope sample (raw 16-bit two's-complement).
Burst-reads 6 bytes starting at OUTX_L_G (0x22) into a 3x16 sample (DS12140 sec 9.29 .. 9.34). The LSM6DSO is little-endian so the bytes are combined as (high << 8) | low.
| [in] | dev | Driver instance. |
| [out] | out | 3-axis raw sample. |
| k_ra8_ok | Sample read. |
| k_ra8_err_null_ptr | dev or out is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 431 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::initialized, internal_lsm6dso_read_xyz(), k_lsm6dso_reg_outx_l_g, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_sample_and_emit().
|
nodiscard |
Read the on-die temperature in centi-degrees Celsius.
Reads the 16-bit two's-complement OUT_TEMP register pair (0x20..0x21, DS12140 sec 9.27 / 9.28) and converts to centi-degrees Celsius using the datasheet formula T[C] = (raw / 256) + 25. Multiplied by 100 to stay in integer arithmetic the formula becomes out_centi_c = (raw * 100) / 256 + 2500, which is what the driver implements.
| [in] | dev | Driver instance. |
| [out] | out_centi_c | Receives the temperature in centi-deg C. |
| k_ra8_ok | Temperature read. |
| k_ra8_err_null_ptr | dev or out_centi_c is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 440 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::bus, ra8_lsm6dso_bus_t::ctx, ra8_lsm6dso_t::initialized, k_lsm6dso_idx_high, k_lsm6dso_idx_low, k_lsm6dso_reg_out_temp_l, k_lsm6dso_temp_burst_bytes, k_lsm6dso_temp_offset_centi_c, k_lsm6dso_temp_scale_den, k_lsm6dso_temp_scale_num, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, ra8_lsm6dso_bus_t::read_regs, and s_lsm6dso_tag.
Referenced by imu_demo_sample_and_emit().
|
nodiscard |
Drain up to max_samples paired XL+G samples from the embedded FIFO.
Polls FIFO_STATUS1/2 (DS12140 sec 9.44 / 9.45) for the live sample count, then issues a burst read of FIFO_DATA_OUT_TAG (0x78, DS12140 sec 9.60 .. 9.66) for each available 7-byte FIFO word. The tag byte identifies the source (XL vs G) per Table 167 "Tag codes"; this helper returns whatever the FIFO happens to hold and lets the caller demux.
| [in] | dev | Driver instance. |
| [out] | out_buf | Destination buffer; receives raw FIFO words laid out as [tag][b0 b1 b2 b3 b4 b5] repeated. |
| [in] | max_words | Maximum FIFO words the caller can store (capacity of out_buf in bytes is max_words * k_lsm6dso_fifo_bytes_word). |
| [out] | out_words | Number of FIFO words actually read into out_buf. |
| k_ra8_ok | FIFO drained (possibly to zero words). |
| k_ra8_err_null_ptr | Any of the pointers is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_invalid_arg | max_words == 0. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 590 of file ra8_lsm6dso.c.
References internal_lsm6dso_burst_fifo(), internal_lsm6dso_fifo_check_args(), internal_lsm6dso_read_fifo_depth(), and k_ra8_ok.
|
nodiscard |
Program the accelerometer full-scale range.
Read-modify-writes the FS_XL field in CTRL1_XL (DS12140 sec 9.12). The ODR_XL nibble is preserved by reading the current value first.
| [in,out] | dev | Driver instance. |
| [in] | fs | Range code (one of k_lsm6dso_xl_fs_*). |
| k_ra8_ok | Range programmed. |
| k_ra8_err_null_ptr | dev is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_invalid_arg | fs out of range. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 291 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::accel_fs_code, ra8_lsm6dso_t::initialized, internal_lsm6dso_read_byte(), internal_lsm6dso_write_byte(), k_lsm6dso_mask_fs_xl, k_lsm6dso_reg_ctrl1_xl, k_lsm6dso_shift_fs_xl, k_lsm6dso_xl_fs_cap, k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_CHECK_RANGE_TAG, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_configure().
|
nodiscard |
Program the gyroscope full-scale range.
Read-modify-writes the FS_G[1:0] and FS_125 fields in CTRL2_G (DS12140 sec 9.13). The ODR_G nibble is preserved by reading the current value first.
| [in,out] | dev | Driver instance. |
| [in] | fs | Range code (one of k_lsm6dso_g_fs_*). |
| k_ra8_ok | Range programmed. |
| k_ra8_err_null_ptr | dev is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_invalid_arg | fs out of range. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 318 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::gyro_fs_code, ra8_lsm6dso_t::initialized, internal_lsm6dso_g_fs_bits(), internal_lsm6dso_read_byte(), internal_lsm6dso_write_byte(), k_lsm6dso_g_fs_cap, k_lsm6dso_mask_fs_g_full, k_lsm6dso_reg_ctrl2_g, k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_CHECK_RANGE_TAG, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_configure().
|
nodiscard |
Program the Output Data Rate for both the accelerometer and the gyroscope.
Writes odr into the ODR_XL field of CTRL1_XL and the ODR_G field of CTRL2_G. The full-scale nibble of each register is preserved by reading the current value first. The two blocks share an ODR scale (DS12140 sec 5.3 "Output data rate and bandwidth selection") so one parameter covers both.
| [in,out] | dev | Driver instance. |
| [in] | odr | ODR code (one of k_lsm6dso_odr_*). |
| k_ra8_ok | ODR programmed for XL and G. |
| k_ra8_err_null_ptr | dev is NULL. |
| k_ra8_err_invalid_state | dev not initialized. |
| k_ra8_err_invalid_arg | odr out of range. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 344 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::initialized, internal_lsm6dso_rmw_odr(), k_lsm6dso_mask_nibble, k_lsm6dso_odr_cap, k_lsm6dso_reg_ctrl1_xl, k_lsm6dso_reg_ctrl2_g, k_lsm6dso_shift_odr, k_ra8_err_invalid_arg, k_ra8_ok, ra8_lsm6dso_t::odr_code, RA8_CHECK_NULL_PTR, RA8_CHECK_RANGE_TAG, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_configure().
|
nodiscard |
Read the WHO_AM_I register.
Reads register 0x0F and returns the raw byte. On a healthy LSM6DSO this is 0x6C (k_lsm6dso_who_am_i_value); any other value means the wrong part is wired or the bus is mis-addressed.
| [in] | dev | Driver instance. |
| [out] | out_id | Receives the WHO_AM_I byte. |
| k_ra8_ok | *out_id populated. |
| k_ra8_err_null_ptr | dev or out_id is NULL. |
| k_ra8_err_invalid_state | dev has not been initialized. |
| k_ra8_err_nack | Transport reported a NACK. |
Definition at line 276 of file ra8_lsm6dso.c.
References ra8_lsm6dso_t::initialized, internal_lsm6dso_read_byte(), k_lsm6dso_reg_who_am_i, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, and s_lsm6dso_tag.
Referenced by imu_demo_check_who_am_i().