HAL FMAC Use Cases

Prerequisites

The following sequence shows the system services that must be configured before using the FMAC driver.

@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 FMAC initialization sequence

The following sequence shows the complete FMAC driver initialization flow, including optional DMA, clock, and advanced FMAC configuration steps.

@startuml

participant App as "User application"
participant "<font color=Black><b>HAL FMAC</b></font>" as FMAC
participant "HAL CORTEX\n(NVIC)" as CORTEX
participant "HAL DMA" as DMA
participant "HAL RCC" as RCC

==FMAC HAL Initialization==
App -> FMAC : HAL_FMAC_Init
alt#skyblue #lightBlue If USE_HAL_FMAC_CLK_ENABLE_MODEL > HAL_CLK_ENABLE_NO
FMAC->RCC : Enable the FMAC clock
RCC-->FMAC
end
App <-- FMAC : HAL_OK

==FMAC System Initialization==
Note over FMAC : FMAC System initialization can be called before\nFMAC HAL initialization

alt#SkyBlue #LightBlue If Interrupt needed
App->CORTEX : Enable needed Interrupt
CORTEX-->App
end


alt#SkyBlue #LightBlue If USE_HAL_FMAC_DMA == 1
App->DMA : Initialization of DMA
DMA-->App
App->FMAC : HAL_FMAC_SetWriteX1DMA / HAL_FMAC_SetReadYDMA
DMA-->App
end

alt#SkyBlue #LightBlue If USE_HAL_FMAC_CLK_ENABLE_MODEL == HAL_CLK_ENABLE_NO
App->RCC : Enable the FMAC clock
RCC --> App
end

==FMAC Buffer Configuration==
App -> FMAC : HAL_FMAC_SetConfig
App <-- FMAC : HAL_OK

==Advanced FMAC Configuration (optional)==
App -> FMAC : HAL_FMAC_SetX1FullWatermark
App <-- FMAC : HAL_OK
App -> FMAC : HAL_FMAC_SetYEmptyWatermark
App <-- FMAC : HAL_OK
App -> FMAC : HAL_FMAC_EnableClip
App <-- FMAC : HAL_OK

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

@enduml

Called functions:

Full FMAC deinitialization sequence

The following sequence shows the complete FMAC driver deinitialization flow and the related system resource cleanup.

@startuml
participant App as "User application"
participant "<font color=Black><b>HAL FMAC</b></font>" as FMAC
participant "HAL CORTEX\n(NVIC)" as CORTEX
participant "HAL RCC" as RCC
participant "HAL GPIO" as GPIO
participant "HAL DMA" as DMA

== FMAC deinitialization ==
App->FMAC : HAL_FMAC_DeInit
App<--FMAC

== FMAC system deinitialization ==

alt#skyblue #lightBlue If Interrupt needed
App->CORTEX : Disable needed Interrupt
CORTEX-->App
end

alt#skyblue #lightBlue If USE_HAL_FMAC_DMA == 1
App->DMA : Deinitialize DMA
DMA-->App
end

App->RCC : Disable the FMAC clock
RCC --> App
@enduml

Called functions:

FIR interrupt input/X1 interrupt and output/Y DMA

This use case describes a FIR or IIR filter execution where X1 input is written by interrupt and Y output is read by DMA.

@startuml
participant App as "User application"
participant App
participant "<font color=Black><b>HAL FMAC</b></font>" as FMAC
participant "<font color=green><b>HAL DMA</b></font>" as DMA
participant "FMACx_IRQHandler"
participant "DMAx_IRQHandler"

== Prerequisite ==
== Full FMAC Initialization ==

== FIR filter with :\n   - input/X1 managed by interrupt process\n   - output/Y managed by DMA process ==

App -> FMAC : HAL_FMAC_SetX1FullWatermark
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_PreloadX2
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_WriteX1_IT
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_ReadY_DMA
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_StartFilterFIR or HAL_FMAC_StartFilterIIR
App <-- FMAC : HAL_OK

loop#FF7088 #FFBFCC while (size-- != 0)
   "FMACx_IRQHandler" <- : FMACx Write interrupt,\nfree space = Watermark
   FMAC <- "FMACx_IRQHandler" : HAL_FMAC_IRQHandler
   note over FMAC : FMAC_ISR()
   alt#skyblue #lightBlue  if (size-- != 0)
      note over FMAC : buffer++;\nWRITE = buffer[0];
   end
   FMAC --> "FMACx_IRQHandler"
   "FMACx_IRQHandler" -->
end

FMAC-> App : HAL_FMAC_WriteX1CpltCallback
FMAC<-- App

note over App : X1 state is IDLE,\nUser can start any Write X1 process.

loop#FF7088 #FFBFCC  while (HAL_FMAC_StopFilter() is not called by user in case a circular DMA)
   "DMAx_IRQHandler" <- : DMAx half complete interrupt
   "DMAx_IRQHandler" -> "DMA" : HAL_DMA_IRQHandler
   "DMA" -> FMAC : XferCpltCallback
   FMAC-> App : HAL_FMAC_ReadYHalfCpltCallback
   "DMA" <-- FMAC
   "DMAx_IRQHandler" <-- "DMA"
   "DMAx_IRQHandler" -->

   "DMAx_IRQHandler" <- : DMAx complete interrupt
   "DMAx_IRQHandler" -> "DMA" : HAL_DMA_IRQHandler
   "DMA" -> FMAC : XferCpltCallback
   FMAC-> App : HAL_FMAC_ReadYCpltCallback
   "DMA" <-- FMAC
   "DMAx_IRQHandler" <-- "DMA"
   "DMAx_IRQHandler" -->
end

note over App : Y state is IDLE,\nUser can start any Read Y process.

App -> FMAC : HAL_FMAC_StopFilter()
App <-- FMAC : HAL_OK

note over App : Filter state is IDLE,\nUser can start any filter or preload process.
== FMAC deinitialization ==
@enduml

Called functions:

FIR interrupt input/X1 peripheral ADC and output/Y DMA

This use case describes a FIR or IIR filter execution where an external peripheral writes X1 directly and Y output is read by DMA.

@startuml

participant App as "User application"
participant App
participant "<font color=Black><b>HAL FMAC</b></font>" as FMAC
participant "<font color=green><b>HAL DMA</b></font>" as DMA
participant "FMACx_IRQHandler"
participant "DMAx_IRQHandler"

== Prerequisite ==
== Full FMAC Initialization ==

== FIR filter with :\n   - input/X1 managed directly by ADC peripheral\n   - output/Y managed by DMA process ==

note over App : Preload the Coeff B and A.
App -> FMAC : HAL_FMAC_PreloadX2
App <-- FMAC : HAL_OK

note over App : Get the X1 write register address.
App -> FMAC : HAL_FMAC_GetX1Address
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_LockX1WriteAccessForExternPeriph
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_ReadY_DMA
App <-- FMAC : HAL_OK

App -> FMAC : HAL_FMAC_StartFilterFIR or HAL_FMAC_StartFilterIIR
App <-- FMAC : HAL_OK

loop#FF7088 #FFBFCC while (HAL_FMAC_StopFilter() is not called by user in case a circular DMA)
   "DMAx_IRQHandler" <- : DMAx half complete interrupt
   "DMAx_IRQHandler" -> "DMA" : HAL_DMA_IRQHandler
   "DMA" -> FMAC : XferCpltCallback
   FMAC-> App : HAL_FMAC_ReadYHalfCpltCallback
   "DMA" <-- FMAC
   "DMAx_IRQHandler" <-- "DMA"
   "DMAx_IRQHandler" -->

   "DMAx_IRQHandler" <- : DMAx complete interrupt
   "DMAx_IRQHandler" -> "DMA" : HAL_DMA_IRQHandler
   "DMA" -> FMAC : XferCpltCallback
   FMAC-> App : HAL_FMAC_ReadYCpltCallback
   "DMA" <-- FMAC
   "DMAx_IRQHandler" <-- "DMA"
   "DMAx_IRQHandler" -->
end

note over App : Y state is IDLE,\nUser can start any Read Y process.

App -> FMAC : HAL_FMAC_UnlockX1WriteAccessForExternPeriph
App <-- FMAC : HAL_OK

note over App : X1 state is IDLE,\nUser can start any Write X1 process.

App -> FMAC : HAL_FMAC_StopFilter()
App <-- FMAC : HAL_OK

note over App : Filter state is IDLE,\nUser can start any filter or preload process.

== FMAC deinitialization ==
@enduml

Called functions:

Error handling

The following sequence shows the callback and error-code retrieval flow used after an FMAC error event.

@startuml
participant App as "User application"
participant "<font color=Black><b>HAL FMAC</b></font>" as FMAC
==3 Errors :\n - X1 overflow\n - Y underflow\n - Saturation==

note over FMAC : Filter is ACTIVE (FILTER or PRELOAD).
note over FMAC : X1 and Y are ACTIVE or not.

...
FMAC <- :  FMACx error interrupt

note over FMAC : In case of error, the Filter is automatically stop and put in Idle state. \
X1 and Y are also stopped and put in Idle state. DMA are aborted.

App <-[#Violet] FMAC :\
<color #Violet> HAL_FMAC_ErrorCallback(&hfmac) </color>

alt#skyblue #lightBlue If USE_HAL_FMAC_GET_LAST_ERRORS == 1
App->FMAC : HAL_FMAC_GetLastErrorCodes()
App <-- FMAC : \
(HAL_FMAC_ERROR_SAT |HAL_FMAC_ERROR_UNFL | HAL_FMAC_ERROR_OVFL)
end


App [#Violet]--> FMAC
FMAC -->

@enduml

Called functions: