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 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"); 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 diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index ed8791607c..564a16be91 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -6,15 +6,16 @@ // ============================================================================ // Global bus instances // ============================================================================ - #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 +86,33 @@ 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; 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); + void *merged = pinmap_merge_peripheral( + pinmap_peripheral(_sdaPin, PinMap_I3C_SDA), + pinmap_peripheral(_sclPin, PinMap_I3C_SCL)); - if ((merged != (void *)NP) && (merged == _instance)) { - pinmap_pinout(_sdaPin, PinMap_I3C_SDA); - pinmap_pinout(_sclPin, PinMap_I3C_SCL); + if (merged != (void *)NP) { + _instance = reinterpret_cast(merged); result = true; } } @@ -121,57 +120,36 @@ 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 - - hal_status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - if (hal_status == HAL_OK) { - __HAL_RCC_I3C1_CLK_ENABLE(); + if ((_sdaPin != NC) && (_sclPin != NC) && (_instance != nullptr)) { + pinmap_pinout(_sdaPin, PinMap_I3C_SDA); + pinmap_pinout(_sclPin, PinMap_I3C_SCL); + result = true; + } - 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); + return result; +} - result = true; - } -#endif +bool I3CBus::initClocks() +{ + bool result = false; +#if defined(I3C1) + 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(); - - 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; - } +#if defined(I3C2) + if (_instance == I3C2) { + __HAL_RCC_I3C2_CLK_ENABLE(); + result = true; } #endif @@ -218,80 +196,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 (!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; - if (HAL_I3C_Init(&_hi3c) != HAL_OK) { - local_ok = false; - } - } - - 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; - } - } + LL_I3C_CtrlBusConfTypeDef outCtrl {}; - 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 (!buildControllerTiming(freq, outCtrl)) { + result = false; + } else { + _hi3c.Init.CtrlBusCharacteristic = outCtrl; } - } - - if (local_ok) { - _initialized = true; - if (freq == 0U) { - freq = 1000000U; + if (result) { + if (HAL_I3C_Init(&_hi3c) != HAL_OK) { + result = false; + } else { +#if defined(I3C_END_OF_FRAME_CPLT_ENABLE) + if (HAL_I3C_SetConfigEndOfFrame(&_hi3c, I3C_END_OF_FRAME_CPLT_ENABLE) != HAL_OK) { + result = false; + } +#endif + 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; @@ -317,60 +296,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; @@ -391,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 // ============================================================================ @@ -409,7 +403,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 +451,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 +498,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 +550,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,24 +645,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; } @@ -677,46 +665,46 @@ 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; - - 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); - - 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) { - result = true; + 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; + + result = (HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option) == HAL_OK); + + 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; + } } } } @@ -726,18 +714,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 +736,26 @@ 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; - if (st == HAL_OK) { - st = HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout); - if (st == HAL_OK) { - result = true; + result = (HAL_I3C_AddDescToFrame( + &_hi3c, + ccc, + nullptr, + &context, + COUNTOF(ccc), + option) == HAL_OK); + + if (result) { + result = (HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout) == HAL_OK); } } } @@ -776,15 +764,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,23 +785,20 @@ 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); - if (st == HAL_OK) { - result = true; - } + if (result) { + result = (HAL_I3C_Ctrl_ReceiveCCC(&_hi3c, &context, timeout) == HAL_OK); } } @@ -938,9 +923,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; @@ -976,21 +961,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); @@ -1003,8 +976,6 @@ void I3CBus::markAddrUsed(uint8_t addr) } } - - void I3CBus::markAddrFree(uint8_t addr) { if ((addr < 128U) && (addr != 0x00U) && (addr != 0x7EU) && (addr != 0x7FU)) { @@ -1071,6 +1042,7 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, result = -3; stop = true; } else { + markAddrUsed(da); devices[count].dynAddr = da; count++; } @@ -1440,98 +1412,52 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) result = (configureTarget(cfg) == 0); } } else { - bool local_ok = true; - - if (!initClocks()) { - local_ok = false; - } + _hi3c.Instance = nullptr; + _instance = nullptr; - 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; @@ -1556,7 +1482,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; } @@ -1654,7 +1579,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 +1602,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; @@ -1734,18 +1672,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; } } @@ -1757,7 +1692,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 +1715,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 +1791,191 @@ void I3CBus::handleHalNotify(uint32_t eventId) } // ============================================================================ -// IRQ handlers +// 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 & 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..97012b06b3 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 @@ -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; @@ -158,6 +158,8 @@ class I3CBus { bool isController() const; bool isTarget() const; + void end(); + // ------------------------------------------------------------------------ // Default I3C controller transfers // ------------------------------------------------------------------------ @@ -397,9 +399,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 +442,11 @@ class I3CBus { } private: + // ------------------------------------------------------------------------ + // Instance + // ------------------------------------------------------------------------ + bool prepareInstanceFromPins(); + enum class I3CAddrState : uint8_t { Free, Reserved, @@ -496,23 +503,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 +527,24 @@ 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; + + // ------------------------------------------------------------------------ + // Irq helpers + // ------------------------------------------------------------------------ + bool enableIRQs(); + void disableIRQs(); + void registerInstanceOwner(); + void unregisterInstanceOwner(); + + void deinitClocks(); + void deinitGPIO(); + // ------------------------------------------------------------------------ // Internal state // ------------------------------------------------------------------------ @@ -541,6 +566,11 @@ class I3CBus { 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); }; @@ -549,12 +579,6 @@ class I3CBus { // Global instances // ============================================================================ -#if defined(I3C1) - extern I3CBus I3C1Bus; -#endif - -#if defined(I3C2) - 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