From 86608c6770cf08c138a2bdab5855072f64be09ef Mon Sep 17 00:00:00 2001 From: joshua Date: Sat, 30 Dec 2023 23:54:31 -0500 Subject: initial commit --- .../STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c | 2533 ++++++++++++++++++++ 1 file changed, 2533 insertions(+) create mode 100644 Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c (limited to 'Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c') diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c new file mode 100644 index 0000000..c29c0a7 --- /dev/null +++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_fmac.c @@ -0,0 +1,2533 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_fmac.c + * @author MCD Application Team + * @brief FMAC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the FMAC peripheral: + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + Callback functions + * + IRQ handler management + * + Peripheral State and Error functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + * + * @verbatim +================================================================================ + ##### How to use this driver ##### +================================================================================ + [..] + The FMAC HAL driver can be used as follows: + + (#) Initialize the FMAC low level resources by implementing the HAL_FMAC_MspInit(): + (++) Enable the FMAC interface clock using __HAL_RCC_FMAC_CLK_ENABLE(). + (++) In case of using interrupts (e.g. access configured as FMAC_BUFFER_ACCESS_IT): + (+++) Configure the FMAC interrupt priority using HAL_NVIC_SetPriority(). + (+++) Enable the FMAC IRQ handler using HAL_NVIC_EnableIRQ(). + (+++) In FMAC IRQ handler, call HAL_FMAC_IRQHandler(). + (++) In case of using DMA to control data transfer (e.g. access configured + as FMAC_BUFFER_ACCESS_DMA): + (+++) Enable the DMA interface clock using __HAL_RCC_DMA1_CLK_ENABLE() + or __HAL_RCC_DMA2_CLK_ENABLE() depending on the used DMA instance. + (+++) Enable the DMAMUX1 interface clock using __HAL_RCC_DMAMUX1_CLK_ENABLE(). + (+++) If the initialization of the internal buffers (coefficients, input, + output) is done via DMA, configure and enable one DMA channel for + managing data transfer from memory to memory (preload channel). + (+++) If the input buffer is accessed via DMA, configure and enable one + DMA channel for managing data transfer from memory to peripheral + (input channel). + (+++) If the output buffer is accessed via DMA, configure and enable + one DMA channel for managing data transfer from peripheral to + memory (output channel). + (+++) Associate the initialized DMA handle(s) to the FMAC DMA handle(s) + using __HAL_LINKDMA(). + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the enabled DMA channel(s) using HAL_NVIC_SetPriority() + and HAL_NVIC_EnableIRQ(). + + (#) Initialize the FMAC HAL using HAL_FMAC_Init(). This function + resorts to HAL_FMAC_MspInit() for low-level initialization. + + (#) Configure the FMAC processing (filter) using HAL_FMAC_FilterConfig() + or HAL_FMAC_FilterConfig_DMA(). + This function: + (++) Defines the memory area within the FMAC internal memory + (input, coefficients, output) and the associated threshold (input, output). + (++) Configures the filter and its parameters: + (+++) Finite Impulse Response (FIR) filter (also known as convolution). + (+++) Infinite Impulse Response (IIR) filter (direct form 1). + (++) Choose the way to access to the input and output buffers: none, polling, + DMA, IT. "none" means the input and/or output data will be handled by + another IP (ADC, DAC, etc.). + (++) Enable the error interruptions in the input access and/or the output + access is done through IT/DMA. If an error occurs, the interruption + will be triggered in loop. In order to recover, the user will have + to reset the IP with the sequence HAL_FMAC_DeInit / HAL_FMAC_Init. + Optionally, he can also disable the interrupt using __HAL_FMAC_DISABLE_IT; + the error status will be kept, but no more interrupt will be triggered. + (++) Write the provided coefficients into the internal memory using polling + mode ( HAL_FMAC_FilterConfig() ) or DMA ( HAL_FMAC_FilterConfig_DMA() ). + In the DMA case, HAL_FMAC_FilterConfigCallback() is called when + the handling is over. + + (#) Optionally, the user can enable the error interruption related to + saturation by calling __HAL_FMAC_ENABLE_IT. This helps in debugging the + filter. If a saturation occurs, the interruption will be triggered in loop. + In order to recover, the user will have to: + (++) Disable the interruption by calling __HAL_FMAC_DISABLE_IT if + the user wishes to continue all the same. + (++) Reset the IP with the sequence HAL_FMAC_DeInit / HAL_FMAC_Init. + + (#) Optionally, preload input (FIR, IIR) and output (IIR) data using + HAL_FMAC_FilterPreload() or HAL_FMAC_FilterPreload_DMA(). + In the DMA case, HAL_FMAC_FilterPreloadCallback() is called when + the handling is over. + This step is optional as the filter can be started without preloaded + data. + + (#) Start the FMAC processing (filter) using HAL_FMAC_FilterStart(). + This function also configures the output buffer that will be filled from + the circular internal output buffer. The function returns immediately + without updating the provided buffer. The IP processing will be active until + HAL_FMAC_FilterStop() is called. + + (#) If the input internal buffer is accessed via DMA, HAL_FMAC_HalfGetDataCallback() + will be called to indicate that half of the input buffer has been handled. + + (#) If the input internal buffer is accessed via DMA or interrupt, HAL_FMAC_GetDataCallback() + will be called to require new input data. It will be provided through + HAL_FMAC_AppendFilterData() if the DMA isn't in circular mode. + + (#) If the output internal buffer is accessed via DMA, HAL_FMAC_HalfOutputDataReadyCallback() + will be called to indicate that half of the output buffer has been handled. + + (#) If the output internal buffer is accessed via DMA or interrupt, + HAL_FMAC_OutputDataReadyCallback() will be called to require a new output + buffer. It will be provided through HAL_FMAC_ConfigFilterOutputBuffer() + if the DMA isn't in circular mode. + + (#) In all modes except none, provide new input data to be processed via HAL_FMAC_AppendFilterData(). + This function should only be called once the previous input data has been handled + (the preloaded input data isn't concerned). + + (#) In all modes except none, provide a new output buffer to be filled via + HAL_FMAC_ConfigFilterOutputBuffer(). This function should only be called once the previous + user's output buffer has been filled. + + (#) In polling mode, handle the input and output data using HAL_FMAC_PollFilterData(). + This function: + (++) Write the user's input data (provided via HAL_FMAC_AppendFilterData()) + into the FMAC input memory area. + (++) Read the FMAC output memory area and write it into the user's output buffer. + It will return either when: + (++) the user's output buffer is filled. + (++) the user's input buffer has been handled. + The unused data (unread input data or free output data) will not be saved. + The user will have to use the updated input and output sizes to keep track + of them. + + (#) Stop the FMAC processing (filter) using HAL_FMAC_FilterStop(). + + (#) Call HAL_FMAC_DeInit() to de-initialize the FMAC peripheral. This function + resorts to HAL_FMAC_MspDeInit() for low-level de-initialization. + + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_FMAC_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function HAL_FMAC_RegisterCallback() to register a user callback. + Function HAL_FMAC_RegisterCallback() allows to register following callbacks: + (+) ErrorCallback : Error Callback. + (+) HalfGetDataCallback : Get Half Data Callback. + (+) GetDataCallback : Get Data Callback. + (+) HalfOutputDataReadyCallback : Half Output Data Ready Callback. + (+) OutputDataReadyCallback : Output Data Ready Callback. + (+) FilterConfigCallback : Filter Configuration Callback. + (+) FilterPreloadCallback : Filter Preload Callback. + (+) MspInitCallback : FMAC MspInit. + (+) MspDeInitCallback : FMAC MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_FMAC_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_FMAC_UnRegisterCallback() takes as parameters the HAL peripheral handle + and the Callback ID. + This function allows to reset following callbacks: + (+) ErrorCallback : Error Callback. + (+) HalfGetDataCallback : Get Half Data Callback. + (+) GetDataCallback : Get Data Callback. + (+) HalfOutputDataReadyCallback : Half Output Data Ready Callback. + (+) OutputDataReadyCallback : Output Data Ready Callback. + (+) FilterConfigCallback : Filter Configuration Callback. + (+) FilterPreloadCallback : Filter Preload Callback. + (+) MspInitCallback : FMAC MspInit. + (+) MspDeInitCallback : FMAC MspDeInit. + + [..] + By default, after the HAL_FMAC_Init() and when the state is HAL_FMAC_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples GetDataCallback(), OutputDataReadyCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_FMAC_Init() + and HAL_FMAC_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_FMAC_Init() and HAL_FMAC_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_FMAC_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_FMAC_STATE_READY or HAL_FMAC_STATE_RESET state, thus registered (user) + MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_FMAC_RegisterCallback() before calling HAL_FMAC_DeInit() + or HAL_FMAC_Init() function. + + [..] + When the compilation define USE_HAL_FMAC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + + @endverbatim + * + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal.h" + +#if defined(FMAC) +#ifdef HAL_FMAC_MODULE_ENABLED + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @defgroup FMAC FMAC + * @brief FMAC HAL driver module + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup FMAC_Private_Constants FMAC Private Constants + * @{ + */ + +#define MAX_FILTER_DATA_SIZE_TO_HANDLE ((uint16_t) 0xFFU) +#define MAX_PRELOAD_INDEX 0xFFU +#define PRELOAD_ACCESS_DMA 0x00U +#define PRELOAD_ACCESS_POLLING 0x01U +#define POLLING_DISABLED 0U +#define POLLING_ENABLED 1U +#define POLLING_NOT_STOPPED 0U +#define POLLING_STOPPED 1U +/* FMAC polling-based communications time-out value */ +#define HAL_FMAC_TIMEOUT_VALUE 1000U +/* FMAC reset time-out value */ +#define HAL_FMAC_RESET_TIMEOUT_VALUE 500U +/* DMA Read Requests Enable */ +#define FMAC_DMA_REN FMAC_CR_DMAREN +/* DMA Write Channel Enable */ +#define FMAC_DMA_WEN FMAC_CR_DMAWEN +/* FMAC Execution Enable */ +#define FMAC_START FMAC_PARAM_START + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FMAC_Private_Macros FMAC Private Macros + * @{ + */ + +/** + * @brief Get the X1 memory area size. + * @param __HANDLE__ FMAC handle. + * @retval X1_BUF_SIZE + */ +#define FMAC_GET_X1_SIZE(__HANDLE__) \ + ((((__HANDLE__)->Instance->X1BUFCFG) & (FMAC_X1BUFCFG_X1_BUF_SIZE)) >> (FMAC_X1BUFCFG_X1_BUF_SIZE_Pos)) + +/** + * @brief Get the X1 watermark. + * @param __HANDLE__ FMAC handle. + * @retval FULL_WM + */ +#define FMAC_GET_X1_FULL_WM(__HANDLE__) \ + (((__HANDLE__)->Instance->X1BUFCFG) & (FMAC_X1BUFCFG_FULL_WM)) + +/** + * @brief Get the X2 memory area size. + * @param __HANDLE__ FMAC handle. + * @retval X2_BUF_SIZE + */ +#define FMAC_GET_X2_SIZE(__HANDLE__) \ + ((((__HANDLE__)->Instance->X2BUFCFG) & (FMAC_X2BUFCFG_X2_BUF_SIZE)) >> (FMAC_X2BUFCFG_X2_BUF_SIZE_Pos)) + +/** + * @brief Get the Y memory area size. + * @param __HANDLE__ FMAC handle. + * @retval Y_BUF_SIZE + */ +#define FMAC_GET_Y_SIZE(__HANDLE__) \ + ((((__HANDLE__)->Instance->YBUFCFG) & (FMAC_YBUFCFG_Y_BUF_SIZE)) >> (FMAC_YBUFCFG_Y_BUF_SIZE_Pos)) + +/** + * @brief Get the Y watermark. + * @param __HANDLE__ FMAC handle. + * @retval EMPTY_WM + */ +#define FMAC_GET_Y_EMPTY_WM(__HANDLE__) \ + (((__HANDLE__)->Instance->YBUFCFG) & (FMAC_YBUFCFG_EMPTY_WM)) + +/** + * @brief Get the start bit state. + * @param __HANDLE__ FMAC handle. + * @retval START + */ +#define FMAC_GET_START_BIT(__HANDLE__) \ + ((((__HANDLE__)->Instance->PARAM) & (FMAC_PARAM_START)) >> (FMAC_PARAM_START_Pos)) + +/** + * @brief Get the threshold matching the watermark. + * @param __WM__ Watermark value. + * @retval THRESHOLD + */ +#define FMAC_GET_THRESHOLD_FROM_WM(__WM__) (((__WM__) == FMAC_THRESHOLD_1)? 1U: \ + ((__WM__) == FMAC_THRESHOLD_2)? 2U: \ + ((__WM__) == FMAC_THRESHOLD_4)? 4U:8U) + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/* Global variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +static HAL_StatusTypeDef FMAC_Reset(FMAC_HandleTypeDef *hfmac); +static void FMAC_ResetDataPointers(FMAC_HandleTypeDef *hfmac); +static void FMAC_ResetOutputStateAndDataPointers(FMAC_HandleTypeDef *hfmac); +static void FMAC_ResetInputStateAndDataPointers(FMAC_HandleTypeDef *hfmac); +static HAL_StatusTypeDef FMAC_FilterConfig(FMAC_HandleTypeDef *hfmac, FMAC_FilterConfigTypeDef *pConfig, + uint8_t PreloadAccess); +static HAL_StatusTypeDef FMAC_FilterPreload(FMAC_HandleTypeDef *hfmac, int16_t *pInput, uint8_t InputSize, + int16_t *pOutput, uint8_t OutputSize, uint8_t PreloadAccess); +static void FMAC_WritePreloadDataIncrementPtr(FMAC_HandleTypeDef *hfmac, int16_t **ppData, uint8_t Size); +static HAL_StatusTypeDef FMAC_WaitOnStartUntilTimeout(FMAC_HandleTypeDef *hfmac, uint32_t Tickstart, uint32_t Timeout); +static HAL_StatusTypeDef FMAC_AppendFilterDataUpdateState(FMAC_HandleTypeDef *hfmac, int16_t *pInput, + uint16_t *pInputSize); +static HAL_StatusTypeDef FMAC_ConfigFilterOutputBufferUpdateState(FMAC_HandleTypeDef *hfmac, int16_t *pOutput, + uint16_t *pOutputSize); +static void FMAC_WriteDataIncrementPtr(FMAC_HandleTypeDef *hfmac, uint16_t MaxSizeToWrite); +static void FMAC_ReadDataIncrementPtr(FMAC_HandleTypeDef *hfmac, uint16_t MaxSizeToRead); +static void FMAC_DMAHalfGetData(DMA_HandleTypeDef *hdma); +static void FMAC_DMAGetData(DMA_HandleTypeDef *hdma); +static void FMAC_DMAHalfOutputDataReady(DMA_HandleTypeDef *hdma); +static void FMAC_DMAOutputDataReady(DMA_HandleTypeDef *hdma); +static void FMAC_DMAFilterConfig(DMA_HandleTypeDef *hdma); +static void FMAC_DMAFilterPreload(DMA_HandleTypeDef *hdma); +static void FMAC_DMAError(DMA_HandleTypeDef *hdma); + +/* Functions Definition ------------------------------------------------------*/ + +/** @defgroup FMAC_Exported_Functions FMAC Exported Functions + * @{ + */ + +/** @defgroup FMAC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the FMAC peripheral and the associated handle + (+) DeInitialize the FMAC peripheral + (+) Initialize the FMAC MSP (MCU Specific Package) + (+) De-Initialize the FMAC MSP + (+) Register a User FMAC Callback + (+) Unregister a FMAC CallBack + + [..] + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the FMAC peripheral and the associated handle. + * @param hfmac pointer to a FMAC_HandleTypeDef structure. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_Init(FMAC_HandleTypeDef *hfmac) +{ + HAL_StatusTypeDef status; + + /* Check the FMAC handle allocation */ + if (hfmac == NULL) + { + return HAL_ERROR; + } + + /* Check the instance */ + assert_param(IS_FMAC_ALL_INSTANCE(hfmac->Instance)); + + if (hfmac->State == HAL_FMAC_STATE_RESET) + { + /* Initialize lock resource */ + hfmac->Lock = HAL_UNLOCKED; + +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + /* Register the default callback functions */ + hfmac->ErrorCallback = HAL_FMAC_ErrorCallback; + hfmac->HalfGetDataCallback = HAL_FMAC_HalfGetDataCallback; + hfmac->GetDataCallback = HAL_FMAC_GetDataCallback; + hfmac->HalfOutputDataReadyCallback = HAL_FMAC_HalfOutputDataReadyCallback; + hfmac->OutputDataReadyCallback = HAL_FMAC_OutputDataReadyCallback; + hfmac->FilterConfigCallback = HAL_FMAC_FilterConfigCallback; + hfmac->FilterPreloadCallback = HAL_FMAC_FilterPreloadCallback; + + if (hfmac->MspInitCallback == NULL) + { + hfmac->MspInitCallback = HAL_FMAC_MspInit; + } + + /* Init the low level hardware */ + hfmac->MspInitCallback(hfmac); +#else + /* Init the low level hardware */ + HAL_FMAC_MspInit(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } + + /* Reset pInput and pOutput */ + hfmac->FilterParam = 0U; + FMAC_ResetDataPointers(hfmac); + + /* Reset FMAC unit (internal pointers) */ + if (FMAC_Reset(hfmac) == HAL_ERROR) + { + /* Update FMAC error code and FMAC peripheral state */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_RESET; + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + + status = HAL_ERROR; + } + else + { + /* Update FMAC error code and FMAC peripheral state */ + hfmac->ErrorCode = HAL_FMAC_ERROR_NONE; + hfmac->State = HAL_FMAC_STATE_READY; + + status = HAL_OK; + } + + __HAL_UNLOCK(hfmac); + + return status; +} + +/** + * @brief De-initialize the FMAC peripheral. + * @param hfmac pointer to a FMAC structure. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_DeInit(FMAC_HandleTypeDef *hfmac) +{ + /* Check the FMAC handle allocation */ + if (hfmac == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_FMAC_ALL_INSTANCE(hfmac->Instance)); + + /* Change FMAC peripheral state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* Set FMAC error code to none */ + hfmac->ErrorCode = HAL_FMAC_ERROR_NONE; + + /* Reset pInput and pOutput */ + hfmac->FilterParam = 0U; + FMAC_ResetDataPointers(hfmac); + +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + if (hfmac->MspDeInitCallback == NULL) + { + hfmac->MspDeInitCallback = HAL_FMAC_MspDeInit; + } + /* DeInit the low level hardware */ + hfmac->MspDeInitCallback(hfmac); +#else + /* DeInit the low level hardware: CLOCK, NVIC, DMA */ + HAL_FMAC_MspDeInit(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + + /* Change FMAC peripheral state */ + hfmac->State = HAL_FMAC_STATE_RESET; + + /* Always release Lock in case of de-initialization */ + __HAL_UNLOCK(hfmac); + + return HAL_OK; +} + +/** + * @brief Initialize the FMAC MSP. + * @param hfmac FMAC handle. + * @retval None + */ +__weak void HAL_FMAC_MspInit(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMAC_MspInit can be implemented in the user file + */ +} + +/** + * @brief De-initialize the FMAC MSP. + * @param hfmac FMAC handle. + * @retval None + */ +__weak void HAL_FMAC_MspDeInit(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMAC_MspDeInit can be implemented in the user file + */ +} + +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User FMAC Callback. + * @note The User FMAC Callback is to be used instead of the weak predefined callback. + * @note The HAL_FMAC_RegisterCallback() may be called before HAL_FMAC_Init() in HAL_FMAC_STATE_RESET to register + * callbacks for HAL_FMAC_MSPINIT_CB_ID and HAL_FMAC_MSPDEINIT_CB_ID. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param CallbackID ID of the callback to be registered. + * This parameter can be one of the following values: + * @arg @ref HAL_FMAC_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_FMAC_HALF_GET_DATA_CB_ID Get Half Data Callback ID + * @arg @ref HAL_FMAC_GET_DATA_CB_ID Get Data Callback ID + * @arg @ref HAL_FMAC_HALF_OUTPUT_DATA_READY_CB_ID Half Output Data Ready Callback ID + * @arg @ref HAL_FMAC_OUTPUT_DATA_READY_CB_ID Output Data Ready Callback ID + * @arg @ref HAL_FMAC_FILTER_CONFIG_CB_ID Filter Configuration Callback ID + * @arg @ref HAL_FMAC_FILTER_PRELOAD_CB_ID Filter Preload Callback ID + * @arg @ref HAL_FMAC_MSPINIT_CB_ID FMAC MspInit ID + * @arg @ref HAL_FMAC_MSPDEINIT_CB_ID FMAC MspDeInit ID + * @param pCallback pointer to the Callback function. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_RegisterCallback(FMAC_HandleTypeDef *hfmac, HAL_FMAC_CallbackIDTypeDef CallbackID, + pFMAC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the FMAC handle allocation */ + if (hfmac == NULL) + { + return HAL_ERROR; + } + + if (pCallback == NULL) + { + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + if (hfmac->State == HAL_FMAC_STATE_READY) + { + switch (CallbackID) + { + case HAL_FMAC_ERROR_CB_ID : + hfmac->ErrorCallback = pCallback; + break; + + case HAL_FMAC_HALF_GET_DATA_CB_ID : + hfmac->HalfGetDataCallback = pCallback; + break; + + case HAL_FMAC_GET_DATA_CB_ID : + hfmac->GetDataCallback = pCallback; + break; + + case HAL_FMAC_HALF_OUTPUT_DATA_READY_CB_ID : + hfmac->HalfOutputDataReadyCallback = pCallback; + break; + + case HAL_FMAC_OUTPUT_DATA_READY_CB_ID : + hfmac->OutputDataReadyCallback = pCallback; + break; + + case HAL_FMAC_FILTER_CONFIG_CB_ID : + hfmac->FilterConfigCallback = pCallback; + break; + + case HAL_FMAC_FILTER_PRELOAD_CB_ID : + hfmac->FilterPreloadCallback = pCallback; + break; + + case HAL_FMAC_MSPINIT_CB_ID : + hfmac->MspInitCallback = pCallback; + break; + + case HAL_FMAC_MSPDEINIT_CB_ID : + hfmac->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hfmac->State == HAL_FMAC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_FMAC_MSPINIT_CB_ID : + hfmac->MspInitCallback = pCallback; + break; + + case HAL_FMAC_MSPDEINIT_CB_ID : + hfmac->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister a FMAC CallBack. + * @note The FMAC callback is redirected to the weak predefined callback. + * @note The HAL_FMAC_UnRegisterCallback() may be called before HAL_FMAC_Init() in HAL_FMAC_STATE_RESET to register + * callbacks for HAL_FMAC_MSPINIT_CB_ID and HAL_FMAC_MSPDEINIT_CB_ID. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module + * @param CallbackID ID of the callback to be unregistered. + * This parameter can be one of the following values: + * @arg @ref HAL_FMAC_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_FMAC_HALF_GET_DATA_CB_ID Get Half Data Callback ID + * @arg @ref HAL_FMAC_GET_DATA_CB_ID Get Data Callback ID + * @arg @ref HAL_FMAC_HALF_OUTPUT_DATA_READY_CB_ID Half Output Data Ready Callback ID + * @arg @ref HAL_FMAC_OUTPUT_DATA_READY_CB_ID Output Data Ready Callback ID + * @arg @ref HAL_FMAC_FILTER_CONFIG_CB_ID Filter Configuration Callback ID + * @arg @ref HAL_FMAC_FILTER_PRELOAD_CB_ID Filter Preload Callback ID + * @arg @ref HAL_FMAC_MSPINIT_CB_ID FMAC MspInit ID + * @arg @ref HAL_FMAC_MSPDEINIT_CB_ID FMAC MspDeInit ID + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_UnRegisterCallback(FMAC_HandleTypeDef *hfmac, HAL_FMAC_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the FMAC handle allocation */ + if (hfmac == NULL) + { + return HAL_ERROR; + } + + if (hfmac->State == HAL_FMAC_STATE_READY) + { + switch (CallbackID) + { + case HAL_FMAC_ERROR_CB_ID : + hfmac->ErrorCallback = HAL_FMAC_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_FMAC_HALF_GET_DATA_CB_ID : + hfmac->HalfGetDataCallback = HAL_FMAC_HalfGetDataCallback; /* Legacy weak HalfGetDataCallback */ + break; + + case HAL_FMAC_GET_DATA_CB_ID : + hfmac->GetDataCallback = HAL_FMAC_GetDataCallback; /* Legacy weak GetDataCallback */ + break; + + case HAL_FMAC_HALF_OUTPUT_DATA_READY_CB_ID : + hfmac->HalfOutputDataReadyCallback = HAL_FMAC_HalfOutputDataReadyCallback; /* Legacy weak + HalfOutputDataReadyCallback */ + break; + + case HAL_FMAC_OUTPUT_DATA_READY_CB_ID : + hfmac->OutputDataReadyCallback = HAL_FMAC_OutputDataReadyCallback; /* Legacy weak + OutputDataReadyCallback */ + break; + + case HAL_FMAC_FILTER_CONFIG_CB_ID : + hfmac->FilterConfigCallback = HAL_FMAC_FilterConfigCallback; /* Legacy weak + FilterConfigCallback */ + break; + + case HAL_FMAC_FILTER_PRELOAD_CB_ID : + hfmac->FilterPreloadCallback = HAL_FMAC_FilterPreloadCallback; /* Legacy weak FilterPreloadCallba */ + break; + + case HAL_FMAC_MSPINIT_CB_ID : + hfmac->MspInitCallback = HAL_FMAC_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_FMAC_MSPDEINIT_CB_ID : + hfmac->MspDeInitCallback = HAL_FMAC_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hfmac->State == HAL_FMAC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_FMAC_MSPINIT_CB_ID : + hfmac->MspInitCallback = HAL_FMAC_MspInit; + break; + + case HAL_FMAC_MSPDEINIT_CB_ID : + hfmac->MspDeInitCallback = HAL_FMAC_MspDeInit; + break; + + default : + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup FMAC_Exported_Functions_Group2 Peripheral Control functions + * @brief Control functions. + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Configure the FMAC peripheral: memory area, filter type and parameters, + way to access to the input and output memory area (none, polling, IT, DMA). + (+) Start the FMAC processing (filter). + (+) Handle the input data that will be provided into FMAC. + (+) Handle the output data provided by FMAC. + (+) Stop the FMAC processing (filter). + +@endverbatim + * @{ + */ + +/** + * @brief Configure the FMAC filter. + * @note The configuration is done according to the parameters + * specified in the FMAC_FilterConfigTypeDef structure. + * The provided data will be loaded using polling mode. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pConfig pointer to a FMAC_FilterConfigTypeDef structure that + * contains the FMAC configuration information. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterConfig(FMAC_HandleTypeDef *hfmac, FMAC_FilterConfigTypeDef *pConfig) +{ + return (FMAC_FilterConfig(hfmac, pConfig, PRELOAD_ACCESS_POLLING)); +} + +/** + * @brief Configure the FMAC filter. + * @note The configuration is done according to the parameters + * specified in the FMAC_FilterConfigTypeDef structure. + * The provided data will be loaded using DMA. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pConfig pointer to a FMAC_FilterConfigTypeDef structure that + * contains the FMAC configuration information. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterConfig_DMA(FMAC_HandleTypeDef *hfmac, FMAC_FilterConfigTypeDef *pConfig) +{ + return (FMAC_FilterConfig(hfmac, pConfig, PRELOAD_ACCESS_DMA)); +} + +/** + * @brief Preload the input (FIR, IIR) and output data (IIR) of the FMAC filter. + * @note The set(s) of data will be used by FMAC as soon as @ref HAL_FMAC_FilterStart is called. + * The provided data will be loaded using polling mode. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pInput Preloading of the first elements of the input buffer (X1). + * If not needed (no data available when starting), it should be set to NULL. + * @param InputSize Size of the input vector. + * As pInput is used for preloading data, it cannot be bigger than the input memory area. + * @param pOutput [IIR] Preloading of the first elements of the output vector (Y). + * If not needed, it should be set to NULL. + * @param OutputSize Size of the output vector. + * As pOutput is used for preloading data, it cannot be bigger than the output memory area. + * @note The input and the output buffers can be filled by calling several times @ref HAL_FMAC_FilterPreload + * (each call filling partly the buffers). In case of overflow (too much data provided through + * all these calls), an error will be returned. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterPreload(FMAC_HandleTypeDef *hfmac, int16_t *pInput, uint8_t InputSize, + int16_t *pOutput, uint8_t OutputSize) +{ + return (FMAC_FilterPreload(hfmac, pInput, InputSize, pOutput, OutputSize, PRELOAD_ACCESS_POLLING)); +} + +/** + * @brief Preload the input (FIR, IIR) and output data (IIR) of the FMAC filter. + * @note The set(s) of data will be used by FMAC as soon as @ref HAL_FMAC_FilterStart is called. + * The provided data will be loaded using DMA. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pInput Preloading of the first elements of the input buffer (X1). + * If not needed (no data available when starting), it should be set to NULL. + * @param InputSize Size of the input vector. + * As pInput is used for preloading data, it cannot be bigger than the input memory area. + * @param pOutput [IIR] Preloading of the first elements of the output vector (Y). + * If not needed, it should be set to NULL. + * @param OutputSize Size of the output vector. + * As pOutput is used for preloading data, it cannot be bigger than the output memory area. + * @note The input and the output buffers can be filled by calling several times @ref HAL_FMAC_FilterPreload + * (each call filling partly the buffers). In case of overflow (too much data provided through + * all these calls), an error will be returned. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterPreload_DMA(FMAC_HandleTypeDef *hfmac, int16_t *pInput, uint8_t InputSize, + int16_t *pOutput, uint8_t OutputSize) +{ + return (FMAC_FilterPreload(hfmac, pInput, InputSize, pOutput, OutputSize, PRELOAD_ACCESS_DMA)); +} + + +/** + * @brief Start the FMAC processing according to the existing FMAC configuration. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pOutput pointer to buffer where output data of FMAC processing will be stored + * in the next steps. + * If it is set to NULL, the output will not be read and it will be up to + * an external IP to empty the output buffer. + * @param pOutputSize pointer to the size of the output buffer. The number of read data will be written here. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterStart(FMAC_HandleTypeDef *hfmac, int16_t *pOutput, uint16_t *pOutputSize) +{ + uint32_t tmpcr = 0U; + HAL_StatusTypeDef status; + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) != 0U) + { + return HAL_ERROR; + } + + /* Check that a valid configuration was done previously */ + if (hfmac->FilterParam == 0U) + { + return HAL_ERROR; + } + + /* Check handle state is ready */ + if (hfmac->State == HAL_FMAC_STATE_READY) + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* CR: Configure the input access (error interruptions enabled only for IT or DMA) */ + if (hfmac->InputAccess == FMAC_BUFFER_ACCESS_DMA) + { + tmpcr |= FMAC_DMA_WEN; + } + else if (hfmac->InputAccess == FMAC_BUFFER_ACCESS_IT) + { + tmpcr |= FMAC_IT_WIEN; + } + else + { + /* nothing to do */ + } + + /* CR: Configure the output access (error interruptions enabled only for IT or DMA) */ + if (hfmac->OutputAccess == FMAC_BUFFER_ACCESS_DMA) + { + tmpcr |= FMAC_DMA_REN; + } + else if (hfmac->OutputAccess == FMAC_BUFFER_ACCESS_IT) + { + tmpcr |= FMAC_IT_RIEN; + } + else + { + /* nothing to do */ + } + + /* CR: Write the configuration */ + MODIFY_REG(hfmac->Instance->CR, \ + FMAC_IT_RIEN | FMAC_IT_WIEN | FMAC_DMA_REN | FMAC_CR_DMAWEN, \ + tmpcr); + + /* Register the new output buffer */ + status = FMAC_ConfigFilterOutputBufferUpdateState(hfmac, pOutput, pOutputSize); + + if (status == HAL_OK) + { + /* PARAM: Start the filter ( this can generate interrupts before the end of the HAL_FMAC_FilterStart ) */ + WRITE_REG(hfmac->Instance->PARAM, (uint32_t)(hfmac->FilterParam)); + } + + /* Reset the busy flag (do not overwrite the possible write and read flag) */ + hfmac->State = HAL_FMAC_STATE_READY; + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Provide a new input buffer that will be loaded into the FMAC input memory area. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pInput New input vector (additional input data). + * @param pInputSize Size of the input vector (if all the data can't be + * written, it will be updated with the number of data read from FMAC). + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_AppendFilterData(FMAC_HandleTypeDef *hfmac, int16_t *pInput, uint16_t *pInputSize) +{ + HAL_StatusTypeDef status; + + /* Check the function parameters */ + if ((pInput == NULL) || (pInputSize == NULL)) + { + return HAL_ERROR; + } + if (*pInputSize == 0U) + { + return HAL_ERROR; + } + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) == 0U) + { + return HAL_ERROR; + } + + /* Check the FMAC configuration */ + if (hfmac->InputAccess == FMAC_BUFFER_ACCESS_NONE) + { + return HAL_ERROR; + } + + /* Check whether the previous input vector has been handled */ + if ((hfmac->pInputSize != NULL) && (hfmac->InputCurrentSize < * (hfmac->pInputSize))) + { + return HAL_ERROR; + } + + /* Check that FMAC was initialized and that no writing is already ongoing */ + if (hfmac->WrState == HAL_FMAC_STATE_READY) + { + /* Register the new input buffer */ + status = FMAC_AppendFilterDataUpdateState(hfmac, pInput, pInputSize); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Provide a new output buffer to be filled with the data computed by FMAC unit. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pOutput New output vector. + * @param pOutputSize Size of the output vector (if the vector can't + * be entirely filled, pOutputSize will be updated with the number + * of data read from FMAC). + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_ConfigFilterOutputBuffer(FMAC_HandleTypeDef *hfmac, int16_t *pOutput, uint16_t *pOutputSize) +{ + HAL_StatusTypeDef status; + + /* Check the function parameters */ + if ((pOutput == NULL) || (pOutputSize == NULL)) + { + return HAL_ERROR; + } + if (*pOutputSize == 0U) + { + return HAL_ERROR; + } + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) == 0U) + { + return HAL_ERROR; + } + + /* Check the FMAC configuration */ + if (hfmac->OutputAccess == FMAC_BUFFER_ACCESS_NONE) + { + return HAL_ERROR; + } + + /* Check whether the previous output vector has been handled */ + if ((hfmac->pOutputSize != NULL) && (hfmac->OutputCurrentSize < * (hfmac->pOutputSize))) + { + return HAL_ERROR; + } + + /* Check that FMAC was initialized and that not reading is already ongoing */ + if (hfmac->RdState == HAL_FMAC_STATE_READY) + { + /* Register the new output buffer */ + status = FMAC_ConfigFilterOutputBufferUpdateState(hfmac, pOutput, pOutputSize); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Handle the input and/or output data in polling mode + * @note This function writes the previously provided user's input data and + * fills the previously provided user's output buffer, + * according to the existing FMAC configuration (polling mode only). + * The function returns when the input data has been handled or + * when the output data is filled. The possible unused data isn't + * kept. It will be up to the user to handle it. The previously + * provided pInputSize and pOutputSize will be used to indicate to the + * size of the read/written data to the user. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param Timeout timeout value. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_PollFilterData(FMAC_HandleTypeDef *hfmac, uint32_t Timeout) +{ + uint32_t tickstart; + uint8_t inpolling; + uint8_t inpollingover = POLLING_NOT_STOPPED; + uint8_t outpolling; + uint8_t outpollingover = POLLING_NOT_STOPPED; + HAL_StatusTypeDef status; + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) == 0U) + { + return HAL_ERROR; + } + + /* Check the configuration */ + + /* Get the input and output mode (if no buffer was previously provided, nothing will be read/written) */ + if ((hfmac->InputAccess == FMAC_BUFFER_ACCESS_POLLING) && (hfmac->pInput != NULL)) + { + inpolling = POLLING_ENABLED; + } + else + { + inpolling = POLLING_DISABLED; + } + if ((hfmac->OutputAccess == FMAC_BUFFER_ACCESS_POLLING) && (hfmac->pOutput != NULL)) + { + outpolling = POLLING_ENABLED; + } + else + { + outpolling = POLLING_DISABLED; + } + + /* Check the configuration */ + if ((inpolling == POLLING_DISABLED) && (outpolling == POLLING_DISABLED)) + { + return HAL_ERROR; + } + + /* Check handle state is ready */ + if (hfmac->State == HAL_FMAC_STATE_READY) + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Loop on reading and writing until timeout */ + while ((HAL_GetTick() - tickstart) < Timeout) + { + /* X1: Check the mode: polling or none */ + if (inpolling != POLLING_DISABLED) + { + FMAC_WriteDataIncrementPtr(hfmac, MAX_FILTER_DATA_SIZE_TO_HANDLE); + if (hfmac->InputCurrentSize == *(hfmac->pInputSize)) + { + inpollingover = POLLING_STOPPED; + } + } + + /* Y: Check the mode: polling or none */ + if (outpolling != POLLING_DISABLED) + { + FMAC_ReadDataIncrementPtr(hfmac, MAX_FILTER_DATA_SIZE_TO_HANDLE); + if (hfmac->OutputCurrentSize == *(hfmac->pOutputSize)) + { + outpollingover = POLLING_STOPPED; + } + } + + /* Exit if there isn't data to handle anymore on one side or another */ + if ((inpollingover != POLLING_NOT_STOPPED) || (outpollingover != POLLING_NOT_STOPPED)) + { + break; + } + } + + /* Change the FMAC state; update the input and output sizes; reset the indexes */ + if (inpolling != POLLING_DISABLED) + { + (*(hfmac->pInputSize)) = hfmac->InputCurrentSize; + FMAC_ResetInputStateAndDataPointers(hfmac); + } + if (outpolling != POLLING_DISABLED) + { + (*(hfmac->pOutputSize)) = hfmac->OutputCurrentSize; + FMAC_ResetOutputStateAndDataPointers(hfmac); + } + + /* Reset the busy flag (do not overwrite the possible write and read flag) */ + hfmac->State = HAL_FMAC_STATE_READY; + + if ((HAL_GetTick() - tickstart) >= Timeout) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + status = HAL_ERROR; + } + else + { + status = HAL_OK; + } + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Stop the FMAC processing. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval HAL_StatusTypeDef HAL status + */ +HAL_StatusTypeDef HAL_FMAC_FilterStop(FMAC_HandleTypeDef *hfmac) +{ + HAL_StatusTypeDef status; + + /* Check handle state is ready */ + if (hfmac->State == HAL_FMAC_STATE_READY) + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* Set the START bit to 0 (stop the previously configured filter) */ + CLEAR_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START); + + /* Disable the interrupts in order to avoid crossing cases */ + CLEAR_BIT(hfmac->Instance->CR, FMAC_DMA_REN | FMAC_DMA_WEN | FMAC_IT_RIEN | FMAC_IT_WIEN); + + /* In case of IT, update the sizes */ + if ((hfmac->InputAccess == FMAC_BUFFER_ACCESS_IT) && (hfmac->pInput != NULL)) + { + (*(hfmac->pInputSize)) = hfmac->InputCurrentSize; + } + if ((hfmac->OutputAccess == FMAC_BUFFER_ACCESS_IT) && (hfmac->pOutput != NULL)) + { + (*(hfmac->pOutputSize)) = hfmac->OutputCurrentSize; + } + + /* Reset FMAC unit (internal pointers) */ + if (FMAC_Reset(hfmac) == HAL_ERROR) + { + /* Update FMAC error code and FMAC peripheral state */ + hfmac->ErrorCode = HAL_FMAC_ERROR_RESET; + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + status = HAL_ERROR; + } + else + { + /* Reset the data pointers */ + FMAC_ResetDataPointers(hfmac); + + status = HAL_OK; + } + + /* Reset the busy flag */ + hfmac->State = HAL_FMAC_STATE_READY; + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @} + */ + +/** @defgroup FMAC_Exported_Functions_Group3 Callback functions + * @brief Callback functions. + * +@verbatim + ============================================================================== + ##### Callback functions ##### + ============================================================================== + [..] This section provides Interruption and DMA callback functions: + (+) DMA or Interrupt: the user's input data is half written (DMA only) + or completely written. + (+) DMA or Interrupt: the user's output buffer is half filled (DMA only) + or completely filled. + (+) DMA or Interrupt: error handling. + +@endverbatim + * @{ + */ + +/** + * @brief FMAC error callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_ErrorCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC get half data callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_HalfGetDataCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_HalfGetDataCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC get data callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_GetDataCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_GetDataCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC half output data ready callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_HalfOutputDataReadyCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_HalfOutputDataReadyCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC output data ready callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_OutputDataReadyCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_OutputDataReadyCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC filter configuration callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_FilterConfigCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_FilterConfigCallback can be implemented in the user file. + */ +} + +/** + * @brief FMAC filter preload callback. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +__weak void HAL_FMAC_FilterPreloadCallback(FMAC_HandleTypeDef *hfmac) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmac); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_FMAC_FilterPreloadCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup FMAC_Exported_Functions_Group4 IRQ handler management + * @brief IRQ handler. + * +@verbatim + ============================================================================== + ##### IRQ handler management ##### + ============================================================================== +[..] This section provides IRQ handler function. + +@endverbatim + * @{ + */ + +/** + * @brief Handle FMAC interrupt request. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval None + */ +void HAL_FMAC_IRQHandler(FMAC_HandleTypeDef *hfmac) +{ + uint32_t itsource; + + /* Check if the read interrupt is enabled and if Y buffer empty flag isn't set */ + itsource = __HAL_FMAC_GET_IT_SOURCE(hfmac, FMAC_IT_RIEN); + if ((__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_YEMPTY) == 0U) && (itsource != 0U)) + { + /* Read some data if possible (Y size is used as a pseudo timeout in order + to not get stuck too long under IT if FMAC keeps on processing input + data reloaded via DMA for instance). */ + if (hfmac->pOutput != NULL) + { + FMAC_ReadDataIncrementPtr(hfmac, (uint16_t)FMAC_GET_Y_SIZE(hfmac)); + } + + /* Indicate that data is ready to be read */ + if ((hfmac->pOutput == NULL) || (hfmac->OutputCurrentSize == *(hfmac->pOutputSize))) + { + /* Reset the pointers to indicate new data will be needed */ + FMAC_ResetOutputStateAndDataPointers(hfmac); + + /* Call the output data ready callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->OutputDataReadyCallback(hfmac); +#else + HAL_FMAC_OutputDataReadyCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } + } + + /* Check if the write interrupt is enabled and if X1 buffer full flag isn't set */ + itsource = __HAL_FMAC_GET_IT_SOURCE(hfmac, FMAC_IT_WIEN); + if ((__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_X1FULL) == 0U) && (itsource != 0U)) + { + /* Write some data if possible (X1 size is used as a pseudo timeout in order + to not get stuck too long under IT if FMAC keep on processing input + data whereas its output emptied via DMA for instance). */ + if (hfmac->pInput != NULL) + { + FMAC_WriteDataIncrementPtr(hfmac, (uint16_t)FMAC_GET_X1_SIZE(hfmac)); + } + + /* Indicate that new data will be needed */ + if ((hfmac->pInput == NULL) || (hfmac->InputCurrentSize == *(hfmac->pInputSize))) + { + /* Reset the pointers to indicate new data will be needed */ + FMAC_ResetInputStateAndDataPointers(hfmac); + + /* Call the get data callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->GetDataCallback(hfmac); +#else + HAL_FMAC_GetDataCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } + } + + /* Check if the overflow error interrupt is enabled and if overflow error flag is raised */ + itsource = __HAL_FMAC_GET_IT_SOURCE(hfmac, FMAC_IT_OVFLIEN); + if ((__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_OVFL) != 0U) && (itsource != 0U)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_OVFL; + } + + /* Check if the underflow error interrupt is enabled and if underflow error flag is raised */ + itsource = __HAL_FMAC_GET_IT_SOURCE(hfmac, FMAC_IT_UNFLIEN); + if ((__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_UNFL) != 0U) && (itsource != 0U)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_UNFL; + } + + /* Check if the saturation error interrupt is enabled and if saturation error flag is raised */ + itsource = __HAL_FMAC_GET_IT_SOURCE(hfmac, FMAC_IT_SATIEN); + if ((__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_SAT) != 0U) && (itsource != 0U)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_SAT; + } + + /* Call the error callback if an error occurred */ + if (hfmac->ErrorCode != HAL_FMAC_ERROR_NONE) + { + /* Call the error callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->ErrorCallback(hfmac); +#else + HAL_FMAC_ErrorCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } +} + +/** + * @} + */ + +/** @defgroup FMAC_Exported_Functions_Group5 Peripheral State and Error functions + * @brief Peripheral State and Error functions. + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] This subsection provides functions allowing to + (+) Check the FMAC state + (+) Get error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the FMAC state. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @retval HAL_FMAC_StateTypeDef FMAC state + */ +HAL_FMAC_StateTypeDef HAL_FMAC_GetState(FMAC_HandleTypeDef *hfmac) +{ + /* Return FMAC state */ + return hfmac->State; +} + +/** + * @brief Return the FMAC peripheral error. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @note The returned error is a bit-map combination of possible errors. + * @retval uint32_t Error bit-map based on @ref FMAC_Error_Code + */ +uint32_t HAL_FMAC_GetError(FMAC_HandleTypeDef *hfmac) +{ + /* Return FMAC error code */ + return hfmac->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup FMAC_Private_Functions FMAC Private Functions + * @{ + */ + +/** + ============================================================================== + ##### FMAC Private Functions ##### + ============================================================================== + */ +/** + * @brief Perform a reset of the FMAC unit. + * @param hfmac FMAC handle. + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_Reset(FMAC_HandleTypeDef *hfmac) +{ + uint32_t tickstart; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Perform the reset */ + SET_BIT(hfmac->Instance->CR, FMAC_CR_RESET); + + /* Wait until flag is reset */ + while (READ_BIT(hfmac->Instance->CR, FMAC_CR_RESET) != 0U) + { + if ((HAL_GetTick() - tickstart) > HAL_FMAC_RESET_TIMEOUT_VALUE) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + return HAL_ERROR; + } + } + + hfmac->ErrorCode = HAL_FMAC_ERROR_NONE; + return HAL_OK; +} + +/** + * @brief Reset the data pointers of the FMAC unit. + * @param hfmac FMAC handle. + * @retval None + */ +static void FMAC_ResetDataPointers(FMAC_HandleTypeDef *hfmac) +{ + FMAC_ResetInputStateAndDataPointers(hfmac); + FMAC_ResetOutputStateAndDataPointers(hfmac); +} + +/** + * @brief Reset the input data pointers of the FMAC unit. + * @param hfmac FMAC handle. + * @retval None + */ +static void FMAC_ResetInputStateAndDataPointers(FMAC_HandleTypeDef *hfmac) +{ + hfmac->pInput = NULL; + hfmac->pInputSize = NULL; + hfmac->InputCurrentSize = 0U; + hfmac->WrState = HAL_FMAC_STATE_READY; +} + +/** + * @brief Reset the output data pointers of the FMAC unit. + * @param hfmac FMAC handle. + * @retval None + */ +static void FMAC_ResetOutputStateAndDataPointers(FMAC_HandleTypeDef *hfmac) +{ + hfmac->pOutput = NULL; + hfmac->pOutputSize = NULL; + hfmac->OutputCurrentSize = 0U; + hfmac->RdState = HAL_FMAC_STATE_READY; +} + +/** + * @brief Configure the FMAC filter. + * @note The configuration is done according to the parameters + * specified in the FMAC_FilterConfigTypeDef structure. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pConfig pointer to a FMAC_FilterConfigTypeDef structure that + * contains the FMAC configuration information. + * @param PreloadAccess access mode used for the preload (polling or DMA). + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_FilterConfig(FMAC_HandleTypeDef *hfmac, FMAC_FilterConfigTypeDef *pConfig, + uint8_t PreloadAccess) +{ + uint32_t tickstart; + uint32_t tmpcr; +#if defined(USE_FULL_ASSERT) + uint32_t x2size; +#endif /* USE_FULL_ASSERT */ + + /* Check the parameters */ + assert_param(IS_FMAC_THRESHOLD(pConfig->InputThreshold)); + assert_param(IS_FMAC_THRESHOLD(pConfig->OutputThreshold)); + assert_param(IS_FMAC_BUFFER_ACCESS(pConfig->InputAccess)); + assert_param(IS_FMAC_BUFFER_ACCESS(pConfig->OutputAccess)); + assert_param(IS_FMAC_CLIP_STATE(pConfig->Clip)); + assert_param(IS_FMAC_FILTER_FUNCTION(pConfig->Filter)); + assert_param(IS_FMAC_PARAM_P(pConfig->Filter, pConfig->P)); + assert_param(IS_FMAC_PARAM_Q(pConfig->Filter, pConfig->Q)); + assert_param(IS_FMAC_PARAM_R(pConfig->Filter, pConfig->R)); + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) != 0U) + { + return HAL_ERROR; + } + + /* Check handle state is ready */ + if (hfmac->State != HAL_FMAC_STATE_READY) + { + return HAL_ERROR; + } + + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Indicate that there is no valid configuration done */ + hfmac->FilterParam = 0U; + + /* FMAC_X1BUFCFG: Configure the input buffer within the internal memory if required */ + if (pConfig->InputBufferSize != 0U) + { + MODIFY_REG(hfmac->Instance->X1BUFCFG, \ + (FMAC_X1BUFCFG_X1_BASE | FMAC_X1BUFCFG_X1_BUF_SIZE), \ + (((((uint32_t)(pConfig->InputBaseAddress)) << FMAC_X1BUFCFG_X1_BASE_Pos) & FMAC_X1BUFCFG_X1_BASE) | \ + ((((uint32_t)(pConfig->InputBufferSize)) << FMAC_X1BUFCFG_X1_BUF_SIZE_Pos) & \ + FMAC_X1BUFCFG_X1_BUF_SIZE))); + } + + /* FMAC_X1BUFCFG: Configure the input threshold if valid when compared to the configured X1 size */ + if (pConfig->InputThreshold != FMAC_THRESHOLD_NO_VALUE) + { + /* Check the parameter */ + assert_param(IS_FMAC_THRESHOLD_APPLICABLE(FMAC_GET_X1_SIZE(hfmac), pConfig->InputThreshold, pConfig->InputAccess)); + + MODIFY_REG(hfmac->Instance->X1BUFCFG, \ + FMAC_X1BUFCFG_FULL_WM, \ + ((pConfig->InputThreshold) & FMAC_X1BUFCFG_FULL_WM)); + } + + /* FMAC_X2BUFCFG: Configure the coefficient buffer within the internal memory */ + if (pConfig->CoeffBufferSize != 0U) + { + MODIFY_REG(hfmac->Instance->X2BUFCFG, \ + (FMAC_X2BUFCFG_X2_BASE | FMAC_X2BUFCFG_X2_BUF_SIZE), \ + (((((uint32_t)(pConfig->CoeffBaseAddress)) << FMAC_X2BUFCFG_X2_BASE_Pos) & FMAC_X2BUFCFG_X2_BASE) | \ + ((((uint32_t)(pConfig->CoeffBufferSize)) << FMAC_X2BUFCFG_X2_BUF_SIZE_Pos) &\ + FMAC_X2BUFCFG_X2_BUF_SIZE))); + } + + /* FMAC_YBUFCFG: Configure the output buffer within the internal memory if required */ + if (pConfig->OutputBufferSize != 0U) + { + MODIFY_REG(hfmac->Instance->YBUFCFG, \ + (FMAC_YBUFCFG_Y_BASE | FMAC_YBUFCFG_Y_BUF_SIZE), \ + (((((uint32_t)(pConfig->OutputBaseAddress)) << FMAC_YBUFCFG_Y_BASE_Pos) & FMAC_YBUFCFG_Y_BASE) | \ + ((((uint32_t)(pConfig->OutputBufferSize)) << FMAC_YBUFCFG_Y_BUF_SIZE_Pos) & FMAC_YBUFCFG_Y_BUF_SIZE))); + } + + /* FMAC_YBUFCFG: Configure the output threshold if valid when compared to the configured Y size */ + if (pConfig->OutputThreshold != FMAC_THRESHOLD_NO_VALUE) + { + /* Check the parameter */ + assert_param(IS_FMAC_THRESHOLD_APPLICABLE(FMAC_GET_Y_SIZE(hfmac), pConfig->OutputThreshold, pConfig->OutputAccess)); + + MODIFY_REG(hfmac->Instance->YBUFCFG, \ + FMAC_YBUFCFG_EMPTY_WM, \ + ((pConfig->OutputThreshold) & FMAC_YBUFCFG_EMPTY_WM)); + } + + /* FMAC_CR: Configure the clip feature */ + tmpcr = pConfig->Clip & FMAC_CR_CLIPEN; + + /* FMAC_CR: If IT or DMA will be used, enable error interrupts. + * Being more a debugging feature, FMAC_CR_SATIEN isn't enabled by default. */ + if ((pConfig->InputAccess == FMAC_BUFFER_ACCESS_DMA) || (pConfig->InputAccess == FMAC_BUFFER_ACCESS_IT) || + (pConfig->OutputAccess == FMAC_BUFFER_ACCESS_DMA) || (pConfig->OutputAccess == FMAC_BUFFER_ACCESS_IT)) + { + tmpcr |= FMAC_IT_UNFLIEN | FMAC_IT_OVFLIEN; + } + + /* FMAC_CR: write the value */ + WRITE_REG(hfmac->Instance->CR, tmpcr); + + /* Save the input/output accesses in order to configure RIEN, WIEN, DMAREN and DMAWEN during filter start */ + hfmac->InputAccess = pConfig->InputAccess; + hfmac->OutputAccess = pConfig->OutputAccess; + + /* Check whether the configured X2 is big enough for the filter */ +#if defined(USE_FULL_ASSERT) + x2size = FMAC_GET_X2_SIZE(hfmac); +#endif /* USE_FULL_ASSERT */ + assert_param(((pConfig->Filter == FMAC_FUNC_CONVO_FIR) && (x2size >= pConfig->P)) || \ + ((pConfig->Filter == FMAC_FUNC_IIR_DIRECT_FORM_1) && \ + (x2size >= ((uint32_t)pConfig->P + (uint32_t)pConfig->Q)))); + + /* Build the PARAM value that will be used when starting the filter */ + hfmac->FilterParam = (FMAC_PARAM_START | pConfig->Filter | \ + ((((uint32_t)(pConfig->P)) << FMAC_PARAM_P_Pos) & FMAC_PARAM_P) | \ + ((((uint32_t)(pConfig->Q)) << FMAC_PARAM_Q_Pos) & FMAC_PARAM_Q) | \ + ((((uint32_t)(pConfig->R)) << FMAC_PARAM_R_Pos) & FMAC_PARAM_R)); + + /* Initialize the coefficient buffer if required (pCoeffA for FIR only) */ + if ((pConfig->pCoeffB != NULL) && (pConfig->CoeffBSize != 0U)) + { + /* FIR/IIR: The provided coefficients should match X2 size */ + assert_param(((uint32_t)pConfig->CoeffASize + (uint32_t)pConfig->CoeffBSize) <= x2size); + /* FIR/IIR: The size of pCoeffB should match the parameter P */ + assert_param(pConfig->CoeffBSize >= pConfig->P); + /* pCoeffA should be provided for IIR but not for FIR */ + /* IIR : if pCoeffB is provided, pCoeffA should also be there */ + /* IIR: The size of pCoeffA should match the parameter Q */ + assert_param(((pConfig->Filter == FMAC_FUNC_CONVO_FIR) && + (pConfig->pCoeffA == NULL) && (pConfig->CoeffASize == 0U)) || + ((pConfig->Filter == FMAC_FUNC_IIR_DIRECT_FORM_1) && + (pConfig->pCoeffA != NULL) && (pConfig->CoeffASize != 0U) && + (pConfig->CoeffASize >= pConfig->Q))); + + /* Write number of values to be loaded, the data load function and start the operation */ + WRITE_REG(hfmac->Instance->PARAM, \ + (((uint32_t)(pConfig->CoeffBSize) << FMAC_PARAM_P_Pos) | \ + ((uint32_t)(pConfig->CoeffASize) << FMAC_PARAM_Q_Pos) | \ + FMAC_FUNC_LOAD_X2 | FMAC_PARAM_START)); + + if (PreloadAccess == PRELOAD_ACCESS_POLLING) + { + /* Load the buffer into the internal memory */ + FMAC_WritePreloadDataIncrementPtr(hfmac, &(pConfig->pCoeffB), pConfig->CoeffBSize); + + /* Load pCoeffA if needed */ + if ((pConfig->pCoeffA != NULL) && (pConfig->CoeffASize != 0U)) + { + /* Load the buffer into the internal memory */ + FMAC_WritePreloadDataIncrementPtr(hfmac, &(pConfig->pCoeffA), pConfig->CoeffASize); + } + + /* Wait for the end of the writing */ + if (FMAC_WaitOnStartUntilTimeout(hfmac, tickstart, HAL_FMAC_TIMEOUT_VALUE) != HAL_OK) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + return HAL_ERROR; + } + + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_READY; + } + else + { + hfmac->pInput = pConfig->pCoeffA; + hfmac->InputCurrentSize = pConfig->CoeffASize; + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaPreload->XferHalfCpltCallback = NULL; + hfmac->hdmaPreload->XferCpltCallback = FMAC_DMAFilterConfig; + /* Set the DMA error callback */ + hfmac->hdmaPreload->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC preload data write */ + return (HAL_DMA_Start_IT(hfmac->hdmaPreload, (uint32_t)pConfig->pCoeffB, (uint32_t)&hfmac->Instance->WDATA, + pConfig->CoeffBSize)); + } + } + else + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_READY; + } + + return HAL_OK; +} + +/** + * @brief Preload the input (FIR, IIR) and output data (IIR) of the FMAC filter. + * @note The set(s) of data will be used by FMAC as soon as @ref HAL_FMAC_FilterStart is called. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pInput Preloading of the first elements of the input buffer (X1). + * If not needed (no data available when starting), it should be set to NULL. + * @param InputSize Size of the input vector. + * As pInput is used for preloading data, it cannot be bigger than the input memory area. + * @param pOutput [IIR] Preloading of the first elements of the output vector (Y). + * If not needed, it should be set to NULL. + * @param OutputSize Size of the output vector. + * As pOutput is used for preloading data, it cannot be bigger than the output memory area. + * @param PreloadAccess access mode used for the preload (polling or DMA). + * @note The input and the output buffers can be filled by calling several times @ref HAL_FMAC_FilterPreload + * (each call filling partly the buffers). In case of overflow (too much data provided through + * all these calls), an error will be returned. + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_FilterPreload(FMAC_HandleTypeDef *hfmac, int16_t *pInput, uint8_t InputSize, + int16_t *pOutput, uint8_t OutputSize, uint8_t PreloadAccess) +{ + uint32_t tickstart; + HAL_StatusTypeDef status; + + /* Check the START bit state */ + if (FMAC_GET_START_BIT(hfmac) != 0U) + { + return HAL_ERROR; + } + + /* Check that a valid configuration was done previously */ + if (hfmac->FilterParam == 0U) + { + return HAL_ERROR; + } + + /* Check the preload input buffers isn't too big */ + if ((InputSize > FMAC_GET_X1_SIZE(hfmac)) && (pInput != NULL)) + { + return HAL_ERROR; + } + + /* Check the preload output buffer isn't too big */ + if ((OutputSize > FMAC_GET_Y_SIZE(hfmac)) && (pOutput != NULL)) + { + return HAL_ERROR; + } + + /* Check handle state is ready */ + if (hfmac->State != HAL_FMAC_STATE_READY) + { + return HAL_ERROR; + } + + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_BUSY; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Preload the input buffer if required */ + if ((pInput != NULL) && (InputSize != 0U)) + { + /* Write number of values to be loaded, the data load function and start the operation */ + WRITE_REG(hfmac->Instance->PARAM, \ + (((uint32_t)InputSize << FMAC_PARAM_P_Pos) | FMAC_FUNC_LOAD_X1 | FMAC_PARAM_START)); + + if (PreloadAccess == PRELOAD_ACCESS_POLLING) + { + /* Load the buffer into the internal memory */ + FMAC_WritePreloadDataIncrementPtr(hfmac, &pInput, InputSize); + + /* Wait for the end of the writing */ + if (FMAC_WaitOnStartUntilTimeout(hfmac, tickstart, HAL_FMAC_TIMEOUT_VALUE) != HAL_OK) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + return HAL_ERROR; + } + } + else + { + hfmac->pInput = pOutput; + hfmac->InputCurrentSize = OutputSize; + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaPreload->XferHalfCpltCallback = NULL; + hfmac->hdmaPreload->XferCpltCallback = FMAC_DMAFilterPreload; + /* Set the DMA error callback */ + hfmac->hdmaPreload->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC preload data write */ + return (HAL_DMA_Start_IT(hfmac->hdmaPreload, (uint32_t)pInput, (uint32_t)&hfmac->Instance->WDATA, InputSize)); + } + } + + /* Preload the output buffer if required */ + if ((pOutput != NULL) && (OutputSize != 0U)) + { + /* Write number of values to be loaded, the data load function and start the operation */ + WRITE_REG(hfmac->Instance->PARAM, \ + (((uint32_t)OutputSize << FMAC_PARAM_P_Pos) | FMAC_FUNC_LOAD_Y | FMAC_PARAM_START)); + + if (PreloadAccess == PRELOAD_ACCESS_POLLING) + { + /* Load the buffer into the internal memory */ + FMAC_WritePreloadDataIncrementPtr(hfmac, &pOutput, OutputSize); + + /* Wait for the end of the writing */ + if (FMAC_WaitOnStartUntilTimeout(hfmac, tickstart, HAL_FMAC_TIMEOUT_VALUE) != HAL_OK) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + return HAL_ERROR; + } + } + else + { + hfmac->pInput = NULL; + hfmac->InputCurrentSize = 0U; + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaPreload->XferHalfCpltCallback = NULL; + hfmac->hdmaPreload->XferCpltCallback = FMAC_DMAFilterPreload; + /* Set the DMA error callback */ + hfmac->hdmaPreload->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC preload data write */ + return (HAL_DMA_Start_IT(hfmac->hdmaPreload, (uint32_t)pOutput, (uint32_t)&hfmac->Instance->WDATA, OutputSize)); + } + } + + /* Update the error codes */ + if (__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_OVFL)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_OVFL; + } + if (__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_UNFL)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_UNFL; + } + if (__HAL_FMAC_GET_FLAG(hfmac, FMAC_FLAG_SAT)) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_SAT; + } + + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_READY; + + /* Return function status */ + if (hfmac->ErrorCode == HAL_FMAC_ERROR_NONE) + { + status = HAL_OK; + } + else + { + status = HAL_ERROR; + } + return status; +} + +/** + * @brief Write data into FMAC internal memory through WDATA and increment input buffer pointer. + * @note This function is only used with preload functions. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param ppData pointer to pointer to the data buffer. + * @param Size size of the data buffer. + * @retval None + */ +static void FMAC_WritePreloadDataIncrementPtr(FMAC_HandleTypeDef *hfmac, int16_t **ppData, uint8_t Size) +{ + uint8_t index; + + /* Load the buffer into the internal memory */ + for (index = Size; index > 0U; index--) + { + WRITE_REG(hfmac->Instance->WDATA, (((uint32_t)(*(*ppData))) & FMAC_WDATA_WDATA)); + (*ppData)++; + } +} + +/** + * @brief Handle FMAC Function Timeout. + * @param hfmac FMAC handle. + * @param Tickstart Tick start value. + * @param Timeout Timeout duration. + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_WaitOnStartUntilTimeout(FMAC_HandleTypeDef *hfmac, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag changes */ + while (READ_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START) != 0U) + { + if ((HAL_GetTick() - Tickstart) > Timeout) + { + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + + return HAL_ERROR; + } + } + return HAL_OK; +} + +/** + * @brief Register the new input buffer, update DMA configuration if needed and change the FMAC state. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pInput New input vector (additional input data). + * @param pInputSize Size of the input vector (if all the data can't be + * written, it will be updated with the number of data read from FMAC). + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_AppendFilterDataUpdateState(FMAC_HandleTypeDef *hfmac, int16_t *pInput, + uint16_t *pInputSize) +{ + /* Change the FMAC state */ + hfmac->WrState = HAL_FMAC_STATE_BUSY_WR; + + /* Reset the current size */ + hfmac->InputCurrentSize = 0U; + + /* Handle the pointer depending on the input access */ + if (hfmac->InputAccess == FMAC_BUFFER_ACCESS_DMA) + { + hfmac->pInput = NULL; + hfmac->pInputSize = NULL; + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaIn->XferHalfCpltCallback = FMAC_DMAHalfGetData; + hfmac->hdmaIn->XferCpltCallback = FMAC_DMAGetData; + /* Set the DMA error callback */ + hfmac->hdmaIn->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC input data write */ + return (HAL_DMA_Start_IT(hfmac->hdmaIn, (uint32_t)pInput, (uint32_t)&hfmac->Instance->WDATA, *pInputSize)); + } + else + { + /* Update the input data information (polling, IT) */ + hfmac->pInput = pInput; + hfmac->pInputSize = pInputSize; + } + + return HAL_OK; +} + +/** + * @brief Register the new output buffer, update DMA configuration if needed and change the FMAC state. + * @param hfmac pointer to a FMAC_HandleTypeDef structure that contains + * the configuration information for FMAC module. + * @param pOutput New output vector. + * @param pOutputSize Size of the output vector (if the vector can't + * be entirely filled, pOutputSize will be updated with the number + * of data read from FMAC). + * @retval HAL_StatusTypeDef HAL status + */ +static HAL_StatusTypeDef FMAC_ConfigFilterOutputBufferUpdateState(FMAC_HandleTypeDef *hfmac, int16_t *pOutput, + uint16_t *pOutputSize) +{ + /* Reset the current size */ + hfmac->OutputCurrentSize = 0U; + + /* Check whether a valid pointer was provided */ + if ((pOutput == NULL) || (pOutputSize == NULL) || (*pOutputSize == 0U)) + { + /* The user will have to provide a valid configuration later */ + hfmac->pOutput = NULL; + hfmac->pOutputSize = NULL; + hfmac->RdState = HAL_FMAC_STATE_READY; + } + /* Handle the pointer depending on the input access */ + else if (hfmac->OutputAccess == FMAC_BUFFER_ACCESS_DMA) + { + hfmac->pOutput = NULL; + hfmac->pOutputSize = NULL; + hfmac->RdState = HAL_FMAC_STATE_BUSY_RD; + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaOut->XferHalfCpltCallback = FMAC_DMAHalfOutputDataReady; + hfmac->hdmaOut->XferCpltCallback = FMAC_DMAOutputDataReady; + /* Set the DMA error callback */ + hfmac->hdmaOut->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC output data read */ + return (HAL_DMA_Start_IT(hfmac->hdmaOut, (uint32_t)&hfmac->Instance->RDATA, (uint32_t)pOutput, *pOutputSize)); + } + else if (hfmac->OutputAccess == FMAC_BUFFER_ACCESS_NONE) + { + hfmac->pOutput = NULL; + hfmac->pOutputSize = NULL; + hfmac->RdState = HAL_FMAC_STATE_READY; + } + else + { + /* Update the output data information (polling, IT) */ + hfmac->pOutput = pOutput; + hfmac->pOutputSize = pOutputSize; + hfmac->RdState = HAL_FMAC_STATE_BUSY_RD; + } + + return HAL_OK; +} + +/** + * @brief Read available output data until Y EMPTY is set. + * @param hfmac FMAC handle. + * @param MaxSizeToRead Maximum number of data to read (this serves as a timeout + * if FMAC continuously writes into the output buffer). + * @retval None + */ +static void FMAC_ReadDataIncrementPtr(FMAC_HandleTypeDef *hfmac, uint16_t MaxSizeToRead) +{ + uint16_t maxsize; + uint16_t threshold; + uint32_t tmpvalue; + + /* Check if there is data to read */ + if (READ_BIT(hfmac->Instance->SR, FMAC_SR_YEMPTY) != 0U) + { + return; + } + + /* Get the maximum index (no wait allowed, no overstepping of the output buffer) */ + if ((hfmac->OutputCurrentSize + MaxSizeToRead) > *(hfmac->pOutputSize)) + { + maxsize = *(hfmac->pOutputSize); + } + else + { + maxsize = hfmac->OutputCurrentSize + MaxSizeToRead; + } + + /* Read until there is no more room or no more data */ + do + { + /* If there is no more room, return */ + if (!(hfmac->OutputCurrentSize < maxsize)) + { + return; + } + + /* Read the available data */ + tmpvalue = ((READ_REG(hfmac->Instance->RDATA))& FMAC_RDATA_RDATA); + *(hfmac->pOutput) = (int16_t)tmpvalue; + hfmac->pOutput++; + hfmac->OutputCurrentSize++; + } while (READ_BIT(hfmac->Instance->SR, FMAC_SR_YEMPTY) == 0U); + + /* Y buffer empty flag has just be raised, read the threshold */ + threshold = (uint16_t)FMAC_GET_THRESHOLD_FROM_WM(FMAC_GET_Y_EMPTY_WM(hfmac)) - 1U; + + /* Update the maximum size if needed (limited data available) */ + if ((hfmac->OutputCurrentSize + threshold) < maxsize) + { + maxsize = hfmac->OutputCurrentSize + threshold; + } + + /* Read the available data */ + while (hfmac->OutputCurrentSize < maxsize) + { + tmpvalue = ((READ_REG(hfmac->Instance->RDATA))& FMAC_RDATA_RDATA); + *(hfmac->pOutput) = (int16_t)tmpvalue; + hfmac->pOutput++; + hfmac->OutputCurrentSize++; + } +} + +/** + * @brief Write available input data until X1 FULL is set. + * @param hfmac FMAC handle. + * @param MaxSizeToWrite Maximum number of data to write (this serves as a timeout + * if FMAC continuously empties the input buffer). + * @retval None + */ +static void FMAC_WriteDataIncrementPtr(FMAC_HandleTypeDef *hfmac, uint16_t MaxSizeToWrite) +{ + uint16_t maxsize; + uint16_t threshold; + + /* Check if there is room in FMAC */ + if (READ_BIT(hfmac->Instance->SR, FMAC_SR_X1FULL) != 0U) + { + return; + } + + /* Get the maximum index (no wait allowed, no overstepping of the output buffer) */ + if ((hfmac->InputCurrentSize + MaxSizeToWrite) > *(hfmac->pInputSize)) + { + maxsize = *(hfmac->pInputSize); + } + else + { + maxsize = hfmac->InputCurrentSize + MaxSizeToWrite; + } + + /* Write until there is no more room or no more data */ + do + { + /* If there is no more room, return */ + if (!(hfmac->InputCurrentSize < maxsize)) + { + return; + } + + /* Write the available data */ + WRITE_REG(hfmac->Instance->WDATA, (((uint32_t)(*(hfmac->pInput))) & FMAC_WDATA_WDATA)); + hfmac->pInput++; + hfmac->InputCurrentSize++; + } while (READ_BIT(hfmac->Instance->SR, FMAC_SR_X1FULL) == 0U); + + /* X1 buffer full flag has just be raised, read the threshold */ + threshold = (uint16_t)FMAC_GET_THRESHOLD_FROM_WM(FMAC_GET_X1_FULL_WM(hfmac)) - 1U; + + /* Update the maximum size if needed (limited data available) */ + if ((hfmac->InputCurrentSize + threshold) < maxsize) + { + maxsize = hfmac->InputCurrentSize + threshold; + } + + /* Write the available data */ + while (hfmac->InputCurrentSize < maxsize) + { + WRITE_REG(hfmac->Instance->WDATA, (((uint32_t)(*(hfmac->pInput))) & FMAC_WDATA_WDATA)); + hfmac->pInput++; + hfmac->InputCurrentSize++; + } +} + +/** + * @brief DMA FMAC Input Data process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAHalfGetData(DMA_HandleTypeDef *hdma) +{ + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Call half get data callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->HalfGetDataCallback(hfmac); +#else + HAL_FMAC_HalfGetDataCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA FMAC Input Data process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAGetData(DMA_HandleTypeDef *hdma) +{ + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Reset the pointers to indicate new data will be needed */ + FMAC_ResetInputStateAndDataPointers(hfmac); + + /* Call get data callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->GetDataCallback(hfmac); +#else + HAL_FMAC_GetDataCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA FMAC Output Data process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAHalfOutputDataReady(DMA_HandleTypeDef *hdma) +{ + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Call half output data ready callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->HalfOutputDataReadyCallback(hfmac); +#else + HAL_FMAC_HalfOutputDataReadyCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA FMAC Output Data process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAOutputDataReady(DMA_HandleTypeDef *hdma) +{ + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Reset the pointers to indicate new data will be needed */ + FMAC_ResetOutputStateAndDataPointers(hfmac); + + /* Call output data ready callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->OutputDataReadyCallback(hfmac); +#else + HAL_FMAC_OutputDataReadyCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA FMAC Filter Configuration process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAFilterConfig(DMA_HandleTypeDef *hdma) +{ + uint8_t index; + + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* If needed, write CoeffA and exit */ + if (hfmac->pInput != NULL) + { + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaPreload->XferHalfCpltCallback = NULL; + hfmac->hdmaPreload->XferCpltCallback = FMAC_DMAFilterConfig; + /* Set the DMA error callback */ + hfmac->hdmaPreload->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC preload data write */ + if (HAL_DMA_Start_IT(hfmac->hdmaPreload, (uint32_t)hfmac->pInput, (uint32_t)&hfmac->Instance->WDATA, + hfmac->InputCurrentSize) == HAL_OK) + { + hfmac->pInput = NULL; + hfmac->InputCurrentSize = 0U; + return; + } + + /* If not exited, there was an error: set FMAC handle state to error */ + hfmac->State = HAL_FMAC_STATE_ERROR; + } + else + { + /* Wait for the end of the writing */ + for (index = 0U; index < MAX_PRELOAD_INDEX; index++) + { + if (READ_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START) == 0U) + { + break; + } + } + + /* If 'START' is still set, there was a timeout: set FMAC handle state to timeout */ + if (READ_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START) != 0U) + { + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + } + else + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_READY; + + /* Call output data ready callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->FilterConfigCallback(hfmac); +#else + HAL_FMAC_FilterConfigCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + return; + } + } + + /* If not exited, there was an error: set FMAC handle error code to DMA error */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_DMA; + + /* Call user callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->ErrorCallback(hfmac); +#else + HAL_FMAC_ErrorCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + +} + +/** + * @brief DMA FMAC Filter Configuration process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAFilterPreload(DMA_HandleTypeDef *hdma) +{ + uint8_t index; + + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Wait for the end of the X1 writing */ + for (index = 0U; index < MAX_PRELOAD_INDEX; index++) + { + if (READ_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START) == 0U) + { + break; + } + } + + /* If 'START' is still set, there was an error: set FMAC handle state to error */ + if (READ_BIT(hfmac->Instance->PARAM, FMAC_PARAM_START) != 0U) + { + hfmac->State = HAL_FMAC_STATE_TIMEOUT; + hfmac->ErrorCode |= HAL_FMAC_ERROR_TIMEOUT; + } + /* If needed, preload Y buffer */ + else if ((hfmac->pInput != NULL) && (hfmac->InputCurrentSize != 0U)) + { + /* Write number of values to be loaded, the data load function and start the operation */ + WRITE_REG(hfmac->Instance->PARAM, \ + (((uint32_t)(hfmac->InputCurrentSize) << FMAC_PARAM_P_Pos) | FMAC_FUNC_LOAD_Y | FMAC_PARAM_START)); + + /* Set the FMAC DMA transfer complete callback */ + hfmac->hdmaPreload->XferHalfCpltCallback = NULL; + hfmac->hdmaPreload->XferCpltCallback = FMAC_DMAFilterPreload; + /* Set the DMA error callback */ + hfmac->hdmaPreload->XferErrorCallback = FMAC_DMAError; + + /* Enable the DMA stream managing FMAC preload data write */ + if (HAL_DMA_Start_IT(hfmac->hdmaPreload, (uint32_t)hfmac->pInput, (uint32_t)&hfmac->Instance->WDATA, + hfmac->InputCurrentSize) == HAL_OK) + { + hfmac->pInput = NULL; + hfmac->InputCurrentSize = 0U; + return; + } + + /* If not exited, there was an error */ + hfmac->ErrorCode = HAL_FMAC_ERROR_DMA; + hfmac->State = HAL_FMAC_STATE_ERROR; + } + else + { + /* nothing to do */ + } + + if (hfmac->ErrorCode == HAL_FMAC_ERROR_NONE) + { + /* Change the FMAC state */ + hfmac->State = HAL_FMAC_STATE_READY; + + /* Call output data ready callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->FilterPreloadCallback(hfmac); +#else + HAL_FMAC_FilterPreloadCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } + else + { + /* Call user callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->ErrorCallback(hfmac); +#else + HAL_FMAC_ErrorCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ + } +} + + +/** + * @brief DMA FMAC communication error callback. + * @param hdma DMA handle. + * @retval None + */ +static void FMAC_DMAError(DMA_HandleTypeDef *hdma) +{ + FMAC_HandleTypeDef *hfmac = (FMAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Set FMAC handle state to error */ + hfmac->State = HAL_FMAC_STATE_ERROR; + + /* Set FMAC handle error code to DMA error */ + hfmac->ErrorCode |= HAL_FMAC_ERROR_DMA; + + /* Call user callback */ +#if (USE_HAL_FMAC_REGISTER_CALLBACKS == 1) + hfmac->ErrorCallback(hfmac); +#else + HAL_FMAC_ErrorCallback(hfmac); +#endif /* USE_HAL_FMAC_REGISTER_CALLBACKS */ +} +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_FMAC_MODULE_ENABLED */ +#endif /* FMAC */ -- cgit v1.2.3