HAL I2C Use Cases

Prerequisite

@startuml

==Prerequisite==



participant App as "User application"

participant "HAL GENERIC" as GENERIC

participant "HAL RCC" as RCC



App -> GENERIC : HAL_Init

GENERIC --> App 

App -> RCC : Configure system clock

RCC --> App

@enduml

Full I2C Initialization Sequence

@startuml



participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

participant "HAL CORTEX\n(NVIC)" as CORTEX

participant "HAL DMA" as DMA

participant "HAL RCC" as RCC

participant "HAL GPIO" as GPIO



==I2C HAL Initialization  ==

App -> I2C : HAL_I2C_Init

alt#grey #lightgrey If USE_HAL_I2C_CLK_ENABLE_MODEL > HAL_CLK_ENABLE_NO

I2C->RCC : Enable the I2C clock

RCC-->I2C

end

App <-- I2C : HAL_OK



==I2C System Initialization==

Note over I2C : I2C System initialization can be called before\nI2C HAL initialization



alt#grey #lightgrey If USE_HAL_I2C_DMA == 1

App->DMA : Initialization of DMA

DMA-->App

App->I2C : HAL_I2C_SetTxDMA / HAL_I2C_SetRxDMA

DMA-->App

end



alt#grey #lightgrey If Interrupt needed

App->CORTEX : Enable needed Interrupt

CORTEX-->App

end



alt#grey #lightgrey If GPIO(s) needed

App->GPIO : Initialization of GPIOs

GPIO-->App

end



alt#grey #lightgrey If USE_HAL_I2C_CLK_ENABLE_MODEL == HAL_CLK_ENABLE_NO

App->RCC : Enable the I2C clock

RCC --> App

end



==I2C Configuration==

App -> I2C : HAL_I2C_SetConfig

App <-- I2C :HAL_OK



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

==Advanced I2C Configuration==

App -> I2C : HAL_I2C_EnableAnalogFilter

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_SetConfigXXX

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_EnableXXX

App <-- I2C :HAL_OK

@enduml

Called functions:

Full I2C Initialization Sequence (AutoCR)

@startuml



participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

participant "HAL CORTEX\n(NVIC)" as CORTEX

participant "HAL DMA" as DMA

participant "HAL RCC" as RCC

participant "HAL GPIO" as GPIO



==I2C HAL Initialization  ==

App -> I2C : HAL_I2C_Init

alt#grey #lightgrey If USE_HAL_I2C_CLK_ENABLE_MODEL > HAL_CLK_ENABLE_NO

I2C->RCC : Enable the I2C clock

RCC-->I2C

end

App <-- I2C : HAL_OK



==I2C System Initialization==

Note over I2C : I2C System initialization can be called before\nI2C HAL initialization



alt#grey #lightgrey If USE_HAL_I2C_DMA == 1

App->DMA : Initialization of DMA

DMA-->App

App->I2C : HAL_I2C_SetTxDMA / HAL_I2C_SetRxDMA

DMA-->App

end



alt#grey #lightgrey If Interrupt needed

App->CORTEX : Enable needed Interrupt

CORTEX-->App

end



alt#grey #lightgrey If GPIO(s) needed

App->GPIO : Initialization of GPIOs

GPIO-->App

end



alt#grey #lightgrey If USE_HAL_I2C_CLK_ENABLE_MODEL == HAL_CLK_ENABLE_NO

App->RCC : Enable the I2C clock

RCC --> App

end



==I2C Configuration==

App -> I2C : HAL_I2C_SetConfig

App <-- I2C :HAL_OK



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

==Advanced I2C Configuration==

App -> I2C : HAL_I2C_EnableAnalogFilter

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_SetConfigAutonomousModeTrigger

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_EnableAutonomousModeTrigger

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_SetConfigXXX

App <-- I2C :HAL_OK

App -> I2C : HAL_I2C_EnableXXX

App <-- I2C :HAL_OK

@enduml

Called functions:

Full I2C Deinitialization Sequence

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

participant "HAL CORTEX\n(NVIC)" as CORTEX

participant "HAL DMA" as DMA

participant "HAL RCC" as RCC

participant "HAL GPIO" as GPIO



==I2C DeInitialisation==

App->I2C : HAL_I2C_DeInit

App<--I2C



==I2C system DeInitalization==

alt#grey #lightgrey If USE_HAL_I2C_DMA == 1

App->DMA : DeInitialization of DMA

DMA-->App

end



alt#grey #lightgrey If Interrupt needed

App->CORTEX : Disable needed Interrupt

CORTEX-->App

end



alt#grey #lightgrey If GPIO(s) needed

App->GPIO : DeInitialization of GPIOs

GPIO-->App

end



App->RCC : Disable the I2C clock

RCC --> App

@enduml

Called functions:

Process Polling

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C



==Process :  Master Transmit Polling==

App -> I2C : HAL_I2C_MASTER_Transmit(...,uint32_t timeout_ms)



alt successful case

   App <-- I2C : HAL_OK

else invalid param

   App <-- I2C : HAL_INVALID_PARAM

else busy

   App <-- I2C : HAL_BUSY

   note over App : Another Process is running...\nPlease wait and retry.

else timeout 

   App <-- I2C : HAL_TIMEOUT

else error case 

   App <-- I2C : HAL_ERROR

App -> I2C : \



alt#grey #lightgrey If USE_HAL_I2C_GET_LAST_ERRORS == 1

App->I2C : HAL_I2C_GetLastErrors()

App <-- I2C : \

(HAL_I2C_ERROR_XXX | HAL_I2C_ERROR_YYY)

end



end

note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Process Master Transmit IT

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C



==Process :  Master Transmit IT==

App -> I2C : HAL_I2C_MASTER_Transmit_IT(handle, addr, &buffer,\n size_in_byte = N)

App <-- I2C : HAL_OK

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt TXIS, Byte 1 ... Byte N 

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Master_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nTXDR = buffer[0];

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt STOP

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag STOP

App <- I2C : HAL_I2C_MASTER_TxCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Process Slave Transmit IT

@startuml

==Process :  Slave Transmit IT==

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C



App -> I2C : HAL_I2C_SLAVE_Transmit_IT(handle, addr, &buffer,\n size_in_byte = N)

App <-- I2C : HAL_OK

...

"I2Cx_IRQHandler" <- : I2Cx interrupt ADDR

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag ADDR

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->

...





loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt TXIS, Byte 1 ... Byte N 

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Slave_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nTXDR = buffer[0];

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt STOP

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag STOP

App <- I2C : HAL_I2C_SLAVE_TxCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Slave Receive IT

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C



==Process :  Slave Receive IT==

App -> I2C : HAL_I2C_SLAVE_Receive_IT(handle, addr, &buffer,\n size_in_byte = N)

App <-- I2C : HAL_OK

...

"I2Cx_IRQHandler" <- : I2Cx interrupt ADDR

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag ADDR

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt RXNE\nByte 1 ...  Byte N

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Slave_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nbuffer[0] = RXDR;

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt STOP

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag STOP

App <- I2C : HAL_I2C_SLAVE_RxCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Master Mode IT

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process :  Master Mode. Send CMD M bytes + Receive N bytes ==



App -> I2C : HAL_I2C_MASTER_SEQ_Transmit_IT(handle, addr, &buffer,\n size_in_byte = M, I2C_FIRST_FRAME)

App <-- I2C : HAL_OK

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt TXIS\nCMD Byte 1 ... CMD Byte M 

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Master_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nTXDR = buffer[0];

   else else

      App <- I2C : HAL_I2C_MASTER_TxCpltCallback

      App --> I2C

   end



   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

App -> I2C : HAL_I2C_MASTER_SEQ_Receive_IT(handle, addr, &buffer,\n size_in_byte = N bytes, I2C_LAST_FRAME)

App <-- I2C : HAL_OK

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt RXNE\nByte 1 ...  Byte N

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Master_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nbuffer[0] = RXDR;

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt STOP

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag STOP

App <- I2C : HAL_I2C_MASTER_RxCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Slave Mode IT

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process :  Slave Mode. Receive CMD M bytes + Send N bytes ==



App -> I2C : HAL_I2C_SLAVE_EnableListen_IT(handle)

note over I2C : Enable ADDRI, STOPI, NACKI, ERRI

App <-- I2C : HAL_OK

...

"I2Cx_IRQHandler" <- : I2Cx interrupt ADDR, DIR=Wr

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : I2C_Slave_ISR()

App <- I2C : HAL_I2C_SLAVE_AddrCallback(handle,\nDirection=Write, Addr Match code)

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->

...

App -> I2C : HAL_I2C_SLAVE_SEQ_Receive_IT(handle, addr, &buffer,\n size_in_byte = M, I2C_FIRST_FRAME)

App <-- I2C : HAL_OK

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt RXNE, CMD Byte 1 ... CMD Byte M 

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Slave_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nbuffer[0] = RXDR;

   else else

      App <- I2C : HAL_I2C_SLAVE_RxCpltCallback

      App --> I2C

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt ADDR, DIR=Rd

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : I2C_Slave_ISR()

App <- I2C : HAL_I2C_SLAVE_AddrCallback(handle,\nDirection=Read, Addr Match Code)

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->

...

App -> I2C : HAL_I2C_SLAVE_SEQ_Transmit_IT(handle, addr, &buffer,\n size_in_byte = N, I2C_LAST_FRAME)

App <-- I2C : HAL_OK

...

loop while (size-- != 0)

   "I2Cx_IRQHandler" <- : I2Cx interrupt TXIS, Byte 1 ... Byte N 

   I2C <- "I2Cx_IRQHandler" : HAL_I2C_EV_IRQHandler

   note over I2C : I2C_Slave_ISR()

   alt if (size-- != 0)

      note over I2C : buffer++;\nTXDR = buffer[0];

   else else

      App <- I2C : HAL_I2C_SLAVE_TxCpltCallback

      App --> I2C

   end

   I2C --> "I2Cx_IRQHandler"

   "I2Cx_IRQHandler" -->

end

...

"I2Cx_IRQHandler" <- : I2Cx interrupt STOP

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

note over I2C : Clear Flag STOP

App <- I2C : HAL_I2C_SLAVE_ListenCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Process DMA

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process :  Master Transmit DMA==



participant App

participant I2C

participant "I2Cx_IRQHandler"

participant "HAL DMA driver"

participant "DMAx_IRQHandler"



App -> I2C : HAL_I2C_MASTER_Transmit_DMA

I2C-> "HAL DMA driver" : HAL_DMA_Start_IT

"HAL DMA driver" --> I2C : HAL_OK

App <-- I2C : HAL_OK



"DMAx_IRQHandler" <- : DMAx complete interrupt

"DMAx_IRQHandler" -> "HAL DMA driver" : HAL_DMA_IRQHandler

"HAL DMA driver" -> I2C : XferCpltCallback

"HAL DMA driver" <-- I2C

"DMAx_IRQHandler" <-- "HAL DMA driver"

"DMAx_IRQHandler" -->



"I2Cx_IRQHandler" <- : I2Cx Stop complete interrupt

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

I2C-> App : HAL_I2C_MASTER_TxCpltCallback

I2C<-- App

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->



note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Process Abort IT

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process abort : Master Transmit asynchrone (IT)\n==



App -> I2C : HAL_I2C_MASTER_Transmit_IT

App <-- I2C : HAL_OK

...

App -> I2C : HAL_I2C_MASTER_Abort_IT

App <-- I2C : HAL_OK

...

"I2Cx_IRQHandler" <- : I2Cx Stop complete interrupt

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

App <- I2C : HAL_I2C_AbortCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->





note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Process Abort DMA

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process abort : Master Transmit asynchrone (DMA)\n==



App -> I2C : HAL_I2C_MASTER_Transmit_DMA

App <-- I2C : HAL_OK

...

App -> I2C : HAL_I2C_MASTER_Abort_IT



I2C -> "HAL DMA driver" : HAL_DMA_Abort_IT 

I2C <-- "HAL DMA driver" : HAL_OK



App <-- I2C : HAL_OK

...

"DMAx_IRQHandler" <- : DMAx interrupt

I2C <- "DMAx_IRQHandler" : I2C_DMAAbort

I2C --> "DMAx_IRQHandler"

"DMAx_IRQHandler" -->



...

"I2Cx_IRQHandler" <- : I2Cx Stop complete interrupt

"I2Cx_IRQHandler" -> I2C : HAL_I2C_EV_IRQHandler

App <- I2C : HAL_I2C_AbortCpltCallback

App --> I2C

"I2Cx_IRQHandler" <-- I2C

"I2Cx_IRQHandler" -->





note over App : Driver state is IDLE,\nUser can start any process or execute any configuration.

@enduml

Called functions:

Recoverable Blocking Error

@startuml

participant App as "User application"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

==Process recoverable blocking error : Master Transmit asynchrone (IT or DMA)\n ==



App -> I2C : HAL_I2C_MASTER_Transmit_IT/DMA

App <-- I2C : HAL_OK

...

I2C <- :  I2Cx or DMAx recoverable error interrupt

App <-[#Orange] I2C :\

<color #Orange> HAL_I2C_ErrorCallback(&hi2c) </color>



alt#grey #lightgrey If USE_HAL_I2C_GET_LAST_ERRORS == 1

App->I2C : HAL_I2C_GetLastErrorCodes()

App <-- I2C : \

(HAL_I2C_ERROR_XXX | HAL_I2C_ERROR_YYY)

end



App [#Orange]--> I2C

I2C -->



note over App : Driver state is IDLE,\nUser can start any process or execute\n any configuration.

@enduml

Called functions:

Acquire/Release

@startuml



participant "User 1"

participant "User 2"

participant "<font color=green><b>HAL I2C</b></font>" as I2C

participant "HAL OS wrapper"



"User 1"-[#green]>I2C : <color #green>HAL_I2C_AcquireBus</color>

I2C-[#green]>"HAL OS wrapper" :<color #green>HAL_OS_SemaphoreTake</color>

I2C <-[#green]- "HAL OS wrapper"

"User 1" <-[#green]- I2C : <color #green>HAL_OK</color>



note over I2C : Bus acquired by user 1. Any Process can be executed.\nFor instance : Master Transmit Polling



"User 2"-[#red]>I2C : <color #red>HAL_I2C_AcquireBus</color>

I2C-[#red]>"HAL OS wrapper" :<color #red>HAL_OS_SemaphoreTake</color>



"User 1"-[#green]>I2C : <color #green>HAL_I2C_ReleaseBus</color>

"User 1" <-[#green]- I2C : <color #green>HAL_OK</color>



I2C <-[#red]- "HAL OS wrapper"

"User 2" <-[#red]- I2C : <color #red>HAL_OK</color>



note over I2C : Bus acquired by user 2. Any Process can be executed.\nFor instance : Master Transmit Polling

@enduml

Called functions: