HAL FDCAN Use Cases

Prerequisite

@startuml

skinparam backgroundColor #FFFFFF
' To add a number by line
'autonumber

' Fix order of each column
participant "User Application" as App
participant System

== Prerequisite ==

App -> System:HAL_Init()
note right
Configure the Flash prefetch, the time base source and the NVIC
end note

System --> App:<color green> HAL_OK

App -> System:SystemClock_Config()
note right
Configure system clock
end note
App <-- System:

@enduml

Full FDCAN Initialization Sequence

@startuml

participant "User application" as App
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "System driver" as System

== FDCAN HAL Initialization  ==
App -> FDCAN:HAL_FDCAN_Init()
note right
Initialize the FDCAN handle and associate an instance
end note
alt if (USE_HAL_FDCAN_CLK_ENABLE_MODEL > HAL_CLK_ENABLE_NO)
FDCAN -> System:Enable the FDCAN clock
FDCAN <-- System:
end
App <-- FDCAN:<font color=green>HAL_OK
hnote over FDCAN
<font color=green>Driver state is INIT
end note

alt if (USE_HAL_FDCAN_CLK_ENABLE_MODEL == HAL_CLK_ENABLE_NO)
App-> System:Enable the FDCAN clock
note right
The application is free to enable the FDCAN clock before or after initialization
end note
App <-- System:
end

== FDCAN System Initialization==
Note over FDCAN#lightyellow:  FDCAN System initialization can be called before\nFDCAN HAL initialization

alt#darkgrey #lightgrey  If Interrupts needed
App-> System : Enable needed Interrupts
System-->App
end

alt#darkgrey #lightgrey  If GPIO(s) needed
App-> System : Initialization of GPIOs
System-->App
end

== FDCAN Configuration==
App -> FDCAN : HAL_FDCAN_SetConfig()
Note right#lightyellow: Configure the FDCAN according to the application requirements
App <-- FDCAN:<font color=green>HAL_OK
hnote over FDCAN
<font color=green>Driver state is IDLE
end note

@enduml

Functions called:

Full FDCAN Initialization and Configuration Sequence

@startuml

participant "User application" as App
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A

== FDCAN HAL Initialization  ==
App -> FDCAN: HAL_FDCAN_Init()
note right
Initialize the FDCAN handle and associate an instance
end note
App <-- FDCAN:<color green>HAL_OK
hnote over FDCAN
<font color=green>Driver state is INIT
end note

== FDCAN Global configuration  ==
App -> FDCAN : HAL_FDCAN_SetConfig()
Note right#lightyellow: Configure the FDCAN according to the application requirements
App <-- FDCAN:<color green>HAL_OK
note over App
<color orange><b> The application can start any process or execute any unitary configuration</b>
end note
hnote over FDCAN
<font color=green>Driver state is IDLE
end note

== FDCAN unitary configurations  ==
App-> FDCAN: HAL_FDCAN_Set/Get<Item>()
FDCAN --> App:<color green>HAL_OK
App-> FDCAN: HAL_FDCAN_Enable/Disable<Item>()
FDCAN --> App:<color green>HAL_OK

@enduml

Functions called:

Acceptance Filter Configuration

@startuml

participant "User application" as App
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
note over FDCAN
The FDCAN was already initialized and configured to send or receive frames over the bus
end note

== Acceptance filters configuration  ==
hnote over FDCAN
<font color=green>Driver state is IDLE
end note
note over App
The application can configure several filters
end note
App -> FDCAN: HAL_FDCAN_SetFilter()
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_SetFilter()
FDCAN --> App:<color green>HAL_OK
...
note over App
The application must specify the acceptance or rejection rules for the messages matching or not-matching the filters
end note
App -> FDCAN: HAL_FDCAN_SetGlobalFilter()
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_Start()
FDCAN --> App:<color green>HAL_OK
hnote over FDCAN
<font color=green>Driver state is ACTIVE
end note

@enduml

Functions called:

Full FDCAN Deinitialization Sequence

@startuml

participant "User application" as App
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "System driver" as System

== FDCAN HAL DeInitialization  ==
App-> FDCAN : HAL_FDCAN_DeInit()
note right
Clear the interrupt lines, error code and user data
end note
App<--FDCAN:
hnote over FDCAN
<font color=green>Driver state is RESET
end note

== FDCAN System DeInitialization  ==
App-> System : Disable NVIC
note right
When using interrupt
end note

App-> System : DeInitialization of GPIOs
note right
When using GPIOs
end note
App-> System : Disable FDCAN clock

@enduml

Functions called:

FDCAN Transmit Message Polling Mode Using HAL_FDCAN_GetTxFifoFreeLevel

@startuml

participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A

== Full FDCAN initialization and configuration sequence  ==

App-> FDCAN: HAL_FDCAN_Start(&hfdcan)
FDCAN --> App:<color green>HAL_OK
Note over App#lightyellow: The application builds the Tx Header and Tx Data structure\n and buffer of the message to be transmitted.

== FDCAN HAL Message Transmit  ==
App-> FDCAN: HAL_FDCAN_ReqTransmitMsgFromFIFOQ(&hfdcan, &TxHeader, TxData)
FDCAN --> App:<color green>HAL_OK

loop#darkgrey #lightgrey until  x == FREE_TX_BUFFER
App-> FDCAN: HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan)
FDCAN --> App: x
Note over App#lightyellow: Up to three Tx buffers can be set up for message\n transmission (FREE_TX_BUFFER = 3)
end

@enduml

Functions called:

FDCAN Transmit Message Polling Mode Using HAL_FDCAN_GetTxBufferMessageStatus

@startuml

participant "User application" as App
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A

== HAL FDCAN2 Transmit a message using FIFO/Queue ==

Note over App #lightyellow: The application builds the header and data structures\nof the message to be transmitted.

hnote over FDCAN
   <font color=green>Driver state is IDLE
end hnote

App -> FDCAN: HAL_FDCAN_Start()
FDCAN --> App: <font color=green>HAL_OK

hnote over FDCAN
   <font color=green>Driver state is ACTIVE
end hnote

loop For each message to transmit
   App -> FDCAN: HAL_FDCAN_ReqTransmitMsgFromFIFOQ()
   note right
      Add a message to the Tx FIFO/Queue and activate the transmission request
   end note
   FDCAN --> App: <font color=green>HAL_OK
end

loop While HAL_FDCAN_BUFFER_PENDING on a specific FIFO/Queue buffer
   App -> FDCAN: HAL_FDCAN_GetTxBufferMessageStatus()
   note right
      The application checks if the message has been transmitted from the FIFO/Queue.
   end note

   alt Message not yet transmitted
      FDCAN --> App: HAL_FDCAN_BUFFER_PENDING
      note right
         The transmit buffer is not empty - message still pending
      end note
   else Message transmitted
      FDCAN --> App: HAL_FDCAN_BUFFER_NOT_PENDING
      note right
         The transmit buffer is empty - message sent
      end note
      destroy App
   end
end

@enduml

Functions called:

FDCAN Reading Message Polling Mode Using HAL_FDCAN_GetRxFifoFillLevel

@startuml

participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "System Driver" as Driver#AliceBlue

== HAL FDCAN Polling Message Receive  ==
Note over App#lightyellow: The acceptance filters have been configured.

hnote over FDCAN
   <font color=green>Diver state is ACTIVE
end note

App -> Driver: HAL_GetTick()
note right
   Get the current time
endnote
Driver --> App: starting_time

loop#darkgrey  if fifo_level != 1
   Note over App #lightyellow: Because one single message is expected, the number of element stored\nin Rx FIFO 0 is 1.
   App -> FDCAN: HAL_FDCAN_GetRxFifoFillLevel()
   note right
      Retrieve the Rx FIFO fill level
   endnote

   Driver --> App: fifo_level
   App -> Driver: HAL_GetTick()
   Note over App#lightyellow: The timeout will trigger if the elapsed time\n is more than the MAX_TIMEOUT value defined by the application.
   alt current_time - starting_time < MAX_TIMEOUT
      Driver --> App: current_time
   else timeout occured
      Driver-->App: break
      destroy App
   end
end

App -> FDCAN: HAL_FDCAN_GetReceivedMessage()
note right
   Retrieve an FDCAN frame from the Rx FIFO
endnote

FDCAN --> App:<color green>HAL_OK
note left
   The application can process the received data or error
end note

@enduml

Functions called:

FDCAN Transmission with IT Using Tx Complete/Tx Cancellation Interrupts

@startuml
participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "FDCAN_IRQHandler" as IRQHandler#AliceBlue

== Full FDCAN initialization and configuration sequence  ==

...

== FDCAN HAL Message Transmit on IT  ==
Note over App#lightyellow: This sequence diagram shows how Tx Complete or Tx Abort events from Tx Buffer 0 trigger interrupts on Line 1. Both interrupts are part of HAL_FDCAN_IT_GROUP_STATUS_MSG group.
App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(handle, HAL_FDCAN_IT_GROUP_STATUS_MSG, HAL_FDCAN_IT_LINE_1)
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_EnableInterruptLines(handle, HAL_FDCAN_IT_LINE_1)
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_EnableInterrupts(handle, HAL_FDCAN_IT_TX_COMPLETE | HAL_FDCAN_IT_TX_ABORT_COMPLETE)
FDCAN --> App:<color green>HAL_OK

Note over App#lightgreen: For Transmission Completed and Transmission Cancellation Finished interrupts,\na buffer index must be provided to indicate on which buffer the interrupt will occur:\nHAL_FDCAN_TX_IT_BUFFER_0 in the present example.
alt#darkgrey #lightgrey if interrupt = HAL_FDCAN_IT_TX_COMPLETE
App -> FDCAN: HAL_FDCAN_EnableTxBufferCompleteInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK
else interrupt = HAL_FDCAN_IT_TX_ABORT_COMPLETE
App -> FDCAN: HAL_FDCAN_EnableTxBufferCancellationInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK
end

App -> FDCAN:  HAL_FDCAN_Start(handle)
FDCAN --> App:<color green>HAL_OK
Note over App#lightyellow: The TxHeader and TxData are configured. Because there is only a single\ntx message TX BUFFER 0 will be the default buffer used for transmission.
App -> FDCAN:  HAL_FDCAN_ReqTransmitMsgFromFIFOQ(handle, &TxHeader, &TxData)
FDCAN --> App:<color green>HAL_OK

alt#darkgrey #lightgrey if interrupt = HAL_FDCAN_IT_TX_COMPLETE
App-[hidden]->App
activate App
Note over IRQHandler#lightgreen: The interrupt Tx complete event from the system can be processed by IRQ Handler.
IRQHandler <-  : FDCAN interrupt Tx Complete
IRQHandler -> FDCAN: HAL_FDCAN_IRQHandler
App -> App: wait for an event from Tx Complete callback
FDCAN -> App: HAL_FDCAN_TxBufferCompleteCallback()
App --> FDCAN:
FDCAN --> IRQHandler:
IRQHandler --> :
App-[hidden]->App
deactivate App
else interrupt = HAL_FDCAN_IT_TX_ABORT_COMPLETE
App-[hidden]->App
activate App
Note over IRQHandler#lightgreen: The interrupt Tx cancellation finished event from the system can be processed by IRQ Handler.
IRQHandler <-  : FDCAN interrupt Tx Cancellation Finished
IRQHandler -> FDCAN: HAL_FDCAN_IRQHandler
App -> App: wait for an event from Tx cancellation finished callback
FDCAN -> App: HAL_FDCAN_TxBufferAbortCallback()
App --> FDCAN:
FDCAN --> IRQHandler:
IRQHandler --> :
deactivate App
App-[hidden]->App
end

Note over App#lightgreen: The User application must disable the buffer connected to the interrupt.
alt#darkgrey #lightgrey if interrupt = HAL_FDCAN_IT_TX_COMPLETE
App -> FDCAN: HAL_FDCAN_DisableTxBufferCompleteInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK
else interrupt = HAL_FDCAN_IT_TX_ABORT_COMPLETE
App -> FDCAN: HAL_FDCAN_DisableTxBufferCancellationInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK
end

App -> FDCAN:  HAL_FDCAN_DisableInterrupts(handle, HAL_FDCAN_IT_TX_COMPLETE | HAL_FDCAN_IT_TX_ABORT_COMPLETE)
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_DisableInterruptLines(handle, HAL_FDCAN_IT_LINE_1)
FDCAN --> App:<color green>HAL_OK

@enduml

Functions called:

FDCAN Transmission Complete with IT Using Transmission Completed

@startuml

participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "NVIC" as NVIC#AliceBlue

== FDCAN HAL Message Transmit on IT Tx Complete ==
hnote over FDCAN
<font color=green>Diver state is IDLE
end note
note over App: The fdcan has been initialized, configured. The acceptance filters\n have been set as required.The Tx header, data buffer have been\n correctly configured
App -> FDCAN: HAL_FDCAN_EnableInterrupts(handle, HAL_FDCAN_IT_TX_COMPLETE)
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_EnableTxBufferCompleteInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(handle, HAL_FDCAN_IT_GROUP_STATUS_MSG, HAL_FDCAN_IT_LINE_[0|1])
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_EnableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN --> App:<color green>HAL_OK
App -> FDCAN:  HAL_FDCAN_Start()
FDCAN --> App:<color green>HAL_OK
hnote over FDCAN
<font color=green>Diver state is ACTIVE
end note
App -> FDCAN:  HAL_FDCAN_ReqTransmitMsgFromFIFOQ()
FDCAN --> App:<color green>HAL_OK

activate App #1000DA
hnote over App
<font color=blue>transmission ongoing...
end note
NVIC <-  : FDCAN interrupt Tx Complete
NVIC -> FDCAN: HAL_FDCAN_IRQHandler
FDCAN -> App: HAL_FDCAN_TxBufferCompleteCallback()
App --> FDCAN:
deactivate App
FDCAN --> NVIC:
NVIC --> :
deactivate App
App -> FDCAN: HAL_FDCAN_DisableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_DisableTxBufferCompleteInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK

App -> FDCAN:  HAL_FDCAN_DisableInterrupts(handle, HAL_FDCAN_IT_TX_COMPLETE)
FDCAN --> App:<color green>HAL_OK

@enduml

Functions called:

FDCAN Receiving Message Using the Rx High-Priority Message Interrupt (HPME)

@startuml

participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "NVIC" as NVIC#AliceBlue

== FDCAN HAL Receive High priority message with IT  ==
hnote over FDCAN
<font color=green>Diver state is IDLE
end note
note over App:  Create filters element to select the Rx High Priority message.
App->FDCAN: HAL_FDCAN_SetFilter()
FDCAN-->App:<color green> HAL_OK

note over App
The application can create specific acceptance rules for the messages selected by the filters
end note
App -> FDCAN: HAL_FDCAN_SetGlobalFilter()
FDCAN --> App:<color green> HAL_OK

App -> FDCAN: HAL_FDCAN_EnableInterrupts(handle, HAL_FDCAN_IT_RX_HIGH_PRIORITY_MSG)
FDCAN --> App:<color green> HAL_OK
App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(handle, HAL_FDCAN_IT_GROUP_STATUS_MSG, HAL_FDCAN_IT_LINE_[0|1])
Note right
Assign the interrupt Status Message Group to an interrupt Line.
endnote
FDCAN --> App:<color green> HAL_OK

App -> FDCAN: HAL_FDCAN_EnableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN --> App:<color green> HAL_OK

App -> FDCAN:  HAL_FDCAN_Start()
FDCAN --> App:<color green> HAL_OK
hnote over FDCAN
<font color=green>Diver state is ACTIVE
end note

App[#FFFFFF]-> App
activate App #1000DA
hnote over App
<font color=blue>reception ongoing...
end note
NVIC <-  : FDCAN interrupt High Priority Message received
NVIC -> FDCAN: HAL_FDCAN_IRQHandler
FDCAN -> App: HAL_FDCAN_HighPriorityMessageCallback()
App --> FDCAN:
deactivate App
FDCAN --> NVIC:
NVIC --> :

App -> FDCAN: HAL_FDCAN_GetReceivedMessage()
note right
Retrieve an FDCAN frame from the Rx FIFO
endnote
FDCAN --> App:<color green> HAL_OK

App -> FDCAN: HAL_FDCAN_DisableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN --> App:<color green> HAL_OK

App -> FDCAN:  HAL_FDCAN_DisableInterrupts(handle, HAL_FDCAN_IT_RX_HIGH_PRIORITY_MSG)
FDCAN --> App:<color green> HAL_OK

@enduml

Functions called:

FDCAN Dual Interrupt-Line Configuration

@startuml

participant "User application"             as App#AliceBlue
participant "<font color=green><b>HAL FDCAN"         as FDCAN#AliceBlue
participant "NVIC"                         as NVIC#AliceBlue
participant "IT0_IRQHandler\n(priority 8)" as IT0#AliceBlue
participant "IT1_IRQHandler\n(priority 2)" as IT1#AliceBlue

== Full FDCAN initialization and configuration sequence ==

== Route interrupts to the appropriate line ==
App -> FDCAN: HAL_FDCAN_EnableInterrupts(handle, HAL_FDCAN_Line_TX_COMPLETE | HAL_FDCAN_Line_RX_HIGH_PRIORITY_MSG)
FDCAN --> App:<color green>HAL_OK

alt#darkgrey #lightgrey if interrupt = HAL_FDCAN_Line_TX_COMPLETE
App -> FDCAN: HAL_FDCAN_EnableTxBufferCompleteInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN --> App:<color green>HAL_OK
Note over App#lightyellow: Latency-critical and safety sources → Line 1 (high priority).\nDiagnostic and non-urgent sources → Line 0 (low priority).
App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(&hfdcan,  HAL_FDCAN_Line_GROUP_RX_FIFO0 ,  HAL_FDCAN_Line_LINE0)
FDCAN --> App:<color green>HAL_OK
App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(&hfdcan, HAL_FDCAN_Line_GROUP_MISC,  HAL_FDCAN_Line_LINE1)
FDCAN --> App:<color green>HAL_OK

Note over App#lightyellow: Tx complete, error status, Tx Event FIFO\nremain on Line 0 (default assignment).
App -> FDCAN: HAL_FDCAN_EnableInterruptLines(&hfdcan,\n  HAL_FDCAN_Line_LINE0 | HAL_FDCAN_Line_LINE1)
FDCAN --> App:<color green>HAL_OK

App -> NVIC: Configure IT0 NVIC priority = 8
NVIC --> App

App -> NVIC: Configure IT1 NVIC priority = 2
NVIC --> App

App -> FDCAN: HAL_FDCAN_Start(&hfdcan)
FDCAN --> App:<color green>HAL_OK

== Concurrent event scenario ==

Note over IT0, IT1#lightyellow: A high priority message event (Line 1)\nand a Tx complete event (Line 0)\noccur at the same moment on the bus.

IT1 <-: FDCAN1_IT1_IRQHandler fires (priority 2: preempts IT0)
activate IT1
Note over IT1#lightgreen: IT1 handler processes only Line 1 events.\n High priority message is handled.\nTx complete flag is not touched:\nit belongs to Line 0.
IT1 -> FDCAN: HAL_FDCAN_Line1_IRQHandler(&hfdcan)
FDCAN -> App: HAL_FDCAN_HighPriorityMessageCallback(&hfdcan, fill_level)
App --> FDCAN
FDCAN --> IT1
deactivate IT1
IT1 -->:

IT0 <-: FDCAN1_IT0_IRQHandler fires (priority 8)
activate IT0
Note over IT0#lightgreen: IT0 handler processes only Line 0 events.\nTx complete is handled.\nRx new message flag was already cleared\nby IT1: no interference in either direction.
IT0 -> FDCAN: HAL_FDCAN_Line0_IRQHandler(&hfdcan)
FDCAN -> App: HAL_FDCAN_TxBufferCompleteCallback(&hfdcan, buffer_mask)
App --> FDCAN
FDCAN --> IT0
deactivate IT0
IT0 -->:

Note over App#lightgreen: Both callbacks fired correctly.\nNeither handler interfered with the other.\nTx complete callback was not missed.

@enduml

Functions called:

FDCAN Transmit Abort Using Transmission Cancellation Finished Interrupt

@startuml

participant "User application" as App#AliceBlue
participant "<font color=black><b>HAL FDCAN"  as FDCAN #19DD3A
participant "NVIC" as NVIC#AliceBlue

== FDCAN HAL IT Transmit Cancellation complete  ==
Note over App#lightyellow:  The acceptance filters, headers and data structres have been\nconfigured, the driver is initialized and configured
hnote over FDCAN
<font color=green>Driver state is ACTIVE
end note
App -> FDCAN: HAL_FDCAN_EnableInterrupts(handle, HAL_FDCAN_IT_TX_ABORT_COMPLETE)
FDCAN -->App : <color green>HAL_OK
App -> FDCAN: HAL_FDCAN_SetInterruptGroupsToLine(handle, HAL_FDCAN_IT_GROUP_STATUS_MSG, HAL_FDCAN_IT_LINE_[0|1] )
FDCAN -->App : <color green>HAL_OK
App -> FDCAN: HAL_FDCAN_EnableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN -->App : <color green>HAL_OK

App -> FDCAN:  HAL_FDCAN_ReqTransmitMsgFromFIFOQ()
FDCAN -->App : <color green>HAL_OK

Note over App: <color orange><b>The application wants to abort the last message added to the fifo before being sent</b>
App -> FDCAN:  HAL_FDCAN_GetLatestTxFifoQRequestBuffer()
note right
Get the last buffer sent for transmission.
endnote

FDCAN --> App: <color black>selected buffer
App -> FDCAN: HAL_FDCAN_EnableTxBufferCancellationInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)

FDCAN -->App : <color green>HAL_OK
App -> FDCAN : HAL_FDCAN_ReqAbortOfTxBuffer(handle, HAL_FDCAN_TX_IT_BUFFER_0)
FDCAN -->App : <color green>HAL_OK

...

NVIC <- : FDCAN interrupt Transmission Cancellation finished
note left
The cancellation of the selected buffer has just finished
endnote

NVIC -> FDCAN : HAL_FDCAN_IRQHandler
FDCAN -> App  : HAL_FDCAN_TxBufferAbortCallback()
App --> FDCAN :

FDCAN --> NVIC:
NVIC --> :
App -> FDCAN: HAL_FDCAN_DisableTxBufferCancellationInterrupts(handle, HAL_FDCAN_TX_IT_BUFFER_0)

FDCAN -->App : <color green>HAL_OK
App -> FDCAN:  HAL_FDCAN_DisableInterrupts(handle, HAL_FDCAN_IT_TX_ABORT_COMPLETE)
FDCAN -->App : <color green>HAL_OK
App -> FDCAN: HAL_FDCAN_DisableInterruptLines(handle, HAL_FDCAN_IT_LINE_[0|1])
FDCAN -->App : <color green>HAL_OK

@enduml

Functions called:

Tx Event FIFO Batch Drain

@startuml

participant "User application"  as App#AliceBlue
participant "<font color=green><b>HAL FDCAN" as FDCAN#AliceBlue
participant "IT0_IRQHandler"    as IT0#AliceBlue

== Full FDCAN initialization and configuration sequence ==

App -> FDCAN: HAL_FDCAN_EnableInterrupts(&hfdcan,\n  HAL_FDCAN_Line_TX_EVT_FIFO_NEW_DATA)
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_RegisterTxEventFifoCallback(&hfdcan,\n  TxEventFifoCallback)
FDCAN --> App:<color green>HAL_OK

App -> FDCAN: HAL_FDCAN_Start(&hfdcan)
FDCAN --> App:<color green>HAL_OK

== Tx Event FIFO interrupt fires ==

IT0 <-: FDCAN1_IT0_IRQHandler: Tx Event FIFO new entry
IT0 -> FDCAN: HAL_FDCAN_Line0_IRQHandler(&hfdcan)
FDCAN -> App: HAL_FDCAN_TxEventFifoCallback(&hfdcan, it_flags)
activate App

== Query exact element count before draining ==

Note over App#lightyellow: Query how many events are waiting.\nThis avoids reading an empty slot (over-reading)\nand avoids missing events accumulated since\nthe last drain (under-reading).\nSymmetric with GetRxFifoFillLevel.
App -> FDCAN: HAL_FDCAN_GetTxEventFifoFillLevel(&hfdcan)
FDCAN --> App: count

== Drain exactly count elements ==

Note over App#lightyellow: Loop exactly count times: no sentinel call.\nEach GetTxEvent call reads one element\nand advances the acknowledge pointer internally.
loop#darkgrey #lightgrey i = 0 to count - 1

    App -> FDCAN: HAL_FDCAN_GetTxEvent(&hfdcan, &TxEventHeader)
    FDCAN --> App:<color green>HAL_OK
    App -> App: process TxEventHeader\n(CAN ID, timestamp, message marker,\ntransmission or cancellation event)

end

Note over App#lightgreen: Exactly count elements drained.\nTx Event FIFO is now empty up to\nthe point when the callback fired.

App --> FDCAN
deactivate App
FDCAN --> IT0
IT0 -->:

@enduml

Functions called: - HAL_FDCAN_EnableInterrupts() - HAL_FDCAN_RegisterTxEventFifoCallback() - HAL_FDCAN_Start() - HAL_FDCAN_GetTxEventFifoFillLevel() - HAL_FDCAN_GetTxEvent() - HAL_FDCAN_Line0_IRQHandler() - HAL_FDCAN_TxEventFifoCallback()