diff --git a/libraries/I3C/examples/BasicBegin/BasicBegin.ino b/libraries/I3C/examples/BasicBegin/BasicBegin.ino index 0883162220..7de8138d49 100644 --- a/libraries/I3C/examples/BasicBegin/BasicBegin.ino +++ b/libraries/I3C/examples/BasicBegin/BasicBegin.ino @@ -1,9 +1,5 @@ #include -// Choose the bus instance available on your board. - -#define I3C_BUS I3C1Bus - void setup() { Serial.begin(115200); while (!Serial) {} @@ -11,7 +7,7 @@ void setup() { 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"); diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index ed8791607c..fdf459cffa 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -9,12 +9,16 @@ #if defined(I3C1) I3CBus I3C1Bus(I3C1); + static I3CBus *g_i3c1Owner = nullptr; #endif #if defined(I3C2) I3CBus I3C2Bus(I3C2); + static I3CBus *g_i3c2Owner = nullptr; #endif +I3CBus I3C; + // ============================================================================ // File-local constants and helpers // ============================================================================ @@ -85,35 +89,44 @@ 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 } } -// ============================================================================ -// Low-level initialization -// ============================================================================ - -bool I3CBus::initGPIO() +// ------------------------------------------------------------------------ +// instance +// ------------------------------------------------------------------------ +bool I3CBus::prepareInstanceFromPins() { bool result = false; + I3C_TypeDef *resolved = nullptr; 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); + if (merged != (void *)NP) { + resolved = reinterpret_cast(merged); + } + } + + if (resolved != nullptr) { + if (_instanceFixed) { + if (resolved == _instance) { + result = true; + } + } else { + _instance = resolved; result = true; } } @@ -121,57 +134,37 @@ bool I3CBus::initGPIO() return result; } -bool I3CBus::initClocks() +// ============================================================================ +// Low-level initialization +// ============================================================================ + +bool I3CBus::initGPIO() { 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 + if ((_sdaPin != NC) && (_sclPin != NC) && (_instance != nullptr)) { + pinmap_pinout(_sdaPin, PinMap_I3C_SDA); + pinmap_pinout(_sclPin, PinMap_I3C_SCL); + result = true; + } - hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - if (hal_status == HAL_OK) { - __HAL_RCC_I3C1_CLK_ENABLE(); + return result; +} - 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); +bool I3CBus::initClocks() +{ + bool result = false; - result = true; - } + if (_instance == I3C1) { +#if defined(I3C1) + __HAL_RCC_I3C1_CLK_ENABLE(); + result = true; #endif } #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(); - - 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; - } + __HAL_RCC_I3C2_CLK_ENABLE(); + result = true; } #endif @@ -219,6 +212,7 @@ bool I3CBus::begin(uint32_t freq, const I3CControllerConfig &ctrlCfg) { bool result = false; + bool handlePrepared = false; if (_initialized) { result = true; @@ -229,7 +223,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; } @@ -241,11 +239,56 @@ bool I3CBus::begin(uint32_t freq, std::memset(&_hi3c, 0, sizeof(_hi3c)); _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_CONTROLLER; + handlePrepared = true; + 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; } } +#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 {}; @@ -276,19 +319,19 @@ bool I3CBus::begin(uint32_t freq, } if (local_ok) { - _initialized = true; - - if (freq == 0U) { - freq = 1000000U; - } - if (setClock(freq) != 0) { - local_ok = false; - } + registerInstanceOwner(); + _initialized = true; + _role = I3CRole::Controller; } - if (local_ok) { - _role = I3CRole::Controller; + if (!local_ok) { + if (handlePrepared) { + (void)HAL_I3C_DeInit(&_hi3c); + } + unregisterInstanceOwner(); + _initialized = false; + _role = I3CRole::None; } result = local_ok; @@ -409,7 +452,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; @@ -457,7 +500,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; @@ -504,7 +547,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; @@ -556,7 +599,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; @@ -677,46 +720,48 @@ 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; 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); + HAL_StatusTypeDef st = HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option); - 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; + } } } } @@ -726,18 +771,18 @@ 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; 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[] = { { @@ -748,26 +793,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; + + HAL_StatusTypeDef st = HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option); - 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; + } } } } @@ -776,15 +824,15 @@ 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; if (_initialized && (rxData != nullptr) && (rxLength != 0U)) { - uint32_t controlBuffer[0xFF]; + uint32_t controlBuffer[2] = {}; I3C_XferTypeDef context {}; I3C_CCCTypeDef ccc[] = { @@ -797,7 +845,7 @@ 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; @@ -938,9 +986,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; @@ -1071,6 +1119,7 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, result = -3; stop = true; } else { + markAddrUsed(da); devices[count].dynAddr = da; count++; } @@ -1434,6 +1483,7 @@ bool I3CBus::beginTarget(pin_size_t sda, pin_size_t scl, const I3CTargetConfig & bool I3CBus::beginTarget(const I3CTargetConfig &cfg) { bool result = false; + bool handlePrepared = false; if (_initialized) { if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { @@ -1442,7 +1492,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; } @@ -1454,6 +1508,7 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) std::memset(&_hi3c, 0, sizeof(_hi3c)); _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_TARGET; + handlePrepared = true; I3C_TgtTimingTypeDef inTiming {}; LL_I3C_TgtBusConfTypeDef outTgt {}; @@ -1508,11 +1563,21 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) if (local_ok) { _initialized = true; _role = I3CRole::Target; + registerInstanceOwner(); } else { _role = I3CRole::None; } result = local_ok; + + if (!local_ok) { + if (handlePrepared) { + (void)HAL_I3C_DeInit(&_hi3c); + } + unregisterInstanceOwner(); + _initialized = false; + _role = I3CRole::None; + } } return result; @@ -1654,7 +1719,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)); } @@ -1668,6 +1742,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; @@ -1757,7 +1835,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)); } @@ -1771,6 +1858,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; @@ -1843,32 +1934,124 @@ void I3CBus::handleHalNotify(uint32_t eventId) } // ============================================================================ -// 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) + 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 b642aceb5f..b8af924c27 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(I3C_TypeDef *inst = nullptr): _instance(inst), _instanceFixed(inst != 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 @@ -520,6 +525,14 @@ class I3CBus { static uint32_t bigToLittle32(uint32_t x); static uint64_t extractPid48FromEntdaaPayload(uint64_t payload); + // ------------------------------------------------------------------------ + // Irq helpers + // ------------------------------------------------------------------------ + bool enableIRQs(); + void disableIRQs(); + void registerInstanceOwner(); + void unregisterInstanceOwner(); + // ------------------------------------------------------------------------ // Internal state // ------------------------------------------------------------------------ @@ -537,10 +550,16 @@ class I3CBus { I3C_HandleTypeDef _hi3c{}; bool _initialized = false; I3C_TypeDef *_instance = nullptr; + bool _instanceFixed = false; I3CBusType _busType = I3CBusType::Pure; uint32_t _mixedBusOdFreq = 1000000U; + 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); }; @@ -557,4 +576,6 @@ class I3CBus { extern I3CBus I3C2Bus; #endif +extern I3CBus I3C; + #endif 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; 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