1#include "stm32_i2c.hpp"
3#include "stm32_dcache.hpp"
4#include "stm32_i2c_timing.hpp"
6#include "stm32f7xx_ll_rcc.h"
9#include "stm32h7xx_ll_rcc.h"
11#ifdef HAL_I2C_MODULE_ENABLED
15STM32I2C* STM32I2C::map[STM32_I2C_NUMBER] = {
nullptr};
17stm32_i2c_id_t STM32_I2C_GetID(I2C_TypeDef* hi2c)
21 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
24 else if (hi2c == I2C1)
26 return stm32_i2c_id_t::STM32_I2C1;
30 else if (hi2c == I2C2)
32 return stm32_i2c_id_t::STM32_I2C2;
36 else if (hi2c == I2C3)
38 return stm32_i2c_id_t::STM32_I2C3;
42 else if (hi2c == I2C4)
44 return stm32_i2c_id_t::STM32_I2C4;
48 else if (hi2c == I2C5)
50 return stm32_i2c_id_t::STM32_I2C5;
54 else if (hi2c == I2C6)
56 return stm32_i2c_id_t::STM32_I2C6;
60 else if (hi2c == I2C7)
62 return stm32_i2c_id_t::STM32_I2C7;
66 else if (hi2c == I2C8)
68 return stm32_i2c_id_t::STM32_I2C8;
71 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
80static inline uint16_t EncodeHalDevAddress(
const I2C_HandleTypeDef* hi2c,
83 DEV_ASSERT(hi2c !=
nullptr);
85#if defined(I2C_ADDRESSINGMODE_10BIT)
86 if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
88 ASSERT(slave_addr <= 0x03FF);
89 return static_cast<uint16_t
>(slave_addr & 0x03FF);
94 ASSERT(slave_addr <= 0x007F);
95 return static_cast<uint16_t
>((slave_addr & 0x007F) << 1);
98static inline ErrorCode MapHalStartFailure(
const I2C_HandleTypeDef* hi2c,
103#ifdef HAL_I2C_ERROR_NONE
104 const uint32_t err = hi2c->ErrorCode;
105#ifdef HAL_I2C_WRONG_START
106 if ((err & (HAL_I2C_ERROR_TIMEOUT | HAL_I2C_WRONG_START)) != 0U)
108 if ((err & HAL_I2C_ERROR_TIMEOUT) != 0U)
111 return ErrorCode::TIMEOUT;
113 if (err != HAL_I2C_ERROR_NONE)
115 return ErrorCode::FAILED;
120 return (st == HAL_BUSY) ? ErrorCode::BUSY : ErrorCode::FAILED;
125 bool analog_filter{
false};
126 uint32_t digital_filter{0U};
129static I2CFilterState CaptureI2CFilterState(
const I2C_HandleTypeDef* handle);
130static void RestoreI2CFilterState(I2C_HandleTypeDef* handle, I2CFilterState state);
131static bool ResetI2CPeripheral(I2C_TypeDef* instance);
133static void RecoverAfterBlockTimeout(
STM32I2C* i2c)
135 DEV_ASSERT(i2c !=
nullptr);
137 auto* hi2c = i2c->i2c_handle_;
138 const I2CFilterState filter_state = CaptureI2CFilterState(hi2c);
139 i2c->recovering_ =
true;
140 if (hi2c->hdmarx !=
nullptr)
142 (void)HAL_DMA_Abort(hi2c->hdmarx);
144 if (hi2c->hdmatx !=
nullptr)
146 (void)HAL_DMA_Abort(hi2c->hdmatx);
152 bool initialized =
false;
153 if (ResetI2CPeripheral(hi2c->Instance))
155 initialized = HAL_I2C_Init(hi2c) == HAL_OK;
159 (void)HAL_I2C_DeInit(hi2c);
160 initialized = HAL_I2C_Init(hi2c) == HAL_OK;
164 RestoreI2CFilterState(hi2c, filter_state);
170 i2c->read_buff_ = {
nullptr, 0};
171 i2c->recovering_ =
false;
174static inline ErrorCode WaitBlockResultAndRecoverTimeout(
STM32I2C* i2c, uint32_t timeout)
176 DEV_ASSERT(i2c !=
nullptr);
178 if (ans == ErrorCode::TIMEOUT)
180 RecoverAfterBlockTimeout(i2c);
185static bool ResetI2CPeripheral(I2C_TypeDef* instance)
187#if defined(I2C1) && defined(__HAL_RCC_I2C1_FORCE_RESET) && \
188 defined(__HAL_RCC_I2C1_RELEASE_RESET)
189 if (instance == I2C1)
191 __HAL_RCC_I2C1_FORCE_RESET();
193 __HAL_RCC_I2C1_RELEASE_RESET();
198#if defined(I2C2) && defined(__HAL_RCC_I2C2_FORCE_RESET) && \
199 defined(__HAL_RCC_I2C2_RELEASE_RESET)
200 if (instance == I2C2)
202 __HAL_RCC_I2C2_FORCE_RESET();
204 __HAL_RCC_I2C2_RELEASE_RESET();
209#if defined(I2C3) && defined(__HAL_RCC_I2C3_FORCE_RESET) && \
210 defined(__HAL_RCC_I2C3_RELEASE_RESET)
211 if (instance == I2C3)
213 __HAL_RCC_I2C3_FORCE_RESET();
215 __HAL_RCC_I2C3_RELEASE_RESET();
220#if defined(I2C4) && defined(__HAL_RCC_I2C4_FORCE_RESET) && \
221 defined(__HAL_RCC_I2C4_RELEASE_RESET)
222 if (instance == I2C4)
224 __HAL_RCC_I2C4_FORCE_RESET();
226 __HAL_RCC_I2C4_RELEASE_RESET();
231#if defined(I2C5) && defined(__HAL_RCC_I2C5_FORCE_RESET) && \
232 defined(__HAL_RCC_I2C5_RELEASE_RESET)
233 if (instance == I2C5)
235 __HAL_RCC_I2C5_FORCE_RESET();
237 __HAL_RCC_I2C5_RELEASE_RESET();
242#if defined(I2C6) && defined(__HAL_RCC_I2C6_FORCE_RESET) && \
243 defined(__HAL_RCC_I2C6_RELEASE_RESET)
244 if (instance == I2C6)
246 __HAL_RCC_I2C6_FORCE_RESET();
248 __HAL_RCC_I2C6_RELEASE_RESET();
253#if defined(I2C7) && defined(__HAL_RCC_I2C7_FORCE_RESET) && \
254 defined(__HAL_RCC_I2C7_RELEASE_RESET)
255 if (instance == I2C7)
257 __HAL_RCC_I2C7_FORCE_RESET();
259 __HAL_RCC_I2C7_RELEASE_RESET();
264#if defined(I2C8) && defined(__HAL_RCC_I2C8_FORCE_RESET) && \
265 defined(__HAL_RCC_I2C8_RELEASE_RESET)
266 if (instance == I2C8)
268 __HAL_RCC_I2C8_FORCE_RESET();
270 __HAL_RCC_I2C8_RELEASE_RESET();
279#if defined(STM32H7) && defined(HAL_RCC_MODULE_ENABLED)
280static uint32_t GetH7HSIClock()
282#if defined(RCC_CR_HSIRDY)
283 if ((RCC->CR & RCC_CR_HSIRDY) == 0U)
288#if defined(__HAL_RCC_GET_HSI_DIVIDER) && defined(RCC_CR_HSIDIV_Pos)
289 return HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> RCC_CR_HSIDIV_Pos);
295static uint32_t GetH7CSIClock()
297#if defined(RCC_CR_CSIRDY)
298 return (RCC->CR & RCC_CR_CSIRDY) != 0U ? CSI_VALUE : 0U;
304static uint32_t GetH7Pll3RClock()
306#if defined(RCC_CR_PLL3RDY)
307 if ((RCC->CR & RCC_CR_PLL3RDY) == 0U)
312#if defined(RCC_PLLCFGR_DIVR3EN)
313 if ((RCC->PLLCFGR & RCC_PLLCFGR_DIVR3EN) == 0U)
317#elif defined(RCC_PLLCFGR_PLL3REN)
318 if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL3REN) == 0U)
325 PLL3_ClocksTypeDef pll3{};
326 HAL_RCCEx_GetPLL3ClockFreq(&pll3);
327 return pll3.PLL3_R_Frequency;
330static uint32_t GetH7I2CClock(I2C_TypeDef* instance)
332#if defined(I2C4) && defined(LL_RCC_I2C4_CLKSOURCE)
333 if (instance == I2C4)
335 const uint32_t source = LL_RCC_GetI2CClockSource(LL_RCC_I2C4_CLKSOURCE);
336#if defined(LL_RCC_I2C4_CLKSOURCE_PCLK4)
337 if (source == LL_RCC_I2C4_CLKSOURCE_PCLK4)
339 return HAL_RCCEx_GetD3PCLK1Freq();
342#if defined(LL_RCC_I2C4_CLKSOURCE_PLL3R)
343 if (source == LL_RCC_I2C4_CLKSOURCE_PLL3R)
345 return GetH7Pll3RClock();
348#if defined(LL_RCC_I2C4_CLKSOURCE_HSI)
349 if (source == LL_RCC_I2C4_CLKSOURCE_HSI)
351 return GetH7HSIClock();
354#if defined(LL_RCC_I2C4_CLKSOURCE_CSI)
355 if (source == LL_RCC_I2C4_CLKSOURCE_CSI)
357 return GetH7CSIClock();
364#if defined(LL_RCC_I2C123_CLKSOURCE)
365 const uint32_t source = LL_RCC_GetI2CClockSource(LL_RCC_I2C123_CLKSOURCE);
366#if defined(LL_RCC_I2C123_CLKSOURCE_PCLK1)
367 if (source == LL_RCC_I2C123_CLKSOURCE_PCLK1)
369 return HAL_RCC_GetPCLK1Freq();
372#if defined(LL_RCC_I2C123_CLKSOURCE_PLL3R)
373 if (source == LL_RCC_I2C123_CLKSOURCE_PLL3R)
375 return GetH7Pll3RClock();
378#if defined(LL_RCC_I2C123_CLKSOURCE_HSI)
379 if (source == LL_RCC_I2C123_CLKSOURCE_HSI)
381 return GetH7HSIClock();
384#if defined(LL_RCC_I2C123_CLKSOURCE_CSI)
385 if (source == LL_RCC_I2C123_CLKSOURCE_CSI)
387 return GetH7CSIClock();
390#elif defined(LL_RCC_I2C1235_CLKSOURCE)
391 const uint32_t source = LL_RCC_GetI2CClockSource(LL_RCC_I2C1235_CLKSOURCE);
392#if defined(LL_RCC_I2C1235_CLKSOURCE_PCLK1)
393 if (source == LL_RCC_I2C1235_CLKSOURCE_PCLK1)
395 return HAL_RCC_GetPCLK1Freq();
398#if defined(LL_RCC_I2C1235_CLKSOURCE_PLL3R)
399 if (source == LL_RCC_I2C1235_CLKSOURCE_PLL3R)
401 return GetH7Pll3RClock();
404#if defined(LL_RCC_I2C1235_CLKSOURCE_HSI)
405 if (source == LL_RCC_I2C1235_CLKSOURCE_HSI)
407 return GetH7HSIClock();
410#if defined(LL_RCC_I2C1235_CLKSOURCE_CSI)
411 if (source == LL_RCC_I2C1235_CLKSOURCE_CSI)
413 return GetH7CSIClock();
421#if defined(STM32F7) && defined(HAL_RCC_MODULE_ENABLED)
422static uint32_t GetF7I2CClock(I2C_TypeDef* instance)
424#define LIBXR_F7_I2C_CLOCK(ID) \
425 if (instance == I2C##ID) \
427 const uint32_t source = LL_RCC_GetI2CClockSource(LL_RCC_I2C##ID##_CLKSOURCE); \
428 if (source == LL_RCC_I2C##ID##_CLKSOURCE_PCLK1) return HAL_RCC_GetPCLK1Freq(); \
429 if (source == LL_RCC_I2C##ID##_CLKSOURCE_SYSCLK) return HAL_RCC_GetSysClockFreq(); \
430 if (source == LL_RCC_I2C##ID##_CLKSOURCE_HSI) \
432 return (RCC->CR & RCC_CR_HSIRDY) != 0U ? HSI_VALUE : 0U; \
437 LIBXR_F7_I2C_CLOCK(1)
440 LIBXR_F7_I2C_CLOCK(2)
443 LIBXR_F7_I2C_CLOCK(3)
446 LIBXR_F7_I2C_CLOCK(4)
448#undef LIBXR_F7_I2C_CLOCK
453template <
typename I2CInstance>
454static uint32_t GetI2CClock(I2CInstance* instance)
456#if defined(STM32H7) && defined(HAL_RCC_MODULE_ENABLED)
457 return GetH7I2CClock(instance);
459#if defined(STM32F7) && defined(HAL_RCC_MODULE_ENABLED)
460 return GetF7I2CClock(instance);
462#if defined(HAL_RCC_MODULE_ENABLED)
463#if defined(RCC_PERIPHCLK_I2C8) && defined(I2C8)
464 if (instance == I2C8)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C8);
466#if defined(RCC_PERIPHCLK_I2C7) && defined(I2C7)
467 if (instance == I2C7)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C7);
469#if defined(RCC_PERIPHCLK_I2C6) && defined(I2C6)
470 if (instance == I2C6)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C6);
472#if defined(RCC_PERIPHCLK_I2C5) && defined(I2C5)
473 if (instance == I2C5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C5);
475#if defined(RCC_PERIPHCLK_I2C4) && defined(I2C4)
476 if (instance == I2C4)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C4);
478#if defined(RCC_PERIPHCLK_I2C1_I3C1) && defined(I2C1)
479 if (instance == I2C1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1_I3C1);
481#if defined(RCC_PERIPHCLK_I2C23)
483 if (instance == I2C2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C23);
486 if (instance == I2C3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C23);
489#if defined(RCC_PERIPHCLK_I2C3) && defined(I2C3)
490 if (instance == I2C3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C3);
492#if defined(RCC_PERIPHCLK_I2C2) && defined(I2C2)
493 if (instance == I2C2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C2);
495#if defined(RCC_PERIPHCLK_I2C1) && defined(I2C1)
496 if (instance == I2C1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1);
498#if defined(RCC_PERIPHCLK_I2C1235) && defined(I2C5)
499 if (instance == I2C5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1235);
501#if defined(RCC_PERIPHCLK_I2C123)
503 if (instance == I2C1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C123);
506 if (instance == I2C2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C123);
509 if (instance == I2C3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C123);
513#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32C0) && defined(I2C2) && \
514 defined(RCC_PERIPHCLK_I2C1) && !defined(RCC_CCIPR_I2C2SEL)
516 if (instance == I2C2)
518 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1);
521#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32F0) && defined(I2C2) && \
522 !defined(RCC_CFGR3_I2C2SW)
524 if (instance == I2C2)
526 return HAL_RCC_GetPCLK1Freq();
529#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32G0) && defined(I2C3) && \
530 !defined(RCC_CCIPR_I2C3SEL)
532 if (instance == I2C3)
534 return HAL_RCC_GetPCLK1Freq();
537#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32U0) && defined(I2C2) && \
538 !defined(RCC_CCIPR_I2C2SEL)
539 if (instance == I2C2)
541 return HAL_RCC_GetPCLK1Freq();
544#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32U0) && defined(I2C4) && \
545 !defined(RCC_CCIPR_I2C4SEL)
546 if (instance == I2C4)
548 return HAL_RCC_GetPCLK1Freq();
551#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32WB0) && \
552 (defined(I2C1) || defined(I2C2))
555 if (instance == I2C2)
557 return HAL_RCC_GetSysClockFreq();
561 if (instance == I2C1)
563 return HAL_RCC_GetSysClockFreq();
567#if defined(HAL_RCC_MODULE_ENABLED) && defined(STM32WL3) && \
568 (defined(I2C1) || defined(I2C2))
571 if (instance == I2C2)
573 return HAL_RCC_GetSysClockFreq();
577 if (instance == I2C1)
579 return HAL_RCC_GetSysClockFreq();
586static I2CFilterState CaptureI2CFilterState(
const I2C_HandleTypeDef* handle)
589 I2CFilterState state;
590#if defined(I2C_CR1_ANFOFF)
591 state.analog_filter = (handle->Instance->CR1 & I2C_CR1_ANFOFF) == 0U;
592#elif defined(I2C_FLTR_ANOFF)
593 state.analog_filter = (handle->Instance->FLTR & I2C_FLTR_ANOFF) == 0U;
595#if defined(I2C_CR1_DNF) && defined(I2C_CR1_DNF_Pos)
596 state.digital_filter = (handle->Instance->CR1 & I2C_CR1_DNF) >> I2C_CR1_DNF_Pos;
597#elif defined(I2C_FLTR_DNF)
598 state.digital_filter = handle->Instance->FLTR & I2C_FLTR_DNF;
603static void RestoreI2CFilterState(I2C_HandleTypeDef* handle, I2CFilterState state)
606 const uint32_t was_enabled = handle->Instance->CR1 & I2C_CR1_PE;
608 CLEAR_BIT(handle->Instance->CR1, I2C_CR1_PE);
609#if defined(I2C_CR1_ANFOFF)
610 MODIFY_REG(handle->Instance->CR1, I2C_CR1_ANFOFF,
611 state.analog_filter ? 0U : I2C_CR1_ANFOFF);
612#elif defined(I2C_FLTR_ANOFF)
613 MODIFY_REG(handle->Instance->FLTR, I2C_FLTR_ANOFF,
614 state.analog_filter ? 0U : I2C_FLTR_ANOFF);
616#if defined(I2C_CR1_DNF) && defined(I2C_CR1_DNF_Pos)
617 MODIFY_REG(handle->Instance->CR1, I2C_CR1_DNF, state.digital_filter << I2C_CR1_DNF_Pos);
618#elif defined(I2C_FLTR_DNF)
619 MODIFY_REG(handle->Instance->FLTR, I2C_FLTR_DNF, state.digital_filter);
621 SET_BIT(handle->Instance->CR1, was_enabled);
624static STM32I2C* FindI2C(I2C_HandleTypeDef* handle)
626 if (handle ==
nullptr || handle->Instance ==
nullptr)
630 const stm32_i2c_id_t
id = STM32_I2C_GetID(handle->Instance);
631 if (
id == STM32_I2C_ID_ERROR ||
id >= STM32_I2C_NUMBER)
635 return STM32I2C::map[id];
640 uint32_t dma_enable_min_size)
642 id_(hi2c == nullptr ? STM32_I2C_ID_ERROR : STM32_I2C_GetID(hi2c->Instance)),
644 dma_enable_min_size_(dma_enable_min_size),
647 ASSERT(id_ != STM32_I2C_ID_ERROR);
648 ASSERT(id_ < STM32_I2C_NUMBER);
655 if (i2c_handle_->State != HAL_I2C_STATE_READY)
662 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
664 if (read_data.
size_ > dma_enable_min_size_)
667 read_buff_ = read_data;
668 if (op.
type == ReadOperation::OperationType::BLOCK)
674 const HAL_StatusTypeDef st = HAL_I2C_Master_Receive_DMA(
675 i2c_handle_, dev_addr,
reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
679 if (op.
type == ReadOperation::OperationType::BLOCK)
682 return MapHalStartFailure(i2c_handle_, st);
684 if (op.
type == ReadOperation::OperationType::POLLING)
690 if (op.
type == ReadOperation::OperationType::BLOCK)
692 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.
timeout);
698 auto ans = HAL_I2C_Master_Receive(i2c_handle_, dev_addr,
699 reinterpret_cast<uint8_t*
>(read_data.
addr_),
700 read_data.
size_, 20) == HAL_OK
705 if (op.
type != ReadOperation::OperationType::BLOCK)
716 if (i2c_handle_->State != HAL_I2C_STATE_READY)
723 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
727 if (write_data.
size_ > dma_enable_min_size_)
730 if (op.
type == WriteOperation::OperationType::BLOCK)
737 const HAL_StatusTypeDef st = HAL_I2C_Master_Transmit_DMA(
738 i2c_handle_, dev_addr,
reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
742 if (op.
type == WriteOperation::OperationType::BLOCK)
745 return MapHalStartFailure(i2c_handle_, st);
747 if (op.
type == WriteOperation::OperationType::POLLING)
753 if (op.
type == WriteOperation::OperationType::BLOCK)
755 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.
timeout);
761 auto ans = HAL_I2C_Master_Transmit(i2c_handle_, dev_addr,
762 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_),
763 write_data.
size_, 20) == HAL_OK
766 if (op.
type != WriteOperation::OperationType::BLOCK)
779 if (i2c_handle_->State != HAL_I2C_STATE_READY)
786 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
788 if (read_data.
size_ > dma_enable_min_size_)
791 read_buff_ = read_data;
792 if (op.
type == ReadOperation::OperationType::BLOCK)
798 const HAL_StatusTypeDef st = HAL_I2C_Mem_Read_DMA(
799 i2c_handle_, dev_addr, mem_addr,
800 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
801 : I2C_MEMADD_SIZE_16BIT,
802 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), read_data.
size_);
805 if (op.
type == ReadOperation::OperationType::BLOCK)
808 return MapHalStartFailure(i2c_handle_, st);
810 if (op.
type == ReadOperation::OperationType::POLLING)
816 if (op.
type == ReadOperation::OperationType::BLOCK)
818 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.
timeout);
825 HAL_I2C_Mem_Read(i2c_handle_, dev_addr, mem_addr,
826 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
827 : I2C_MEMADD_SIZE_16BIT,
828 reinterpret_cast<uint8_t*
>(read_data.
addr_), read_data.
size_,
833 if (op.
type != ReadOperation::OperationType::BLOCK)
843 MemAddrLength mem_addr_size,
bool in_isr)
847 if (i2c_handle_->State != HAL_I2C_STATE_READY)
854 const uint16_t dev_addr = EncodeHalDevAddress(i2c_handle_, slave_addr);
858 if (write_data.
size_ > dma_enable_min_size_)
861 if (op.
type == WriteOperation::OperationType::BLOCK)
868 const HAL_StatusTypeDef st = HAL_I2C_Mem_Write_DMA(
869 i2c_handle_, dev_addr, mem_addr,
870 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
871 : I2C_MEMADD_SIZE_16BIT,
872 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), write_data.
size_);
875 if (op.
type == WriteOperation::OperationType::BLOCK)
878 return MapHalStartFailure(i2c_handle_, st);
880 if (op.
type == WriteOperation::OperationType::POLLING)
886 if (op.
type == WriteOperation::OperationType::BLOCK)
888 return WaitBlockResultAndRecoverTimeout(
this, op.
data.sem_info.
timeout);
895 HAL_I2C_Mem_Write(i2c_handle_, dev_addr, mem_addr,
896 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
897 : I2C_MEMADD_SIZE_16BIT,
898 reinterpret_cast<uint8_t*
>(dma_buff_.
addr_), write_data.
size_,
903 if (op.
type != WriteOperation::OperationType::BLOCK)
913 if (i2c_handle_ ==
nullptr ||
914 STM32_I2C_GetID(i2c_handle_->Instance) == STM32_I2C_ID_ERROR ||
919 const auto is_busy = [
this]()
921 return recovering_ || i2c_handle_->State != HAL_I2C_STATE_READY ||
922 i2c_handle_->Lock == HAL_LOCKED ||
923 __HAL_I2C_GET_FLAG(i2c_handle_, I2C_FLAG_BUSY) != RESET;
925 uint32_t timing = 0U;
926 const auto old_init = i2c_handle_->Init;
927 const I2CFilterState old_filter_state = CaptureI2CFilterState(i2c_handle_);
934#if defined(I2C_CCR_CCR) && defined(HAL_RCC_MODULE_ENABLED)
935 const uint32_t pclk = HAL_RCC_GetPCLK1Freq();
936 const uint32_t factor =
939 : (i2c_handle_->Init.DutyCycle == I2C_DUTYCYCLE_16_9 ? 25U : 3U);
940 const uint64_t denominator = uint64_t(config.
clock_speed) * factor;
941 if (pclk == 0U || (uint64_t(pclk) + denominator - 1U) / denominator > I2C_CCR_CCR)
947 else if constexpr (
HasTiming<
decltype(i2c_handle_)>::value)
949 if (!STM32I2CTiming::Compute(GetI2CClock(i2c_handle_->Instance), config.
clock_speed,
950 old_filter_state.analog_filter,
951 old_filter_state.digital_filter, timing))
969 SetClockSpeed(i2c_handle_, config);
973 SetTiming(i2c_handle_, timing);
975 if (!ResetI2CPeripheral(i2c_handle_->Instance))
977 i2c_handle_->Init = old_init;
980 if (HAL_I2C_Init(i2c_handle_) != HAL_OK)
982 i2c_handle_->Init = old_init;
983 if (ResetI2CPeripheral(i2c_handle_->Instance) && HAL_I2C_Init(i2c_handle_) == HAL_OK)
985 RestoreI2CFilterState(i2c_handle_, old_filter_state);
989 RestoreI2CFilterState(i2c_handle_, old_filter_state);
993extern "C" void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef* hi2c)
996 if (i2c && !i2c->recovering_ &&
997 (i2c->read_op_.
type != ReadOperation::OperationType::NONE))
1000#ifdef HAL_I2C_ERROR_NONE
1007 i2c->read_buff_.
size_);
1009 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
1011 (void)i2c->block_wait_.
TryPost(
true, ec);
1020extern "C" void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef* hi2c)
1023 if (i2c && !i2c->recovering_ &&
1024 (i2c->write_op_.
type != WriteOperation::OperationType::NONE))
1027#ifdef HAL_I2C_ERROR_NONE
1030 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
1032 (void)i2c->block_wait_.
TryPost(
true, ec);
1041extern "C" void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef* hi2c)
1044 if (i2c && !i2c->recovering_ &&
1045 (i2c->write_op_.
type != WriteOperation::OperationType::NONE))
1048#ifdef HAL_I2C_ERROR_NONE
1051 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
1053 (void)i2c->block_wait_.
TryPost(
true, ec);
1062extern "C" void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef* hi2c)
1065 if (i2c && !i2c->recovering_ &&
1066 (i2c->read_op_.
type != ReadOperation::OperationType::NONE))
1069#ifdef HAL_I2C_ERROR_NONE
1076 i2c->read_buff_.
size_);
1078 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
1080 (void)i2c->block_wait_.
TryPost(
true, ec);
1089extern "C" void HAL_I2C_ErrorCallback(I2C_HandleTypeDef* hi2c)
1093 if (i2c && !i2c->recovering_)
1097 if (i2c->read_op_.
type == ReadOperation::OperationType::BLOCK)
1108 if (i2c->write_op_.
type == WriteOperation::OperationType::BLOCK)
bool TryPost(bool in_isr, ErrorCode ec)
尝试认领完成并唤醒调用者 / Try to claim completion and wake the caller.
void Start(Semaphore &sem)
绑定信号量并开始等待 / Bind a semaphore and start waiting.
ErrorCode Wait(uint32_t timeout)
等待完成或超时交接 / Wait for completion or a timeout handoff.
void Cancel()
清除等待状态,不发送通知 / Clear the wait state without posting.
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
uint32_t timeout
等待超时值 / Wait timeout.
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
Semaphore * sem
借用的信号量 / Borrowed semaphore.
OperationType type
当前通知方式 / Current notification mode.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
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
LibXR 命名空间 / LibXR namespace.
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ INIT_ERR
初始化错误 / Initialization error
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
清理指定内存范围覆盖的 D-Cache cache line Cleans D-Cache lines covering the specified memory range
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz) / The I2C clock speed (in Hz).