diff options
Diffstat (limited to 'bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c')
-rw-r--r-- | bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c | 3800 |
1 files changed, 1899 insertions, 1901 deletions
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c index 8dd757acf6..e1f36fdd24 100644 --- a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c +++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c @@ -1,1902 +1,1900 @@ -/**
- ******************************************************************************
- * @file stm32h7xx_hal_mdma.c
- * @author MCD Application Team
- * @brief This file provides firmware functions to manage the following
- * functionalities of the Master Direct Memory Access (MDMA) peripheral:
- * + Initialization/de-initialization functions
- * + I/O operation functions
- * + Peripheral State and errors functions
- @verbatim
- ==============================================================================
- ##### How to use this driver #####
- ==============================================================================
- [..]
- (#) Enable and configure the peripheral to be connected to the MDMA Channel
- (except for internal SRAM/FLASH memories: no initialization is
- necessary) please refer to Reference manual for connection between peripherals
- and MDMA requests.
-
- (#)
- For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters:
- transfer request , channel priority, data endianness, Source increment, destination increment ,
- source data size, destination data size, data alignment, source Burst, destination Burst ,
- buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer
- or full transfer) source and destination block address offset, mask address and data.
-
- If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node.
- Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero.
- Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position.
- User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the
- last node of the list to the first one in order to make the list circular.
- In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init
-
- -@- The initial transfer itself (node 0 corresponding to the Init).
- User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove
- the connection between last node and first one.
-
- Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list.
- When a linked list is circular (last node connected to first one), if removing node1 (node where the linked list loops),
- the linked list remains circular and node 2 becomes the first one.
- Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user).
-
- [..]
- (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be
- transfer upon a request :
- (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data
- with BufferTransferLength defined within the HAL_MDMA_Init.
- (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block
- with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
- or within the current linked list node parameters.
- (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks
- with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
- or within the current linked list node parameters.
- (++) MDMA_FULL_TRANSFER : each request triggers a full transfer
- all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode).
-
- *** Polling mode IO operation ***
- =================================
- [..]
- (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source
- address and destination address and the Length of data to be transferred.
- (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level
- In this case a fixed Timeout can be configured by User depending from his application.
- (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns
- when the abort ends or timeout (should not be called from an interrupt service routine).
-
- *** Interrupt mode IO operation ***
- ===================================
- [..]
- (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority()
- (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ()
- (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of
- Source address and destination address and the Length of data to be transferred. In this
- case the MDMA interrupt is configured.
- (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine
- (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can
- add his own function by customization of function pointer XferCpltCallback and
- XferErrorCallback (i.e a member of MDMA handle structure).
-
- (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately
- then the callback XferAbortCallback (if specified by the user) is asserted once the MDMA channel has effectively aborted.
- (could be called from an interrupt service routine).
-
- (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks
- from the following list :
- (++) XferCpltCallback : transfer complete callback.
- (++) XferBufferCpltCallback : buffer transfer complete callback.
- (++) XferBlockCpltCallback : block transfer complete callback.
- (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback.
- (++) XferErrorCallback : transfer error callback.
- (++) XferAbortCallback : transfer abort complete callback.
-
- [..]
- (+) If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to
- trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions:
- (++) This function returns an error if used while the Transfer has ended or not started.
- (++) If used while the current request has not been served yet (current request transfer on going)
- this function returns an error and the new request is ignored.
-
- Generally this function should be used in conjunctions with the MDMA callbacks:
- (++) example 1:
- (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER
- (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID)
- (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data.
- (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer
- request using HAL_MDMA_GenerateSWRequest.
-
- (++) example 2:
- (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER
- (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID)
- (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data.
- (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask
- for a new block transfer request using HAL_MDMA_GenerateSWRequest.
-
- [..] Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
-
- *** MDMA HAL driver macros list ***
- =============================================
- [..]
- Below the list of most used macros in MDMA HAL driver.
-
- (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel.
- (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel.
- (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags.
- (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags.
- (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts.
- (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts.
- (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not.
-
- [..]
- (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
-
- [..]
-
- @endverbatim
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
-
-/* Includes ------------------------------------------------------------------*/
-#include "stm32h7xx_hal.h"
-
-/** @addtogroup STM32H7xx_HAL_Driver
- * @{
- */
-
-/** @defgroup MDMA MDMA
+/** + ****************************************************************************** + * @file stm32h7xx_hal_mdma.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the Master Direct Memory Access (MDMA) peripheral: + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral State and errors 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 ##### + ============================================================================== + [..] + (#) Enable and configure the peripheral to be connected to the MDMA Channel + (except for internal SRAM/FLASH memories: no initialization is + necessary) please refer to Reference manual for connection between peripherals + and MDMA requests. + + (#) + For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters: + transfer request , channel priority, data endianness, Source increment, destination increment , + source data size, destination data size, data alignment, source Burst, destination Burst , + buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer + or full transfer) source and destination block address offset, mask address and data. + + If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node. + Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero. + Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position. + User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the + last node of the list to the first one in order to make the list circular. + In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init + + -@- The initial transfer itself (node 0 corresponding to the Init). + User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove + the connection between last node and first one. + + Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list. + When a linked list is circular (last node connected to first one), if removing node1 (node where the linked list loops), + the linked list remains circular and node 2 becomes the first one. + Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user). + + [..] + (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be + transfer upon a request : + (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data + with BufferTransferLength defined within the HAL_MDMA_Init. + (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block + with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT + or within the current linked list node parameters. + (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks + with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT + or within the current linked list node parameters. + (++) MDMA_FULL_TRANSFER : each request triggers a full transfer + all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode). + + *** Polling mode IO operation *** + ================================= + [..] + (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source + address and destination address and the Length of data to be transferred. + (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level + In this case a fixed Timeout can be configured by User depending from his application. + (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns + when the abort ends or timeout (should not be called from an interrupt service routine). + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority() + (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ() + (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of + Source address and destination address and the Length of data to be transferred. In this + case the MDMA interrupt is configured. + (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine + (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can + add his own function by customization of function pointer XferCpltCallback and + XferErrorCallback (i.e a member of MDMA handle structure). + + (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately + then the callback XferAbortCallback (if specified by the user) is asserted once the MDMA channel has effectively aborted. + (could be called from an interrupt service routine). + + (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks + from the following list : + (++) XferCpltCallback : transfer complete callback. + (++) XferBufferCpltCallback : buffer transfer complete callback. + (++) XferBlockCpltCallback : block transfer complete callback. + (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback. + (++) XferErrorCallback : transfer error callback. + (++) XferAbortCallback : transfer abort complete callback. + + [..] + (+) If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to + trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions: + (++) This function returns an error if used while the Transfer has ended or not started. + (++) If used while the current request has not been served yet (current request transfer on going) + this function returns an error and the new request is ignored. + + Generally this function should be used in conjunctions with the MDMA callbacks: + (++) example 1: + (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER + (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID) + (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data. + (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer + request using HAL_MDMA_GenerateSWRequest. + + (++) example 2: + (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER + (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID) + (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data. + (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask + for a new block transfer request using HAL_MDMA_GenerateSWRequest. + + [..] Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection. + + *** MDMA HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in MDMA HAL driver. + + (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel. + (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel. + (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags. + (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags. + (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts. + (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts. + (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not. + + [..] + (@) You can refer to the header file of the MDMA HAL driver for more useful macros. + + [..] + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @defgroup MDMA MDMA * @ingroup RTEMSBSPsARMSTM32H7 - * @brief MDMA HAL module driver
- * @{
- */
-
-#ifdef HAL_MDMA_MODULE_ENABLED
-
-/* Private typedef -----------------------------------------------------------*/
-/* Private constants ---------------------------------------------------------*/
-/** @addtogroup MDMA_Private_Constants
- * @{
- */
-#define HAL_TIMEOUT_MDMA_ABORT 5U /* 5 ms */
-#define HAL_MDMA_CHANNEL_SIZE 0x40U /* an MDMA instance channel size is 64 byte */
-/**
- * @}
- */
-/* Private macro -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-/* Private function prototypes -----------------------------------------------*/
-/** @addtogroup MDMA_Private_Functions_Prototypes
- * @{
- */
-static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount);
-static void MDMA_Init(MDMA_HandleTypeDef *hmdma);
-
-/**
- * @}
- */
-
-/** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
- * @{
- */
-
-/** @addtogroup MDMA_Exported_Functions_Group1
- *
-@verbatim
- ===============================================================================
- ##### Initialization and de-initialization functions #####
- ===============================================================================
- [..]
- This section provides functions allowing to :
- Initialize and de-initialize the MDMA channel.
- Register and Unregister MDMA callbacks
- [..]
- The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
- reference manual.
- The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel.
- HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback functions allows
- respectevely to register/unregister an MDMA callback function.
-
-@endverbatim
- * @{
- */
-
-/**
- * @brief Initializes the MDMA according to the specified
- * parameters in the MDMA_InitTypeDef and create the associated handle.
- * @param hmdma: Pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
-{
- uint32_t tickstart = HAL_GetTick();
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Check the parameters */
- assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
- assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
- assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
- assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
- assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
- assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
- assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
- assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
- assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
- assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
- assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
- assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));
- assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
-
-
- /* Allocate lock resource */
- __HAL_UNLOCK(hmdma);
-
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* Disable the MDMA channel */
- __HAL_MDMA_DISABLE(hmdma);
-
- /* Check if the MDMA channel is effectively disabled */
- while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
- {
- /* Check for the Timeout */
- if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
- {
- /* Update error code */
- hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
-
- /* Change the MDMA state */
- hmdma->State = HAL_MDMA_STATE_ERROR;
-
- return HAL_ERROR;
- }
- }
-
- /* Initialize the MDMA channel registers */
- MDMA_Init(hmdma);
-
- /* Reset the MDMA first/last linkedlist node addresses and node counter */
- hmdma->FirstLinkedListNodeAddress = 0;
- hmdma->LastLinkedListNodeAddress = 0;
- hmdma->LinkedListNodeCounter = 0;
-
- /* Initialize the error code */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
-
- /* Initialize the MDMA state */
- hmdma->State = HAL_MDMA_STATE_READY;
-
- return HAL_OK;
-}
-
-/**
- * @brief DeInitializes the MDMA peripheral
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
-{
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Disable the selected MDMA Channelx */
- __HAL_MDMA_DISABLE(hmdma);
-
- /* Reset MDMA Channel control register */
- hmdma->Instance->CCR = 0;
- hmdma->Instance->CTCR = 0;
- hmdma->Instance->CBNDTR = 0;
- hmdma->Instance->CSAR = 0;
- hmdma->Instance->CDAR = 0;
- hmdma->Instance->CBRUR = 0;
- hmdma->Instance->CLAR = 0;
- hmdma->Instance->CTBR = 0;
- hmdma->Instance->CMAR = 0;
- hmdma->Instance->CMDR = 0;
-
- /* Clear all flags */
- __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
-
- /* Reset the MDMA first/last linkedlist node addresses and node counter */
- hmdma->FirstLinkedListNodeAddress = 0;
- hmdma->LastLinkedListNodeAddress = 0;
- hmdma->LinkedListNodeCounter = 0;
-
- /* Initialize the error code */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
-
- /* Initialize the MDMA state */
- hmdma->State = HAL_MDMA_STATE_RESET;
-
- /* Release Lock */
- __HAL_UNLOCK(hmdma);
-
- return HAL_OK;
-}
-
-/**
- * @brief Config the Post request Mask address and Mask data
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
- * @param MaskData: specifies the value to be written to MaskAddress after a request is served.
- * MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
-{
- HAL_StatusTypeDef status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* if HW request set Post Request MaskAddress and MaskData, */
- if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
- {
- /* Set the HW request clear Mask and Data */
- hmdma->Instance->CMAR = MaskAddress;
- hmdma->Instance->CMDR = MaskData;
-
- /*
- -If the request is done by SW : BWM could be set to 1 or 0.
- -If the request is done by a peripheral :
- If mask address not set (0) => BWM must be set to 0
- If mask address set (different than 0) => BWM could be set to 1 or 0
- */
- if(MaskAddress == 0U)
- {
- hmdma->Instance->CTCR &= ~MDMA_CTCR_BWM;
- }
- else
- {
- hmdma->Instance->CTCR |= MDMA_CTCR_BWM;
- }
- }
- else
- {
- /* Return error status */
- status = HAL_ERROR;
- }
- }
- else
- {
- /* Return error status */
- status = HAL_ERROR;
- }
- /* Release Lock */
- __HAL_UNLOCK(hmdma);
-
- return status;
-}
-
-/**
- * @brief Register callbacks
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param CallbackID: User Callback identifier
- * @param pCallback: pointer to callbacsk function.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
-{
- HAL_StatusTypeDef status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- switch (CallbackID)
- {
- case HAL_MDMA_XFER_CPLT_CB_ID:
- hmdma->XferCpltCallback = pCallback;
- break;
-
- case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
- hmdma->XferBufferCpltCallback = pCallback;
- break;
-
- case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
- hmdma->XferBlockCpltCallback = pCallback;
- break;
-
- case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
- hmdma->XferRepeatBlockCpltCallback = pCallback;
- break;
-
- case HAL_MDMA_XFER_ERROR_CB_ID:
- hmdma->XferErrorCallback = pCallback;
- break;
-
- case HAL_MDMA_XFER_ABORT_CB_ID:
- hmdma->XferAbortCallback = pCallback;
- break;
-
- default:
- break;
- }
- }
- else
- {
- /* Return error status */
- status = HAL_ERROR;
- }
-
- /* Release Lock */
- __HAL_UNLOCK(hmdma);
-
- return status;
-}
-
-/**
- * @brief UnRegister callbacks
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param CallbackID: User Callback identifier
- * a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
-{
- HAL_StatusTypeDef status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- switch (CallbackID)
- {
- case HAL_MDMA_XFER_CPLT_CB_ID:
- hmdma->XferCpltCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
- hmdma->XferBufferCpltCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
- hmdma->XferBlockCpltCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
- hmdma->XferRepeatBlockCpltCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_ERROR_CB_ID:
- hmdma->XferErrorCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_ABORT_CB_ID:
- hmdma->XferAbortCallback = NULL;
- break;
-
- case HAL_MDMA_XFER_ALL_CB_ID:
- hmdma->XferCpltCallback = NULL;
- hmdma->XferBufferCpltCallback = NULL;
- hmdma->XferBlockCpltCallback = NULL;
- hmdma->XferRepeatBlockCpltCallback = NULL;
- hmdma->XferErrorCallback = NULL;
- hmdma->XferAbortCallback = NULL;
- break;
-
- default:
- status = HAL_ERROR;
- break;
- }
- }
- else
- {
- status = HAL_ERROR;
- }
-
- /* Release Lock */
- __HAL_UNLOCK(hmdma);
-
- return status;
-}
-
-/**
- * @}
- */
-
-/** @addtogroup MDMA_Exported_Functions_Group2
- *
-@verbatim
- ===============================================================================
- ##### Linked list operation functions #####
- ===============================================================================
- [..] This section provides functions allowing to:
- (+) Create a linked list node
- (+) Add a node to the MDMA linked list
- (+) Remove a node from the MDMA linked list
- (+) Enable/Disable linked list circular mode
-@endverbatim
- * @{
- */
-
-/**
- * @brief Initializes an MDMA Link Node according to the specified
- * parameters in the pMDMA_LinkedListNodeConfig .
- * @param pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
- * registers configurations.
- * @param pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
- * the configuration information for the specified MDMA Linked List Node.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
-{
- uint32_t addressMask;
- uint32_t blockoffset;
-
- /* Check the MDMA peripheral state */
- if((pNode == NULL) || (pNodeConfig == NULL))
- {
- return HAL_ERROR;
- }
-
- /* Check the parameters */
- assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
- assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
- assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
- assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
- assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
- assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
- assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
- assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
- assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
- assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
- assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
- assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
- assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
-
- assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
- assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
-
-
- /* Configure next Link node Address Register to zero */
- pNode->CLAR = 0;
-
- /* Configure the Link Node registers*/
- pNode->CTBR = 0;
- pNode->CMAR = 0;
- pNode->CMDR = 0;
- pNode->Reserved = 0;
-
- /* Write new CTCR Register value */
- pNode->CTCR = pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
- pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize | \
- pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst | \
- pNodeConfig->Init.DestBurst | \
- ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
- pNodeConfig->Init.TransferTriggerMode;
-
- /* If SW request set the CTCR register to SW Request Mode*/
- if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
- {
- pNode->CTCR |= MDMA_CTCR_SWRM;
- }
-
- /*
- -If the request is done by SW : BWM could be set to 1 or 0.
- -If the request is done by a peripheral :
- If mask address not set (0) => BWM must be set to 0
- If mask address set (different than 0) => BWM could be set to 1 or 0
- */
- if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
- {
- pNode->CTCR |= MDMA_CTCR_BWM;
- }
-
- /* Set the new CBNDTR Register value */
- pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
-
- /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
- if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
- {
- pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
- /*write new CBRUR Register value : source repeat block offset */
- blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
- pNode->CBRUR = blockoffset & 0x0000FFFFU;
- }
- else
- {
- /*write new CBRUR Register value : source repeat block offset */
- pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
- }
-
- /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
- if(pNodeConfig->Init.DestBlockAddressOffset < 0)
- {
- pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
- /*write new CBRUR Register value : destination repeat block offset */
- blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
- pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
- }
- else
- {
- /*write new CBRUR Register value : destination repeat block offset */
- pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
- }
-
- /* Configure MDMA Link Node data length */
- pNode->CBNDTR |= pNodeConfig->BlockDataLength;
-
- /* Configure MDMA Link Node destination address */
- pNode->CDAR = pNodeConfig->DstAddress;
-
- /* Configure MDMA Link Node Source address */
- pNode->CSAR = pNodeConfig->SrcAddress;
-
- /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
- if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
- {
- /* Set the HW request in CTBR register */
- pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
- /* Set the HW request clear Mask and Data */
- pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
- pNode->CMDR = pNodeConfig->PostRequestMaskData;
- }
-
- addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
- if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
- {
- /*The AHBSbus is used as source (read operation) on channel x */
- pNode->CTBR |= MDMA_CTBR_SBUS;
- }
-
- addressMask = pNodeConfig->DstAddress & 0xFF000000U;
- if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
- {
- /*The AHB bus is used as destination (write operation) on channel x */
- pNode->CTBR |= MDMA_CTBR_DBUS;
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Connect a node to the linked list.
- * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
- * to be add to the list.
- * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
- * at the end of the list
- *
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
-{
- MDMA_LinkNodeTypeDef *pNode;
- uint32_t counter = 0, nodeInserted = 0;
- HAL_StatusTypeDef hal_status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if((hmdma == NULL) || (pNewNode == NULL))
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* Check if this is the first node (after the Inititlization node) */
- if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
- {
- if(pPrevNode == NULL)
- {
- /* if this is the first node after the initialization
- connect this node to the node 0 by updating
- the MDMA channel CLAR register to this node address */
- hmdma->Instance->CLAR = (uint32_t)pNewNode;
- /* Set the MDMA handle First linked List node*/
- hmdma->FirstLinkedListNodeAddress = pNewNode;
-
- /*reset New node link */
- pNewNode->CLAR = 0;
-
- /* Update the Handle last node address */
- hmdma->LastLinkedListNodeAddress = pNewNode;
-
- hmdma->LinkedListNodeCounter = 1;
- }
- else
- {
- hal_status = HAL_ERROR;
- }
- }
- else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
- {
- /* Check if the node to insert already exists*/
- pNode = hmdma->FirstLinkedListNodeAddress;
- while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
- {
- if(pNode->CLAR == (uint32_t)pNewNode)
- {
- hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
- }
- pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
- counter++;
- }
-
- if(hal_status == HAL_OK)
- {
- /* Check if the previous node is the last one in the current list or zero */
- if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
- {
- /* insert the new node at the end of the list */
- pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
- hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
- /* Update the Handle last node address */
- hmdma->LastLinkedListNodeAddress = pNewNode;
- /* Increment the linked list node counter */
- hmdma->LinkedListNodeCounter++;
- }
- else
- {
- /*insert the new node after the pPreviousNode node */
- pNode = hmdma->FirstLinkedListNodeAddress;
- counter = 0;
- while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
- {
- counter++;
- if(pNode == pPrevNode)
- {
- /*Insert the new node after the previous one */
- pNewNode->CLAR = pNode->CLAR;
- pNode->CLAR = (uint32_t)pNewNode;
- /* Increment the linked list node counter */
- hmdma->LinkedListNodeCounter++;
- nodeInserted = 1;
- }
- else
- {
- pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
- }
- }
-
- if(nodeInserted == 0U)
- {
- hal_status = HAL_ERROR;
- }
- }
- }
- }
- else
- {
- hal_status = HAL_ERROR;
- }
-
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- hmdma->State = HAL_MDMA_STATE_READY;
-
- return hal_status;
- }
- else
- {
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Return error status */
- return HAL_BUSY;
- }
-}
-
-/**
- * @brief Disconnect/Remove a node from the transfer linked list.
- * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
- * to be removed from the list.
- *
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
-{
- MDMA_LinkNodeTypeDef *ptmpNode;
- uint32_t counter = 0, nodeDeleted = 0;
- HAL_StatusTypeDef hal_status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if((hmdma == NULL) || (pNode == NULL))
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* If first and last node are null (no nodes in the list) : return error*/
- if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
- {
- hal_status = HAL_ERROR;
- }
- else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
- {
- /* Delete 1st node */
- if(hmdma->LastLinkedListNodeAddress == pNode)
- {
- /*if the last node is at the same time the first one (1 single node after the init node 0)
- then update the last node too */
-
- hmdma->FirstLinkedListNodeAddress = 0;
- hmdma->LastLinkedListNodeAddress = 0;
- hmdma->LinkedListNodeCounter = 0;
-
- hmdma->Instance->CLAR = 0;
- }
- else
- {
- if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
- {
- /* if last node is looping to first (circular list) one update the last node connection */
- hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
- }
-
- /* if deleting the first node after the initialization
- connect the next node to the node 0 by updating
- the MDMA channel CLAR register to this node address */
- hmdma->Instance->CLAR = pNode->CLAR;
- hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
- /* Update the Handle node counter */
- hmdma->LinkedListNodeCounter--;
- }
- }
- else /* Deleting any other node */
- {
- /*Deleted node is not the first one : find it */
- ptmpNode = hmdma->FirstLinkedListNodeAddress;
- while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
- {
- counter++;
- if(ptmpNode->CLAR == ((uint32_t)pNode))
- {
- /* if deleting the last node */
- if(pNode == hmdma->LastLinkedListNodeAddress)
- {
- /*Update the linked list last node address in the handle*/
- hmdma->LastLinkedListNodeAddress = ptmpNode;
- }
- /* update the next node link after deleting pMDMA_LinkedListNode */
- ptmpNode->CLAR = pNode->CLAR;
- nodeDeleted = 1;
- /* Update the Handle node counter */
- hmdma->LinkedListNodeCounter--;
- }
- else
- {
- ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
- }
- }
-
- if(nodeDeleted == 0U)
- {
- /* last node reashed without finding the node to delete : return error */
- hal_status = HAL_ERROR;
- }
- }
-
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- hmdma->State = HAL_MDMA_STATE_READY;
-
- return hal_status;
- }
- else
- {
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Return error status */
- return HAL_BUSY;
- }
-}
-
-/**
- * @brief Make the linked list circular by connecting the last node to the first.
- * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
-{
- HAL_StatusTypeDef hal_status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* If first and last node are null (no nodes in the list) : return error*/
- if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
- {
- hal_status = HAL_ERROR;
- }
- else
- {
- /* to enable circular mode Last Node should be connected to first node */
- hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
- }
-
- }
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- hmdma->State = HAL_MDMA_STATE_READY;
-
- return hal_status;
-}
-
-/**
- * @brief Disable the linked list circular mode by setting the last node connection to null
- * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
-{
- HAL_StatusTypeDef hal_status = HAL_OK;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* If first and last node are null (no nodes in the list) : return error*/
- if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
- {
- hal_status = HAL_ERROR;
- }
- else
- {
- /* to disable circular mode Last Node should be connected to NULL */
- hmdma->LastLinkedListNodeAddress->CLAR = 0;
- }
-
- }
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- hmdma->State = HAL_MDMA_STATE_READY;
-
- return hal_status;
-}
-
-/**
- * @}
- */
-
-/** @addtogroup MDMA_Exported_Functions_Group3
- *
-@verbatim
- ===============================================================================
- ##### IO operation functions #####
- ===============================================================================
- [..] This section provides functions allowing to:
- (+) Configure the source, destination address and data length and Start MDMA transfer
- (+) Configure the source, destination address and data length and
- Start MDMA transfer with interrupt
- (+) Abort MDMA transfer
- (+) Poll for transfer complete
- (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
- (+) Handle MDMA interrupt request
-
-@endverbatim
- * @{
- */
-
-/**
- * @brief Starts the MDMA Transfer.
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param SrcAddress : The source memory Buffer address
- * @param DstAddress : The destination memory Buffer address
- * @param BlockDataLength : The length of a block transfer in bytes
- * @param BlockCount : The number of a blocks to be transfer
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
-{
- /* Check the parameters */
- assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
- assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* Initialize the error code */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
-
- /* Disable the peripheral */
- __HAL_MDMA_DISABLE(hmdma);
-
- /* Configure the source, destination address and the data length */
- MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
-
- /* Enable the Peripheral */
- __HAL_MDMA_ENABLE(hmdma);
-
- if(hmdma->Init.Request == MDMA_REQUEST_SW)
- {
- /* activate If SW request mode*/
- hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
- }
- }
- else
- {
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Return error status */
- return HAL_BUSY;
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Starts the MDMA Transfer with interrupts enabled.
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param SrcAddress : The source memory Buffer address
- * @param DstAddress : The destination memory Buffer address
- * @param BlockDataLength : The length of a block transfer in bytes
- * @param BlockCount : The number of a blocks to be transfer
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
-{
- /* Check the parameters */
- assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
- assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Process locked */
- __HAL_LOCK(hmdma);
-
- if(HAL_MDMA_STATE_READY == hmdma->State)
- {
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_BUSY;
-
- /* Initialize the error code */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
-
- /* Disable the peripheral */
- __HAL_MDMA_DISABLE(hmdma);
-
- /* Configure the source, destination address and the data length */
- MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
-
- /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
- __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
-
- if(hmdma->XferBlockCpltCallback != NULL)
- {
- /* if Block transfer complete Callback is set enable the corresponding IT*/
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
- }
-
- if(hmdma->XferRepeatBlockCpltCallback != NULL)
- {
- /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
- }
-
- if(hmdma->XferBufferCpltCallback != NULL)
- {
- /* if buffer transfer complete Callback is set enable the corresponding IT*/
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
- }
-
- /* Enable the Peripheral */
- __HAL_MDMA_ENABLE(hmdma);
-
- if(hmdma->Init.Request == MDMA_REQUEST_SW)
- {
- /* activate If SW request mode*/
- hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
- }
- }
- else
- {
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Return error status */
- return HAL_BUSY;
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Aborts the MDMA Transfer.
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- *
- * @note After disabling a MDMA Channel, a check for wait until the MDMA Channel is
- * effectively disabled is added. If a Channel is disabled
- * while a data transfer is ongoing, the current data will be transferred
- * and the Channel will be effectively disabled only after the transfer of
- * this single data is finished.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
-{
- uint32_t tickstart = HAL_GetTick();
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- if(HAL_MDMA_STATE_BUSY != hmdma->State)
- {
- hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
-
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- return HAL_ERROR;
- }
- else
- {
- /* Disable all the transfer interrupts */
- __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
-
- /* Disable the channel */
- __HAL_MDMA_DISABLE(hmdma);
-
- /* Check if the MDMA Channel is effectively disabled */
- while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
- {
- /* Check for the Timeout */
- if( (HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
- {
- /* Update error code */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
-
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Change the MDMA state */
- hmdma->State = HAL_MDMA_STATE_ERROR;
-
- return HAL_ERROR;
- }
- }
-
- /* Clear all interrupt flags */
- __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
-
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Change the MDMA state*/
- hmdma->State = HAL_MDMA_STATE_READY;
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Aborts the MDMA Transfer in Interrupt mode.
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
-{
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- if(HAL_MDMA_STATE_BUSY != hmdma->State)
- {
- /* No transfer ongoing */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
-
- return HAL_ERROR;
- }
- else
- {
- /* Set Abort State */
- hmdma->State = HAL_MDMA_STATE_ABORT;
-
- /* Disable the stream */
- __HAL_MDMA_DISABLE(hmdma);
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Polling for transfer complete.
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param CompleteLevel: Specifies the MDMA level complete.
- * @param Timeout: Timeout duration.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
-{
- uint32_t levelFlag, errorFlag;
- uint32_t tickstart;
-
- /* Check the parameters */
- assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- if(HAL_MDMA_STATE_BUSY != hmdma->State)
- {
- /* No transfer ongoing */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
-
- return HAL_ERROR;
- }
-
- /* Get the level transfer complete flag */
- levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER) ? MDMA_FLAG_CTC : \
- (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
- (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT : \
- MDMA_FLAG_BRT);
-
-
- /* Get timeout */
- tickstart = HAL_GetTick();
-
- while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
- {
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
- {
- /* Get the transfer error source flag */
- errorFlag = hmdma->Instance->CESR;
-
- if((errorFlag & MDMA_CESR_TED) == 0U)
- {
- /* Update error code : Read Transfer error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
- }
- else
- {
- /* Update error code : Write Transfer error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
- }
-
- if((errorFlag & MDMA_CESR_TEMD) != 0U)
- {
- /* Update error code : Error Mask Data */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
- }
-
- if((errorFlag & MDMA_CESR_TELD) != 0U)
- {
- /* Update error code : Error Linked list */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
- }
-
- if((errorFlag & MDMA_CESR_ASE) != 0U)
- {
- /* Update error code : Address/Size alignment error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
- }
-
- if((errorFlag & MDMA_CESR_BSE) != 0U)
- {
- /* Update error code : Block Size error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
- }
-
- (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
-
- /*
- Note that the Abort function will
- - Clear all transfer flags
- - Unlock
- - Set the State
- */
-
- return HAL_ERROR;
-
- }
-
- /* Check for the Timeout */
- if(Timeout != HAL_MAX_DELAY)
- {
- if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
- {
- /* Update error code */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
-
- (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
-
- /*
- Note that the Abort function will
- - Clear all transfer flags
- - Unlock
- - Set the State
- */
-
- return HAL_ERROR;
- }
- }
- }
-
- /* Clear the transfer level flag */
- if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
- {
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
-
- }
- else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
- {
- __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
-
- }
- else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
- {
- __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
- }
- else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
- {
- __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
-
- /* Process unlocked */
- __HAL_UNLOCK(hmdma);
-
- hmdma->State = HAL_MDMA_STATE_READY;
- }
- else
- {
- return HAL_ERROR;
- }
-
- return HAL_OK;
-}
-
-/**
- * @brief Generate an MDMA SW request trigger to activate the request on the given Channel.
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Stream.
- * @retval HAL status
- */
-HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
-{
- uint32_t request_mode;
-
- /* Check the MDMA peripheral handle */
- if(hmdma == NULL)
- {
- return HAL_ERROR;
- }
-
- /* Get the softawre request mode */
- request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
-
- if((hmdma->Instance->CCR & MDMA_CCR_EN) == 0U)
- {
- /* if no Transfer on going (MDMA enable bit not set) retrun error */
- hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
-
- return HAL_ERROR;
- }
- else if(((hmdma->Instance->CISR & MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
- {
- /* if an MDMA ongoing request has not yet end or if request mode is not SW request retrun error */
- hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
-
- return HAL_ERROR;
- }
- else
- {
- /* Set the SW request bit to activate the request on the Channel */
- hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
-
- return HAL_OK;
- }
-}
-
-/**
- * @brief Handles MDMA interrupt request.
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval None
- */
-void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
-{
- __IO uint32_t count = 0;
- uint32_t timeout = SystemCoreClock / 9600U;
-
- uint32_t generalIntFlag, errorFlag;
-
- /* General Interrupt Flag management ****************************************/
- generalIntFlag = 1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
- if((MDMA->GISR0 & generalIntFlag) == 0U)
- {
- return; /* the General interrupt flag for the current channel is down , nothing to do */
- }
-
- /* Transfer Error Interrupt management ***************************************/
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
- {
- if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
- {
- /* Disable the transfer error interrupt */
- __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
-
- /* Get the transfer error source flag */
- errorFlag = hmdma->Instance->CESR;
-
- if((errorFlag & MDMA_CESR_TED) == 0U)
- {
- /* Update error code : Read Transfer error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
- }
- else
- {
- /* Update error code : Write Transfer error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
- }
-
- if((errorFlag & MDMA_CESR_TEMD) != 0U)
- {
- /* Update error code : Error Mask Data */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
- }
-
- if((errorFlag & MDMA_CESR_TELD) != 0U)
- {
- /* Update error code : Error Linked list */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
- }
-
- if((errorFlag & MDMA_CESR_ASE) != 0U)
- {
- /* Update error code : Address/Size alignment error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
- }
-
- if((errorFlag & MDMA_CESR_BSE) != 0U)
- {
- /* Update error code : Block Size error error */
- hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
- }
-
- /* Clear the transfer error flags */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
- }
- }
-
- /* Buffer Transfer Complete Interrupt management ******************************/
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
- {
- if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
- {
- /* Clear the buffer transfer complete flag */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
-
- if(hmdma->XferBufferCpltCallback != NULL)
- {
- /* Buffer transfer callback */
- hmdma->XferBufferCpltCallback(hmdma);
- }
- }
- }
-
- /* Block Transfer Complete Interrupt management ******************************/
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
- {
- if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
- {
- /* Clear the block transfer complete flag */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
-
- if(hmdma->XferBlockCpltCallback != NULL)
- {
- /* Block transfer callback */
- hmdma->XferBlockCpltCallback(hmdma);
- }
- }
- }
-
- /* Repeated Block Transfer Complete Interrupt management ******************************/
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
- {
- if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
- {
- /* Clear the repeat block transfer complete flag */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
-
- if(hmdma->XferRepeatBlockCpltCallback != NULL)
- {
- /* Repeated Block transfer callback */
- hmdma->XferRepeatBlockCpltCallback(hmdma);
- }
- }
- }
-
- /* Channel Transfer Complete Interrupt management ***********************************/
- if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
- {
- if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
- {
- /* Disable all the transfer interrupts */
- __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
-
- if(HAL_MDMA_STATE_ABORT == hmdma->State)
- {
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Change the DMA state */
- hmdma->State = HAL_MDMA_STATE_READY;
-
- if(hmdma->XferAbortCallback != NULL)
- {
- hmdma->XferAbortCallback(hmdma);
- }
- return;
- }
-
- /* Clear the Channel Transfer Complete flag */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
-
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- /* Change MDMA peripheral state */
- hmdma->State = HAL_MDMA_STATE_READY;
-
- if(hmdma->XferCpltCallback != NULL)
- {
- /* Channel Transfer Complete callback */
- hmdma->XferCpltCallback(hmdma);
- }
- }
- }
-
- /* manage error case */
- if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
- {
- hmdma->State = HAL_MDMA_STATE_ABORT;
-
- /* Disable the channel */
- __HAL_MDMA_DISABLE(hmdma);
-
- do
- {
- if (++count > timeout)
- {
- break;
- }
- }
- while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
-
- /* Process Unlocked */
- __HAL_UNLOCK(hmdma);
-
- if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
- {
- /* Change the MDMA state to error if MDMA disable fails */
- hmdma->State = HAL_MDMA_STATE_ERROR;
- }
- else
- {
- /* Change the MDMA state to Ready if MDMA disable success */
- hmdma->State = HAL_MDMA_STATE_READY;
- }
-
-
- if (hmdma->XferErrorCallback != NULL)
- {
- /* Transfer error callback */
- hmdma->XferErrorCallback(hmdma);
- }
- }
-}
-
-/**
- * @}
- */
-
-/** @addtogroup MDMA_Exported_Functions_Group4
- *
-@verbatim
- ===============================================================================
- ##### State and Errors functions #####
- ===============================================================================
- [..]
- This subsection provides functions allowing to
- (+) Check the MDMA state
- (+) Get error code
-
-@endverbatim
- * @{
- */
-
-/**
- * @brief Returns the MDMA state.
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval HAL state
- */
-HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma)
-{
- return hmdma->State;
-}
-
-/**
- * @brief Return the MDMA error code
- * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval MDMA Error Code
- */
-uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma)
-{
- return hmdma->ErrorCode;
-}
-
-/**
- * @}
- */
-
-/**
- * @}
- */
-
-/** @addtogroup MDMA_Private_Functions
- * @{
- */
-
-/**
- * @brief Sets the MDMA Transfer parameter.
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @param SrcAddress: The source memory Buffer address
- * @param DstAddress: The destination memory Buffer address
- * @param BlockDataLength : The length of a block transfer in bytes
- * @param BlockCount: The number of blocks to be transfered
- * @retval HAL status
- */
-static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
-{
- uint32_t addressMask;
-
- /* Configure the MDMA Channel data length */
- MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
-
- /* Configure the MDMA block repeat count */
- MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
-
- /* Clear all interrupt flags */
- __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
-
- /* Configure MDMA Channel destination address */
- hmdma->Instance->CDAR = DstAddress;
-
- /* Configure MDMA Channel Source address */
- hmdma->Instance->CSAR = SrcAddress;
-
- addressMask = SrcAddress & 0xFF000000U;
- if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
- {
- /*The AHBSbus is used as source (read operation) on channel x */
- hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
- }
- else
- {
- /*The AXI bus is used as source (read operation) on channel x */
- hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
- }
-
- addressMask = DstAddress & 0xFF000000U;
- if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
- {
- /*The AHB bus is used as destination (write operation) on channel x */
- hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
- }
- else
- {
- /*The AXI bus is used as destination (write operation) on channel x */
- hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
- }
-
- /* Set the linked list register to the first node of the list */
- hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
-}
-
-/**
- * @brief Initializes the MDMA handle according to the specified
- * parameters in the MDMA_InitTypeDef
- * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
- * the configuration information for the specified MDMA Channel.
- * @retval None
- */
-static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
-{
- uint32_t blockoffset;
-
- /* Prepare the MDMA Channel configuration */
- hmdma->Instance->CCR = hmdma->Init.Priority | hmdma->Init.Endianness;
-
- /* Write new CTCR Register value */
- hmdma->Instance->CTCR = hmdma->Init.SourceInc | hmdma->Init.DestinationInc | \
- hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize | \
- hmdma->Init.DataAlignment | hmdma->Init.SourceBurst | \
- hmdma->Init.DestBurst | \
- ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
- hmdma->Init.TransferTriggerMode;
-
- /* If SW request set the CTCR register to SW Request Mode */
- if(hmdma->Init.Request == MDMA_REQUEST_SW)
- {
- /*
- -If the request is done by SW : BWM could be set to 1 or 0.
- -If the request is done by a peripheral :
- If mask address not set (0) => BWM must be set to 0
- If mask address set (different than 0) => BWM could be set to 1 or 0
- */
- hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
- }
-
- /* Reset CBNDTR Register */
- hmdma->Instance->CBNDTR = 0;
-
- /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
- if(hmdma->Init.SourceBlockAddressOffset < 0)
- {
- hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
- /* Write new CBRUR Register value : source repeat block offset */
- blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
- hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
- }
- else
- {
- /* Write new CBRUR Register value : source repeat block offset */
- hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
- }
-
- /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
- if(hmdma->Init.DestBlockAddressOffset < 0)
- {
- hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
- /* Write new CBRUR Register value : destination repeat block offset */
- blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
- hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
- }
- else
- {
- /*write new CBRUR Register value : destination repeat block offset */
- hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
- }
-
- /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
- if(hmdma->Init.Request != MDMA_REQUEST_SW)
- {
- /* Set the HW request in CTRB register */
- hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
- }
- else /* SW request : reset the CTBR register */
- {
- hmdma->Instance->CTBR = 0;
- }
-
- /* Write Link Address Register */
- hmdma->Instance->CLAR = 0;
-}
-
-/**
- * @}
- */
-
-#endif /* HAL_MDMA_MODULE_ENABLED */
-/**
- * @}
- */
-
-/**
- * @}
- */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+ * @brief MDMA HAL module driver + * @{ + */ + +#ifdef HAL_MDMA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup MDMA_Private_Constants + * @{ + */ +#define HAL_TIMEOUT_MDMA_ABORT 5U /* 5 ms */ +#define HAL_MDMA_CHANNEL_SIZE 0x40U /* an MDMA instance channel size is 64 byte */ +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup MDMA_Private_Functions_Prototypes + * @{ + */ +static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount); +static void MDMA_Init(MDMA_HandleTypeDef *hmdma); + +/** + * @} + */ + +/** @addtogroup MDMA_Exported_Functions MDMA Exported Functions + * @{ + */ + +/** @addtogroup MDMA_Exported_Functions_Group1 + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + This section provides functions allowing to : + Initialize and de-initialize the MDMA channel. + Register and Unregister MDMA callbacks + [..] + The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in + reference manual. + The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel. + HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback functions allows + respectevely to register/unregister an MDMA callback function. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the MDMA according to the specified + * parameters in the MDMA_InitTypeDef and create the associated handle. + * @param hmdma: Pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance)); + assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority)); + assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness)); + assert_param(IS_MDMA_REQUEST(hmdma->Init.Request)); + assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc)); + assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc)); + assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize)); + assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize)); + assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment)); + assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst)); + assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst)); + assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength)); + assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode)); + assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset)); + assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset)); + + + /* Allocate lock resource */ + __HAL_UNLOCK(hmdma); + + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* Disable the MDMA channel */ + __HAL_MDMA_DISABLE(hmdma); + + /* Check if the MDMA channel is effectively disabled */ + while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT) + { + /* Update error code */ + hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT; + + /* Change the MDMA state */ + hmdma->State = HAL_MDMA_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Initialize the MDMA channel registers */ + MDMA_Init(hmdma); + + /* Reset the MDMA first/last linkedlist node addresses and node counter */ + hmdma->FirstLinkedListNodeAddress = 0; + hmdma->LastLinkedListNodeAddress = 0; + hmdma->LinkedListNodeCounter = 0; + + /* Initialize the error code */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; + + /* Initialize the MDMA state */ + hmdma->State = HAL_MDMA_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the MDMA peripheral + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma) +{ + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Disable the selected MDMA Channelx */ + __HAL_MDMA_DISABLE(hmdma); + + /* Reset MDMA Channel control register */ + hmdma->Instance->CCR = 0; + hmdma->Instance->CTCR = 0; + hmdma->Instance->CBNDTR = 0; + hmdma->Instance->CSAR = 0; + hmdma->Instance->CDAR = 0; + hmdma->Instance->CBRUR = 0; + hmdma->Instance->CLAR = 0; + hmdma->Instance->CTBR = 0; + hmdma->Instance->CMAR = 0; + hmdma->Instance->CMDR = 0; + + /* Clear all flags */ + __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC)); + + /* Reset the MDMA first/last linkedlist node addresses and node counter */ + hmdma->FirstLinkedListNodeAddress = 0; + hmdma->LastLinkedListNodeAddress = 0; + hmdma->LinkedListNodeCounter = 0; + + /* Initialize the error code */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; + + /* Initialize the MDMA state */ + hmdma->State = HAL_MDMA_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hmdma); + + return HAL_OK; +} + +/** + * @brief Config the Post request Mask address and Mask data + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param MaskAddress: specifies the address to be updated (written) with MaskData after a request is served. + * @param MaskData: specifies the value to be written to MaskAddress after a request is served. + * MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* if HW request set Post Request MaskAddress and MaskData, */ + if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U) + { + /* Set the HW request clear Mask and Data */ + hmdma->Instance->CMAR = MaskAddress; + hmdma->Instance->CMDR = MaskData; + + /* + -If the request is done by SW : BWM could be set to 1 or 0. + -If the request is done by a peripheral : + If mask address not set (0) => BWM must be set to 0 + If mask address set (different than 0) => BWM could be set to 1 or 0 + */ + if(MaskAddress == 0U) + { + hmdma->Instance->CTCR &= ~MDMA_CTCR_BWM; + } + else + { + hmdma->Instance->CTCR |= MDMA_CTCR_BWM; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + /* Release Lock */ + __HAL_UNLOCK(hmdma); + + return status; +} + +/** + * @brief Register callbacks + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param CallbackID: User Callback identifier + * @param pCallback: pointer to callbacsk function. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma)) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + switch (CallbackID) + { + case HAL_MDMA_XFER_CPLT_CB_ID: + hmdma->XferCpltCallback = pCallback; + break; + + case HAL_MDMA_XFER_BUFFERCPLT_CB_ID: + hmdma->XferBufferCpltCallback = pCallback; + break; + + case HAL_MDMA_XFER_BLOCKCPLT_CB_ID: + hmdma->XferBlockCpltCallback = pCallback; + break; + + case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID: + hmdma->XferRepeatBlockCpltCallback = pCallback; + break; + + case HAL_MDMA_XFER_ERROR_CB_ID: + hmdma->XferErrorCallback = pCallback; + break; + + case HAL_MDMA_XFER_ABORT_CB_ID: + hmdma->XferAbortCallback = pCallback; + break; + + default: + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hmdma); + + return status; +} + +/** + * @brief UnRegister callbacks + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param CallbackID: User Callback identifier + * a HAL_MDMA_CallbackIDTypeDef ENUM as parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + switch (CallbackID) + { + case HAL_MDMA_XFER_CPLT_CB_ID: + hmdma->XferCpltCallback = NULL; + break; + + case HAL_MDMA_XFER_BUFFERCPLT_CB_ID: + hmdma->XferBufferCpltCallback = NULL; + break; + + case HAL_MDMA_XFER_BLOCKCPLT_CB_ID: + hmdma->XferBlockCpltCallback = NULL; + break; + + case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID: + hmdma->XferRepeatBlockCpltCallback = NULL; + break; + + case HAL_MDMA_XFER_ERROR_CB_ID: + hmdma->XferErrorCallback = NULL; + break; + + case HAL_MDMA_XFER_ABORT_CB_ID: + hmdma->XferAbortCallback = NULL; + break; + + case HAL_MDMA_XFER_ALL_CB_ID: + hmdma->XferCpltCallback = NULL; + hmdma->XferBufferCpltCallback = NULL; + hmdma->XferBlockCpltCallback = NULL; + hmdma->XferRepeatBlockCpltCallback = NULL; + hmdma->XferErrorCallback = NULL; + hmdma->XferAbortCallback = NULL; + break; + + default: + status = HAL_ERROR; + break; + } + } + else + { + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hmdma); + + return status; +} + +/** + * @} + */ + +/** @addtogroup MDMA_Exported_Functions_Group2 + * +@verbatim + =============================================================================== + ##### Linked list operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Create a linked list node + (+) Add a node to the MDMA linked list + (+) Remove a node from the MDMA linked list + (+) Enable/Disable linked list circular mode +@endverbatim + * @{ + */ + +/** + * @brief Initializes an MDMA Link Node according to the specified + * parameters in the pMDMA_LinkedListNodeConfig . + * @param pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node + * registers configurations. + * @param pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains + * the configuration information for the specified MDMA Linked List Node. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig) +{ + uint32_t addressMask; + uint32_t blockoffset; + + /* Check the MDMA peripheral state */ + if((pNode == NULL) || (pNodeConfig == NULL)) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority)); + assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness)); + assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request)); + assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc)); + assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc)); + assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize)); + assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize)); + assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment)); + assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst)); + assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst)); + assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength)); + assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode)); + assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset)); + assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset)); + + assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength)); + assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount)); + + + /* Configure next Link node Address Register to zero */ + pNode->CLAR = 0; + + /* Configure the Link Node registers*/ + pNode->CTBR = 0; + pNode->CMAR = 0; + pNode->CMDR = 0; + pNode->Reserved = 0; + + /* Write new CTCR Register value */ + pNode->CTCR = pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \ + pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize | \ + pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst | \ + pNodeConfig->Init.DestBurst | \ + ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \ + pNodeConfig->Init.TransferTriggerMode; + + /* If SW request set the CTCR register to SW Request Mode*/ + if(pNodeConfig->Init.Request == MDMA_REQUEST_SW) + { + pNode->CTCR |= MDMA_CTCR_SWRM; + } + + /* + -If the request is done by SW : BWM could be set to 1 or 0. + -If the request is done by a peripheral : + If mask address not set (0) => BWM must be set to 0 + If mask address set (different than 0) => BWM could be set to 1 or 0 + */ + if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U)) + { + pNode->CTCR |= MDMA_CTCR_BWM; + } + + /* Set the new CBNDTR Register value */ + pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC; + + /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */ + if(pNodeConfig->Init.SourceBlockAddressOffset < 0) + { + pNode->CBNDTR |= MDMA_CBNDTR_BRSUM; + /*write new CBRUR Register value : source repeat block offset */ + blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset); + pNode->CBRUR = blockoffset & 0x0000FFFFU; + } + else + { + /*write new CBRUR Register value : source repeat block offset */ + pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU); + } + + /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */ + if(pNodeConfig->Init.DestBlockAddressOffset < 0) + { + pNode->CBNDTR |= MDMA_CBNDTR_BRDUM; + /*write new CBRUR Register value : destination repeat block offset */ + blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset); + pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos); + } + else + { + /*write new CBRUR Register value : destination repeat block offset */ + pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos); + } + + /* Configure MDMA Link Node data length */ + pNode->CBNDTR |= pNodeConfig->BlockDataLength; + + /* Configure MDMA Link Node destination address */ + pNode->CDAR = pNodeConfig->DstAddress; + + /* Configure MDMA Link Node Source address */ + pNode->CSAR = pNodeConfig->SrcAddress; + + /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */ + if(pNodeConfig->Init.Request != MDMA_REQUEST_SW) + { + /* Set the HW request in CTBR register */ + pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL; + /* Set the HW request clear Mask and Data */ + pNode->CMAR = pNodeConfig->PostRequestMaskAddress; + pNode->CMDR = pNodeConfig->PostRequestMaskData; + } + + addressMask = pNodeConfig->SrcAddress & 0xFF000000U; + if((addressMask == 0x20000000U) || (addressMask == 0x00000000U)) + { + /*The AHBSbus is used as source (read operation) on channel x */ + pNode->CTBR |= MDMA_CTBR_SBUS; + } + + addressMask = pNodeConfig->DstAddress & 0xFF000000U; + if((addressMask == 0x20000000U) || (addressMask == 0x00000000U)) + { + /*The AHB bus is used as destination (write operation) on channel x */ + pNode->CTBR |= MDMA_CTBR_DBUS; + } + + return HAL_OK; +} + +/** + * @brief Connect a node to the linked list. + * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node + * to be add to the list. + * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node + * at the end of the list + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode) +{ + MDMA_LinkNodeTypeDef *pNode; + uint32_t counter = 0, nodeInserted = 0; + HAL_StatusTypeDef hal_status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if((hmdma == NULL) || (pNewNode == NULL)) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* Check if this is the first node (after the Inititlization node) */ + if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) + { + if(pPrevNode == NULL) + { + /* if this is the first node after the initialization + connect this node to the node 0 by updating + the MDMA channel CLAR register to this node address */ + hmdma->Instance->CLAR = (uint32_t)pNewNode; + /* Set the MDMA handle First linked List node*/ + hmdma->FirstLinkedListNodeAddress = pNewNode; + + /*reset New node link */ + pNewNode->CLAR = 0; + + /* Update the Handle last node address */ + hmdma->LastLinkedListNodeAddress = pNewNode; + + hmdma->LinkedListNodeCounter = 1; + } + else + { + hal_status = HAL_ERROR; + } + } + else if(hmdma->FirstLinkedListNodeAddress != pNewNode) + { + /* Check if the node to insert already exists*/ + pNode = hmdma->FirstLinkedListNodeAddress; + while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK)) + { + if(pNode->CLAR == (uint32_t)pNewNode) + { + hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */ + } + pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR; + counter++; + } + + if(hal_status == HAL_OK) + { + /* Check if the previous node is the last one in the current list or zero */ + if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL)) + { + /* insert the new node at the end of the list */ + pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR; + hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode; + /* Update the Handle last node address */ + hmdma->LastLinkedListNodeAddress = pNewNode; + /* Increment the linked list node counter */ + hmdma->LinkedListNodeCounter++; + } + else + { + /*insert the new node after the pPreviousNode node */ + pNode = hmdma->FirstLinkedListNodeAddress; + counter = 0; + while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U)) + { + counter++; + if(pNode == pPrevNode) + { + /*Insert the new node after the previous one */ + pNewNode->CLAR = pNode->CLAR; + pNode->CLAR = (uint32_t)pNewNode; + /* Increment the linked list node counter */ + hmdma->LinkedListNodeCounter++; + nodeInserted = 1; + } + else + { + pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR; + } + } + + if(nodeInserted == 0U) + { + hal_status = HAL_ERROR; + } + } + } + } + else + { + hal_status = HAL_ERROR; + } + + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + hmdma->State = HAL_MDMA_STATE_READY; + + return hal_status; + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + /* Return error status */ + return HAL_BUSY; + } +} + +/** + * @brief Disconnect/Remove a node from the transfer linked list. + * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node + * to be removed from the list. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode) +{ + MDMA_LinkNodeTypeDef *ptmpNode; + uint32_t counter = 0, nodeDeleted = 0; + HAL_StatusTypeDef hal_status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if((hmdma == NULL) || (pNode == NULL)) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* If first and last node are null (no nodes in the list) : return error*/ + if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U)) + { + hal_status = HAL_ERROR; + } + else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */ + { + /* Delete 1st node */ + if(hmdma->LastLinkedListNodeAddress == pNode) + { + /*if the last node is at the same time the first one (1 single node after the init node 0) + then update the last node too */ + + hmdma->FirstLinkedListNodeAddress = 0; + hmdma->LastLinkedListNodeAddress = 0; + hmdma->LinkedListNodeCounter = 0; + + hmdma->Instance->CLAR = 0; + } + else + { + if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR) + { + /* if last node is looping to first (circular list) one update the last node connection */ + hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR; + } + + /* if deleting the first node after the initialization + connect the next node to the node 0 by updating + the MDMA channel CLAR register to this node address */ + hmdma->Instance->CLAR = pNode->CLAR; + hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR; + /* Update the Handle node counter */ + hmdma->LinkedListNodeCounter--; + } + } + else /* Deleting any other node */ + { + /*Deleted node is not the first one : find it */ + ptmpNode = hmdma->FirstLinkedListNodeAddress; + while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U)) + { + counter++; + if(ptmpNode->CLAR == ((uint32_t)pNode)) + { + /* if deleting the last node */ + if(pNode == hmdma->LastLinkedListNodeAddress) + { + /*Update the linked list last node address in the handle*/ + hmdma->LastLinkedListNodeAddress = ptmpNode; + } + /* update the next node link after deleting pMDMA_LinkedListNode */ + ptmpNode->CLAR = pNode->CLAR; + nodeDeleted = 1; + /* Update the Handle node counter */ + hmdma->LinkedListNodeCounter--; + } + else + { + ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR; + } + } + + if(nodeDeleted == 0U) + { + /* last node reashed without finding the node to delete : return error */ + hal_status = HAL_ERROR; + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + hmdma->State = HAL_MDMA_STATE_READY; + + return hal_status; + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + /* Return error status */ + return HAL_BUSY; + } +} + +/** + * @brief Make the linked list circular by connecting the last node to the first. + * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* If first and last node are null (no nodes in the list) : return error*/ + if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U)) + { + hal_status = HAL_ERROR; + } + else + { + /* to enable circular mode Last Node should be connected to first node */ + hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress; + } + + } + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + hmdma->State = HAL_MDMA_STATE_READY; + + return hal_status; +} + +/** + * @brief Disable the linked list circular mode by setting the last node connection to null + * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* If first and last node are null (no nodes in the list) : return error*/ + if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U)) + { + hal_status = HAL_ERROR; + } + else + { + /* to disable circular mode Last Node should be connected to NULL */ + hmdma->LastLinkedListNodeAddress->CLAR = 0; + } + + } + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + hmdma->State = HAL_MDMA_STATE_READY; + + return hal_status; +} + +/** + * @} + */ + +/** @addtogroup MDMA_Exported_Functions_Group3 + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the source, destination address and data length and Start MDMA transfer + (+) Configure the source, destination address and data length and + Start MDMA transfer with interrupt + (+) Abort MDMA transfer + (+) Poll for transfer complete + (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW) + (+) Handle MDMA interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Starts the MDMA Transfer. + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param SrcAddress : The source memory Buffer address + * @param DstAddress : The destination memory Buffer address + * @param BlockDataLength : The length of a block transfer in bytes + * @param BlockCount : The number of a blocks to be transfer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount) +{ + /* Check the parameters */ + assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength)); + assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* Initialize the error code */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_MDMA_DISABLE(hmdma); + + /* Configure the source, destination address and the data length */ + MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount); + + /* Enable the Peripheral */ + __HAL_MDMA_ENABLE(hmdma); + + if(hmdma->Init.Request == MDMA_REQUEST_SW) + { + /* activate If SW request mode*/ + hmdma->Instance->CCR |= MDMA_CCR_SWRQ; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + /* Return error status */ + return HAL_BUSY; + } + + return HAL_OK; +} + +/** + * @brief Starts the MDMA Transfer with interrupts enabled. + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param SrcAddress : The source memory Buffer address + * @param DstAddress : The destination memory Buffer address + * @param BlockDataLength : The length of a block transfer in bytes + * @param BlockCount : The number of a blocks to be transfer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount) +{ + /* Check the parameters */ + assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength)); + assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmdma); + + if(HAL_MDMA_STATE_READY == hmdma->State) + { + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_BUSY; + + /* Initialize the error code */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_MDMA_DISABLE(hmdma); + + /* Configure the source, destination address and the data length */ + MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount); + + /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/ + __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC)); + + if(hmdma->XferBlockCpltCallback != NULL) + { + /* if Block transfer complete Callback is set enable the corresponding IT*/ + __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT); + } + + if(hmdma->XferRepeatBlockCpltCallback != NULL) + { + /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/ + __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT); + } + + if(hmdma->XferBufferCpltCallback != NULL) + { + /* if buffer transfer complete Callback is set enable the corresponding IT*/ + __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC); + } + + /* Enable the Peripheral */ + __HAL_MDMA_ENABLE(hmdma); + + if(hmdma->Init.Request == MDMA_REQUEST_SW) + { + /* activate If SW request mode*/ + hmdma->Instance->CCR |= MDMA_CCR_SWRQ; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + /* Return error status */ + return HAL_BUSY; + } + + return HAL_OK; +} + +/** + * @brief Aborts the MDMA Transfer. + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * + * @note After disabling a MDMA Channel, a check for wait until the MDMA Channel is + * effectively disabled is added. If a Channel is disabled + * while a data transfer is ongoing, the current data will be transferred + * and the Channel will be effectively disabled only after the transfer of + * this single data is finished. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + if(HAL_MDMA_STATE_BUSY != hmdma->State) + { + hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER; + + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + return HAL_ERROR; + } + else + { + /* Disable all the transfer interrupts */ + __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC)); + + /* Disable the channel */ + __HAL_MDMA_DISABLE(hmdma); + + /* Check if the MDMA Channel is effectively disabled */ + while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U) + { + /* Check for the Timeout */ + if( (HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT) + { + /* Update error code */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + /* Change the MDMA state */ + hmdma->State = HAL_MDMA_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Clear all interrupt flags */ + __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC)); + + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + /* Change the MDMA state*/ + hmdma->State = HAL_MDMA_STATE_READY; + } + + return HAL_OK; +} + +/** + * @brief Aborts the MDMA Transfer in Interrupt mode. + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma) +{ + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + if(HAL_MDMA_STATE_BUSY != hmdma->State) + { + /* No transfer ongoing */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER; + + return HAL_ERROR; + } + else + { + /* Set Abort State */ + hmdma->State = HAL_MDMA_STATE_ABORT; + + /* Disable the stream */ + __HAL_MDMA_DISABLE(hmdma); + } + + return HAL_OK; +} + +/** + * @brief Polling for transfer complete. + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param CompleteLevel: Specifies the MDMA level complete. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout) +{ + uint32_t levelFlag, errorFlag; + uint32_t tickstart; + + /* Check the parameters */ + assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel)); + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + if(HAL_MDMA_STATE_BUSY != hmdma->State) + { + /* No transfer ongoing */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER; + + return HAL_ERROR; + } + + /* Get the level transfer complete flag */ + levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER) ? MDMA_FLAG_CTC : \ + (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \ + (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT : \ + MDMA_FLAG_BRT); + + + /* Get timeout */ + tickstart = HAL_GetTick(); + + while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U) + { + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U)) + { + /* Get the transfer error source flag */ + errorFlag = hmdma->Instance->CESR; + + if((errorFlag & MDMA_CESR_TED) == 0U) + { + /* Update error code : Read Transfer error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER; + } + else + { + /* Update error code : Write Transfer error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER; + } + + if((errorFlag & MDMA_CESR_TEMD) != 0U) + { + /* Update error code : Error Mask Data */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA; + } + + if((errorFlag & MDMA_CESR_TELD) != 0U) + { + /* Update error code : Error Linked list */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST; + } + + if((errorFlag & MDMA_CESR_ASE) != 0U) + { + /* Update error code : Address/Size alignment error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT; + } + + if((errorFlag & MDMA_CESR_BSE) != 0U) + { + /* Update error code : Block Size error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE; + } + + (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */ + + /* + Note that the Abort function will + - Clear all transfer flags + - Unlock + - Set the State + */ + + return HAL_ERROR; + + } + + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U)) + { + /* Update error code */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT; + + (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */ + + /* + Note that the Abort function will + - Clear all transfer flags + - Unlock + - Set the State + */ + + return HAL_ERROR; + } + } + } + + /* Clear the transfer level flag */ + if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER) + { + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC); + + } + else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) + { + __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT)); + + } + else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER) + { + __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT)); + } + else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER) + { + __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC)); + + /* Process unlocked */ + __HAL_UNLOCK(hmdma); + + hmdma->State = HAL_MDMA_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Generate an MDMA SW request trigger to activate the request on the given Channel. + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Stream. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma) +{ + uint32_t request_mode; + + /* Check the MDMA peripheral handle */ + if(hmdma == NULL) + { + return HAL_ERROR; + } + + /* Get the softawre request mode */ + request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM; + + if((hmdma->Instance->CCR & MDMA_CCR_EN) == 0U) + { + /* if no Transfer on going (MDMA enable bit not set) return error */ + hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER; + + return HAL_ERROR; + } + else if(((hmdma->Instance->CISR & MDMA_CISR_CRQA) != 0U) || (request_mode == 0U)) + { + /* if an MDMA ongoing request has not yet end or if request mode is not SW request return error */ + hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY; + + return HAL_ERROR; + } + else + { + /* Set the SW request bit to activate the request on the Channel */ + hmdma->Instance->CCR |= MDMA_CCR_SWRQ; + + return HAL_OK; + } +} + +/** + * @brief Handles MDMA interrupt request. + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval None + */ +void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma) +{ + __IO uint32_t count = 0; + uint32_t timeout = SystemCoreClock / 9600U; + + uint32_t generalIntFlag, errorFlag; + + /* General Interrupt Flag management ****************************************/ + generalIntFlag = 1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU); + if((MDMA->GISR0 & generalIntFlag) == 0U) + { + return; /* the General interrupt flag for the current channel is down , nothing to do */ + } + + /* Transfer Error Interrupt management ***************************************/ + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U)) + { + if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U) + { + /* Disable the transfer error interrupt */ + __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE); + + /* Get the transfer error source flag */ + errorFlag = hmdma->Instance->CESR; + + if((errorFlag & MDMA_CESR_TED) == 0U) + { + /* Update error code : Read Transfer error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER; + } + else + { + /* Update error code : Write Transfer error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER; + } + + if((errorFlag & MDMA_CESR_TEMD) != 0U) + { + /* Update error code : Error Mask Data */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA; + } + + if((errorFlag & MDMA_CESR_TELD) != 0U) + { + /* Update error code : Error Linked list */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST; + } + + if((errorFlag & MDMA_CESR_ASE) != 0U) + { + /* Update error code : Address/Size alignment error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT; + } + + if((errorFlag & MDMA_CESR_BSE) != 0U) + { + /* Update error code : Block Size error error */ + hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE; + } + + /* Clear the transfer error flags */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE); + } + } + + /* Buffer Transfer Complete Interrupt management ******************************/ + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U)) + { + if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U) + { + /* Clear the buffer transfer complete flag */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC); + + if(hmdma->XferBufferCpltCallback != NULL) + { + /* Buffer transfer callback */ + hmdma->XferBufferCpltCallback(hmdma); + } + } + } + + /* Block Transfer Complete Interrupt management ******************************/ + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U)) + { + if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U) + { + /* Clear the block transfer complete flag */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT); + + if(hmdma->XferBlockCpltCallback != NULL) + { + /* Block transfer callback */ + hmdma->XferBlockCpltCallback(hmdma); + } + } + } + + /* Repeated Block Transfer Complete Interrupt management ******************************/ + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U)) + { + if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U) + { + /* Clear the repeat block transfer complete flag */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT); + + if(hmdma->XferRepeatBlockCpltCallback != NULL) + { + /* Repeated Block transfer callback */ + hmdma->XferRepeatBlockCpltCallback(hmdma); + } + } + } + + /* Channel Transfer Complete Interrupt management ***********************************/ + if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U)) + { + if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U) + { + /* Disable all the transfer interrupts */ + __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC)); + + if(HAL_MDMA_STATE_ABORT == hmdma->State) + { + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + /* Change the DMA state */ + hmdma->State = HAL_MDMA_STATE_READY; + + if(hmdma->XferAbortCallback != NULL) + { + hmdma->XferAbortCallback(hmdma); + } + return; + } + + /* Clear the Channel Transfer Complete flag */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC); + + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + /* Change MDMA peripheral state */ + hmdma->State = HAL_MDMA_STATE_READY; + + if(hmdma->XferCpltCallback != NULL) + { + /* Channel Transfer Complete callback */ + hmdma->XferCpltCallback(hmdma); + } + } + } + + /* manage error case */ + if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE) + { + hmdma->State = HAL_MDMA_STATE_ABORT; + + /* Disable the channel */ + __HAL_MDMA_DISABLE(hmdma); + + do + { + if (++count > timeout) + { + break; + } + } + while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U); + + /* Process Unlocked */ + __HAL_UNLOCK(hmdma); + + if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U) + { + /* Change the MDMA state to error if MDMA disable fails */ + hmdma->State = HAL_MDMA_STATE_ERROR; + } + else + { + /* Change the MDMA state to Ready if MDMA disable success */ + hmdma->State = HAL_MDMA_STATE_READY; + } + + + if (hmdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hmdma->XferErrorCallback(hmdma); + } + } +} + +/** + * @} + */ + +/** @addtogroup MDMA_Exported_Functions_Group4 + * +@verbatim + =============================================================================== + ##### State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the MDMA state + (+) Get error code + +@endverbatim + * @{ + */ + +/** + * @brief Returns the MDMA state. + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval HAL state + */ +HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma) +{ + return hmdma->State; +} + +/** + * @brief Return the MDMA error code + * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval MDMA Error Code + */ +uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma) +{ + return hmdma->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup MDMA_Private_Functions + * @{ + */ + +/** + * @brief Sets the MDMA Transfer parameter. + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param BlockDataLength : The length of a block transfer in bytes + * @param BlockCount: The number of blocks to be transferred + * @retval HAL status + */ +static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount) +{ + uint32_t addressMask; + + /* Configure the MDMA Channel data length */ + MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT)); + + /* Configure the MDMA block repeat count */ + MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC); + + /* Clear all interrupt flags */ + __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF); + + /* Configure MDMA Channel destination address */ + hmdma->Instance->CDAR = DstAddress; + + /* Configure MDMA Channel Source address */ + hmdma->Instance->CSAR = SrcAddress; + + addressMask = SrcAddress & 0xFF000000U; + if((addressMask == 0x20000000U) || (addressMask == 0x00000000U)) + { + /*The AHBSbus is used as source (read operation) on channel x */ + hmdma->Instance->CTBR |= MDMA_CTBR_SBUS; + } + else + { + /*The AXI bus is used as source (read operation) on channel x */ + hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS); + } + + addressMask = DstAddress & 0xFF000000U; + if((addressMask == 0x20000000U) || (addressMask == 0x00000000U)) + { + /*The AHB bus is used as destination (write operation) on channel x */ + hmdma->Instance->CTBR |= MDMA_CTBR_DBUS; + } + else + { + /*The AXI bus is used as destination (write operation) on channel x */ + hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS); + } + + /* Set the linked list register to the first node of the list */ + hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress; +} + +/** + * @brief Initializes the MDMA handle according to the specified + * parameters in the MDMA_InitTypeDef + * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains + * the configuration information for the specified MDMA Channel. + * @retval None + */ +static void MDMA_Init(MDMA_HandleTypeDef *hmdma) +{ + uint32_t blockoffset; + + /* Prepare the MDMA Channel configuration */ + hmdma->Instance->CCR = hmdma->Init.Priority | hmdma->Init.Endianness; + + /* Write new CTCR Register value */ + hmdma->Instance->CTCR = hmdma->Init.SourceInc | hmdma->Init.DestinationInc | \ + hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize | \ + hmdma->Init.DataAlignment | hmdma->Init.SourceBurst | \ + hmdma->Init.DestBurst | \ + ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \ + hmdma->Init.TransferTriggerMode; + + /* If SW request set the CTCR register to SW Request Mode */ + if(hmdma->Init.Request == MDMA_REQUEST_SW) + { + /* + -If the request is done by SW : BWM could be set to 1 or 0. + -If the request is done by a peripheral : + If mask address not set (0) => BWM must be set to 0 + If mask address set (different than 0) => BWM could be set to 1 or 0 + */ + hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM); + } + + /* Reset CBNDTR Register */ + hmdma->Instance->CBNDTR = 0; + + /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */ + if(hmdma->Init.SourceBlockAddressOffset < 0) + { + hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM; + /* Write new CBRUR Register value : source repeat block offset */ + blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset); + hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU); + } + else + { + /* Write new CBRUR Register value : source repeat block offset */ + hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU); + } + + /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */ + if(hmdma->Init.DestBlockAddressOffset < 0) + { + hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM; + /* Write new CBRUR Register value : destination repeat block offset */ + blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset); + hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos); + } + else + { + /*write new CBRUR Register value : destination repeat block offset */ + hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos); + } + + /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */ + if(hmdma->Init.Request != MDMA_REQUEST_SW) + { + /* Set the HW request in CTRB register */ + hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL; + } + else /* SW request : reset the CTBR register */ + { + hmdma->Instance->CTBR = 0; + } + + /* Write Link Address Register */ + hmdma->Instance->CLAR = 0; +} + +/** + * @} + */ + +#endif /* HAL_MDMA_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + |