HAL I3C How to Use ¶
- group I3C_How_To_Use
-
How to use the I3C HAL ¶
Use the I3C HAL driver as follows:
1. Declare ¶
A hal_i3c_handle_t handle structure, for example: hal_i3c_handle_t hi3c;
A hal_i3c_transfer_ctx_t transfer descriptor structure (controller only), for example: hal_i3c_transfer_ctx_t my_transfer_ctx;
2. Initialize ¶
Initialize the I3Cx driver with an I3C HW instance by calling HAL_I3C_Init().
The I3Cx clock is enabled inside HAL_I3C_Init() if USE_HAL_I3C_CLK_ENABLE_MODEL > HAL_CLK_ENABLE_NO.
3. Configure low-level hardware ¶
Enable the I3Cx clock if USE_HAL_I3C_CLK_ENABLE_MODEL = HAL_CLK_ENABLE_NO.
I3Cx pin configuration:
Enable the clock for the I3Cx GPIOs.
Configure I3C pins as alternate function push-pull with no-pull.
NVIC configuration for interrupt processing:
Configure the I3Cx interrupt priority.
Enable the NVIC I3C IRQ Channel.
DMA configuration for DMA processing:
Declare a hal_dma_handle_t handle structure for the Control Register (CR) management channel.
Declare a hal_dma_handle_t handle structure for the transmit channel.
Declare a hal_dma_handle_t handle structure for the receive channel.
Enable the DMAx interface clock.
Configure the DMA handle parameters.
Configure the DMA Control Register (CR) channel.
Configure the DMA Tx channel.
Configure the DMA Rx channel.
Associate the initialized DMA handle with the hi3c DMA CR, Tx, or Rx as necessary.
Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA CR, Tx or Rx instance.
4. Configure communication mode ¶
Controller mode: HAL_I3C_CTRL_SetConfig()
Target mode: HAL_I3C_TGT_SetConfig()
5. Configure FIFOs (optional) ¶
Controller: HAL_I3C_CTRL_SetConfigFifo()
Target: HAL_I3C_TGT_SetConfigFifo()
At the end of a transfer, all FIFOs can be flushed: HAL_I3C_FlushAllFifos(), or individually: HAL_I3C_FlushTxFifo(), HAL_I3C_FlushRxFifo(), HAL_I3C_CTRL_FlushControlFifo(), HAL_I3C_FlushstatusFifo().
6. Target advanced features ¶
6.1 ENTDAA payload configuration ¶
Before initiating any ENTDAA, the target must configure the target payload of the ENTDAA by using HAL_I3C_TGT_SetPayloadENTDAAConfig().
6.2 Target Hot-Join (interrupt mode) ¶
Request a Hot-Join in target mode: HAL_I3C_TGT_HotJoinReq_IT(). At completion, HAL_I3C_TGT_HotJoinCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
6.3 Target In-Band Interrupt (interrupt mode) ¶
Request an In-Band Interrupt in target mode: HAL_I3C_TGT_IBIReq_IT() At completion, HAL_I3C_NotifyCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
6.4 Target Controller-Role request (interrupt mode) ¶
Request a Controller Role in target mode: HAL_I3C_TGT_ControlRoleReq_IT() At completion, HAL_I3C_NotifyCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
6.5 Target Wakeup capability ¶
To manage the wakeup capability, use HAL_I3C_TGT_ActivateNotification() or HAL_I3C_TGT_DeactivateNotification() to enable or disable the wakeup interrupt. At wakeup detection, the associated HAL_I3C_NotifyCallback() is executed.
7. Controller advanced features ¶
7.1 Dynamic Address Assignment procedure ¶
Before initiating any IO operation, launch an assignment of the different target dynamic addresses by using HAL_I3C_CTRL_DynAddrAssign() in polling mode or HAL_I3C_CTRL_DynAddrAssign_IT() in interrupt mode. This procedure is named Enter Dynamic Address Assignment (ENTDAA CCC command).
For the initiation of ENTDAA procedure, each target connected and powered on the I3C bus must respond to this particular Command Common Code (CCC) by sending its proper Payload (an amount of 48-bits which contain the target characteristics). Each time a target responds to ENTDAA sequence, the controller application is informed through HAL_I3C_CTRL_TgtReqDynAddrCallback() of the reception of the target payload.
Then send an associated dynamic address through HAL_I3C_CTRL_SetDynAddr(). This procedure loops automatically in hardware side until a target responds to repeated ENTDAA sequence.
The controller application is informed of the end of the procedure at reception of HAL_I3C_CTRL_DAACpltCallback().
Then retrieve ENTDAA payload information through HAL_I3C_CTRL_Get_ENTDAA_Payload_Info().
At the end of the procedure, the function HAL_I3C_CTRL_SetConfigBusDevices() must be called to store the target capabilities in the hardware register, including dynamic address, IBI support with or without additional data byte, Controller-Role request support, or controller automatic stop transfer after IBI.
7.3 Device ready checks ¶
To check if I3C target device is ready for communication, use the function HAL_I3C_CTRL_PoolForDeviceI3cReady().
To check if I2C target device is ready for communication, use the function HAL_I3C_CTRL_PoolForDeviceI2cReady().
7.4 Bus arbitration generation ¶
To send a message header {S + 0x7E + W + STOP}, use the function HAL_I3C_CTRL_GenerateArbitration().
7.5 Reset pattern insertion ¶
The controller app must enable the reset pattern configuration using HAL_I3C_CTRL_EnableResetPattern() before calling HAL_I3C_CTRL_Transfer(). To have a standard STOP emitted at the end of a frame containing a RSTACT CCC command, the application must disable the reset pattern configuration using HAL_I3C_CTRL_DisableResetPattern() before calling HAL_I3C_CTRL_Transfer(). Use HAL_I3C_CTRL_IsEnabledResetPattern() to check Reset pattern configuration.
7.6 Pattern generation ¶
To send a target reset pattern or HDR exit pattern, use the function HAL_I3C_CTRL_GeneratePatterns().
8. Controller IO operations ¶
8.1 Prepare transfer context ¶
Before initiating any IO operation, prepare the frame descriptors in the transfer context with their associated buffer allocation. It is purely software; no I3C handle is needed. Respect the following steps:
Reset the transfer context: HAL_I3C_CTRL_ResetTransferCtx().
Provide the control buffer: HAL_I3C_CTRL_InitTransferCtxTc()
Provide the Tx buffer (if needed): HAL_I3C_CTRL_InitTransferCtxTc()
Provide the Rx buffer (if needed): HAL_I3C_CTRL_InitTransferCtxRx()
Build the transfer context. Private: HAL_I3C_CTRL_BuildTransferCtxPrivate() or CCC: HAL_I3C_CTRL_BuildTransferCtxCCC()
The built transfer context is ready for controller IO operation. The driver does not modify it during the operation. It can be reused or stored.
8.2 Controller polling IO operation (blocking) ¶
Start a controller-mode transfer of a Common Command Code in a direct or direct receive CCC with defbyte or private data in an I2C or I3C communication: HAL_I3C_CTRL_Transfer().
8.3 Controller DMA and interrupt mode IO operation ¶
Transmit and/or receive a quantity of private data in an I3C or an I2C or a broadcast or a direct communication in non-blocking mode: HAL_I3C_CTRL_Transfer_IT() or HAL_I3C_CTRL_Transfer_DMA().
At the end of the transfer, HAL_I3C_CTRL_TransferCpltCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
9. Target IO operations ¶
9.1 Target polling IO operation (blocking) ¶
Transmit private data in target mode: HAL_I3C_TGT_Transmit()
Receive private data in target mode: HAL_I3C_TGT_Receive()
At the end of a transfer, flush FIFOs if needed by using HAL_I3C_FlushAllFifos() to flush all FIFOs, or flush individual FIFOs by using HAL_I3C_FlushTxFifo(), HAL_I3C_FlushRxFifo().
Request a Hot-Join in target mode: HAL_I3C_TGT_HotJoinReq()
Request an In-Band Interrupt in target mode: HAL_I3C_TGT_IBIReq()
Request a Controller-Role in target mode: HAL_I3C_TGT_ControlRoleReq()
9.2 Target DMA and Interrupt mode IO operation ¶
Transmit private data in target mode in an I3C communication by using HAL_I3C_TGT_Transmit_IT() or HAL_I3C_TGT_Transmit_DMA().
At the end of the transfer, HAL_I3C_TGT_TxCpltCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
Receive private data in target mode in an I3C communication: HAL_I3C_TGT_Receive_IT() or HAL_I3C_TGT_Receive_DMA().
At the end of the transfer, HAL_I3C_TGT_RxCpltCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
10. Notifications and asynchronous events ¶
To get asynchronous events, use HAL_I3C_CTRL_ActivateNotification() or HAL_I3C_TGT_ActivateNotification(). Each time one or more events are detected by hardware, HAL_I3C_NotifyCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function. Then retrieve specific associated event data through HAL_I3C_GetCCCInfo().
11. Error management ¶
In case of transfer error, HAL_I3C_ErrorCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
12. Abort operation ¶
Abort an I3C communication process with interrupt using HAL_I3C_Abort_IT(). At the end of the abort process, HAL_I3C_AbortCpltCallback() is executed, and user code can add custom handling by overriding this weak callback function or by registering a callback function.
13. Callback registration ¶
The compilation flag USE_HAL_I3C_REGISTER_CALLBACKS allows dynamic configuration of the driver callbacks via dedicated registration APIs, instead of relying on weak default functions.
Pointer in hal_i3c_handle_t
weak default functions
Callback registration function
DAACpltCallback
TransferCpltCallback
TgtReqDynAddrCallback
TgtTxCpltCallback
TgtRxCpltCallback
TgtHotJoinCallback
NotifyCallback
AbortCpltCallback
ErrorCallback
Notes:
To unregister and restore the default weak callback, re-register the corresponding default function.
By default, after HAL_I3C_Init() and when the state is HAL_I3C_STATE_INIT, all callbacks are set to their default weak implementations.
Register callbacks when handle global_state is HAL_I3C_STATE_INIT or HAL_I3C_STATE_IDLE.
When USE_HAL_I3C_REGISTER_CALLBACKS is set to 0 or not defined, the callback registration feature is not available and weak callbacks are used.
14. Acquire/Release the I3C bus ¶
When the compilation flag USE_HAL_MUTEX is set to 1, it allows the user to acquire/reserve the whole I3C bus for executing a process. The HAL Acquire/Release are based on the HAL OS abstraction layer (stm32_hal_os.c/.h osal):
HAL_I3C_AcquireBus() to acquire the bus or wait for it.
HAL_I3C_ReleaseBus() to release the bus.
When the compilation flag USE_HAL_MUTEX is set to 0 or not defined, HAL_I3C_AcquireBus() and HAL_I3C_ReleaseBus() are not available.