ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
imu_i2c.c
Go to the documentation of this file.
1
4#include "imu_i2c.h"
5
6#define I2C_TIMEOUT_MS 10u
7#define FLAG_DMA_DONE 0x0100u /* bits distinct from the IMU IRQ flag used by the same task */
8#define FLAG_DMA_ERR 0x0200u
9
10#define LOCK_TIMEOUT_MS 5u
11
12static I2C_HandleTypeDef *s_hi2c;
13static uint16_t s_addr8;
14static osThreadId_t s_waiter;
15static osMutexId_t s_lock;
16
17/* ---- bus lock (IMU + expansion devices on the same I2C) ----
18 * Priority inheritance: the ImuTask waits at most for one short expansion
19 * transaction (a few hundred us at 400 kHz). Before the kernel runs, or
20 * before imu_i2c_bus_init, there is no lock and only one user. */
21void imu_i2c_bus_init(I2C_HandleTypeDef *hi2c)
22{
23 static const osMutexAttr_t a = { .name = "i2c1", .attr_bits = osMutexPrioInherit };
24 s_hi2c = hi2c;
25 if (!s_lock) s_lock = osMutexNew(&a);
26}
27
28int imu_i2c_lock(void)
29{
30 if (!s_lock || osKernelGetState() != osKernelRunning) return 0;
31 return osMutexAcquire(s_lock, LOCK_TIMEOUT_MS) == osOK ? 0 : -1;
32}
33
35{
36 if (s_lock && osKernelGetState() == osKernelRunning) (void)osMutexRelease(s_lock);
37}
38
39I2C_HandleTypeDef *imu_i2c_handle(void) { return s_hi2c; }
40
41static int32_t wr(void *h, uint8_t reg, const uint8_t *d, uint16_t len)
42{
43 (void)h;
44 if (imu_i2c_lock()) return -1;
45 const int32_t r = HAL_I2C_Mem_Write(s_hi2c, s_addr8, reg, I2C_MEMADD_SIZE_8BIT,
46 (uint8_t *)d, len, I2C_TIMEOUT_MS) == HAL_OK ? 0 : -1;
48 return r;
49}
50
51static int32_t rd(void *h, uint8_t reg, uint8_t *d, uint16_t len)
52{
53 (void)h;
54 if (imu_i2c_lock()) return -1;
55 const int32_t r = HAL_I2C_Mem_Read(s_hi2c, s_addr8, reg, I2C_MEMADD_SIZE_8BIT,
56 d, len, I2C_TIMEOUT_MS) == HAL_OK ? 0 : -1;
58 return r;
59}
60
61static void dly(uint32_t ms)
62{
63 if (osKernelGetState() == osKernelRunning) osDelay(ms); else HAL_Delay(ms);
64}
65
66void imu_i2c_make_bus(sensor_bus_t *bus, I2C_HandleTypeDef *hi2c, uint8_t addr7)
67{
68 s_hi2c = hi2c;
69 s_addr8 = (uint16_t)(addr7 << 1);
70 bus->write = wr;
71 bus->read = rd;
72 bus->delay_ms = dly;
73 bus->handle = NULL;
74}
75
76int32_t imu_i2c_read_dma(uint8_t reg, uint8_t *buf, uint16_t len, uint32_t timeout_ms)
77{
78 if (imu_i2c_lock()) return -1;
79 s_waiter = osThreadGetId();
80 (void)osThreadFlagsClear(FLAG_DMA_DONE | FLAG_DMA_ERR);
81 if (HAL_I2C_Mem_Read_DMA(s_hi2c, s_addr8, reg, I2C_MEMADD_SIZE_8BIT, buf, len) != HAL_OK) {
83 return -1;
84 }
85 uint32_t f = osThreadFlagsWait(FLAG_DMA_DONE | FLAG_DMA_ERR, osFlagsWaitAny, timeout_ms);
87 if ((int32_t)f < 0 || (f & FLAG_DMA_ERR)) return -1;
88 return 0;
89}
90
91void imu_i2c_rx_cplt_isr(I2C_HandleTypeDef *hi2c)
92{
93 if (hi2c == s_hi2c && s_waiter) (void)osThreadFlagsSet(s_waiter, FLAG_DMA_DONE);
94}
95
96void imu_i2c_error_isr(I2C_HandleTypeDef *hi2c)
97{
98 if (hi2c == s_hi2c && s_waiter) (void)osThreadFlagsSet(s_waiter, FLAG_DMA_ERR);
99}
#define FLAG_DMA_ERR
Definition imu_i2c.c:8
void imu_i2c_make_bus(sensor_bus_t *bus, I2C_HandleTypeDef *hi2c, uint8_t addr7)
Definition imu_i2c.c:66
void imu_i2c_error_isr(I2C_HandleTypeDef *hi2c)
Definition imu_i2c.c:96
void imu_i2c_rx_cplt_isr(I2C_HandleTypeDef *hi2c)
To be called from HAL_I2C_MemRxCpltCallback / HAL_I2C_ErrorCallback.
Definition imu_i2c.c:91
static int32_t wr(void *h, uint8_t reg, const uint8_t *d, uint16_t len)
Definition imu_i2c.c:41
int32_t imu_i2c_read_dma(uint8_t reg, uint8_t *buf, uint16_t len, uint32_t timeout_ms)
Starts the DMA read and blocks the calling task until completion.
Definition imu_i2c.c:76
static I2C_HandleTypeDef * s_hi2c
Definition imu_i2c.c:12
int imu_i2c_lock(void)
0 = taken (or no kernel yet), -1 = timeout
Definition imu_i2c.c:28
static void dly(uint32_t ms)
Definition imu_i2c.c:61
static osMutexId_t s_lock
Definition imu_i2c.c:15
#define FLAG_DMA_DONE
Definition imu_i2c.c:7
static uint16_t s_addr8
Definition imu_i2c.c:13
void imu_i2c_unlock(void)
Definition imu_i2c.c:34
static osThreadId_t s_waiter
Definition imu_i2c.c:14
void imu_i2c_bus_init(I2C_HandleTypeDef *hi2c)
Creates the bus lock: call once before starting the tasks that use the bus.
Definition imu_i2c.c:21
static int32_t rd(void *h, uint8_t reg, uint8_t *d, uint16_t len)
Definition imu_i2c.c:51
#define I2C_TIMEOUT_MS
Definition imu_i2c.c:6
I2C_HandleTypeDef * imu_i2c_handle(void)
Definition imu_i2c.c:39
#define LOCK_TIMEOUT_MS
Definition imu_i2c.c:10
STM32 HAL (STM32WB55) binding of the sensor_bus_t interface + DMA burst read of the FIFO with task no...
uint16_t ms
Definition log_task.c:42
bus_delay_fn delay_ms
optional (used only in init/reset)
Definition sensor_bus.h:22
bus_write_fn write
Definition sensor_bus.h:20
void * handle
opaque context passed to read/write
Definition sensor_bus.h:23
bus_read_fn read
Definition sensor_bus.h:21