diff --git a/CI/build/examples/BareMinimum/BareMinimum.ino b/CI/build/examples/BareMinimum/BareMinimum.ino index 340fb4e731..cab9b3cc03 100644 --- a/CI/build/examples/BareMinimum/BareMinimum.ino +++ b/CI/build/examples/BareMinimum/BareMinimum.ino @@ -15,7 +15,7 @@ #include #include #include -#if (defined(I3C1_BASE) || defined(I3C2_BASE)) && defined(HAL_I3C_MODULE_ENABLED) +#if defined(I3C1_BASE) || defined(I3C2_BASE) #include #endif @@ -137,7 +137,7 @@ void setup() { Wire.requestFrom(2, 1); Wire.end(); -#if (defined(I3C1_BASE) || defined(I3C2_BASE)) && defined(HAL_I3C_MODULE_ENABLED) +#if defined(I3C1_BASE) || defined(I3C2_BASE) // I3C I3C.setBusType(I3CBusType::Pure); I3C.setMixedBusOpenDrainFrequency(1000000U); diff --git a/cores/arduino/stm32/stm32yyxx_hal_conf.h b/cores/arduino/stm32/stm32yyxx_hal_conf.h index 42c18839c0..b4d7393229 100644 --- a/cores/arduino/stm32/stm32yyxx_hal_conf.h +++ b/cores/arduino/stm32/stm32yyxx_hal_conf.h @@ -54,6 +54,16 @@ #define USE_HAL_I2S_MODULE 1U #endif + #if defined(HAL_I3C_MODULE_DISABLED) + #if defined(USE_HAL_I3C_MODULE) + #undef USE_HAL_I3C_MODULE + #endif + #define USE_HAL_I3C_MODULE 0U + #else + #define USE_HAL_I3C_MODULE 1U + #define USE_HAL_I3C_GET_LAST_ERRORS 0U + #endif + #if defined(HAL_RTC_MODULE_DISABLED) #if defined(USE_HAL_RTC_MODULE) #undef USE_HAL_RTC_MODULE diff --git a/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino b/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino index 0dc26c76c9..00c5f2b6cb 100644 --- a/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino +++ b/libraries/I3C/examples/Controller_Target/TargetReceive/TargetReceive.ino @@ -30,7 +30,7 @@ void setup() { Serial.print("DA = 0x"); Serial.println(I3C.address(), HEX); - HAL_I3C_FlushAllFifo(I3C.halHandle()); + Serial.printf("flushAllFifos = %s\n", (I3C.flushAllFifos()) ? "true" : "false"); int rc = I3C.receive(rxBuf, sizeof(rxBuf), 10000); Serial.print("receive rc = "); diff --git a/libraries/I3C/src/I3C.cpp b/libraries/I3C/src/I3C.cpp index d0dc633c0a..cdf65061f7 100644 --- a/libraries/I3C/src/I3C.cpp +++ b/libraries/I3C/src/I3C.cpp @@ -2,7 +2,6 @@ #include #if defined(I3C1_BASE) || defined(I3C2_BASE) -#if !defined(USE_HALV2_DRIVER) // ============================================================================ // Global bus instances @@ -43,39 +42,41 @@ static constexpr uint8_t I3C_CCC_GETDCR_DIR = 0x8FU; static constexpr uint8_t I3C_CCC_ENEC_DIR = 0x80U; static constexpr uint8_t I3C_CCC_DISEC_DIR = 0x81U; -#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) +#if defined(USE_HALV2_DRIVER) + static constexpr hal_i3c_transfer_mode_t I3C_PRIVATE_WITH_ARB_RESTART_V2 = + static_cast(LL_I3C_CONTROLLER_MTYPE_PRIVATE); +#endif static bool isValidI3CTransferAddr(uint8_t addr) { return (addr != 0U) && (addr < 0x7EU); } -static uint8_t reconstructBcr(const I3C_BCRTypeDef &bcrInfo) +#if defined(USE_HALV2_DRIVER) +static uint8_t reconstructBcr(const hal_i3c_bcr_t &bcrInfo) { uint8_t bcr = 0U; - if (bcrInfo.MaxDataSpeedLimitation) { - bcr |= (1U << 0); - } - if (bcrInfo.IBIRequestCapable) { - bcr |= (1U << 1); - } - if (bcrInfo.IBIPayload) { - bcr |= (1U << 2); - } - if (bcrInfo.OfflineCapable) { - bcr |= (1U << 3); - } - if (bcrInfo.VirtualTargetSupport) { - bcr |= (1U << 4); - } - if (bcrInfo.AdvancedCapabilities) { - bcr |= (1U << 5); - } - if (bcrInfo.DeviceRole) { - bcr |= (1U << 6); - } + bcr |= (bcrInfo.max_data_speed_limitation ? (1U << 0) : 0U); + bcr |= (bcrInfo.ibi_request_capable ? (1U << 1) : 0U); + bcr |= (bcrInfo.ibi_payload ? (1U << 2) : 0U); + bcr |= (bcrInfo.offline_capable ? (1U << 3) : 0U); + bcr |= (bcrInfo.virtual_target_support ? (1U << 4) : 0U); + bcr |= (bcrInfo.advanced_capabilities ? (1U << 5) : 0U); + bcr |= (bcrInfo.ctrl_role ? (1U << 6) : 0U); +#else +static uint8_t reconstructBcr(const I3C_BCRTypeDef &bcrInfo) +{ + uint8_t bcr = 0U; + bcr |= (bcrInfo.MaxDataSpeedLimitation ? (1U << 0) : 0U); + bcr |= (bcrInfo.IBIRequestCapable ? (1U << 1) : 0U); + bcr |= (bcrInfo.IBIPayload ? (1U << 2) : 0U); + bcr |= (bcrInfo.OfflineCapable ? (1U << 3) : 0U); + bcr |= (bcrInfo.VirtualTargetSupport ? (1U << 4) : 0U); + bcr |= (bcrInfo.AdvancedCapabilities ? (1U << 5) : 0U); + bcr |= (bcrInfo.DeviceRole ? (1U << 6) : 0U); +#endif return bcr; } @@ -83,6 +84,18 @@ static uint8_t reconstructBcr(const I3C_BCRTypeDef &bcrInfo) // HAL callback bridge // ============================================================================ +#if defined(USE_HALV2_DRIVER) +extern "C" void HAL_I3C_NotifyCallback(hal_i3c_handle_t *hi3c, uint32_t eventId) +{ + if (hi3c != nullptr) { +#if defined(I3C1) + if ((hi3c->instance == HAL_I3C1) && (g_i3c1Owner != nullptr)) { + g_i3c1Owner->handleHalNotify(eventId); + } +#endif + } +} +#else extern "C" void HAL_I3C_NotifyCallback(I3C_HandleTypeDef *hi3c, uint32_t eventId) { if ((hi3c != nullptr) && (hi3c->Instance != nullptr)) { @@ -99,6 +112,7 @@ extern "C" void HAL_I3C_NotifyCallback(I3C_HandleTypeDef *hi3c, uint32_t eventId #endif } } +#endif // ------------------------------------------------------------------------ // instance @@ -141,16 +155,26 @@ bool I3CBus::initGPIO() bool I3CBus::initClocks() { bool result = false; + #if defined(I3C1) if (_instance == I3C1) { +#if defined(USE_HALV2_DRIVER) + HAL_RCC_I3C1_EnableClock(); +#else __HAL_RCC_I3C1_CLK_ENABLE(); +#endif result = true; } #endif + #if defined(I3C2) if (_instance == I3C2) { +#if !defined(USE_HALV2_DRIVER) __HAL_RCC_I3C2_CLK_ENABLE(); result = true; +#else + result = false; +#endif } #endif @@ -200,7 +224,11 @@ bool I3CBus::begin(uint32_t freq, bool result = true; if (!_initialized) { +#if defined(USE_HALV2_DRIVER) + std::memset(&_hi3c, 0, sizeof(_hi3c)); +#else _hi3c.Instance = nullptr; +#endif _instance = nullptr; _busType = type; @@ -211,6 +239,119 @@ bool I3CBus::begin(uint32_t freq, result = false; } else { std::memset(&_hi3c, 0, sizeof(_hi3c)); + +#if defined(USE_HALV2_DRIVER) + + hal_i3c_t halInstance = HAL_I3C1; + if (_instance != I3C1) { + result = false; + } else { + if (HAL_I3C_Init(&_hi3c, halInstance) != HAL_OK) { + result = false; + } + } + + if (result) { + hal_i3c_ctrl_config_t ctrlTimingCfg {}; + uint32_t srcFreq = HAL_I3C_GetClockFreq(&_hi3c); + + if (!buildControllerTiming(srcFreq, freq, _busType, _mixedBusOdFreq, ctrlTimingCfg)) { + result = false; + } else if (HAL_I3C_CTRL_SetConfig(&_hi3c, &ctrlTimingCfg) != HAL_OK) { + result = false; + } + } + +#if defined(LL_I3C_END_OF_FRAME_CPLT_ENABLE) + if (result) { + LL_I3C_SetEndOfFrameMode(_instance, LL_I3C_END_OF_FRAME_CPLT_ENABLE); + } +#endif + + if (result) { + hal_i3c_ctrl_fifo_config_t fifoCfg {}; + + fifoCfg.rx_fifo_threshold = static_cast(_ctrlCfg.rxFifoThreshold); + fifoCfg.tx_fifo_threshold = static_cast(_ctrlCfg.txFifoThreshold); + + const bool controlFifoEnabled = (_ctrlCfg.controlFifo != 0U); + const bool statusFifoEnabled = (_ctrlCfg.statusFifo != 0U); + + if (controlFifoEnabled && statusFifoEnabled) { + fifoCfg.ctrl_fifo = HAL_I3C_CTRL_FIFO_ALL; + } else if (controlFifoEnabled) { + fifoCfg.ctrl_fifo = HAL_I3C_CTRL_FIFO_CONTROL_ONLY; + } else if (statusFifoEnabled) { + fifoCfg.ctrl_fifo = HAL_I3C_CTRL_FIFO_STATUS_ONLY; + } else { + fifoCfg.ctrl_fifo = HAL_I3C_CTRL_FIFO_NONE; + } + + if (HAL_I3C_CTRL_SetConfigFifo(&_hi3c, &fifoCfg) != HAL_OK) { + result = false; + } + } + + if (result) { + if (HAL_I3C_CTRL_SetConfigOwnDynamicAddress(&_hi3c, _ctrlCfg.dynamicAddr) != HAL_OK) { + result = false; + } + } + + if (result) { + uint32_t stallFeatures = HAL_I3C_CTRL_STALL_NONE; + + if (_ctrlCfg.ackStall) { + stallFeatures |= HAL_I3C_CTRL_STALL_ACK; + } + if (_ctrlCfg.cccStall) { + stallFeatures |= HAL_I3C_CTRL_STALL_CCC; + } + if (_ctrlCfg.txStall) { + stallFeatures |= HAL_I3C_CTRL_STALL_TX; + } + if (_ctrlCfg.rxStall) { + stallFeatures |= HAL_I3C_CTRL_STALL_RX; + } + + if (HAL_I3C_CTRL_SetConfigStallTime(&_hi3c, _ctrlCfg.stallTime, stallFeatures) != HAL_OK) { + result = false; + } + } + + if (result) { + if (_ctrlCfg.hotJoinAllowed) { + if (HAL_I3C_CTRL_EnableHotJoinAllowed(&_hi3c) != HAL_OK) { + result = false; + } + } else { + if (HAL_I3C_CTRL_DisableHotJoinAllowed(&_hi3c) != HAL_OK) { + result = false; + } + } + } + + if (result) { + if (_ctrlCfg.highKeeperSDA) { + if (HAL_I3C_CTRL_EnableHighKeeperSDA(&_hi3c) != HAL_OK) { + result = false; + } + } else { + if (HAL_I3C_CTRL_DisableHighKeeperSDA(&_hi3c) != HAL_OK) { + result = false; + } + } + } + + if (result) { + _hi3c.mode = HAL_I3C_MODE_CTRL; + registerInstanceOwner(); + _initialized = true; + _role = I3CRole::Controller; + } + +#else + _hi3c.Instance = _instance; _hi3c.Mode = HAL_I3C_MODE_CONTROLLER; @@ -226,10 +367,8 @@ bool I3CBus::begin(uint32_t freq, 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; - } +#if defined(LL_I3C_END_OF_FRAME_CPLT_ENABLE) + LL_I3C_SetEndOfFrameMode(_instance, LL_I3C_END_OF_FRAME_CPLT_ENABLE); #endif if (result) { I3C_FifoConfTypeDef fifoCfg {}; @@ -263,10 +402,16 @@ bool I3CBus::begin(uint32_t freq, } } +#endif + if (!result) { +#if defined(USE_HALV2_DRIVER) + HAL_I3C_DeInit(&_hi3c); +#else if (_hi3c.Instance != nullptr) { (void)HAL_I3C_DeInit(&_hi3c); } +#endif unregisterInstanceOwner(); _initialized = false; _role = I3CRole::None; @@ -277,6 +422,7 @@ bool I3CBus::begin(uint32_t freq, return result; } + void I3CBus::setBusType(I3CBusType type) { _busType = type; @@ -297,26 +443,6 @@ uint32_t I3CBus::getMixedBusOpenDrainFrequency() const return _mixedBusOdFreq; } -bool I3CBus::setClock(uint32_t i3cFreq) -{ - bool result = false; - -#if !defined(HAL_I3C_MODULE_ENABLED) - (void)i3cFreq; -#else - if (_initialized && (i3cFreq != 0U)) { - LL_I3C_CtrlBusConfTypeDef outCtrl {}; - - if (buildControllerTiming(i3cFreq, outCtrl) && - (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) == HAL_OK)) { - result = true; - } - } -#endif - - return result; -} - I3CRole I3CBus::getRole() const { return _role; @@ -332,9 +458,45 @@ bool I3CBus::isTarget() const return _role == I3CRole::Target; } + + +bool I3CBus::setClock(uint32_t i3cFreq) +{ + bool result = false; + + if (_initialized && (i3cFreq != 0U)) { +#if defined(USE_HALV2_DRIVER) + if (_hi3c.mode == HAL_I3C_MODE_CTRL) { + hal_i3c_ctrl_config_t outCtrl {}; + + if (buildControllerTiming(getPeripheralClockFreq(), + i3cFreq, + _busType, + _mixedBusOdFreq, + outCtrl) && + (HAL_I3C_CTRL_SetConfig(&_hi3c, &outCtrl) == HAL_OK)) { + result = true; + } + } +#else + if (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) { + LL_I3C_CtrlBusConfTypeDef outCtrl {}; + + if (buildControllerTiming(i3cFreq, outCtrl) && + (HAL_I3C_Ctrl_BusCharacteristicConfig(&_hi3c, &outCtrl) == HAL_OK)) { + result = true; + } + } +#endif + } + + return result; +} + void I3CBus::end() { if (_initialized) { + disableIRQs(); unregisterInstanceOwner(); @@ -346,10 +508,12 @@ void I3CBus::end() _initialized = false; _role = I3CRole::None; +#if !defined(USE_HALV2_DRIVER) _ibiPending = false; _lastIbi = {}; _targetEventPending = false; _lastTargetEventId = 0U; +#endif std::memset(&_hi3c, 0, sizeof(_hi3c)); _instance = nullptr; @@ -360,17 +524,24 @@ void I3CBus::deinitClocks() { #if defined(I3C1) if (_instance == I3C1) { +#if defined(USE_HALV2_DRIVER) + HAL_RCC_I3C1_Reset(); + HAL_RCC_I3C1_DisableClock(); +#else __HAL_RCC_I3C1_FORCE_RESET(); __HAL_RCC_I3C1_RELEASE_RESET(); __HAL_RCC_I3C1_CLK_DISABLE(); +#endif } #endif #if defined(I3C2) if (_instance == I3C2) { +#if !defined(USE_HALV2_DRIVER) __HAL_RCC_I3C2_FORCE_RESET(); __HAL_RCC_I3C2_RELEASE_RESET(); __HAL_RCC_I3C2_CLK_DISABLE(); +#endif } #endif } @@ -378,14 +549,29 @@ void I3CBus::deinitClocks() void I3CBus::deinitGPIO() { if (_sdaPin != NC) { - pin_function(_sdaPin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + pin_function(_sdaPin, STM_PIN_DATA(STM_MODE_ANALOG, LL_GPIO_PULL_NO, 0)); } if (_sclPin != NC) { - pin_function(_sclPin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + pin_function(_sclPin, STM_PIN_DATA(STM_MODE_ANALOG, LL_GPIO_PULL_NO, 0)); } } +bool I3CBus::flushAllFifos() +{ + bool result = false; + + if (_initialized) { +#if defined(USE_HALV2_DRIVER) + result = (HAL_I3C_FlushAllFifos(&_hi3c) == HAL_OK); +#else + result = (HAL_I3C_FlushAllFifo(&_hi3c) == HAL_OK); +#endif + } + + return result; +} + // ============================================================================ // Default I3C controller transfers // ============================================================================ @@ -397,6 +583,30 @@ int I3CBus::write(uint8_t dynAddr, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_CTRL) && + isValidI3CTransferAddr(dynAddr) && + (buf != nullptr) && + (len != 0U)) { + uint32_t controlBuffer[1] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { dynAddr, static_cast(len), HAL_I3C_DIRECTION_WRITE }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, buf, static_cast(len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + HAL_I3C_PRIVATE_WITH_ARB_STOP) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && isValidI3CTransferAddr(dynAddr) && @@ -434,6 +644,7 @@ int I3CBus::write(uint8_t dynAddr, result = -static_cast(HAL_I3C_GetError(&_hi3c)); } } +#endif return result; } @@ -445,6 +656,27 @@ int I3CBus::read(uint8_t dynAddr, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_CTRL) && + isValidI3CTransferAddr(dynAddr) && + (buf != nullptr) && + (len != 0U)) { + uint32_t controlBuffer[1] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { dynAddr, static_cast(len), HAL_I3C_DIRECTION_READ }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxRx(&ctx, buf, static_cast(len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, priv, COUNTOF(priv), HAL_I3C_PRIVATE_WITH_ARB_STOP) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && isValidI3CTransferAddr(dynAddr) && @@ -482,6 +714,7 @@ int I3CBus::read(uint8_t dynAddr, result = -static_cast(HAL_I3C_GetError(&_hi3c)); } } +#endif return result; } @@ -497,6 +730,30 @@ int I3CBus::writeRegBuffer(uint8_t dynAddr, if ((!_initialized) || (pData == nullptr) || (len == 0U) || (len > 31U)) { result = -1; } else { +#if defined(USE_HALV2_DRIVER) + uint32_t controlBuffer[1] = {}; + uint8_t data[32] = {0}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { dynAddr, static_cast(1U + len), HAL_I3C_DIRECTION_WRITE }, + }; + + data[0] = reg; + memcpy(&data[1], pData, len); + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, data, static_cast(1U + len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + I3C_PRIVATE_WITH_ARB_RESTART_V2) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } else { + result = -1; + } +#else I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; uint32_t controlBuffer[1] = {}; @@ -533,6 +790,7 @@ int I3CBus::writeRegBuffer(uint8_t dynAddr, st = HAL_I3C_Ctrl_Transmit(&_hi3c, &context, timeout); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif } return result; @@ -549,6 +807,29 @@ int I3CBus::readRegBuffer(uint8_t dynAddr, if ((!_initialized) || (pData == nullptr) || (len == 0U) || (len > 32U)) { result = -1; } else { +#if defined(USE_HALV2_DRIVER) + uint32_t controlBuffer[2] = {}; + uint8_t regBuf[1] = { reg }; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { dynAddr, 1U, HAL_I3C_DIRECTION_WRITE }, + { dynAddr, static_cast(len), HAL_I3C_DIRECTION_READ }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 2U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, regBuf, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxRx(&ctx, pData, static_cast(len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + I3C_PRIVATE_WITH_ARB_RESTART_V2) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } else { + result = -1; + } +#else I3C_XferTypeDef context {}; I3C_PrivateTypeDef priv {}; uint32_t controlBuffer[1] = {}; @@ -618,6 +899,7 @@ int I3CBus::readRegBuffer(uint8_t dynAddr, } } } +#endif } return result; @@ -647,7 +929,16 @@ bool I3CBus::isI2CDeviceReady(uint8_t addr, uint32_t trials, uint32_t timeout) { bool result = false; if (_initialized) { +#if defined(USE_HALV2_DRIVER) + for (uint32_t i = 0U; i < trials; ++i) { + if (HAL_I3C_CTRL_PoolForDeviceI2cReady(&_hi3c, addr, timeout) == HAL_OK) { + result = true; + break; + } + } +#else result = (HAL_I3C_Ctrl_IsDeviceI2C_Ready(&_hi3c, addr, trials, timeout) == HAL_OK); +#endif } return result; } @@ -656,11 +947,21 @@ bool I3CBus::isI3CDeviceReady(uint8_t dynAddr, uint32_t trials, uint32_t timeout { bool result = false; if (_initialized) { +#if defined(USE_HALV2_DRIVER) + for (uint32_t i = 0U; i < trials; ++i) { + if (HAL_I3C_CTRL_PoolForDeviceI3cReady(&_hi3c, dynAddr, timeout) == HAL_OK) { + result = true; + break; + } + } +#else result = (HAL_I3C_Ctrl_IsDeviceI3C_Ready(&_hi3c, dynAddr, trials, timeout) == HAL_OK); +#endif } return result; } + // ============================================================================ // Low-level CCC helpers // ============================================================================ @@ -674,6 +975,45 @@ bool I3CBus::cccBroadcastWrite(uint8_t cccId, bool result = false; if (_initialized) { +#if defined(USE_HALV2_DRIVER) + uint32_t txControlBuffer[1] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_ccc_desc_t ccc[] = { + { 0x7EU, cccId, length, HAL_I3C_DIRECTION_WRITE }, + }; + + if (length <= I3C_CCC_TX_SCRATCH_MAX) { + hal_i3c_transfer_mode_t mode = withDefByte + ? HAL_I3C_CCC_BROADCAST_WITH_DEFBYTE_RESTART + : HAL_I3C_CCC_BROADCAST_WITHOUT_DEFBYTE_RESTART; + + result = (HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK); + + if (result) { + result = (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, txControlBuffer, 1U) == HAL_OK); + } + + if (result && (length != 0U)) { + result = (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, data, length) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_BuildTransferCtxCCC(&ctx, ccc, COUNTOF(ccc), mode) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout) == HAL_OK); + + if (!result) { + uint32_t err = LL_I3C_GetRegister_SER(_instance); + if ((err & HAL_I3C_CTRL_ERROR_2) == HAL_I3C_CTRL_ERROR_2) { + result = true; + } + } + } + } + +#else uint32_t controlBuffer[1] = {}; uint8_t txBuffer[I3C_CCC_TX_SCRATCH_MAX] = {}; I3C_XferTypeDef context {}; @@ -709,6 +1049,7 @@ bool I3CBus::cccBroadcastWrite(uint8_t cccId, } } } +#endif } return result; @@ -724,6 +1065,43 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, bool result = false; if (_initialized) { +#if defined(USE_HALV2_DRIVER) + uint32_t txControlBuffer[2] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_ccc_desc_t ccc[] = { + { + static_cast(targetAddr & 0x7FU), + cccId, + length, + HAL_I3C_DIRECTION_WRITE + }, + }; + + if (length <= I3C_CCC_TX_SCRATCH_MAX) { + hal_i3c_transfer_mode_t mode = withDefByte + ? HAL_I3C_CCC_DIRECT_WITH_DEFBYTE_RESTART + : HAL_I3C_CCC_DIRECT_WITHOUT_DEFBYTE_RESTART; + + result = (HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK); + + if (result) { + result = (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, txControlBuffer, 2U) == HAL_OK); + } + + if (result && (length != 0U)) { + result = (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, data, length) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_BuildTransferCtxCCC(&ctx, ccc, COUNTOF(ccc), mode) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout) == HAL_OK); + } + } + +#else uint32_t controlBuffer[2] = {}; uint8_t txBuffer[I3C_CCC_TX_SCRATCH_MAX] = {}; I3C_XferTypeDef context {}; @@ -759,6 +1137,7 @@ bool I3CBus::cccDirectWrite(uint8_t targetAddr, result = (HAL_I3C_Ctrl_TransmitCCC(&_hi3c, &context, timeout) == HAL_OK); } } +#endif } return result; @@ -773,6 +1152,40 @@ bool I3CBus::cccDirectRead(uint8_t targetAddr, bool result = false; if (_initialized && (rxData != nullptr) && (rxLength != 0U)) { +#if defined(USE_HALV2_DRIVER) + uint32_t rxControlBuffer[2] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_ccc_desc_t ccc[] = { + { + static_cast(targetAddr & 0x7FU), + cccId, + rxLength, + HAL_I3C_DIRECTION_READ + }, + }; + + result = (HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK); + + if (result) { + result = (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, rxControlBuffer, 2U) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_InitTransferCtxRx(&ctx, rxData, rxLength) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_BuildTransferCtxCCC(&ctx, + ccc, + COUNTOF(ccc), + HAL_I3C_CCC_DIRECT_WITHOUT_DEFBYTE_RESTART) == HAL_OK); + } + + if (result) { + result = (HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout) == HAL_OK); + } + +#else uint32_t controlBuffer[2] = {}; I3C_XferTypeDef context {}; @@ -801,6 +1214,7 @@ bool I3CBus::cccDirectRead(uint8_t targetAddr, if (result) { result = (HAL_I3C_Ctrl_ReceiveCCC(&_hi3c, &context, timeout) == HAL_OK); } +#endif } return result; @@ -898,10 +1312,17 @@ bool I3CBus::rstactWholeTarget() if (_initialized) { uint8_t defByte = I3C_CCC_RSTACT_RESET_WHOLE_TARGET; +#if defined(USE_HALV2_DRIVER) + if (HAL_I3C_CTRL_EnableResetPattern(&_hi3c) == HAL_OK) { + result = cccBroadcastWrite(I3C_CCC_RSTACT_BCAST, &defByte, 1U, true, 1000U); + (void)HAL_I3C_CTRL_DisableResetPattern(&_hi3c); + } +#else if (HAL_I3C_Ctrl_SetConfigResetPattern(&_hi3c, HAL_I3C_RESET_PATTERN_ENABLE) == HAL_OK) { result = cccBroadcastWrite(I3C_CCC_RSTACT_BCAST, &defByte, 1U, true, 1000U); (void)HAL_I3C_Ctrl_SetConfigResetPattern(&_hi3c, HAL_I3C_RESET_PATTERN_DISABLE); } +#endif } return result; @@ -914,10 +1335,17 @@ bool I3CBus::rstactPeripheralOnly() if (_initialized) { uint8_t defByte = I3C_CCC_RSTACT_PERIPHERAL_ONLY; +#if defined(USE_HALV2_DRIVER) + if (HAL_I3C_CTRL_EnableResetPattern(&_hi3c) == HAL_OK) { + result = cccBroadcastWrite(I3C_CCC_RSTACT_BCAST, &defByte, 1U, true, 1000U); + (void)HAL_I3C_CTRL_DisableResetPattern(&_hi3c); + } +#else if (HAL_I3C_Ctrl_SetConfigResetPattern(&_hi3c, HAL_I3C_RESET_PATTERN_ENABLE) == HAL_OK) { result = cccBroadcastWrite(I3C_CCC_RSTACT_BCAST, &defByte, 1U, true, 1000U); (void)HAL_I3C_Ctrl_SetConfigResetPattern(&_hi3c, HAL_I3C_RESET_PATTERN_DISABLE); } +#endif } return result; @@ -930,7 +1358,11 @@ bool I3CBus::setEvents(uint8_t dynAddr, { bool result = false; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_CTRL)) { +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { +#endif uint8_t ev = events; uint8_t cccId = enable ? I3C_CCC_ENEC_DIR : I3C_CCC_DISEC_DIR; result = cccDirectWrite(dynAddr, cccId, &ev, 1U, false, timeout); @@ -984,6 +1416,7 @@ void I3CBus::markAddrFree(uint8_t addr) } } + uint8_t I3CBus::allocNextDynamicAddr(uint8_t start) const { uint8_t result = 0U; @@ -1006,7 +1439,6 @@ uint8_t I3CBus::allocNextDynamicAddr(uint8_t start) const // ============================================================================ // 11. Discovery and address assignment flow // ============================================================================ - int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, size_t maxDevices, uint8_t firstDynAddr, @@ -1017,13 +1449,58 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, if ((!_initialized) || (devices == nullptr) || (maxDevices == 0U)) { result = -1; } else { - HAL_StatusTypeDef st = HAL_OK; - uint64_t entdaaPayload = 0ULL; - size_t count = 0U; - bool stop = false; + uint64_t entdaaPayload = 0ULL; + size_t count = 0U; + bool stop = false; uint8_t nextDynAddr = (firstDynAddr != 0U) ? firstDynAddr : 0x10U; +#if defined(USE_HALV2_DRIVER) + + do { + entdaaPayload = 0ULL; + + hal_i3c_dyn_addr_opt_t dynOpt = (count == 0U) + ? HAL_I3C_DYN_ADDR_RSTDAA_THEN_ENTDAA + : HAL_I3C_DYN_ADDR_ONLY_ENTDAA; + + hal_i3c_target_detection_status_t detected = HAL_I3C_TGT_NOT_DETECTED; + hal_status_t st = HAL_I3C_CTRL_DynAddrAssign(&_hi3c, + &entdaaPayload, + dynOpt, + &detected, + timeout); + + if (st != HAL_OK) { + result = -1; + stop = true; + } else if (detected == HAL_I3C_TGT_DETECTED) { + if (count >= maxDevices) { + result = -2; + stop = true; + } else { + uint8_t da = nextDynAddr; + nextDynAddr = static_cast(nextDynAddr + 2U); + + if (HAL_I3C_CTRL_SetDynAddr(&_hi3c, da) != HAL_OK) { + result = -3; + stop = true; + } else { + markAddrUsed(da); + devices[count].dynAddr = da; + count++; + } + } + } else { + result = static_cast(count); + stop = true; + } + } while (!stop); + +#else + + HAL_StatusTypeDef st = HAL_OK; + do { entdaaPayload = 0ULL; @@ -1044,7 +1521,7 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, stop = true; } else { markAddrUsed(da); - devices[count].dynAddr = da; + devices[count].dynAddr = da; count++; } } @@ -1057,6 +1534,8 @@ int I3CBus::assignDynamicAddresses(I3CDiscoveredDevice *devices, if ((!stop) && (st == HAL_OK)) { result = static_cast(count); } + +#endif } return result; @@ -1133,29 +1612,106 @@ int I3CBus::assignKnownDevices(const I3CKnownDevice *knownDevices, } } } - } - - return result; -} - -int I3CBus::doDaaPhase(const I3CBusBeginConfig &cfg, - const I3CKnownDevice *knownDevices, - size_t numKnownDevices, - I3CDiscoveredDevice *discovered, - size_t maxDiscovered, - size_t &count) -{ - int result = 0; - bool done = false; - - HAL_StatusTypeDef st; - uint64_t payload = 0ULL; - uint8_t nextAddr = cfg.firstAutoDynAddr ? cfg.firstAutoDynAddr : 0x10U; + } + + return result; +} + +int I3CBus::doDaaPhase(const I3CBusBeginConfig &cfg, + const I3CKnownDevice *knownDevices, + size_t numKnownDevices, + I3CDiscoveredDevice *discovered, + size_t maxDiscovered, + size_t &count) +{ + int result = 0; + bool done = false; + + uint64_t payload = 0ULL; + uint8_t nextAddr = cfg.firstAutoDynAddr ? cfg.firstAutoDynAddr : 0x10U; + + while (!done) { + payload = 0ULL; + +#if defined(USE_HALV2_DRIVER) + + hal_i3c_target_detection_status_t detected = HAL_I3C_TGT_NOT_DETECTED; + hal_status_t st = HAL_I3C_CTRL_DynAddrAssign(&_hi3c, + &payload, + HAL_I3C_DYN_ADDR_ONLY_ENTDAA, + &detected, + 1000U); + + if (st != HAL_OK) { + result = -1; + done = true; + } else if (detected == HAL_I3C_TGT_NOT_DETECTED) { + result = 0; + done = true; + } else { + hal_i3c_entdaa_payload_t info {}; + if (HAL_I3C_CTRL_GetENTDAA_PayloadInfo(payload, &info) != HAL_OK) { + result = -2; + done = true; + } else { + uint64_t pid48 = extractPid48FromEntdaaPayload(payload); + + uint8_t chosen = 0U; + + if (knownDevices != nullptr) { + for (size_t i = 0; i < numKnownDevices; ++i) { + const auto &kd = knownDevices[i]; + + if (!kd.present || (kd.pid == 0U)) { + continue; + } + + if (kd.pid == pid48) { + uint8_t pref = kd.preferredDynAddr; + if ((pref != 0U) && isValidUsableDynamicAddr(pref) && isAddrFree(pref)) { + chosen = pref; + } + break; + } + } + } + + if (chosen == 0U) { + chosen = allocNextDynamicAddr(nextAddr); + if (chosen == 0U) { + result = -3; + done = true; + } + } + + if (!done) { + if (HAL_I3C_CTRL_SetDynAddr(&_hi3c, chosen) != HAL_OK) { + result = -4; + done = true; + } else { + markAddrUsed(chosen); + + if (count < maxDiscovered) { + auto &d = discovered[count++]; + d.dynAddr = chosen; + d.staticAddr = 0U; + d.bcr = reconstructBcr(info.bcr); + d.dcr = static_cast(info.dcr); + d.pid = pid48; + d.entdaaPayloadRaw = payload; + d.fromDaa = true; + d.matchedKnown = false; + } + + nextAddr = static_cast(chosen + 2U); + } + } + } + } - while (!done) { - payload = 0ULL; +#else - st = HAL_I3C_Ctrl_DynAddrAssign(&_hi3c, &payload, I3C_ONLY_ENTDAA, 1000U); + HAL_StatusTypeDef st = HAL_I3C_Ctrl_DynAddrAssign(&_hi3c, &payload, I3C_ONLY_ENTDAA, 1000U); if (st == HAL_OK) { result = 0; @@ -1223,19 +1779,44 @@ int I3CBus::doDaaPhase(const I3CBusBeginConfig &cfg, } } } + +#endif } return result; } + + int I3CBus::configBusDevicesFromDiscovery(const I3CDiscoveredDevice *discovered, size_t count) { int result = 0; if ((discovered != nullptr) && (count != 0U)) { - I3C_DeviceConfTypeDef desc[4] {}; uint8_t n = 0U; +#if defined(USE_HALV2_DRIVER) + + hal_i3c_ctrl_device_config_t desc[4] {}; + + for (size_t i = 0; (i < count) && (n < 4U); ++i) { + desc[n].device_index = n; + desc[n].tgt_dynamic_addr = discovered[i].dynAddr; + desc[n].ibi_ack = HAL_I3C_CTRL_IBI_ACK_DISABLED; + desc[n].ctrl_role_req_ack = HAL_I3C_CTRL_ROLE_ACK_DISABLED; + desc[n].ctrl_stop_transfer = HAL_I3C_CTRL_STOP_TRANSFER_DISABLED; + desc[n].ibi_payload = HAL_I3C_CTRL_IBI_PAYLOAD_DISABLED; + ++n; + } + + if (n != 0U) { + result = (HAL_I3C_CTRL_SetConfigBusDevices(&_hi3c, desc, n) == HAL_OK) ? 0 : -1; + } + +#else + + I3C_DeviceConfTypeDef desc[4] {}; + for (size_t i = 0; (i < count) && (n < 4U); ++i) { desc[n].DeviceIndex = static_cast(n + 1U); desc[n].TargetDynamicAddr = discovered[i].dynAddr; @@ -1249,11 +1830,13 @@ int I3CBus::configBusDevicesFromDiscovery(const I3CDiscoveredDevice *discovered, if (n != 0U) { result = (HAL_I3C_Ctrl_ConfigBusDevices(&_hi3c, desc, n) == HAL_OK) ? 0 : -1; } + +#endif } return result; } - +///////////////////////////////// int I3CBus::discover(const I3CBusBeginConfig &cfg, const I3CKnownDevice *knownDevices, size_t numKnownDevices, @@ -1392,6 +1975,24 @@ uint64_t I3CBus::extractPid48FromEntdaaPayload(uint64_t payload) return pid & 0xFFFFFFFFFFFFULL; } +#if defined(USE_HALV2_DRIVER) +int I3CBus::HAL_I3C_GetError(const hal_i3c_handle_t &hi3c, hal_status_t st) +{ + int result = 0; + + if (st != HAL_OK) { +#if defined(USE_HAL_I3C_GET_LAST_ERRORS) && (USE_HAL_I3C_GET_LAST_ERRORS == 1) + result = -static_cast(HAL_I3C_GetLastErrorCodes(&hi3c)); +#else + (void)hi3c; + result = -1; +#endif + } + + return result; +} +#endif + // ============================================================================ // Target-mode initialization // ============================================================================ @@ -1408,6 +2009,53 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) { bool result = false; +#if defined(USE_HALV2_DRIVER) + + if (_initialized) { + if (_hi3c.mode == HAL_I3C_MODE_TGT) { + result = (configureTarget(cfg) == 0); + } + } else { + std::memset(&_hi3c, 0, sizeof(_hi3c)); + _instance = nullptr; + + if (prepareInstanceFromPins() && initClocks() && initGPIO()) { + hal_i3c_t halInstance = HAL_I3C1; + if (_instance == I3C1) { + if (HAL_I3C_Init(&_hi3c, halInstance) != HAL_OK) { + result = false; + } else { + hal_i3c_tgt_config_t tgtCfg {}; + + if (buildTargetTiming(getPeripheralClockFreq(), tgtCfg) && + (HAL_I3C_TGT_SetConfig(&_hi3c, &tgtCfg) == HAL_OK)) { + hal_i3c_tgt_fifo_config_t fifoCfg {}; + fifoCfg.rx_fifo_threshold = HAL_I3C_RX_FIFO_THRESHOLD_1_8; + fifoCfg.tx_fifo_threshold = HAL_I3C_TX_FIFO_THRESHOLD_1_8; + + if (HAL_I3C_TGT_SetConfigFifo(&_hi3c, &fifoCfg) == HAL_OK) { + if (configureTarget(cfg) == 0) { + _initialized = true; + _role = I3CRole::Target; + registerInstanceOwner(); + result = true; + } + } + } + } + + if (!result) { + unregisterInstanceOwner(); + HAL_I3C_DeInit(&_hi3c); + _initialized = false; + _role = I3CRole::None; + } + } + } + } + +#else + if (_initialized) { if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { result = (configureTarget(cfg) == 0); @@ -1452,12 +2100,68 @@ bool I3CBus::beginTarget(const I3CTargetConfig &cfg) } } } + +#endif + return result; } int I3CBus::configureTarget(const I3CTargetConfig &cfg) { int result = -1; + +#if defined(USE_HALV2_DRIVER) + + if (_hi3c.mode == HAL_I3C_MODE_TGT) { + hal_i3c_tgt_config_payload_entdaa_t entdaaCfg {}; + hal_i3c_tgt_ibi_config_t ibiCfg {}; + hal_i3c_tgt_getmxds_config_t getmxdsCfg {}; + hal_status_t st = HAL_OK; + + entdaaCfg.identifier = cfg.identifier; + entdaaCfg.mipi_identifier = cfg.mipiIdentifier; + entdaaCfg.ctrl_role = cfg.ctrlCapability ? HAL_I3C_CTRL_ROLE_ENABLED : HAL_I3C_CTRL_ROLE_DISABLED; + entdaaCfg.ibi_payload = cfg.ibiPayload ? HAL_I3C_IBI_PAYLOAD_ENABLED : HAL_I3C_IBI_PAYLOAD_DISABLED; + entdaaCfg.max_data_speed_limitation = cfg.maxSpeedLimitation ? HAL_I3C_MAX_SPEED_LIMITATION_ENABLED : HAL_I3C_MAX_SPEED_LIMITATION_DISABLED; + + ibiCfg.ibi_payload_size_byte = static_cast(cfg.ibiPayloadSize); + ibiCfg.pending_read_mdb = cfg.pendingReadMDB ? HAL_I3C_PENDING_READ_MDB_ENABLED : HAL_I3C_PENDING_READ_MDB_DISABLED; + + getmxdsCfg.getmxds_format = static_cast(cfg.maxDataSpeed); + getmxdsCfg.ctrl_handoff_activity = static_cast(cfg.handOffActivityState); + getmxdsCfg.data_turnaround_duration = static_cast(cfg.dataTurnAroundDuration); + getmxdsCfg.max_read_turnaround = cfg.maxReadTurnAround; + + st = HAL_I3C_TGT_SetPayloadENTDAAConfig(&_hi3c, &entdaaCfg); + if (st == HAL_OK) { + st = HAL_I3C_TGT_SetConfigIBI(&_hi3c, &ibiCfg); + } + if (st == HAL_OK) { + st = HAL_I3C_TGT_SetConfigMaxDataSize(&_hi3c, cfg.maxReadDataSize, cfg.maxWriteDataSize); + } + if (st == HAL_OK) { + st = HAL_I3C_TGT_SetConfigGETMXDS(&_hi3c, &getmxdsCfg); + } + if (st == HAL_OK) { + st = cfg.ctrlRoleRequest ? HAL_I3C_TGT_EnableCtrlRoleRequest(&_hi3c) : HAL_I3C_TGT_DisableCtrlRoleRequest(&_hi3c); + } + if (st == HAL_OK) { + st = cfg.hotJoinRequest ? HAL_I3C_TGT_EnableHotJoinRequest(&_hi3c) : HAL_I3C_TGT_DisableHotJoinRequest(&_hi3c); + } + if (st == HAL_OK) { + st = cfg.ibiRequest ? HAL_I3C_TGT_EnableIBI(&_hi3c) : HAL_I3C_TGT_DisableIBI(&_hi3c); + } + if (st == HAL_OK) { + st = cfg.groupAddrCapability ? HAL_I3C_TGT_EnableGroupAddrCapability(&_hi3c) : HAL_I3C_TGT_DisableGroupAddrCapability(&_hi3c); + } + if (st == HAL_OK) { + st = cfg.handOffDelay ? HAL_I3C_TGT_EnableHandOffDelay(&_hi3c) : HAL_I3C_TGT_DisableHandOffDelay(&_hi3c); + } + result = HAL_I3C_GetError(_hi3c, st); + } + +#else + if (_hi3c.Mode == HAL_I3C_MODE_TARGET) { I3C_TgtConfTypeDef tgtCfg {}; @@ -1483,6 +2187,9 @@ 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)); } + +#endif + return result; } @@ -1491,9 +2198,13 @@ bool I3CBus::hasAddress() const bool result = false; if (_initialized && +#if defined(USE_HALV2_DRIVER) + (_hi3c.mode == HAL_I3C_MODE_TGT) && +#else (_hi3c.Mode == HAL_I3C_MODE_TARGET) && - (_hi3c.Instance != nullptr)) { - result = (LL_I3C_IsEnabledOwnDynAddress(_hi3c.Instance) == 1U); +#endif + (_instance != nullptr)) { + result = (LL_I3C_IsEnabledOwnDynAddress(_instance) == 1U); } return result; @@ -1504,7 +2215,7 @@ uint8_t I3CBus::address() const uint8_t result = 0U; if (hasAddress()) { - result = LL_I3C_GetOwnDynamicAddress(_hi3c.Instance); + result = LL_I3C_GetOwnDynamicAddress(_instance); } return result; @@ -1520,6 +2231,15 @@ int I3CBus::send(uint8_t *buf, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_TGT) && + (buf != nullptr) && + (len != 0U)) { + hal_status_t st = HAL_I3C_TGT_Transmit(&_hi3c, buf, len, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET) && (buf != nullptr) && @@ -1531,6 +2251,7 @@ int I3CBus::send(uint8_t *buf, HAL_StatusTypeDef st = HAL_I3C_Tgt_Transmit(&_hi3c, &xfer, timeout); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif return result; } @@ -1541,6 +2262,15 @@ int I3CBus::receive(uint8_t *buf, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_TGT) && + (buf != nullptr) && + (len != 0U)) { + hal_status_t st = HAL_I3C_TGT_Receive(&_hi3c, buf, len, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET) && (buf != nullptr) && @@ -1552,6 +2282,7 @@ int I3CBus::receive(uint8_t *buf, HAL_StatusTypeDef st = HAL_I3C_Tgt_Receive(&_hi3c, &xfer, timeout); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif return result; } @@ -1566,22 +2297,45 @@ int I3CBus::sendIbi(const uint8_t *payload, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_TGT)) { + hal_status_t st = HAL_I3C_TGT_IBIReq(&_hi3c, payload, payloadSize, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET)) { HAL_StatusTypeDef st = HAL_I3C_Tgt_IBIReq(&_hi3c, payload, payloadSize, timeout); result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif return result; } - -int I3CBus::enableTargetEvents(I3C_XferTypeDef *pXferData, +int I3CBus::enableTargetEvents(const I3CTargetEventConfig &cfg, uint32_t interruptMask) { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_TGT)) { + enableIRQs(); + hal_status_t st = HAL_I3C_TGT_ActivateNotification(&_hi3c, cfg.rxData, cfg.rxSize, interruptMask); + if (st != HAL_OK) { + disableIRQs(); + } + result = HAL_I3C_GetError(_hi3c, st); + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_TARGET)) { + I3C_XferTypeDef xfer {}; + I3C_DataTypeDef rxBuf {}; + + rxBuf.pBuffer = cfg.rxData; + rxBuf.Size = cfg.rxSize; + xfer.RxBuf = rxBuf; + enableIRQs(); - HAL_StatusTypeDef st = HAL_I3C_ActivateNotification(&_hi3c, pXferData, interruptMask); + HAL_StatusTypeDef st = HAL_I3C_ActivateNotification(&_hi3c, &xfer, interruptMask); if (st != HAL_OK) { if (_hi3c.Instance->IER == 0U) { disableIRQs(); @@ -1589,6 +2343,7 @@ int I3CBus::enableTargetEvents(I3C_XferTypeDef *pXferData, } result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif return result; } @@ -1597,6 +2352,16 @@ int I3CBus::disableTargetEvents(uint32_t interruptMask) { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_TGT)) { + hal_status_t st = HAL_I3C_TGT_DeactivateNotification(&_hi3c, interruptMask); + result = HAL_I3C_GetError(_hi3c, st); + + if ((st == HAL_OK) && (LL_I3C_GetEnabledIT(_instance) == 0U)) { + disableIRQs(); + } + } +#else 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)); @@ -1605,6 +2370,7 @@ int I3CBus::disableTargetEvents(uint32_t interruptMask) disableIRQs(); } } +#endif return result; } @@ -1629,6 +2395,42 @@ bool I3CBus::readTargetEvent(uint32_t &eventId) return result; } +bool I3CBus::getTargetCccInfo(uint32_t eventId, I3CTargetCccInfo &out) +{ + bool result = false; + out = {}; + +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_TGT) && + ((eventId & HAL_I3C_TGT_NOTIFICATION_ENEC_DISEC) != 0U)) { + hal_i3c_ccc_info_t info {}; + + if (HAL_I3C_GetCCCInfo(&_hi3c, HAL_I3C_TGT_NOTIFICATION_ENEC_DISEC, &info) == HAL_OK) { + out.hotJoinAllowed = (info.hot_join_allowed != 0U); + out.inBandAllowed = (info.in_band_allowed != 0U); + out.ctrlRoleAllowed = (info.ctrl_role_allowed != 0U); + result = true; + } + } +#else + if (_initialized && + (_hi3c.Mode == HAL_I3C_MODE_TARGET) && + ((eventId & EVENT_ID_ENEC_DISEC) != 0U)) { + I3C_CCCInfoTypeDef info {}; + + if (HAL_I3C_GetCCCInfo(&_hi3c, EVENT_ID_ENEC_DISEC, &info) == HAL_OK) { + out.hotJoinAllowed = (info.HotJoinAllowed != 0U); + out.inBandAllowed = (info.InBandAllowed != 0U); + out.ctrlRoleAllowed = (info.CtrlRoleAllowed != 0U); + result = true; + } + } +#endif + + return result; +} + // ============================================================================ // Controller-side IBI support // ============================================================================ @@ -1642,6 +2444,27 @@ int I3CBus::configureControllerDevice(uint8_t deviceIndex, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_CTRL)) { + if ((deviceIndex >= 1U) && (deviceIndex <= 4U)) { + hal_i3c_ctrl_device_config_t desc {}; + + desc.device_index = static_cast(deviceIndex - 1U); + desc.tgt_dynamic_addr = dynAddr; + desc.ibi_ack = ibiAck ? HAL_I3C_CTRL_IBI_ACK_ENABLED + : HAL_I3C_CTRL_IBI_ACK_DISABLED; + desc.ibi_payload = ibiPayload ? HAL_I3C_CTRL_IBI_PAYLOAD_ENABLED + : HAL_I3C_CTRL_IBI_PAYLOAD_DISABLED; + desc.ctrl_role_req_ack = ctrlRoleReqAck ? HAL_I3C_CTRL_ROLE_ACK_ENABLED + : HAL_I3C_CTRL_ROLE_ACK_DISABLED; + desc.ctrl_stop_transfer = stopTransfer ? HAL_I3C_CTRL_STOP_TRANSFER_ENABLED + : HAL_I3C_CTRL_STOP_TRANSFER_DISABLED; + + hal_status_t st = HAL_I3C_CTRL_SetConfigBusDevices(&_hi3c, &desc, 1U); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { if ((deviceIndex >= 1U) && (deviceIndex <= 4U)) { I3C_DeviceConfTypeDef desc {}; @@ -1657,6 +2480,7 @@ int I3CBus::configureControllerDevice(uint8_t deviceIndex, result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } } +#endif return result; } @@ -1669,7 +2493,11 @@ int I3CBus::enableIbi(uint8_t deviceIndex, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_CTRL)) { +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { +#endif result = configureControllerDevice(deviceIndex, dynAddr, true, @@ -1689,6 +2517,16 @@ int I3CBus::enableControllerEvents(uint32_t interruptMask) { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_CTRL)) { + enableIRQs(); + hal_status_t st = HAL_I3C_CTRL_ActivateNotification(&_hi3c, interruptMask); + if (st != HAL_OK) { + disableIRQs(); + } + result = HAL_I3C_GetError(_hi3c, st); + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER)) { enableIRQs(); HAL_StatusTypeDef st = HAL_I3C_ActivateNotification(&_hi3c, nullptr, interruptMask); @@ -1699,6 +2537,7 @@ int I3CBus::enableControllerEvents(uint32_t interruptMask) } result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); } +#endif return result; } @@ -1707,6 +2546,16 @@ int I3CBus::disableControllerEvents(uint32_t interruptMask) { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && (_hi3c.mode == HAL_I3C_MODE_CTRL)) { + hal_status_t st = HAL_I3C_CTRL_DeactivateNotification(&_hi3c, interruptMask); + result = HAL_I3C_GetError(_hi3c, st); + + if ((st == HAL_OK) && (LL_I3C_GetEnabledIT(_instance) == 0U)) { + disableIRQs(); + } + } +#else 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)); @@ -1715,6 +2564,7 @@ int I3CBus::disableControllerEvents(uint32_t interruptMask) disableIRQs(); } } +#endif return result; } @@ -1762,6 +2612,32 @@ void I3CBus::onIbi(I3CIbiCallback cb, void *user) void I3CBus::handleHalNotify(uint32_t eventId) { +#if defined(USE_HALV2_DRIVER) + + if (_hi3c.mode == HAL_I3C_MODE_CTRL) { + if ((eventId & HAL_I3C_CTRL_NOTIFICATION_IBI) != 0U) { + hal_i3c_ccc_info_t info {}; + if (HAL_I3C_GetCCCInfo(&_hi3c, HAL_I3C_CTRL_NOTIFICATION_IBI, &info) == HAL_OK) { + _lastIbi.pending = true; + _lastIbi.eventId = eventId; + _lastIbi.sourceDa = static_cast(info.ibi_cr_tgt_addr); + _lastIbi.payloadSize = static_cast(info.ibi_tgt_nb_payload); + _lastIbi.payloadRaw = info.ibi_tgt_payload; + _lastIbi.timestampMs = millis(); + _ibiPending = true; + + if (_ibiCb != nullptr) { + _ibiCb(_lastIbi, _ibiCbUser); + } + } + } + } else if (_hi3c.mode == HAL_I3C_MODE_TGT) { + _lastTargetEventId = eventId; + _targetEventPending = true; + } + +#else + if (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) { if ((eventId & EVENT_ID_IBI) != 0U) { I3C_CCCInfoTypeDef info{}; @@ -1783,6 +2659,8 @@ void I3CBus::handleHalNotify(uint32_t eventId) _lastTargetEventId = eventId; _targetEventPending = true; } + +#endif } // ============================================================================ @@ -1792,6 +2670,12 @@ uint32_t I3CBus::getPeripheralClockFreq() const { uint32_t srcFreq = 0U; +#if defined(USE_HALV2_DRIVER) + + srcFreq = HAL_I3C_GetClockFreq(&_hi3c); + +#else + #if defined(I3C1) if (_instance == I3C1) { srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C1); @@ -1802,11 +2686,64 @@ uint32_t I3CBus::getPeripheralClockFreq() const if (_instance == I3C2) { srcFreq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I3C2); } +#endif #endif return srcFreq; } +#if defined(USE_HALV2_DRIVER) +bool I3CBus::buildControllerTiming(uint32_t srcFreq, + uint32_t freq, + I3CBusType busType, + uint32_t mixedBusOdFreq, + hal_i3c_ctrl_config_t &outCtrl) +{ + bool result = false; + + if (srcFreq != 0U) { + stm32_utils_i3c_ctrl_timing_config_t inTiming {}; + uint32_t timingReg0 = 0U; + uint32_t timingReg1 = 0U; + + inTiming.clock_src_freq_hz = srcFreq; + inTiming.i3c_pp_freq_hz = (freq == 0U) ? 1000000U : freq; + inTiming.i2c_od_freq_hz = (busType == I3CBusType::Pure) ? 0U : mixedBusOdFreq; + inTiming.duty_cycle_purcent = 50U; + inTiming.wait_time = STM32_UTILS_I3C_ACTIVITY_STATE_0; + inTiming.bus_type = (busType == I3CBusType::Pure) + ? STM32_UTILS_I3C_PURE_I3C_BUS + : STM32_UTILS_I3C_I2C_MIXED_BUS; + + if (STM32_UTILS_I3C_CTRL_ComputeTiming(&inTiming, &timingReg0, &timingReg1) == STM32_UTILS_I3C_OK) { + outCtrl.timing_reg0 = timingReg0; + outCtrl.timing_reg1 = timingReg1; + result = true; + } + } + + return result; +} + +bool I3CBus::buildTargetTiming(uint32_t srcFreq, hal_i3c_tgt_config_t &outTgt) +{ + bool result = false; + + if (srcFreq != 0U) { + stm32_utils_i3c_tgt_timing_config_t inTiming {}; + uint32_t timingReg1 = 0U; + + inTiming.clock_src_freq_hz = srcFreq; + + if (STM32_UTILS_I3C_TGT_ComputeTiming(&inTiming, &timingReg1) == STM32_UTILS_I3C_OK) { + outTgt.timing_reg1 = timingReg1; + result = true; + } + } + + return result; +} +#else bool I3CBus::buildControllerTiming(uint32_t freq, LL_I3C_CtrlBusConfTypeDef &outCtrl) const { bool result = false; @@ -1851,31 +2788,40 @@ bool I3CBus::buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const return result; } +#endif // ============================================================================ // IRQ handlers & helpers // ============================================================================ - void I3CBus::enableIRQs() { if (!_irqEnabled) { #if defined(I3C1) if (_instance == I3C1) { +#if defined(USE_HALV2_DRIVER) + HAL_CORTEX_NVIC_SetPriority(I3C1_EV_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_5, HAL_CORTEX_NVIC_SUB_PRIORITY_0); + HAL_CORTEX_NVIC_EnableIRQ(I3C1_EV_IRQn); + HAL_CORTEX_NVIC_SetPriority(I3C1_ERR_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_5, HAL_CORTEX_NVIC_SUB_PRIORITY_0); + HAL_CORTEX_NVIC_EnableIRQ(I3C1_ERR_IRQn); +#else 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); +#endif _irqEnabled = true; } #endif #if defined(I3C2) if (_instance == I3C2) { +#if !defined(USE_HALV2_DRIVER) 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; +#endif } #endif } @@ -1886,15 +2832,22 @@ void I3CBus::disableIRQs() if (_irqEnabled) { #if defined(I3C1) if (_instance == I3C1) { +#if defined(USE_HALV2_DRIVER) + HAL_CORTEX_NVIC_DisableIRQ(I3C1_EV_IRQn); + HAL_CORTEX_NVIC_DisableIRQ(I3C1_ERR_IRQn); +#else HAL_NVIC_DisableIRQ(I3C1_EV_IRQn); HAL_NVIC_DisableIRQ(I3C1_ER_IRQn); +#endif } #endif #if defined(I3C2) if (_instance == I3C2) { +#if !defined(USE_HALV2_DRIVER) HAL_NVIC_DisableIRQ(I3C2_EV_IRQn); HAL_NVIC_DisableIRQ(I3C2_ER_IRQn); +#endif } #endif @@ -1941,6 +2894,16 @@ extern "C" void I3C1_EV_IRQHandler(void) #endif } +#if defined(USE_HALV2_DRIVER) +extern "C" void I3C1_ERR_IRQHandler(void) +{ +#if defined(I3C1) + if (g_i3c1Owner != nullptr) { + HAL_I3C_ERR_IRQHandler(g_i3c1Owner->halHandle()); + } +#endif +} +#else extern "C" void I3C1_ER_IRQHandler(void) { #if defined(I3C1) @@ -1949,6 +2912,7 @@ extern "C" void I3C1_ER_IRQHandler(void) } #endif } +#endif #if defined(I3C2) extern "C" void I3C2_EV_IRQHandler(void) @@ -1961,10 +2925,11 @@ extern "C" void I3C2_EV_IRQHandler(void) extern "C" void I3C2_ER_IRQHandler(void) { if (g_i3c2Owner != nullptr) { +#if !defined(USE_HALV2_DRIVER) HAL_I3C_ER_IRQHandler(g_i3c2Owner->halHandle()); +#endif } } #endif -#endif /* !USE_HALV2_DRIVER */ -#endif /* I3C1_BASE || I3C2_BASE */ +#endif diff --git a/libraries/I3C/src/I3C.h b/libraries/I3C/src/I3C.h index 34c2cd8da9..a2cdd76df4 100644 --- a/libraries/I3C/src/I3C.h +++ b/libraries/I3C/src/I3C.h @@ -4,14 +4,12 @@ #if defined(I3C1_BASE) || defined(I3C2_BASE) -#if defined(USE_HALV2_DRIVER) -#warning "I3C library is not yet compatible with HALv2 driver." -#else #include "stm32yyxx_utils_i3c.h" // ============================================================================ // Descriptors, configuration structures, and enums // ============================================================================ +#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) struct I3CDiscoveredDevice { uint8_t dynAddr = 0; // 7-bit dynamic address @@ -60,7 +58,7 @@ struct I3CTargetConfig { bool ibiRequest = false; bool ibiPayload = false; - uint32_t ibiPayloadSize = HAL_I3C_PAYLOAD_EMPTY; + uint32_t ibiPayloadSize = LL_I3C_PAYLOAD_EMPTY; uint16_t maxReadDataSize = 0xFFFF; uint16_t maxWriteDataSize = 0xFFFF; @@ -71,9 +69,9 @@ struct I3CTargetConfig { uint32_t dataTurnAroundDuration = HAL_I3C_TURNAROUND_TIME_TSCO_LESS_12NS; uint8_t maxReadTurnAround = 0; uint32_t maxDataSpeed = HAL_I3C_GETMXDS_FORMAT_1; - bool maxSpeedLimitation = false; - uint32_t handOffActivityState = HAL_I3C_HANDOFF_ACTIVITY_STATE_0; + + bool maxSpeedLimitation = false; bool handOffDelay = false; bool pendingReadMDB = false; }; @@ -100,10 +98,18 @@ enum class I3CTransferType : uint8_t { }; struct I3CControllerConfig { + +#if defined(USE_HALV2_DRIVER) + uint32_t rxFifoThreshold = HAL_I3C_RX_FIFO_THRESHOLD_1_8; + uint32_t txFifoThreshold = HAL_I3C_TX_FIFO_THRESHOLD_1_8; + uint32_t controlFifo = 0U; + uint32_t statusFifo = 0U; +#else uint32_t rxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4; uint32_t txFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4; uint32_t controlFifo = HAL_I3C_CONTROLFIFO_DISABLE; uint32_t statusFifo = HAL_I3C_STATUSFIFO_DISABLE; +#endif uint8_t dynamicAddr = 0U; uint8_t stallTime = 0x00U; @@ -116,6 +122,16 @@ struct I3CControllerConfig { bool highKeeperSDA = false; }; +struct I3CTargetEventConfig { + uint8_t *rxData = nullptr; + uint32_t rxSize = 0U; +}; + +struct I3CTargetCccInfo { + bool hotJoinAllowed = false; + bool inBandAllowed = false; + bool ctrlRoleAllowed = false; +}; // ============================================================================ // I3CBus // ============================================================================ @@ -163,6 +179,8 @@ class I3CBus { void end(); + bool flushAllFifos(); + // ------------------------------------------------------------------------ // Default I3C controller transfers // ------------------------------------------------------------------------ @@ -292,11 +310,11 @@ class I3CBus { // ------------------------------------------------------------------------ bool isI2CDeviceReady(uint8_t staticAddr, uint32_t trials = 3U, - uint32_t timeout = 1000U); + uint32_t timeout = 10U); bool isI3CDeviceReady(uint8_t dynAddr, uint32_t trials = 3U, - uint32_t timeout = 1000U); + uint32_t timeout = 10U); // ------------------------------------------------------------------------ // CCC broadcast & direct commands @@ -396,7 +414,7 @@ class I3CBus { uint8_t payloadSize, uint32_t timeout = 1000U); - int enableTargetEvents(I3C_XferTypeDef *pXferData, + int enableTargetEvents(const I3CTargetEventConfig &cfg, uint32_t interruptMask); int disableTargetEvents(uint32_t interruptMask); @@ -408,6 +426,7 @@ class I3CBus { bool hasTargetEvent() const; bool readTargetEvent(uint32_t &eventId); + bool getTargetCccInfo(uint32_t eventId, I3CTargetCccInfo &out); // ------------------------------------------------------------------------ // Controller-side IBI support @@ -425,8 +444,8 @@ class I3CBus { bool stopTransfer = false, uint32_t timeout = 1000U); - int enableControllerEvents(uint32_t interruptMask = HAL_I3C_IT_IBIIE); - int disableControllerEvents(uint32_t interruptMask = HAL_I3C_IT_IBIIE); + int enableControllerEvents(uint32_t interruptMask = LL_I3C_IER_IBIIE); + int disableControllerEvents(uint32_t interruptMask = LL_I3C_IER_IBIIE); bool hasIbi() const; bool readIbi(I3CControllerIbiInfo &out); @@ -439,10 +458,17 @@ class I3CBus { // ------------------------------------------------------------------------ void handleHalNotify(uint32_t eventId); +#if defined(USE_HALV2_DRIVER) + hal_i3c_handle_t *halHandle() + { + return &_hi3c; + } +#else I3C_HandleTypeDef *halHandle() { return &_hi3c; } +#endif private: // ------------------------------------------------------------------------ @@ -530,12 +556,26 @@ class I3CBus { static uint32_t bigToLittle32(uint32_t x); static uint64_t extractPid48FromEntdaaPayload(uint64_t payload); +#if defined(USE_HALV2_DRIVER) + static int HAL_I3C_GetError(const hal_i3c_handle_t &hi3c, hal_status_t st = HAL_OK); +#endif + // ------------------------------------------------------------------------ // Clock helpers // ------------------------------------------------------------------------ uint32_t getPeripheralClockFreq() const; + +#if defined(USE_HALV2_DRIVER) + bool buildControllerTiming(uint32_t srcFreq, + uint32_t freq, + I3CBusType busType, + uint32_t mixedBusOdFreq, + hal_i3c_ctrl_config_t &outCtrl) ; + bool buildTargetTiming(uint32_t srcFreq, hal_i3c_tgt_config_t &outTgt) ; +#else bool buildControllerTiming(uint32_t freq, LL_I3C_CtrlBusConfTypeDef &outCtrl) const; bool buildTargetTiming(LL_I3C_TgtBusConfTypeDef &outTgt) const; +#endif // ------------------------------------------------------------------------ // Irq helpers @@ -562,7 +602,13 @@ class I3CBus { volatile bool _targetEventPending = false; volatile uint32_t _lastTargetEventId = 0U; - I3C_HandleTypeDef _hi3c{}; + +#if defined(USE_HALV2_DRIVER) + hal_i3c_handle_t _hi3c {}; +#else + I3C_HandleTypeDef _hi3c {}; +#endif + bool _initialized = false; I3C_TypeDef *_instance = nullptr; @@ -584,5 +630,4 @@ class I3CBus { extern I3CBus I3C; -#endif /* !USE_HALV2_DRIVER */ -#endif /* I3C1_BASE || I3C2_BASE */ +#endif diff --git a/libraries/I3C/src/I3C_I2C.cpp b/libraries/I3C/src/I3C_I2C.cpp index 30e4cbdec6..ba2a11ae91 100644 --- a/libraries/I3C/src/I3C_I2C.cpp +++ b/libraries/I3C/src/I3C_I2C.cpp @@ -3,7 +3,6 @@ #if defined(I3C1_BASE) || defined(I3C2_BASE) -#if !defined(USE_HALV2_DRIVER) // ============================================================================ // I2C helpers on mixed I3C bus // ============================================================================ @@ -30,6 +29,31 @@ int I3CBus::i2cWrite(uint8_t staticAddr, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_CTRL) && + (_busType == I3CBusType::Mixed) && + isValidI2CStaticAddr(staticAddr) && + (buf != nullptr) && + (len != 0U)) { + uint32_t controlBuffer[1] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { staticAddr, static_cast(len), HAL_I3C_DIRECTION_WRITE }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, buf, static_cast(len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + HAL_I2C_PRIVATE_WITHOUT_ARB_STOP) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && (_busType == I3CBusType::Mixed) && @@ -68,6 +92,7 @@ int I3CBus::i2cWrite(uint8_t staticAddr, result = -static_cast(HAL_I3C_GetError(&_hi3c)); } } +#endif return result; } @@ -79,6 +104,31 @@ int I3CBus::i2cRead(uint8_t staticAddr, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if (_initialized && + (_hi3c.mode == HAL_I3C_MODE_CTRL) && + (_busType == I3CBusType::Mixed) && + isValidI2CStaticAddr(staticAddr) && + (buf != nullptr) && + (len != 0U)) { + uint32_t controlBuffer[1] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { staticAddr, static_cast(len), HAL_I3C_DIRECTION_READ }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxRx(&ctx, buf, static_cast(len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + HAL_I2C_PRIVATE_WITHOUT_ARB_STOP) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else if (_initialized && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && (_busType == I3CBusType::Mixed) && @@ -117,6 +167,7 @@ int I3CBus::i2cRead(uint8_t staticAddr, result = -static_cast(HAL_I3C_GetError(&_hi3c)); } } +#endif return result; } @@ -131,8 +182,6 @@ int I3CBus::i2cWriteRead(uint8_t staticAddr, int result = -1; if ((!_initialized) || - (_hi3c.Mode != HAL_I3C_MODE_CONTROLLER) || - (_busType != I3CBusType::Mixed) || (!isValidI2CStaticAddr(staticAddr)) || (txBuf == nullptr) || (txLen == 0U) || @@ -140,70 +189,97 @@ int I3CBus::i2cWriteRead(uint8_t staticAddr, (rxLen == 0U)) { result = -1; } else { - I3C_XferTypeDef context {}; - I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[1] = {}; - HAL_StatusTypeDef st; - - // 1) write phase with RESTART - priv.TargetAddr = staticAddr; - priv.TxBuf.pBuffer = const_cast(txBuf); - priv.TxBuf.Size = static_cast(txLen); - priv.RxBuf.pBuffer = nullptr; - priv.RxBuf.Size = 0U; - priv.Direction = HAL_I3C_DIRECTION_WRITE; - - std::memset(&context, 0, sizeof(context)); - context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = 1U; - context.TxBuf.pBuffer = const_cast(txBuf); - context.TxBuf.Size = static_cast(txLen); - - st = HAL_I3C_AddDescToFrame( - &_hi3c, - nullptr, - &priv, - &context, - context.CtrlBuf.Size, - I2C_PRIVATE_WITHOUT_ARB_RESTART); +#if defined(USE_HALV2_DRIVER) + if ((_hi3c.mode == HAL_I3C_MODE_CTRL) && + (_busType == I3CBusType::Mixed)) { + uint32_t controlBuffer[2] = {}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { staticAddr, static_cast(txLen), HAL_I3C_DIRECTION_WRITE }, + { staticAddr, static_cast(rxLen), HAL_I3C_DIRECTION_READ }, + }; + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 2U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, txBuf, static_cast(txLen)) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxRx(&ctx, rxBuf, static_cast(rxLen)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + HAL_I2C_PRIVATE_WITHOUT_ARB_RESTART) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else + if ((_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && + (_busType == I3CBusType::Mixed)) { + I3C_XferTypeDef context {}; + I3C_PrivateTypeDef priv {}; + uint32_t controlBuffer[1] = {}; + HAL_StatusTypeDef st; + + // 1) write phase with RESTART + priv.TargetAddr = staticAddr; + priv.TxBuf.pBuffer = const_cast(txBuf); + priv.TxBuf.Size = static_cast(txLen); + priv.RxBuf.pBuffer = nullptr; + priv.RxBuf.Size = 0U; + priv.Direction = HAL_I3C_DIRECTION_WRITE; + + std::memset(&context, 0, sizeof(context)); + context.CtrlBuf.pBuffer = controlBuffer; + context.CtrlBuf.Size = 1U; + context.TxBuf.pBuffer = const_cast(txBuf); + context.TxBuf.Size = static_cast(txLen); + + st = HAL_I3C_AddDescToFrame( + &_hi3c, + nullptr, + &priv, + &context, + context.CtrlBuf.Size, + I2C_PRIVATE_WITHOUT_ARB_RESTART); - if (st != HAL_OK) { - result = -static_cast(HAL_I3C_GetError(&_hi3c)); - } else { - st = HAL_I3C_Ctrl_Transmit(&_hi3c, &context, timeout); if (st != HAL_OK) { result = -static_cast(HAL_I3C_GetError(&_hi3c)); } else { - // 2) read phase with STOP - priv.TargetAddr = staticAddr; - priv.TxBuf.pBuffer = nullptr; - priv.TxBuf.Size = 0U; - priv.RxBuf.pBuffer = rxBuf; - priv.RxBuf.Size = static_cast(rxLen); - priv.Direction = HAL_I3C_DIRECTION_READ; - - std::memset(&context, 0, sizeof(context)); - context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = 1U; - context.RxBuf.pBuffer = rxBuf; - context.RxBuf.Size = static_cast(rxLen); - - st = HAL_I3C_AddDescToFrame( - &_hi3c, - nullptr, - &priv, - &context, - context.CtrlBuf.Size, - I2C_PRIVATE_WITHOUT_ARB_STOP); - + st = HAL_I3C_Ctrl_Transmit(&_hi3c, &context, timeout); if (st != HAL_OK) { result = -static_cast(HAL_I3C_GetError(&_hi3c)); } else { - st = HAL_I3C_Ctrl_Receive(&_hi3c, &context, timeout); - result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + // 2) read phase with STOP + priv.TargetAddr = staticAddr; + priv.TxBuf.pBuffer = nullptr; + priv.TxBuf.Size = 0U; + priv.RxBuf.pBuffer = rxBuf; + priv.RxBuf.Size = static_cast(rxLen); + priv.Direction = HAL_I3C_DIRECTION_READ; + + std::memset(&context, 0, sizeof(context)); + context.CtrlBuf.pBuffer = controlBuffer; + context.CtrlBuf.Size = 1U; + context.RxBuf.pBuffer = rxBuf; + context.RxBuf.Size = static_cast(rxLen); + + st = HAL_I3C_AddDescToFrame( + &_hi3c, + nullptr, + &priv, + &context, + context.CtrlBuf.Size, + I2C_PRIVATE_WITHOUT_ARB_STOP); + + if (st != HAL_OK) { + result = -static_cast(HAL_I3C_GetError(&_hi3c)); + } else { + st = HAL_I3C_Ctrl_Receive(&_hi3c, &context, timeout); + result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + } } } } +#endif } return result; @@ -218,48 +294,74 @@ int I3CBus::i2cWriteRegBuffer(uint8_t staticAddr, int result = -1; if ((_initialized) && - (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && (_busType == I3CBusType::Mixed) && isValidI2CStaticAddr(staticAddr) && (pData != nullptr) && (len != 0U) && (len <= 31U)) { - I3C_XferTypeDef context {}; - I3C_PrivateTypeDef priv {}; - uint32_t controlBuffer[1] = {}; - uint8_t data[32] = {0}; - HAL_StatusTypeDef st; - - data[0] = reg; - memcpy(&data[1], pData, len); - - priv.TargetAddr = staticAddr; - priv.TxBuf.pBuffer = data; - priv.TxBuf.Size = static_cast(1U + len); - priv.RxBuf.pBuffer = nullptr; - priv.RxBuf.Size = 0U; - priv.Direction = HAL_I3C_DIRECTION_WRITE; - - std::memset(&context, 0, sizeof(context)); - context.CtrlBuf.pBuffer = controlBuffer; - context.CtrlBuf.Size = 1U; - context.TxBuf.pBuffer = data; - context.TxBuf.Size = static_cast(1U + len); - - st = HAL_I3C_AddDescToFrame( - &_hi3c, - nullptr, - &priv, - &context, - context.CtrlBuf.Size, - I2C_PRIVATE_WITHOUT_ARB_STOP); +#if defined(USE_HALV2_DRIVER) + if (_hi3c.mode == HAL_I3C_MODE_CTRL) { + uint32_t controlBuffer[1] = {}; + uint8_t data[32] = {0}; + hal_i3c_transfer_ctx_t ctx {}; + hal_i3c_private_desc_t priv[] = { + { staticAddr, static_cast(1U + len), HAL_I3C_DIRECTION_WRITE }, + }; + + data[0] = reg; + memcpy(&data[1], pData, len); + + if ((HAL_I3C_CTRL_ResetTransferCtx(&ctx) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTc(&ctx, controlBuffer, 1U) == HAL_OK) && + (HAL_I3C_CTRL_InitTransferCtxTx(&ctx, data, static_cast(1U + len)) == HAL_OK) && + (HAL_I3C_CTRL_BuildTransferCtxPrivate(&ctx, + priv, + COUNTOF(priv), + HAL_I2C_PRIVATE_WITHOUT_ARB_STOP) == HAL_OK)) { + hal_status_t st = HAL_I3C_CTRL_Transfer(&_hi3c, &ctx, timeout); + result = HAL_I3C_GetError(_hi3c, st); + } + } +#else + if (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) { + I3C_XferTypeDef context {}; + I3C_PrivateTypeDef priv {}; + uint32_t controlBuffer[1] = {}; + uint8_t data[32] = {0}; + HAL_StatusTypeDef st; + + data[0] = reg; + memcpy(&data[1], pData, len); + + priv.TargetAddr = staticAddr; + priv.TxBuf.pBuffer = data; + priv.TxBuf.Size = static_cast(1U + len); + priv.RxBuf.pBuffer = nullptr; + priv.RxBuf.Size = 0U; + priv.Direction = HAL_I3C_DIRECTION_WRITE; + + std::memset(&context, 0, sizeof(context)); + context.CtrlBuf.pBuffer = controlBuffer; + context.CtrlBuf.Size = 1U; + context.TxBuf.pBuffer = data; + context.TxBuf.Size = static_cast(1U + len); + + st = HAL_I3C_AddDescToFrame( + &_hi3c, + nullptr, + &priv, + &context, + context.CtrlBuf.Size, + I2C_PRIVATE_WITHOUT_ARB_STOP); - if (st != HAL_OK) { - result = -static_cast(HAL_I3C_GetError(&_hi3c)); - } else { - st = HAL_I3C_Ctrl_Transmit(&_hi3c, &context, timeout); - result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + if (st != HAL_OK) { + result = -static_cast(HAL_I3C_GetError(&_hi3c)); + } else { + st = HAL_I3C_Ctrl_Transmit(&_hi3c, &context, timeout); + result = (st == HAL_OK) ? 0 : -static_cast(HAL_I3C_GetError(&_hi3c)); + } } +#endif } return result; @@ -302,11 +404,19 @@ int I3CBus::scanI2CDevices(uint8_t *addrs, { int result = -1; +#if defined(USE_HALV2_DRIVER) + if ((_initialized) && + (_hi3c.mode == HAL_I3C_MODE_CTRL) && + (_busType == I3CBusType::Mixed) && + (addrs != nullptr) && + (foundCount != nullptr)) { +#else if ((_initialized) && (_hi3c.Mode == HAL_I3C_MODE_CONTROLLER) && (_busType == I3CBusType::Mixed) && (addrs != nullptr) && (foundCount != nullptr)) { +#endif size_t count = 0U; for (uint8_t addr = 0x08U; addr < 0x78U; ++addr) { @@ -399,5 +509,4 @@ int I3CBus::readRegBuffer(uint8_t addr, : readRegBuffer(addr, reg, pData, len, timeout); } -#endif /* !USE_HALV2_DRIVER */ -#endif /* I3C1_BASE || I3C2_BASE */ +#endif /* I3C1_BASE || I3C2_BASE */ diff --git a/libraries/SrcWrapper/CMakeLists.txt b/libraries/SrcWrapper/CMakeLists.txt index d02d774a8f..33ece07bba 100644 --- a/libraries/SrcWrapper/CMakeLists.txt +++ b/libraries/SrcWrapper/CMakeLists.txt @@ -153,6 +153,7 @@ add_library(SrcWrapper_bin OBJECT EXCLUDE_FROM_ALL src/HAL/stm32yyxx_hal_xspi.c src/HAL/stm32yyxx_usb_drd_core.c src/HAL/stm32yyxx_util_i3c.c + src/HAL/stm32yyxx_utils_i3c.c src/HardwareTimer.cpp src/LL/stm32yyxx_ll_adc.c src/LL/stm32yyxx_ll_bdma.c