1#include "stm32_i2c.hpp"
3#ifdef HAL_I2C_MODULE_ENABLED
7STM32I2C* STM32I2C::map[STM32_I2C_NUMBER] = {
nullptr};
9stm32_i2c_id_t STM32_I2C_GetID(I2C_TypeDef* hi2c)
13 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
16 else if (hi2c == I2C1)
18 return stm32_i2c_id_t::STM32_I2C1;
22 else if (hi2c == I2C2)
24 return stm32_i2c_id_t::STM32_I2C2;
28 else if (hi2c == I2C3)
30 return stm32_i2c_id_t::STM32_I2C3;
34 else if (hi2c == I2C4)
36 return stm32_i2c_id_t::STM32_I2C4;
40 else if (hi2c == I2C5)
42 return stm32_i2c_id_t::STM32_I2C5;
46 else if (hi2c == I2C6)
48 return stm32_i2c_id_t::STM32_I2C6;
52 else if (hi2c == I2C7)
54 return stm32_i2c_id_t::STM32_I2C7;
58 else if (hi2c == I2C8)
60 return stm32_i2c_id_t::STM32_I2C8;
63 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
72static inline uint16_t EncodeHalDevAddress(
const I2C_HandleTypeDef* hi2c,
75 ASSERT(hi2c !=
nullptr);
77#if defined(I2C_ADDRESSINGMODE_10BIT)
78 if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
80 ASSERT(slave_addr <= 0x03FF);
81 return static_cast<uint16_t
>(slave_addr & 0x03FF);
86 ASSERT(slave_addr <= 0x007F);
87 return static_cast<uint16_t
>((slave_addr & 0x007F) << 1);
90static inline ErrorCode MapHalStartFailure(
const I2C_HandleTypeDef* hi2c,
95#ifdef HAL_I2C_ERROR_NONE
96 const uint32_t err = hi2c->ErrorCode;
97#ifdef HAL_I2C_WRONG_START
98 if ((err & (HAL_I2C_ERROR_TIMEOUT | HAL_I2C_WRONG_START)) != 0U)
100 if ((err & HAL_I2C_ERROR_TIMEOUT) != 0U)
103 return ErrorCode::TIMEOUT;
105 if (err != HAL_I2C_ERROR_NONE)
107 return ErrorCode::FAILED;
112 return (st == HAL_BUSY) ? ErrorCode::BUSY : ErrorCode::FAILED;
115static void RecoverAfterBlockTimeout(
STM32I2C* i2c)
117 ASSERT(i2c !=
nullptr);
119 auto* hi2c = i2c->i2c_handle_;
120 i2c->recovering_ =
true;
121 if (hi2c->hdmarx !=
nullptr)
123 (void)HAL_DMA_Abort(hi2c->hdmarx);
125 if (hi2c->hdmatx !=
nullptr)
127 (void)HAL_DMA_Abort(hi2c->hdmatx);
132 (void)HAL_I2C_DeInit(hi2c);
133 (void)HAL_I2C_Init(hi2c);
138 i2c->read_buff_ = {
nullptr, 0};
139 i2c->recovering_ =
false;
142static inline ErrorCode WaitBlockResultAndRecoverTimeout(
STM32I2C* i2c, uint32_t timeout)
144 ASSERT(i2c !=
nullptr);
145 const ErrorCode ans = i2c->block_wait_.Wait(timeout);
146 if (ans == ErrorCode::TIMEOUT)
148 RecoverAfterBlockTimeout(i2c);
156 uint32_t dma_enable_min_size)
158 id_(STM32_I2C_GetID(hi2c->Instance)),
160 dma_enable_min_size_(dma_enable_min_size),
169 if (i2c_handle_->State != HAL_I2C_STATE_READY)
176 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
178 if (read_data.
size_ > dma_enable_min_size_)
181 read_buff_ = read_data;
182 if (op.
type == ReadOperation::OperationType::BLOCK)
185 block_wait_.Start(*op.
data.sem_info.sem);
187 const HAL_StatusTypeDef st = HAL_I2C_Master_Receive_DMA(
188 i2c_handle_, dev_addr,
reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
192 if (op.
type == ReadOperation::OperationType::BLOCK)
194 block_wait_.Cancel();
195 return MapHalStartFailure(i2c_handle_, st);
200 if (op.
type == ReadOperation::OperationType::BLOCK)
202 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.timeout);
208 auto ans = HAL_I2C_Master_Receive(i2c_handle_, dev_addr,
209 reinterpret_cast<uint8_t*
>(read_data.
addr_),
210 read_data.
size_, 20) == HAL_OK
215 if (op.
type != ReadOperation::OperationType::BLOCK)
226 if (i2c_handle_->State != HAL_I2C_STATE_READY)
233 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
237 if (write_data.
size_ > dma_enable_min_size_)
240 if (op.
type == WriteOperation::OperationType::BLOCK)
243 block_wait_.Start(*op.
data.sem_info.sem);
245#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
246 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t*
>(dma_buff_.
addr_),
249 const HAL_StatusTypeDef st = HAL_I2C_Master_Transmit_DMA(
250 i2c_handle_, dev_addr,
reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
254 if (op.
type == WriteOperation::OperationType::BLOCK)
256 block_wait_.Cancel();
257 return MapHalStartFailure(i2c_handle_, st);
262 if (op.
type == WriteOperation::OperationType::BLOCK)
264 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.timeout);
270 auto ans = HAL_I2C_Master_Transmit(i2c_handle_, dev_addr,
271 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
272 write_data.
size_, 20) == HAL_OK
275 if (op.
type != WriteOperation::OperationType::BLOCK)
288 if (i2c_handle_->State != HAL_I2C_STATE_READY)
295 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
297 if (read_data.
size_ > dma_enable_min_size_)
300 read_buff_ = read_data;
301 if (op.
type == ReadOperation::OperationType::BLOCK)
304 block_wait_.Start(*op.
data.sem_info.sem);
306 const HAL_StatusTypeDef st = HAL_I2C_Mem_Read_DMA(
307 i2c_handle_, dev_addr, mem_addr,
308 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
309 : I2C_MEMADD_SIZE_16BIT,
310 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), read_data.
size_);
313 if (op.
type == ReadOperation::OperationType::BLOCK)
315 block_wait_.Cancel();
316 return MapHalStartFailure(i2c_handle_, st);
321 if (op.
type == ReadOperation::OperationType::BLOCK)
323 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.timeout);
330 HAL_I2C_Mem_Read(i2c_handle_, dev_addr, mem_addr,
331 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
332 : I2C_MEMADD_SIZE_16BIT,
333 reinterpret_cast<uint8_t*
>(read_data.
addr_), read_data.
size_,
338 if (op.
type != ReadOperation::OperationType::BLOCK)
348 MemAddrLength mem_addr_size,
bool in_isr)
352 if (i2c_handle_->State != HAL_I2C_STATE_READY)
359 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
363 if (write_data.
size_ > dma_enable_min_size_)
366 if (op.
type == WriteOperation::OperationType::BLOCK)
369 block_wait_.Start(*op.
data.sem_info.sem);
371#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
372 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t*
>(dma_buff_.
addr_),
375 const HAL_StatusTypeDef st = HAL_I2C_Mem_Write_DMA(
376 i2c_handle_, dev_addr, mem_addr,
377 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
378 : I2C_MEMADD_SIZE_16BIT,
379 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), write_data.
size_);
382 if (op.
type == WriteOperation::OperationType::BLOCK)
384 block_wait_.Cancel();
385 return MapHalStartFailure(i2c_handle_, st);
390 if (op.
type == WriteOperation::OperationType::BLOCK)
392 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.timeout);
399 HAL_I2C_Mem_Write(i2c_handle_, dev_addr, mem_addr,
400 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
401 : I2C_MEMADD_SIZE_16BIT,
402 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), write_data.
size_,
407 if (op.
type != WriteOperation::OperationType::BLOCK)
419 SetClockSpeed<decltype(i2c_handle_)>(i2c_handle_, config);
426 if (HAL_I2C_Init(i2c_handle_) != HAL_OK)
433extern "C" void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef* hi2c)
435 STM32I2C* i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
436 if (i2c && !i2c->recovering_ &&
437 (i2c->read_op_.
type != ReadOperation::OperationType::NONE))
440#ifdef HAL_I2C_ERROR_NONE
443#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
444 SCB_InvalidateDCache_by_Addr(i2c->dma_buff_.
addr_, i2c->read_buff_.
size_);
449 i2c->read_buff_.
size_);
451 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
453 (void)i2c->block_wait_.TryPost(
true, ec);
462extern "C" void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef* hi2c)
464 STM32I2C* i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
465 if (i2c && !i2c->recovering_ &&
466 (i2c->write_op_.
type != WriteOperation::OperationType::NONE))
469#ifdef HAL_I2C_ERROR_NONE
472 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
474 (void)i2c->block_wait_.TryPost(
true, ec);
483extern "C" void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef* hi2c)
485 STM32I2C* i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
486 if (i2c && !i2c->recovering_ &&
487 (i2c->write_op_.
type != WriteOperation::OperationType::NONE))
490#ifdef HAL_I2C_ERROR_NONE
493 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
495 (void)i2c->block_wait_.TryPost(
true, ec);
504extern "C" void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef* hi2c)
506 STM32I2C* i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
507 if (i2c && !i2c->recovering_ &&
508 (i2c->read_op_.
type != ReadOperation::OperationType::NONE))
511#ifdef HAL_I2C_ERROR_NONE
514#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
515 SCB_InvalidateDCache_by_Addr(i2c->dma_buff_.
addr_, i2c->read_buff_.
size_);
520 i2c->read_buff_.
size_);
522 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
524 (void)i2c->block_wait_.TryPost(
true, ec);
533extern "C" void HAL_I2C_ErrorCallback(I2C_HandleTypeDef* hi2c)
535 STM32I2C* i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
537 if (i2c && !i2c->recovering_)
541 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
552 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
STM32 I2C 驱动实现 / STM32 I2C driver implementation.
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size, bool in_isr) override
从 I2C 设备指定寄存器读取数据。 Reads data from a specific register of an I2C device.
ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data, WriteOperation &op, MemAddrLength mem_addr_size, bool in_isr) override
向 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr) override
向 I2C 设备写入数据。 Writes data to an I2C device.
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr) override
读取 I2C 设备的数据。 Reads data from an I2C device.
STM32I2C(I2C_HandleTypeDef *hi2c, RawData dma_buff, uint32_t dma_enable_min_size=3)
构造 I2C 对象 / Construct I2C object
@ INIT_ERR
初始化错误 | Initialization error
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.