Попытка реализовать очередь в чтении IMU. Неудача - HardFault

This commit is contained in:
2026-04-09 12:50:11 +03:00
parent 3b0bf415a9
commit 9948fc6497
2 changed files with 121 additions and 52 deletions

View File

@@ -24,11 +24,11 @@
#define ACCEL_FCHOICE_ON 1
#define ACCEL_FCHOICE_OFF 0
static volatile uint8_t i2c_busy = 0;
/*static volatile uint8_t i2c_busy = 0;
static uint8_t i2c_buf[16];
static uint8_t i2c_len = 0;
static uint8_t i2c_reg = 0;
static uint8_t i2c_addr = 0;
static uint8_t i2c_addr = 0;*/
typedef struct
{
@@ -36,7 +36,22 @@ typedef struct
int16_t gx, gy, gz; // lsb
} imu_raw_t;
static void (*i2c_callback)(uint8_t* buf) = 0;
typedef struct I2C_Request
{
uint8_t addr;
uint8_t reg;
uint8_t *buf;
uint8_t len;
void (*callback)(uint8_t*);
struct I2C_Request* next;
} I2C_Request;
static I2C_Request* i2c_head = 0;
static uint8_t i2c_busy = 0;
//static void (*i2c_callback)(uint8_t* buf) = 0;
void imu_pow_init();
@@ -50,7 +65,9 @@ void imu_tim6_init(const uint16_t freq);
void i2c_read(uint8_t addr, uint8_t reg, uint8_t* buf, uint8_t len);
uint8_t i2c_read_async(uint8_t addr, uint8_t reg, uint8_t len, void (*cb)(uint8_t*));
void i2c_enqueue(I2C_Request* req);
void i2c_start_next();
void i2c_read_async(uint8_t addr, uint8_t reg, uint8_t len, void (*cb)(uint8_t*));
void i2c_write(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -1,5 +1,9 @@
#include "imu.h"
static I2C_Request* current_req = 0;
static uint8_t i2c_buf[16];
static uint8_t i2c_index = 0;
void imu_pow_init()
{
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;
@@ -42,6 +46,13 @@ void i2c1_init()
I2C1->TIMINGR = 0x10802D9BUL; // 400 kHz @ 16 MHz
I2C1->CR1 |= I2C_CR1_PE;
I2C1->CR1 |= I2C_CR1_TXIE |
I2C_CR1_RXIE |
I2C_CR1_TCIE |
I2C_CR1_STOPIE;
NVIC_EnableIRQ(I2C1_EV_IRQn);
}
void imu_init()
@@ -103,25 +114,66 @@ void i2c_read(uint8_t addr, uint8_t reg, uint8_t* buf, uint8_t len)
I2C1->ICR |= I2C_ICR_STOPCF;
}
uint8_t i2c_read_async(uint8_t addr, uint8_t reg, uint8_t len, void (*cb)(uint8_t*))
void i2c_enqueue(I2C_Request* req)
{
if (i2c_busy) return 0;
req->next = 0;
i2c_busy = 1;
__disable_irq();
i2c_addr = addr;
i2c_reg = reg;
i2c_len = len;
i2c_callback = cb;
// включаем прерывания
I2C1->CR1 |= I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE;
NVIC_EnableIRQ(I2C1_EV_IRQn);
if (!i2c_head)
{
i2c_head = req;
}
else
{
I2C_Request* cur = i2c_head;
while (cur->next) cur = cur->next;
cur->next = req;
}
// старт записи регистра
I2C1->CR2 = (addr << 1) | (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START;
__enable_irq();
return 1;
// если I2C свободен — стартуем
if (!i2c_busy)
{
NVIC_SetPendingIRQ(I2C1_EV_IRQn);
}
}
void i2c_start_next()
{
if (!i2c_head)
{
i2c_busy = 0;
return;
}
i2c_busy = 1;
current_req = i2c_head;
i2c_head = i2c_head->next;
i2c_index = 0;
// сначала пишем регистр
I2C1->CR2 = (current_req->addr << 1) |
(1 << I2C_CR2_NBYTES_Pos) |
I2C_CR2_START;
}
void i2c_read_async(uint8_t addr, uint8_t reg, uint8_t len, void (*cb)(uint8_t*))
{
static I2C_Request req;
static uint8_t buf[16];
req.addr = addr;
req.reg = reg;
req.buf = buf;
req.len = len;
req.callback = cb;
i2c_enqueue(&req);
}
void i2c_write(uint8_t addr, uint8_t reg, uint8_t data)
@@ -143,47 +195,47 @@ void i2c_write(uint8_t addr, uint8_t reg, uint8_t data)
void I2C1_EV_IRQHandler()
{
static uint8_t index = 0;
static uint8_t stage = 0; // 0 = send reg, 1 = read
uint32_t isr = I2C1->ISR;
// TX — отправляем регистр
if (I2C1->ISR & I2C_ISR_TXIS)
{
I2C1->TXDR = i2c_reg;
}
// --- TXIS ---
if (isr & I2C_ISR_TXIS)
{
I2C1->TXDR = current_req->reg;
}
// переход к чтению
if (I2C1->ISR & I2C_ISR_TC)
{
I2C1->CR2 = (i2c_addr << 1) |
I2C_CR2_RD_WRN |
(i2c_len << I2C_CR2_NBYTES_Pos) |
I2C_CR2_AUTOEND |
I2C_CR2_START;
// --- TC ---
else if (isr & I2C_ISR_TC)
{
// запускаем чтение
I2C1->CR2 = (current_req->addr << 1) |
I2C_CR2_RD_WRN |
(current_req->len << I2C_CR2_NBYTES_Pos) |
I2C_CR2_AUTOEND |
I2C_CR2_START;
}
index = 0;
stage = 1;
}
// --- RXNE ---
else if (isr & I2C_ISR_RXNE)
{
i2c_buf[i2c_index++] = I2C1->RXDR;
}
// чтение данных
if (I2C1->ISR & I2C_ISR_RXNE)
{
i2c_buf[index++] = I2C1->RXDR;
}
// --- STOP ---
else if (isr & I2C_ISR_STOPF)
{
I2C1->ICR |= I2C_ICR_STOPCF;
// завершение
if (I2C1->ISR & I2C_ISR_STOPF)
{
I2C1->ICR |= I2C_ICR_STOPCF;
// копируем данные
for (uint8_t i = 0; i < current_req->len; i++)
current_req->buf[i] = i2c_buf[i];
i2c_busy = 0;
// отключаем IRQ
I2C1->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE);
// callback
if (current_req->callback)
current_req->callback(current_req->buf);
if (i2c_callback)
i2c_callback(i2c_buf);
}
// следующий запрос
i2c_start_next();
}
}
void imu_read_raw(imu_raw_t* data)