From b72d79e942ae50a841623a9ce119e1f26065e2ab Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 10:04:06 +0200 Subject: [PATCH 01/14] feat(i3c): replace fixed bus instances with an auto-resolved I3C bus Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 88 +++++++++++++++++++++++---------------- libraries/I3C/src/I3C.h | 47 ++++++++++----------- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index ed8791607c..89c2e6646b 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -6,14 +6,7 @@ // ============================================================================ // Global bus instances // ============================================================================ - -#if defined(I3C1) - I3CBus I3C1Bus(I3C1); -#endif - -#if defined(I3C2) - I3CBus I3C2Bus(I3C2); -#endif +I3CBus I3C; // ============================================================================ // File-local constants and helpers @@ -98,6 +91,27 @@ extern "C" void HAL_I3C_NotifyCallback(I3C_HandleTypeDef *hi3c, uint32_t eventId } } +// ------------------------------------------------------------------------ +// instance +// ------------------------------------------------------------------------ +bool I3CBus::prepareInstanceFromPins() +{ + bool result = false; + + if ((_sdaPin != NC) && (_sclPin != NC)) { + void *merged = pinmap_merge_peripheral( + pinmap_peripheral(_sdaPin, PinMap_I3C_SDA), + pinmap_peripheral(_sclPin, PinMap_I3C_SCL)); + + if (merged != (void *)NP) { + _instance = reinterpret_cast(merged); + result = true; + } + } + + return result; +} + // ============================================================================ // Low-level initialization // ============================================================================ @@ -106,16 +120,10 @@ bool I3CBus::initGPIO() { bool result = false; - if ((_sdaPin != NC) && (_sclPin != NC)) { - void *periphSDA = pinmap_peripheral(_sdaPin, PinMap_I3C_SDA); - void *periphSCL = pinmap_peripheral(_sclPin, PinMap_I3C_SCL); - void *merged = pinmap_merge_peripheral(periphSDA, periphSCL); - - if ((merged != (void *)NP) && (merged == _instance)) { - pinmap_pinout(_sdaPin, PinMap_I3C_SDA); - pinmap_pinout(_sclPin, PinMap_I3C_SCL); - result = true; - } + if ((_sdaPin != NC) && (_sclPin != NC) && (_instance != nullptr)) { + pinmap_pinout(_sdaPin, PinMap_I3C_SDA); + pinmap_pinout(_sclPin, PinMap_I3C_SCL); + result = true; } return result; @@ -229,7 +237,11 @@ bool I3CBus::begin(uint32_t freq, _mixedBusOdFreq = mixedOdHz; _ctrlCfg = ctrlCfg; - if (!initClocks()) { + if (!prepareInstanceFromPins()) { + local_ok = false; + } + + if (local_ok && !initClocks()) { local_ok = false; } @@ -677,10 +689,10 @@ bool I3CBus::isI3CDeviceReady(uint8_t dynAddr, uint32_t trials, uint32_t timeout // ============================================================================ bool I3CBus::cccBroadcastWrite(uint8_t cccId, - const uint8_t *data, - uint16_t length, - bool withDefByte, - uint32_t timeout) + const uint8_t *data, + uint16_t length, + bool withDefByte, + uint32_t timeout) { bool result = false; @@ -726,11 +738,11 @@ bool I3CBus::cccBroadcastWrite(uint8_t cccId, } bool I3CBus::cccDirectWrite(uint8_t targetAddr, - uint8_t cccId, - const uint8_t *data, - uint16_t length, - bool withDefByte, - uint32_t timeout) + uint8_t cccId, + const uint8_t *data, + uint16_t length, + bool withDefByte, + uint32_t timeout) { bool result = false; @@ -776,10 +788,10 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, } bool I3CBus::cccDirectRead(uint8_t targetAddr, - uint8_t cccId, - uint8_t *rxData, - uint16_t rxLength, - uint32_t timeout) + uint8_t cccId, + uint8_t *rxData, + uint16_t rxLength, + uint32_t timeout) { bool result = false; @@ -938,9 +950,9 @@ bool I3CBus::rstactPeripheralOnly() } bool I3CBus::setEvents(uint8_t dynAddr, - bool enable, - uint8_t events, - uint32_t timeout) + bool enable, + uint8_t events, + uint32_t timeout) { bool result = false; @@ -1442,7 +1454,11 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) } else { bool local_ok = true; - if (!initClocks()) { + if (!prepareInstanceFromPins()) { + local_ok = false; + } + + if (local_ok && !initClocks()) { local_ok = false; } diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index b642aceb5f..b4e3790d41 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -119,7 +119,7 @@ struct I3CControllerConfig { class I3CBus { public: - explicit I3CBus(I3C_TypeDef *inst = I3C1) : _instance(inst) {} + explicit I3CBus() : _instance(nullptr) {} // ------------------------------------------------------------------------ // Controller initialization and bus configuration @@ -397,9 +397,9 @@ class I3CBus { int disableTargetEvents(uint32_t interruptMask); bool setEvents(uint8_t dynAddr, - bool enable, - uint8_t events, - uint32_t timeout = 1000U); + bool enable, + uint8_t events, + uint32_t timeout = 1000U); bool hasTargetEvent() const; bool readTargetEvent(uint32_t &eventId); @@ -440,6 +440,11 @@ class I3CBus { } private: + // ------------------------------------------------------------------------ + // Instance + // ------------------------------------------------------------------------ + bool prepareInstanceFromPins(); + enum class I3CAddrState : uint8_t { Free, Reserved, @@ -496,23 +501,23 @@ class I3CBus { // Low-level CCC helpers // ------------------------------------------------------------------------ bool cccBroadcastWrite(uint8_t cccId, - const uint8_t *data, - uint16_t length, - bool withDefByte, - uint32_t timeout = 1000U); + const uint8_t *data, + uint16_t length, + bool withDefByte, + uint32_t timeout = 1000U); bool cccDirectWrite(uint8_t targetAddr, - uint8_t cccId, - const uint8_t *data, - uint16_t length, - bool withDefByte, - uint32_t timeout = 1000U); + uint8_t cccId, + const uint8_t *data, + uint16_t length, + bool withDefByte, + uint32_t timeout = 1000U); bool cccDirectRead(uint8_t targetAddr, - uint8_t cccId, - uint8_t *rxData, - uint16_t rxLength, - uint32_t timeout = 1000); + uint8_t cccId, + uint8_t *rxData, + uint16_t rxLength, + uint32_t timeout = 1000); // ------------------------------------------------------------------------ // Internal utility helpers @@ -549,12 +554,6 @@ class I3CBus { // Global instances // ============================================================================ -#if defined(I3C1) - extern I3CBus I3C1Bus; -#endif - -#if defined(I3C2) - extern I3CBus I3C2Bus; -#endif +extern I3CBus I3C; #endif From 06537c9b9b03160dbee973dfceba43d6dd08a160 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:57:55 +0200 Subject: [PATCH 02/14] fix(i3c): compute bus timing before HAL init and unify timing handling Changing setClock() to return bool Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 155 +++++++++++++++++++++++++++----------- libraries/I3C/src/I3C.h | 9 ++- 2 files changed, 118 insertions(+), 46 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index 89c2e6646b..bca1084ea9 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -254,6 +254,43 @@ bool I3CBus::begin(uint32_t freq, _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_CONTROLLER; + I3C_CtrlTimingTypeDef inTiming {}; + LL_I3C_CtrlBusConfTypeDef outCtrl {}; + uint32_t srcFreq = 0U; + + if (_instance == I3C1) { + srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); + } +#if defined(I3C2) + else if (_instance == I3C2) { + srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); + } +#endif + + if (srcFreq == 0U) { + local_ok = false; + } else { + inTiming.clockSrcFreq = srcFreq; + inTiming.i3cPPFreq = (freq == 0U) ? 1000000U : freq; + inTiming.dutyCycle = 50U; + + if (_busType == I3CBusType::Pure) { + inTiming.busType = I3C_PURE_I3C_BUS; + inTiming.i2cODFreq = 0U; + } else { + inTiming.busType = I3C_MIXED_BUS; + inTiming.i2cODFreq = _mixedBusOdFreq; + } + + if (I3C_CtrlTimingComputation(&inTiming, &outCtrl) != SUCCESS) { + local_ok = false; + } else { + _hi3c.Init.CtrlBusCharacteristic = outCtrl; + } + } + } + + if (local_ok) { if (HAL_I3C_Init(&_hi3c) != HAL_OK) { local_ok = false; } @@ -329,60 +366,21 @@ uint32_t I3CBus::getMixedBusOpenDrainFrequency() const return _mixedBusOdFreq; } -int I3CBus::setClock(uint32_t i3cFreq) +bool I3CBus::setClock(uint32_t i3cFreq) { - int result = 0; + bool result = false; #if !defined(HAL_I3C_MODULE_ENABLED) - (void)i3cFreq; - result = 0; - #else - - if (!_initialized) { - result = -1; - } else if (i3cFreq == 0U) { - result = 0; - } else { - I3C_CtrlTimingTypeDef inTiming {}; + if (_initialized && (i3cFreq != 0U)) { LL_I3C_CtrlBusConfTypeDef outCtrl {}; - uint32_t srcFreq = 0U; - - if (_instance == I3C1) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); - } -#if defined(I3C2) - else if (_instance == I3C2) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); - } -#endif - if (srcFreq == 0U) { - result = -1; - } else { - inTiming.clockSrcFreq = srcFreq; - inTiming.i3cPPFreq = i3cFreq; - inTiming.dutyCycle = 50U; - - if (_busType == I3CBusType::Pure) { - inTiming.busType = I3C_PURE_I3C_BUS; - inTiming.i2cODFreq = 0U; - } else { - inTiming.busType = I3C_MIXED_BUS; - inTiming.i2cODFreq = _mixedBusOdFreq; - } - - if (I3C_CtrlTimingComputation(&inTiming, &outCtrl) != SUCCESS) { - result = -1; - } else if (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) != HAL_OK) { - result = -1; - } else { - result = 0; - } + if (buildControllerTiming(i3cFreq, outCtrl) && + (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) == HAL_OK)) { + result = true; } } - #endif return result; @@ -1858,6 +1856,73 @@ void I3CBus::handleHalNotify(uint32_t eventId) } } +// ============================================================================ +// Clock helpers +// ============================================================================ +uint32_t I3CBus::getPeripheralClockFreq() const +{ + uint32_t srcFreq = 0U; + +#if defined(I3C1) + if (_instance == I3C1) { + srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); + } +#endif + +#if defined(I3C2) + if (_instance == I3C2) { + srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); + } +#endif + + return srcFreq; +} + +bool I3CBus::buildControllerTiming(uint32_t freq, LL_I3C_CtrlBusConfTypeDef &outCtrl) const +{ + bool result = false; + uint32_t srcFreq = getPeripheralClockFreq(); + + if (srcFreq != 0U) { + I3C_CtrlTimingTypeDef inTiming {}; + + inTiming.clockSrcFreq = srcFreq; + inTiming.i3cPPFreq = (freq == 0U) ? 1000000U : freq; + inTiming.dutyCycle = 50U; + + if (_busType == I3CBusType::Pure) { + inTiming.busType = I3C_PURE_I3C_BUS; + inTiming.i2cODFreq = 0U; + } else { + inTiming.busType = I3C_MIXED_BUS; + inTiming.i2cODFreq = _mixedBusOdFreq; + } + + if (I3C_CtrlTimingComputation(&inTiming, &outCtrl) == SUCCESS) { + result = true; + } + } + + return result; +} + +bool I3CBus::buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const +{ + bool result = false; + uint32_t srcFreq = getPeripheralClockFreq(); + + if (srcFreq != 0U) { + I3C_TgtTimingTypeDef inTiming {}; + inTiming.clockSrcFreq = srcFreq; + + if (I3C_TgtTimingComputation(&inTiming, &outTgt) == SUCCESS) { + result = true; + } + } + + return result; +} + // ============================================================================ // IRQ handlers // ============================================================================ diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index b4e3790d41..41e5abede5 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -146,7 +146,7 @@ class I3CBus { uint32_t mixedOdHz, const I3CControllerConfig &ctrlCfg); - int setClock(uint32_t hz); + bool setClock(uint32_t hz); void setBusType(I3CBusType type); I3CBusType getBusType() const; @@ -525,6 +525,13 @@ class I3CBus { static uint32_t bigToLittle32(uint32_t x); static uint64_t extractPid48FromEntdaaPayload(uint64_t payload); + // ------------------------------------------------------------------------ + // Clock helpers + // ------------------------------------------------------------------------ + uint32_t getPeripheralClockFreq() const; + bool buildControllerTiming(uint32_t freq, LL_I3C_CtrlBusConfTypeDef &outCtrl) const; + bool buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const; + // ------------------------------------------------------------------------ // Internal state // ------------------------------------------------------------------------ From ff4068dffe1160c78d0ce19ae4da5299abf534f8 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:50:37 +0200 Subject: [PATCH 03/14] fix(i3c): guard family-specific end-of-frame configuration Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index bca1084ea9..58b84b2ba8 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -295,6 +295,13 @@ bool I3CBus::begin(uint32_t freq, local_ok = false; } } +#if defined(I3C_END_OF_FRAME_CPLT_ENABLE) + if (local_ok) { + if (HAL_I3C_SetConfigEndOfFrame(&_hi3c, I3C_END_OF_FRAME_CPLT_ENABLE) != HAL_OK) { + local_ok = false; + } + } +#endif if (local_ok) { I3C_FifoConfTypeDef fifoCfg {}; From 113a7d5ee21410790c301a7c890098cd0a963f84 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:35:40 +0200 Subject: [PATCH 04/14] fix(i3c): route IRQ and HAL notify callbacks to the active bus instance Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 61 ++++++++++++++++++++++++++++++++++----- libraries/I3C/src/I3C.h | 6 ++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index 58b84b2ba8..a7f2fd48cc 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -6,6 +6,14 @@ // ============================================================================ // Global bus instances // ============================================================================ +#if defined(I3C1) + static I3CBus *g_i3c1Owner = nullptr; +#endif + +#if defined(I3C2) + static I3CBus *g_i3c2Owner = nullptr; +#endif + I3CBus I3C; // ============================================================================ @@ -78,14 +86,14 @@ extern "C" void HAL_I3C_NotifyCallback(I3C_HandleTypeDef *hi3c, uint32_t eventId { if ((hi3c != nullptr) && (hi3c->Instance != nullptr)) { #if defined(I3C1) - if (hi3c->Instance == I3C1) { - I3C1Bus.handleHalNotify(eventId); + if ((hi3c->Instance == I3C1) && (g_i3c1Owner != nullptr)) { + g_i3c1Owner->handleHalNotify(eventId); } #endif #if defined(I3C2) - if (hi3c->Instance == I3C2) { - I3C2Bus.handleHalNotify(eventId); + if ((hi3c->Instance == I3C2) && (g_i3c2Owner != nullptr)) { + g_i3c2Owner->handleHalNotify(eventId); } #endif } @@ -1933,30 +1941,67 @@ bool I3CBus::buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const // ============================================================================ // IRQ handlers // ============================================================================ +void I3CBus::registerInstanceOwner() +{ +#if defined(I3C1) + if (_instance == I3C1) { + g_i3c1Owner = this; + } +#endif + +#if defined(I3C2) + if (_instance == I3C2) { + g_i3c2Owner = this; + } +#endif +} + +void I3CBus::unregisterInstanceOwner() +{ +#if defined(I3C1) + if ((g_i3c1Owner == this) && (_instance == I3C1)) { + g_i3c1Owner = nullptr; + } +#endif + +#if defined(I3C2) + if ((g_i3c2Owner == this) && (_instance == I3C2)) { + g_i3c2Owner = nullptr; + } +#endif +} extern "C" void I3C1_EV_IRQHandler(void) { #if defined(I3C1) - HAL_I3C_EV_IRQHandler(I3C1Bus.halHandle()); + if (g_i3c1Owner != nullptr) { + HAL_I3C_EV_IRQHandler(g_i3c1Owner->halHandle()); + } #endif } extern "C" void I3C1_ER_IRQHandler(void) { #if defined(I3C1) - HAL_I3C_ER_IRQHandler(I3C1Bus.halHandle()); + if (g_i3c1Owner != nullptr) { + HAL_I3C_ER_IRQHandler(g_i3c1Owner->halHandle()); + } #endif } #if defined(I3C2) extern "C" void I3C2_EV_IRQHandler(void) { - HAL_I3C_EV_IRQHandler(I3C2Bus.halHandle()); + if (g_i3c2Owner != nullptr) { + HAL_I3C_EV_IRQHandler(g_i3c2Owner->halHandle()); + } } extern "C" void I3C2_ER_IRQHandler(void) { - HAL_I3C_ER_IRQHandler(I3C2Bus.halHandle()); + if (g_i3c2Owner != nullptr) { + HAL_I3C_ER_IRQHandler(g_i3c2Owner->halHandle()); + } } #endif diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index 41e5abede5..88c2aeee76 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -532,6 +532,12 @@ class I3CBus { bool buildControllerTiming(uint32_t freq, LL_I3C_CtrlBusConfTypeDef &outCtrl) const; bool buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const; + // ------------------------------------------------------------------------ + // Irq helpers + // ------------------------------------------------------------------------ + void registerInstanceOwner(); + void unregisterInstanceOwner(); + // ------------------------------------------------------------------------ // Internal state // ------------------------------------------------------------------------ From 2f3eae3dd943c99aad9545e7c9229e32bf1bd276 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:39:09 +0200 Subject: [PATCH 05/14] fix(i3c): enable I3C IRQs on demand and harden init and cleanup flows Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 359 ++++++++++++++++++-------------------- libraries/I3C/src/I3C.h | 4 + 2 files changed, 169 insertions(+), 194 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index a7f2fd48cc..8563457863 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -155,12 +155,6 @@ bool I3CBus::initClocks() hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); if (hal_status == HAL_OK) { __HAL_RCC_I3C1_CLK_ENABLE(); - - HAL_NVIC_SetPriority(I3C1_EV_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(I3C1_EV_IRQn); - HAL_NVIC_SetPriority(I3C1_ER_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(I3C1_ER_IRQn); - result = true; } #endif @@ -180,12 +174,6 @@ bool I3CBus::initClocks() hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); if (hal_status == HAL_OK) { __HAL_RCC_I3C2_CLK_ENABLE(); - - HAL_NVIC_SetPriority(I3C2_EV_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(I3C2_EV_IRQn); - HAL_NVIC_SetPriority(I3C2_ER_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(I3C2_ER_IRQn); - result = true; } } @@ -234,128 +222,81 @@ bool I3CBus::begin(uint32_t freq, uint32_t mixedOdHz, const I3CControllerConfig &ctrlCfg) { - bool result = false; + bool result = true; - if (_initialized) { - result = true; - } else { - bool local_ok = true; + if (!_initialized) { + _hi3c.Instance = nullptr; + _instance = nullptr; _busType = type; _mixedBusOdFreq = mixedOdHz; _ctrlCfg = ctrlCfg; - if (!prepareInstanceFromPins()) { - local_ok = false; - } - - if (local_ok && !initClocks()) { - local_ok = false; - } - - if (local_ok && !initGPIO()) { - local_ok = false; - } - - if (local_ok) { + if (!prepareInstanceFromPins() || !initClocks() || !initGPIO()) { + result = false; + } else { std::memset(&_hi3c, 0, sizeof(_hi3c)); _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_CONTROLLER; - I3C_CtrlTimingTypeDef inTiming {}; LL_I3C_CtrlBusConfTypeDef outCtrl {}; - uint32_t srcFreq = 0U; - if (_instance == I3C1) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); - } -#if defined(I3C2) - else if (_instance == I3C2) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); - } -#endif - - if (srcFreq == 0U) { - local_ok = false; + if (!buildControllerTiming(freq, outCtrl)) { + result = false; } else { - inTiming.clockSrcFreq = srcFreq; - inTiming.i3cPPFreq = (freq == 0U) ? 1000000U : freq; - inTiming.dutyCycle = 50U; - - if (_busType == I3CBusType::Pure) { - inTiming.busType = I3C_PURE_I3C_BUS; - inTiming.i2cODFreq = 0U; - } else { - inTiming.busType = I3C_MIXED_BUS; - inTiming.i2cODFreq = _mixedBusOdFreq; - } - - if (I3C_CtrlTimingComputation(&inTiming, &outCtrl) != SUCCESS) { - local_ok = false; - } else { - _hi3c.Init.CtrlBusCharacteristic = outCtrl; - } + _hi3c.Init.CtrlBusCharacteristic = outCtrl; } - } - if (local_ok) { - if (HAL_I3C_Init(&_hi3c) != HAL_OK) { - local_ok = false; - } - } + if (result) { + if (HAL_I3C_Init(&_hi3c) != HAL_OK) { + result = false; + } else { #if defined(I3C_END_OF_FRAME_CPLT_ENABLE) - if (local_ok) { - if (HAL_I3C_SetConfigEndOfFrame(&_hi3c, I3C_END_OF_FRAME_CPLT_ENABLE) != HAL_OK) { - local_ok = false; - } - } + if (HAL_I3C_SetConfigEndOfFrame(&_hi3c, I3C_END_OF_FRAME_CPLT_ENABLE) != HAL_OK) { + result = false; + } #endif - - if (local_ok) { - I3C_FifoConfTypeDef fifoCfg {}; - fifoCfg.RxFifoThreshold = _ctrlCfg.rxFifoThreshold; - fifoCfg.TxFifoThreshold = _ctrlCfg.txFifoThreshold; - fifoCfg.ControlFifo = _ctrlCfg.controlFifo; - fifoCfg.StatusFifo = _ctrlCfg.statusFifo; - - if (HAL_I3C_SetConfigFifo(&_hi3c, &fifoCfg) != HAL_OK) { - local_ok = false; - } - } - - if (local_ok) { - I3C_CtrlConfTypeDef ctrlCfgHal {}; - ctrlCfgHal.DynamicAddr = _ctrlCfg.dynamicAddr; - ctrlCfgHal.StallTime = _ctrlCfg.stallTime; - ctrlCfgHal.HotJoinAllowed = _ctrlCfg.hotJoinAllowed ? ENABLE : DISABLE; - ctrlCfgHal.ACKStallState = _ctrlCfg.ackStall ? ENABLE : DISABLE; - ctrlCfgHal.CCCStallState = _ctrlCfg.cccStall ? ENABLE : DISABLE; - ctrlCfgHal.TxStallState = _ctrlCfg.txStall ? ENABLE : DISABLE; - ctrlCfgHal.RxStallState = _ctrlCfg.rxStall ? ENABLE : DISABLE; - ctrlCfgHal.HighKeeperSDA = _ctrlCfg.highKeeperSDA ? ENABLE : DISABLE; - - if (HAL_I3C_Ctrl_Config(&_hi3c, &ctrlCfgHal) != HAL_OK) { - local_ok = false; - } - } - - if (local_ok) { - _initialized = true; - - if (freq == 0U) { - freq = 1000000U; + if (result) { + I3C_FifoConfTypeDef fifoCfg {}; + fifoCfg.RxFifoThreshold = _ctrlCfg.rxFifoThreshold; + fifoCfg.TxFifoThreshold = _ctrlCfg.txFifoThreshold; + fifoCfg.ControlFifo = _ctrlCfg.controlFifo; + fifoCfg.StatusFifo = _ctrlCfg.statusFifo; + + if (HAL_I3C_SetConfigFifo(&_hi3c, &fifoCfg) != HAL_OK) { + result = false; + } else { + I3C_CtrlConfTypeDef ctrlCfgHal {}; + ctrlCfgHal.DynamicAddr = _ctrlCfg.dynamicAddr; + ctrlCfgHal.StallTime = _ctrlCfg.stallTime; + ctrlCfgHal.HotJoinAllowed = _ctrlCfg.hotJoinAllowed ? ENABLE : DISABLE; + ctrlCfgHal.ACKStallState = _ctrlCfg.ackStall ? ENABLE : DISABLE; + ctrlCfgHal.CCCStallState = _ctrlCfg.cccStall ? ENABLE : DISABLE; + ctrlCfgHal.TxStallState = _ctrlCfg.txStall ? ENABLE : DISABLE; + ctrlCfgHal.RxStallState = _ctrlCfg.rxStall ? ENABLE : DISABLE; + ctrlCfgHal.HighKeeperSDA = _ctrlCfg.highKeeperSDA ? ENABLE : DISABLE; + + if (HAL_I3C_Ctrl_Config(&_hi3c, &ctrlCfgHal) != HAL_OK) { + result = false; + } else{ + registerInstanceOwner(); + _initialized = true; + _role = I3CRole::Controller; + } + } + } + } } - if (setClock(freq) != 0) { - local_ok = false; + if (!result) { + if (_hi3c.Instance != nullptr) { + (void)HAL_I3C_DeInit(&_hi3c); + } + unregisterInstanceOwner(); + _initialized = false; + _role = I3CRole::None; } } - - if (local_ok) { - _role = I3CRole::Controller; - } - - result = local_ok; } return result; @@ -1465,102 +1406,52 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) result = (configureTarget(cfg) == 0); } } else { - bool local_ok = true; + _hi3c.Instance = nullptr; + _instance = nullptr; - if (!prepareInstanceFromPins()) { - local_ok = false; - } - - if (local_ok && !initClocks()) { - local_ok = false; - } - - if (local_ok && !initGPIO()) { - local_ok = false; - } - - if (local_ok) { + if (prepareInstanceFromPins() && initClocks() && initGPIO()) { std::memset(&_hi3c, 0, sizeof(_hi3c)); _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_TARGET; - I3C_TgtTimingTypeDef inTiming {}; LL_I3C_TgtBusConfTypeDef outTgt {}; - uint32_t srcFreq = 0U; - if (_instance == I3C1) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); - } -#if defined(I3C2) - else if (_instance == I3C2) { - srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); - } -#endif - - if (srcFreq == 0U) { - local_ok = false; - } else { - inTiming.clockSrcFreq = srcFreq; - - if (I3C_TgtTimingComputation(&inTiming, &outTgt) != SUCCESS) { - local_ok = false; - } else { - _hi3c.Init.TgtBusCharacteristic = outTgt; + if (buildTargetTiming(outTgt)) { + _hi3c.Init.TgtBusCharacteristic = outTgt; + if (HAL_I3C_Init(&_hi3c) == HAL_OK) { + I3C_FifoConfTypeDef fifoCfg {}; + fifoCfg.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4; + fifoCfg.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4; + fifoCfg.ControlFifo = HAL_I3C_CONTROLFIFO_DISABLE; + fifoCfg.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE; + + if (HAL_I3C_SetConfigFifo(&_hi3c, &fifoCfg) == HAL_OK) { + if (configureTarget(cfg) == 0) { + _initialized = true; + _role = I3CRole::Target; + registerInstanceOwner(); + result = true; + } + } + if (!result) { + if (_hi3c.Instance != nullptr) { + (void)HAL_I3C_DeInit(&_hi3c); + } + unregisterInstanceOwner(); + _initialized = false; + _role = I3CRole::None; + } } } } - - if (local_ok) { - if (HAL_I3C_Init(&_hi3c) != HAL_OK) { - local_ok = false; - } - } - - if (local_ok) { - I3C_FifoConfTypeDef fifoCfg {}; - fifoCfg.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4; - fifoCfg.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4; - fifoCfg.ControlFifo = HAL_I3C_CONTROLFIFO_DISABLE; - fifoCfg.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE; - - if (HAL_I3C_SetConfigFifo(&_hi3c, &fifoCfg) != HAL_OK) { - local_ok = false; - } - } - - if (local_ok) { - if (configureTarget(cfg) != 0) { - local_ok = false; - } - } - - if (local_ok) { - _initialized = true; - _role = I3CRole::Target; - } else { - _role = I3CRole::None; - } - - result = local_ok; } - return result; } int I3CBus::configureTarget(const I3CTargetConfig &cfg) { int result = -1; - bool can_configure = false; - - if (!_initialized) { - if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { - can_configure = true; - } - } else if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { - can_configure = true; - } - - if (can_configure) { + if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { I3C_TgtConfTypeDef tgtCfg {}; tgtCfg.Identifier = cfg.identifier; @@ -1585,7 +1476,6 @@ int I3CBus::configureTarget(const I3CTargetConfig &cfg) HAL_StatusTypeDef st = HAL_I3C_Tgt_Config(&_hi3c, &tgtCfg); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } - return result; } @@ -1683,7 +1573,16 @@ int I3CBus::enableTargetEvents(I3C_XferTypeDef *pXferData, int result = -1; if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET)) { + if (!enableIRQs()) { + return -1; + } + HAL_StatusTypeDef st = HAL_I3C_ActivateNotification(&_hi3c, pXferData, interruptMask); + if (st != HAL_OK) { + if (_hi3c.Instance->IER == 0U) { + disableIRQs(); + } + } result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } @@ -1697,6 +1596,10 @@ int I3CBus::disableTargetEvents(uint32_t interruptMask) if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET)) { HAL_StatusTypeDef st = HAL_I3C_DeactivateNotification(&_hi3c, interruptMask); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + + if ((st == HAL_OK) && (_hi3c.Instance->IER == 0U)) { + disableIRQs(); + } } return result; @@ -1786,7 +1689,16 @@ int I3CBus::enableControllerEvents(uint32_t interruptMask) int result = -1; if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { + if (!enableIRQs()) { + return -1; + } + HAL_StatusTypeDef st = HAL_I3C_ActivateNotification(&_hi3c, nullptr, interruptMask); + if (st != HAL_OK) { + if (_hi3c.Instance->IER == 0U) { + disableIRQs(); + } + } result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } @@ -1800,6 +1712,10 @@ int I3CBus::disableControllerEvents(uint32_t interruptMask) if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { HAL_StatusTypeDef st = HAL_I3C_DeactivateNotification(&_hi3c, interruptMask); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + + if ((st == HAL_OK) && (_hi3c.Instance->IER == 0U)) { + disableIRQs(); + } } return result; @@ -1939,8 +1855,63 @@ bool I3CBus::buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const } // ============================================================================ -// IRQ handlers +// IRQ handlers & helpers // ============================================================================ + +bool I3CBus::enableIRQs() +{ + if (_irqEnabled) { + return true; + } + +#if defined(I3C1) + if (_instance == I3C1) { + HAL_NVIC_SetPriority(I3C1_EV_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I3C1_EV_IRQn); + HAL_NVIC_SetPriority(I3C1_ER_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I3C1_ER_IRQn); + _irqEnabled = true; + return true; + } +#endif + +#if defined(I3C2) + if (_instance == I3C2) { + HAL_NVIC_SetPriority(I3C2_EV_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I3C2_EV_IRQn); + HAL_NVIC_SetPriority(I3C2_ER_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I3C2_ER_IRQn); + _irqEnabled = true; + return true; + } +#endif + + return false; +} + +void I3CBus::disableIRQs() +{ + if (!_irqEnabled) { + return; + } + +#if defined(I3C1) + if (_instance == I3C1) { + HAL_NVIC_DisableIRQ(I3C1_EV_IRQn); + HAL_NVIC_DisableIRQ(I3C1_ER_IRQn); + } +#endif + +#if defined(I3C2) + if (_instance == I3C2) { + HAL_NVIC_DisableIRQ(I3C2_EV_IRQn); + HAL_NVIC_DisableIRQ(I3C2_ER_IRQn); + } +#endif + + _irqEnabled = false; +} + void I3CBus::registerInstanceOwner() { #if defined(I3C1) diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index 88c2aeee76..d54e8535dc 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -535,6 +535,8 @@ class I3CBus { // ------------------------------------------------------------------------ // Irq helpers // ------------------------------------------------------------------------ + bool enableIRQs(); + void disableIRQs(); void registerInstanceOwner(); void unregisterInstanceOwner(); @@ -559,6 +561,8 @@ class I3CBus { I3CBusType _busType = I3CBusType::Pure; uint32_t _mixedBusOdFreq = 1000000U; + bool _irqEnabled = false; + PinName _sdaPin = digitalPinToPinName(I3C_SDA); PinName _sclPin = digitalPinToPinName(I3C_SCL); }; From eec057700dfdb37cf46a62bb0078861c4acb16a7 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:49:36 +0200 Subject: [PATCH 06/14] refactor(i3c): right-size temporary transfer buffers to required frame sizes Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 113 ++++++++++++++++++---------------- libraries/I3C/src/I3C.h | 3 + libraries/I3C/src/I3C_I2C.cpp | 8 +-- 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index 8563457863..6cb237040e 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -278,7 +278,7 @@ bool I3CBus::begin(uint32_t freq, if (HAL_I3C_Ctrl_Config(&_hi3c, &ctrlCfgHal) != HAL_OK) { result = false; - } else{ + } else { registerInstanceOwner(); _initialized = true; _role = I3CRole::Controller; @@ -333,7 +333,7 @@ bool I3CBus::setClock(uint32_t i3cFreq) LL_I3C_CtrlBusConfTypeDef outCtrl {}; if (buildControllerTiming(i3cFreq, outCtrl) && - (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) == HAL_OK)) { + (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) == HAL_OK)) { result = true; } } @@ -375,7 +375,7 @@ int I3CBus::write(uint8_t dynAddr, (len != 0U)) { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; HAL_StatusTypeDef st; priv.TargetAddr = dynAddr; @@ -423,7 +423,7 @@ int I3CBus::read(uint8_t dynAddr, (len != 0U)) { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; HAL_StatusTypeDef st; priv.TargetAddr = dynAddr; @@ -470,7 +470,7 @@ int I3CBus::writeRegBuffer(uint8_t dynAddr, } else { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; uint8_t data[32] = {0}; HAL_StatusTypeDef st; @@ -522,7 +522,7 @@ int I3CBus::readRegBuffer(uint8_t dynAddr, } else { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; uint8_t regBuf[1] = { reg }; uint8_t data[32] = {0}; HAL_StatusTypeDef st; @@ -651,38 +651,40 @@ bool I3CBus::cccBroadcastWrite(uint8_t cccId, bool result = false; if (_initialized) { - uint32_t controlBuffer[0xFF]; + uint32_t controlBuffer[1] = {}; + uint8_t txBuffer[I3C_CCC_TX_SCRATCH_MAX] = {}; I3C_XferTypeDef context {}; - uint8_t txBuffer[0x0F]; I3C_CCCTypeDef ccc[] = { { 0x00U, cccId, { const_cast(data), length }, HAL_I3C_DIRECTION_WRITE }, }; - context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = COUNTOF(controlBuffer); - context.TxBuf.pBuffer = txBuffer; - context.TxBuf.Size = 4U; + if (!(length > sizeof(txBuffer))) { + context.CtrlBuf.pBuffer = controlBuffer; + context.CtrlBuf.Size = 1U; + context.TxBuf.pBuffer = txBuffer; + context.TxBuf.Size = length; - uint32_t option = withDefByte ? I3C_BROADCAST_WITH_DEFBYTE_RESTART - : I3C_BROADCAST_WITHOUT_DEFBYTE_RESTART; + uint32_t option = withDefByte ? I3C_BROADCAST_WITH_DEFBYTE_RESTART + : I3C_BROADCAST_WITHOUT_DEFBYTE_RESTART; - HAL_StatusTypeDef st = HAL_I3C_AddDescToFrame( - &_hi3c, - ccc, - nullptr, - &context, - COUNTOF(ccc), - option); + result = (HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option) == HAL_OK); - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); if (st == HAL_OK) { - result = true; - } else { - uint32_t err = HAL_I3C_GetError(&_hi3c); - if ((err & HAL_I3C_ERROR_CE2) != 0U) { + st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); + if (st == HAL_OK) { result = true; + } else { + uint32_t err = HAL_I3C_GetError(&_hi3c); + if ((err & HAL_I3C_ERROR_CE2) != 0U) { + result = true; + } } } } @@ -701,9 +703,9 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, bool result = false; if (_initialized) { - uint32_t controlBuffer[0xFF]; + uint32_t controlBuffer[2] = {}; + uint8_t txBuffer[I3C_CCC_TX_SCRATCH_MAX] = {}; I3C_XferTypeDef context {}; - uint8_t txBuffer[0x0F]; I3C_CCCTypeDef ccc[] = { { @@ -714,26 +716,29 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, }, }; - context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = COUNTOF(controlBuffer); - context.TxBuf.pBuffer = txBuffer; - context.TxBuf.Size = 4U; + if (!(length > sizeof(txBuffer))) { - uint32_t option = withDefByte ? I3C_DIRECT_WITH_DEFBYTE_RESTART - : I3C_DIRECT_WITHOUT_DEFBYTE_RESTART; + context.CtrlBuf.pBuffer = controlBuffer; + context.CtrlBuf.Size = 2U; + context.TxBuf.pBuffer = txBuffer; + context.TxBuf.Size = length; - HAL_StatusTypeDef st = HAL_I3C_AddDescToFrame( - &_hi3c, - ccc, - nullptr, - &context, - COUNTOF(ccc), - option); + uint32_t option = withDefByte ? I3C_DIRECT_WITH_DEFBYTE_RESTART + : I3C_DIRECT_WITHOUT_DEFBYTE_RESTART; + + result = (HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option) == HAL_OK); - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); if (st == HAL_OK) { - result = true; + st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); + if (st == HAL_OK) { + result = true; + } } } } @@ -750,7 +755,7 @@ bool I3CBus::cccDirectRead(uint8_t targetAddr, bool result = false; if (_initialized && (rxData != nullptr) && (rxLength != 0U)) { - uint32_t controlBuffer[0xFF]; + uint32_t controlBuffer[2] = {}; I3C_XferTypeDef context {}; I3C_CCCTypeDef ccc[] = { @@ -763,17 +768,17 @@ bool I3CBus::cccDirectRead(uint8_t targetAddr, }; context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = COUNTOF(controlBuffer); + context.CtrlBuf.Size = 2U; context.RxBuf.pBuffer = rxData; context.RxBuf.Size = rxLength; - HAL_StatusTypeDef st = HAL_I3C_AddDescToFrame( - &_hi3c, - ccc, - nullptr, - &context, - COUNTOF(ccc), - I3C_DIRECT_WITHOUT_DEFBYTE_RESTART); + result = (HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + I3C_DIRECT_WITHOUT_DEFBYTE_RESTART) == HAL_OK); if (st == HAL_OK) { st = HAL_I3C_Ctrl_ReceiveCCC(&_hi3c, &context, timeout); diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index d54e8535dc..269cbaeec2 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -563,6 +563,9 @@ class I3CBus { bool _irqEnabled = false; + static constexpr uint32_t I3C_CTRL_WORDS_MAX = 2U; + static constexpr uint32_t I3C_CCC_TX_SCRATCH_MAX = 16U; + PinName _sdaPin = digitalPinToPinName(I3C_SDA); PinName _sclPin = digitalPinToPinName(I3C_SCL); }; diff --git a/libraries/I3C/src/I3C_I2C.cpp b/libraries/I3C/src/I3C_I2C.cpp index f9390ca866..b95b2c4378 100644 --- a/libraries/I3C/src/I3C_I2C.cpp +++ b/libraries/I3C/src/I3C_I2C.cpp @@ -37,7 +37,7 @@ int I3CBus::i2cWrite(uint8_t staticAddr, (len != 0U)) { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; HAL_StatusTypeDef st; priv.TargetAddr = staticAddr; @@ -86,7 +86,7 @@ int I3CBus::i2cRead(uint8_t staticAddr, (len != 0U)) { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; HAL_StatusTypeDef st; priv.TargetAddr = staticAddr; @@ -141,7 +141,7 @@ int I3CBus::i2cWriteRead(uint8_t staticAddr, } else { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; HAL_StatusTypeDef st; // 1) write phase with RESTART @@ -225,7 +225,7 @@ int I3CBus::i2cWriteRegBuffer(uint8_t staticAddr, (len <= 31U)) { I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[0x0F]; + uint32_t controlBuffer[1] = {}; uint8_t data[32] = {0}; HAL_StatusTypeDef st; From 0bbda7112ebe4bdd6fe68014edeb7e88e94af541 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:45:43 +0200 Subject: [PATCH 07/14] fix(i3c): mark dynamically assigned addresses as used during DAA Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 49 +++++++++------------------------------ 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index 6cb237040e..e9487d46ca 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -617,24 +617,18 @@ int I3CBus::readReg(uint8_t dynAddr, bool I3CBus::isI2CDeviceReady(uint8_t addr, uint32_t trials, uint32_t timeout) { bool result = false; - if (_initialized) { - HAL_StatusTypeDef st = HAL_I3C_Ctrl_IsDeviceI2C_Ready(&_hi3c, addr, trials, timeout); - result = (st == HAL_OK); + result = (HAL_I3C_Ctrl_IsDeviceI2C_Ready(&_hi3c, addr, trials, timeout) == HAL_OK); } - return result; } bool I3CBus::isI3CDeviceReady(uint8_t dynAddr, uint32_t trials, uint32_t timeout) { bool result = false; - if (_initialized) { - HAL_StatusTypeDef st = HAL_I3C_Ctrl_IsDeviceI3C_Ready(&_hi3c, dynAddr, trials, timeout); - result = (st == HAL_OK); + result = (HAL_I3C_Ctrl_IsDeviceI3C_Ready(&_hi3c, dynAddr, trials, timeout) == HAL_OK); } - return result; } @@ -676,11 +670,9 @@ bool I3CBus::cccBroadcastWrite(uint8_t cccId, COUNTOF(ccc), option) == HAL_OK); - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); - if (st == HAL_OK) { - result = true; - } else { + if (result) { + result = (HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout) == HAL_OK); + if (!result) { uint32_t err = HAL_I3C_GetError(&_hi3c); if ((err & HAL_I3C_ERROR_CE2) != 0U) { result = true; @@ -734,11 +726,8 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, COUNTOF(ccc), option) == HAL_OK); - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); - if (st == HAL_OK) { - result = true; - } + if (result) { + result = (HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout) == HAL_OK); } } } @@ -780,11 +769,8 @@ bool I3CBus::cccDirectRead(uint8_t targetAddr, COUNTOF(ccc), I3C_DIRECT_WITHOUT_DEFBYTE_RESTART) == HAL_OK); - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_ReceiveCCC(&_hi3c, &context, timeout); - if (st == HAL_OK) { - result = true; - } + if (result) { + result = (HAL_I3C_Ctrl_ReceiveCCC(&_hi3c, &context, timeout) == HAL_OK); } } @@ -947,21 +933,9 @@ void I3CBus::initAddressMap() bool I3CBus::isValidUsableDynamicAddr(uint8_t addr) const { - bool result = true; - - if ((addr == 0U) || (addr >= 0x7EU)) { - result = false; - } - - if (result && ((addr & 0x01U) != 0U)) { - result = false; - } - - return result; + return (((addr != 0U) && (addr < 0x7EU)) && (addr & 0x01U) == 0U); } - - bool I3CBus::isAddrFree(uint8_t addr) const { return (addr < 128U) && (_addrMap[addr] == I3CAddrState::Free); @@ -974,8 +948,6 @@ void I3CBus::markAddrUsed(uint8_t addr) } } - - void I3CBus::markAddrFree(uint8_t addr) { if ((addr < 128U) && (addr != 0x00U) && (addr != 0x7EU) && (addr != 0x7FU)) { @@ -1042,6 +1014,7 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, result = -3; stop = true; } else { + markAddrUsed(da); devices[count].dynAddr = da; count++; } From b6ed7616be7cdee7186127c3fc8879b98f718984 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 11:52:27 +0200 Subject: [PATCH 08/14] refactor(i3c): delegate kernel clock source selection to variant clock config Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 40 +++++++-------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index e9487d46ca..eb98ee878e 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -140,42 +140,16 @@ bool I3CBus::initGPIO() bool I3CBus::initClocks() { bool result = false; - HAL_StatusTypeDef hal_status = HAL_OK; - - if (_instance == I3C1) { #if defined(I3C1) - RCC_PeriphCLKInitTypeDef PeriphClkInit {}; - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I3C1; -#if defined(RCC_I3C1CLKSOURCE_PCLK1) - PeriphClkInit.I3c1ClockSelection = RCC_I3C1CLKSOURCE_PCLK1; -#else -#error "I3C1: no known PCLK source" -#endif - - hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - if (hal_status == HAL_OK) { - __HAL_RCC_I3C1_CLK_ENABLE(); - result = true; - } -#endif + if (_instance == I3C1) { + __HAL_RCC_I3C1_CLK_ENABLE(); + result = true; } -#if defined(I3C2) - else if (_instance == I3C2) { - RCC_PeriphCLKInitTypeDef PeriphClkInit {}; - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I3C2; -#if defined(RCC_I3C2CLKSOURCE_PCLK2) - PeriphClkInit.I3c2ClockSelection = RCC_I3C2CLKSOURCE_PCLK2; -#elif defined(RCC_I3C2CLKSOURCE_PCLK3) - PeriphClkInit.I3c2ClockSelection = RCC_I3C2CLKSOURCE_PCLK3; -#else -#error "I3C2: no known PCLK source" #endif - - hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - if (hal_status == HAL_OK) { - __HAL_RCC_I3C2_CLK_ENABLE(); - result = true; - } +#if defined(I3C2) + if (_instance == I3C2) { + __HAL_RCC_I3C2_CLK_ENABLE(); + result = true; } #endif From ea48f5e1c5bb31c8b65507824a16e46e21a2ecd6 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 12:05:21 +0200 Subject: [PATCH 09/14] Revert "fix(I3C): Increase minimum stack size for (H503RB - H563ZI)" This reverts commit bc2168519a386f242b0663f6522a0fe7424b42a5. --- variants/STM32H5xx/H503RBT/ldscript.ld | 2 +- variants/STM32H5xx/H563Z(G-I)T_H573ZIT/ldscript.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/variants/STM32H5xx/H503RBT/ldscript.ld b/variants/STM32H5xx/H503RBT/ldscript.ld index eca72facc5..3a3ba417b8 100644 --- a/variants/STM32H5xx/H503RBT/ldscript.ld +++ b/variants/STM32H5xx/H503RBT/ldscript.ld @@ -40,7 +40,7 @@ _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ _sstack = _estack - _Min_Stack_Size; _Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x1000; /* required amount of stack */ +_Min_Stack_Size = 0x400; /* required amount of stack */ /* Memories definition */ MEMORY { diff --git a/variants/STM32H5xx/H563Z(G-I)T_H573ZIT/ldscript.ld b/variants/STM32H5xx/H563Z(G-I)T_H573ZIT/ldscript.ld index 1c36625468..c9360eef52 100644 --- a/variants/STM32H5xx/H563Z(G-I)T_H573ZIT/ldscript.ld +++ b/variants/STM32H5xx/H563Z(G-I)T_H573ZIT/ldscript.ld @@ -40,7 +40,7 @@ _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ _sstack = _estack - _Min_Stack_Size; _Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x2000; /* required amount of stack */ +_Min_Stack_Size = 0x400; /* required amount of stack */ /* Memories definition */ MEMORY From 3449c5aa0dd47f0a0924efddd01477a3a004aee3 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Fri, 26 Jun 2026 12:02:44 +0200 Subject: [PATCH 10/14] chore(examples): switch examples to generic auto-resolved I3C bus Signed-off-by: Aymane Bahssain --- .../I3C/examples/BasicBegin/BasicBegin.ino | 7 +------ .../ControllerWrite/ControllerWrite.ino | 7 +++---- .../TargetReceive/TargetReceive.ino | 11 +++++------ .../I3C/examples/DeviceReady/DeviceReady.ino | 7 ++----- libraries/I3C/examples/ScanBus/ScanBus.ino | 4 ++-- .../TargetIBI/Controller/Controller.ino | 17 ++++++++--------- .../I3C/examples/TargetIBI/Target/Target.ino | 10 ++++------ .../Controller/Controller.ino | 9 ++++----- .../TargetNotifications/Target/Target.ino | 14 ++++++-------- 9 files changed, 35 insertions(+), 51 deletions(-) diff --git a/libraries/I3C/examples/BasicBegin/BasicBegin.ino b/libraries/I3C/examples/BasicBegin/BasicBegin.ino index 0883162220..18b03b47de 100644 --- a/libraries/I3C/examples/BasicBegin/BasicBegin.ino +++ b/libraries/I3C/examples/BasicBegin/BasicBegin.ino @@ -1,17 +1,12 @@ #include -// Choose the bus instance available on your board. - -#define I3C_BUS I3C1Bus - void setup() { Serial.begin(115200); while (!Serial) {} Serial.println("I3C Basic Begin"); - // Option 1: use default board I3C pins - if (!I3C_BUS.begin(1000000)) { + if (!I3C.begin(1000000)) { Serial.println("Failed to initialize I3C bus"); while (1) {} } diff --git a/libraries/I3C/examples/Controller_Target/ControllerWrite/ControllerWrite.ino b/libraries/I3C/examples/Controller_Target/ControllerWrite/ControllerWrite.ino index 103c37faca..5e049da80f 100644 --- a/libraries/I3C/examples/Controller_Target/ControllerWrite/ControllerWrite.ino +++ b/libraries/I3C/examples/Controller_Target/ControllerWrite/ControllerWrite.ino @@ -1,6 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus static I3CDiscoveredDevice devices[8]; void printHex2(uint8_t v) { @@ -15,13 +14,13 @@ void setup() { Serial.println("=== Controller Write / Target Receive ==="); - if (!I3C_BUS.begin(I3C_SDA, I3C_SCL, 1000000U)) { + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { Serial.println("begin() failed"); while (1) {} } size_t found = 0; - int rc = I3C_BUS.discover(devices, 8, &found); + int rc = I3C.discover(devices, 8, &found); if (rc != 0 || found == 0) { Serial.println("No target found"); @@ -43,7 +42,7 @@ void setup() { 0x0D, 0x0E, 0x0F, 0x10 }; - int wr = I3C_BUS.write(da, tx, sizeof(tx), 1000); + int wr = I3C.write(da, tx, sizeof(tx), 1000); Serial.print("write rc = "); Serial.println(wr); } diff --git a/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino b/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino index 0eba19a6bc..0dc26c76c9 100644 --- a/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino +++ b/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino @@ -1,6 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus static uint8_t rxBuf[16]; void printHex2(uint8_t v) { @@ -19,21 +18,21 @@ void setup() { cfg.identifier = 0x62; cfg.mipiIdentifier = 0x1; - if (!I3C_BUS.beginTarget(I3C_SDA, I3C_SCL, cfg)) { + if (!I3C.beginTarget(I3C_SDA, I3C_SCL, cfg)) { Serial.println("beginTarget failed"); while (1) {} } - while (!I3C_BUS.hasAddress()) { + while (!I3C.hasAddress()) { delay(10); } Serial.print("DA = 0x"); - Serial.println(I3C_BUS.address(), HEX); + Serial.println(I3C.address(), HEX); - HAL_I3C_FlushAllFifo(I3C_BUS.halHandle()); + HAL_I3C_FlushAllFifo(I3C.halHandle()); - int rc = I3C_BUS.receive(rxBuf, sizeof(rxBuf), 10000); + int rc = I3C.receive(rxBuf, sizeof(rxBuf), 10000); Serial.print("receive rc = "); Serial.println(rc); diff --git a/libraries/I3C/examples/DeviceReady/DeviceReady.ino b/libraries/I3C/examples/DeviceReady/DeviceReady.ino index 216cfb9be8..df9170a20e 100644 --- a/libraries/I3C/examples/DeviceReady/DeviceReady.ino +++ b/libraries/I3C/examples/DeviceReady/DeviceReady.ino @@ -1,22 +1,19 @@ #include -#define I3C_BUS I3C1Bus - - void setup() { Serial.begin(115200); while (!Serial) {} Serial.println("I3C Device Ready Example"); - if (!I3C_BUS.begin(1000000)) { + if (!I3C.begin(1000000)) { Serial.println("Failed to initialize I3C bus"); while (1) {} } for (uint8_t addr = 1; addr < 0x7F; ++addr) { - bool i3cReady = I3C_BUS.isI3CDeviceReady(addr); + bool i3cReady = I3C.isI3CDeviceReady(addr); if (i3cReady) { Serial.print("I3C device at DA 0x"); Serial.print(addr, HEX); diff --git a/libraries/I3C/examples/ScanBus/ScanBus.ino b/libraries/I3C/examples/ScanBus/ScanBus.ino index 230726c9fc..5dd40c32ba 100644 --- a/libraries/I3C/examples/ScanBus/ScanBus.ino +++ b/libraries/I3C/examples/ScanBus/ScanBus.ino @@ -21,14 +21,14 @@ void setup() { Serial.println("=== I3C ScanBus ==="); - if (!I3C1Bus.begin(I3C_SDA, I3C_SCL, 1000000U)) { + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { Serial.println("begin() failed"); while (1) {} } size_t found = 0; - int rc = I3C1Bus.discover(devices, 8, &found); + int rc = I3C.discover(devices, 8, &found); Serial.print("discover rc = "); Serial.println(rc); diff --git a/libraries/I3C/examples/TargetIBI/Controller/Controller.ino b/libraries/I3C/examples/TargetIBI/Controller/Controller.ino index 84c689cbb8..2029c3e8be 100644 --- a/libraries/I3C/examples/TargetIBI/Controller/Controller.ino +++ b/libraries/I3C/examples/TargetIBI/Controller/Controller.ino @@ -1,6 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus static I3CDiscoveredDevice devices[8]; static volatile bool callbackSeen = false; @@ -24,13 +23,13 @@ void setup() { Serial.println("=== Controller IBI Example ==="); - if (!I3C_BUS.begin(I3C_SDA, I3C_SCL, 1000000U)) { + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { Serial.println("begin() failed"); while (1) {} } size_t found = 0; - int rc = I3C_BUS.discover(devices, 8, &found); + int rc = I3C.discover(devices, 8, &found); if (rc != 0 || found == 0) { Serial.println("No target found"); @@ -39,13 +38,13 @@ void setup() { uint8_t da = devices[0].dynAddr; - I3C_BUS.onIbi(myIbiCallback, (void *)&callbackSeen); + I3C.onIbi(myIbiCallback, (void *)&callbackSeen); - rc = I3C_BUS.enableIbi(1, da, false, false, 1000); + rc = I3C.enableIbi(1, da, false, false, 1000); Serial.print("enableIbi rc = "); Serial.println(rc); - rc = I3C_BUS.enableControllerEvents(); + rc = I3C.enableControllerEvents(); Serial.print("enableControllerEvents rc = "); Serial.println(rc); @@ -53,15 +52,15 @@ void setup() { } void loop() { - if (I3C_BUS.hasIbi()) { + if (I3C.hasIbi()) { I3CControllerIbiInfo ibi{}; - if (I3C_BUS.peekIbi(ibi)) { + if (I3C.peekIbi(ibi)) { Serial.print("peekIbi source DA = 0x"); printHex2(ibi.sourceDa); Serial.println(); } - if (I3C_BUS.readIbi(ibi)) { + if (I3C.readIbi(ibi)) { Serial.print("readIbi source DA = 0x"); printHex2(ibi.sourceDa); Serial.println(); diff --git a/libraries/I3C/examples/TargetIBI/Target/Target.ino b/libraries/I3C/examples/TargetIBI/Target/Target.ino index 8026261dcd..89b03647a0 100644 --- a/libraries/I3C/examples/TargetIBI/Target/Target.ino +++ b/libraries/I3C/examples/TargetIBI/Target/Target.ino @@ -1,7 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus - void setup() { Serial.begin(115200); while (!Serial) {} @@ -15,21 +13,21 @@ void setup() { cfg.ibiRequest = true; cfg.ibiPayload = false; - if (!I3C_BUS.beginTarget(I3C_SDA, I3C_SCL, cfg)) { + if (!I3C.beginTarget(I3C_SDA, I3C_SCL, cfg)) { Serial.println("beginTarget failed"); while (1) {} } - while (!I3C_BUS.hasAddress()) { + while (!I3C.hasAddress()) { delay(10); } Serial.print("DA = 0x"); - Serial.println(I3C_BUS.address(), HEX); + Serial.println(I3C.address(), HEX); delay(2000); - int rc = I3C_BUS.sendIbi(nullptr, 0, 1000); + int rc = I3C.sendIbi(nullptr, 0, 1000); Serial.print("sendIbi rc = "); Serial.println(rc); } diff --git a/libraries/I3C/examples/TargetNotifications/Controller/Controller.ino b/libraries/I3C/examples/TargetNotifications/Controller/Controller.ino index aa9689ac49..32f4d62d35 100644 --- a/libraries/I3C/examples/TargetNotifications/Controller/Controller.ino +++ b/libraries/I3C/examples/TargetNotifications/Controller/Controller.ino @@ -1,6 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus static I3CDiscoveredDevice devices[8]; void printHex2(uint8_t v) { @@ -15,13 +14,13 @@ void setup() { Serial.println("=== Controller Trigger Target Events ==="); - if (!I3C_BUS.begin(I3C_SDA, I3C_SCL, 1000000U)) { + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { Serial.println("begin() failed"); while (1) {} } size_t found = 0; - int rc = I3C_BUS.discover(devices, 8, &found); + int rc = I3C.discover(devices, 8, &found); if (rc != 0 || found == 0) { Serial.println("No target found"); @@ -36,13 +35,13 @@ void setup() { delay(2000); - rc = I3C_BUS.setEvents(da, false, 0x01, 1000); // DISEC INTR + rc = I3C.setEvents(da, false, 0x01, 1000); // DISEC INTR Serial.print("DISEC(INTR) rc = "); Serial.println(rc); delay(5000); - rc = I3C_BUS.setEvents(da, true, 0x01, 1000); // ENEC INTR + rc = I3C.setEvents(da, true, 0x01, 1000); // ENEC INTR Serial.print("ENEC(INTR) rc = "); Serial.println(rc); } diff --git a/libraries/I3C/examples/TargetNotifications/Target/Target.ino b/libraries/I3C/examples/TargetNotifications/Target/Target.ino index 7e4c6c7a78..2c75593da4 100644 --- a/libraries/I3C/examples/TargetNotifications/Target/Target.ino +++ b/libraries/I3C/examples/TargetNotifications/Target/Target.ino @@ -1,7 +1,5 @@ #include "I3C.h" -#define I3C_BUS I3C1Bus - void setup() { Serial.begin(115200); while (!Serial) {} @@ -13,32 +11,32 @@ void setup() { cfg.identifier = 0x62; cfg.mipiIdentifier = 0x1; - if (!I3C_BUS.beginTarget(I3C_SDA, I3C_SCL, cfg)) { + if (!I3C.beginTarget(I3C_SDA, I3C_SCL, cfg)) { Serial.println("beginTarget failed"); while (1) {} } - while (!I3C_BUS.hasAddress()) { + while (!I3C.hasAddress()) { delay(10); } Serial.print("DA = 0x"); - Serial.println(I3C_BUS.address(), HEX); + Serial.println(I3C.address(), HEX); - int rc = I3C_BUS.enableTargetEvents(nullptr, HAL_I3C_IT_INTUPDIE); + int rc = I3C.enableTargetEvents(nullptr, HAL_I3C_IT_INTUPDIE); Serial.print("enableTargetEvents rc = "); Serial.println(rc); } void loop() { uint32_t eventId = 0; - if (I3C_BUS.readTargetEvent(eventId)) { + if (I3C.readTargetEvent(eventId)) { Serial.print("Target event = 0x"); Serial.println(eventId, HEX); if ((eventId & EVENT_ID_ENEC_DISEC) != 0U) { I3C_CCCInfoTypeDef info{}; - if (HAL_I3C_GetCCCInfo(I3C_BUS.halHandle(), EVENT_ID_ENEC_DISEC, &info) == HAL_OK) { + if (HAL_I3C_GetCCCInfo(I3C.halHandle(), EVENT_ID_ENEC_DISEC, &info) == HAL_OK) { Serial.print(" HotJoinAllowed = "); Serial.println(info.HotJoinAllowed ? "YES" : "NO"); From b2133ba183ebc9c708945530cac3c9dfa6669ab0 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Tue, 30 Jun 2026 15:20:41 +0200 Subject: [PATCH 11/14] fix(i3c): fix enableIbi return value handling Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index eb98ee878e..fc050673fb 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -1618,18 +1618,15 @@ int I3CBus::enableIbi(uint8_t deviceIndex, int result = -1; if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { - int rc = configureControllerDevice(deviceIndex, + result = configureControllerDevice(deviceIndex, dynAddr, true, withPayload, false, stopTransfer); - if (rc != 0) { - result = rc; - } else { - rc = setEvents(dynAddr, true, I3C_CCC_EVT_INTR, timeout); - result = rc; + if (result == 0) { + result = setEvents(dynAddr, true, I3C_CCC_EVT_INTR, timeout) ? 0 : -1; } } From d7441e38aeedd02c097cf516767dd502edacbda8 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Tue, 30 Jun 2026 17:25:29 +0200 Subject: [PATCH 12/14] ci(build): switch BareMinimum example to generic auto-resolved I3C bus Signed-off-by: Aymane Bahssain --- CI/build/examples/BareMinimum/BareMinimum.ino | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CI/build/examples/BareMinimum/BareMinimum.ino b/CI/build/examples/BareMinimum/BareMinimum.ino index 860ab074f1..7dc46a5c3d 100644 --- a/CI/build/examples/BareMinimum/BareMinimum.ino +++ b/CI/build/examples/BareMinimum/BareMinimum.ino @@ -14,7 +14,7 @@ #include #include #include -#if defined(I3C1_BASE) +#if defined(I3C1_BASE) || defined(I3C2_BASE) #include #endif @@ -135,18 +135,18 @@ void setup() { Wire.requestFrom(2, 1); Wire.end(); -#if defined(I3C1_BASE) +#if defined(I3C1_BASE) || defined(I3C2_BASE) // I3C - I3C1Bus.setBusType(I3CBusType::Pure); - I3C1Bus.setMixedBusOpenDrainFrequency(1000000U); - I3C1Bus.begin(I3C_SDA, I3C_SCL, 1000000U, I3CBusType::Pure, 1000000U); - I3C1Bus.setClock(1000000U); + I3C.setBusType(I3CBusType::Pure); + I3C.setMixedBusOpenDrainFrequency(1000000U); + I3C.begin(I3C_SDA, I3C_SCL, 1000000U, I3CBusType::Pure, 1000000U); + I3C.setClock(1000000U); uint8_t i3cData = 0; - I3C1Bus.isI3CDeviceReady(0x30, 1, 1); - I3C1Bus.isI2CDeviceReady(0x48, 1, 1); - I3C1Bus.readReg(0x30, 0x00, i3cData, 1); - I3C1Bus.readReg(0x48, 0x00, i3cData, I3CTransferType::I2C, 1); + I3C.isI3CDeviceReady(0x30, 1, 1); + I3C.isI2CDeviceReady(0x48, 1, 1); + I3C.readReg(0x30, 0x00, i3cData, 1); + I3C.readReg(0x48, 0x00, i3cData, I3CTransferType::I2C, 1); #endif // CMSIS DSP From 9e6a501921c12ca3eb46fd2e7c2f77d6e02db671 Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Wed, 1 Jul 2026 16:10:45 +0200 Subject: [PATCH 13/14] feat(i3c): add end() to deinitialize the active bus Signed-off-by: Aymane Bahssain --- libraries/I3C/src/I3C.cpp | 54 +++++++++++++++++++++++++++++++++++++++ libraries/I3C/src/I3C.h | 5 ++++ 2 files changed, 59 insertions(+) diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index fc050673fb..564a16be91 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -331,6 +331,60 @@ bool I3CBus::isTarget() const return _role == I3CRole::Target; } +void I3CBus::end() +{ + if (_initialized) { + disableIRQs(); + unregisterInstanceOwner(); + + (void)HAL_I3C_DeInit(&_hi3c); + + deinitGPIO(); + deinitClocks(); + + _initialized = false; + _role = I3CRole::None; + + _ibiPending = false; + _lastIbi = {}; + _targetEventPending = false; + _lastTargetEventId = 0U; + + std::memset(&_hi3c, 0, sizeof(_hi3c)); + _instance = nullptr; + } +} + +void I3CBus::deinitClocks() +{ +#if defined(I3C1) + if (_instance == I3C1) { + __HAL_RCC_I3C1_FORCE_RESET(); + __HAL_RCC_I3C1_RELEASE_RESET(); + __HAL_RCC_I3C1_CLK_DISABLE(); + } +#endif + +#if defined(I3C2) + if (_instance == I3C2) { + __HAL_RCC_I3C2_FORCE_RESET(); + __HAL_RCC_I3C2_RELEASE_RESET(); + __HAL_RCC_I3C2_CLK_DISABLE(); + } +#endif +} + +void I3CBus::deinitGPIO() +{ + if (_sdaPin != NC) { + pin_function(_sdaPin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + } + + if (_sclPin != NC) { + pin_function(_sclPin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + } +} + // ============================================================================ // Default I3C controller transfers // ============================================================================ diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index 269cbaeec2..97012b06b3 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -158,6 +158,8 @@ class I3CBus { bool isController() const; bool isTarget() const; + void end(); + // ------------------------------------------------------------------------ // Default I3C controller transfers // ------------------------------------------------------------------------ @@ -540,6 +542,9 @@ class I3CBus { void registerInstanceOwner(); void unregisterInstanceOwner(); + void deinitClocks(); + void deinitGPIO(); + // ------------------------------------------------------------------------ // Internal state // ------------------------------------------------------------------------ From 846339cf6a76f6cdd5afaf94cb8e4cbd704794fd Mon Sep 17 00:00:00 2001 From: Aymane Bahssain Date: Wed, 1 Jul 2026 16:18:11 +0200 Subject: [PATCH 14/14] chore(i3c): refresh Arduino keywords to match the current public API Signed-off-by: Aymane Bahssain --- libraries/I3C/keywords.txt | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/libraries/I3C/keywords.txt b/libraries/I3C/keywords.txt index 21407eb206..c0706cb177 100644 --- a/libraries/I3C/keywords.txt +++ b/libraries/I3C/keywords.txt @@ -1,17 +1,28 @@ I3CBus KEYWORD1 +I3C KEYWORD1 I3CDiscoveredDevice KEYWORD1 I3CKnownDevice KEYWORD1 I3CBusBeginConfig KEYWORD1 I3CTargetConfig KEYWORD1 I3CControllerIbiInfo KEYWORD1 I3CRole KEYWORD1 +I3CBusType KEYWORD1 +I3CTransferType KEYWORD1 +I3CControllerConfig KEYWORD1 begin KEYWORD2 beginTarget KEYWORD2 -beginBus KEYWORD2 discover KEYWORD2 -setBusFrequency KEYWORD2 +assignDynamicAddresses KEYWORD2 setClock KEYWORD2 +setBusType KEYWORD2 +getBusType KEYWORD2 +setMixedBusOpenDrainFrequency KEYWORD2 +getMixedBusOpenDrainFrequency KEYWORD2 +getRole KEYWORD2 +isController KEYWORD2 +isTarget KEYWORD2 +end KEYWORD2 write KEYWORD2 read KEYWORD2 @@ -20,31 +31,37 @@ readReg KEYWORD2 writeRegBuffer KEYWORD2 readRegBuffer KEYWORD2 +i2cWrite KEYWORD2 +i2cRead KEYWORD2 +i2cWriteRead KEYWORD2 +i2cWriteReg KEYWORD2 +i2cReadReg KEYWORD2 +i2cWriteRegBuffer KEYWORD2 +i2cReadRegBuffer KEYWORD2 +scanI2CDevices KEYWORD2 + isI2CDeviceReady KEYWORD2 isI3CDeviceReady KEYWORD2 resetDynamicAddresses KEYWORD2 disableEvents KEYWORD2 -disableAllEvents KEYWORD2 assignDynamicAddress KEYWORD2 assignAllStaticAsDynamic KEYWORD2 +setEvents KEYWORD2 getbcr KEYWORD2 getdcr KEYWORD2 getpid KEYWORD2 -entdaa KEYWORD2 - hasAddress KEYWORD2 address KEYWORD2 +configureTarget KEYWORD2 send KEYWORD2 receive KEYWORD2 sendIbi KEYWORD2 enableTargetEvents KEYWORD2 disableTargetEvents KEYWORD2 -availableTargetEvent KEYWORD2 -fetchTargetEvent KEYWORD2 hasTargetEvent KEYWORD2 readTargetEvent KEYWORD2 @@ -56,3 +73,5 @@ hasIbi KEYWORD2 peekIbi KEYWORD2 readIbi KEYWORD2 onIbi KEYWORD2 + +halHandle KEYWORD2