425 lines
16 KiB
C
425 lines
16 KiB
C
/*
|
|
******************************************************************************
|
|
* @file HAL_DMA.c
|
|
* @version V1.0.0
|
|
* @date 2020
|
|
* @brief DMA HAL module driver.
|
|
* This file provides firmware functions to manage the following
|
|
* functionalities of the Direct Memory Access (DMA) peripheral:
|
|
* @ Initialization and de-initialization functions
|
|
* @ IO operation functions
|
|
******************************************************************************
|
|
*/
|
|
#include "ACM32Fxx_HAL.h"
|
|
|
|
/**************** Used in cycle mode ****************/
|
|
static DMA_LLI_InitTypeDef Cycle_Channel[DMA_CHANNEL_NUM];
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_IRQHandler
|
|
* Description : This function handles DMA interrupt request.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
__weak void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
|
|
{
|
|
uint32_t lu32_Channel_Index;
|
|
|
|
/* Get DMA Channel number */
|
|
lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
|
|
|
|
/* Channel has been interrupted */
|
|
if (DMA->INT_STATUS & (1 << lu32_Channel_Index))
|
|
{
|
|
/* Transfer complete interrupt */
|
|
if (DMA->INT_TC_STATUS & (1 << lu32_Channel_Index))
|
|
{
|
|
DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
|
|
|
|
if (NULL != hdma->DMA_ITC_Callback)
|
|
{
|
|
hdma->DMA_ITC_Callback();
|
|
}
|
|
}
|
|
|
|
/* Transfer error interrupt */
|
|
if (DMA->INT_ERR_STATUS & (1 << lu32_Channel_Index))
|
|
{
|
|
DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
|
|
|
|
if (NULL != hdma->DMA_IE_Callback)
|
|
{
|
|
hdma->DMA_IE_Callback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_Init
|
|
* Description : DMA initial with parameters.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
|
|
{
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
if (!IS_DMA_DATA_FLOW(hdma->Init.Data_Flow)) return HAL_ERROR;
|
|
if (!IS_DMA_REQUEST_ID(hdma->Init.Request_ID)) return HAL_ERROR;
|
|
if (!IS_DMA_SRC_WIDTH(hdma->Init.Source_Width)) return HAL_ERROR;
|
|
if (!IS_DMA_DST_WIDTH(hdma->Init.Desination_Width)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Enable DMA Module */
|
|
System_Module_Enable(EN_DMA);
|
|
|
|
/* Enable External Interrupt */
|
|
NVIC_ClearPendingIRQ(DMA_IRQn);
|
|
NVIC_EnableIRQ(DMA_IRQn);
|
|
|
|
/* Default Little-Endian、Enable DMA */
|
|
DMA->CONFIG = DMA_CONFIG_EN;
|
|
|
|
/* Clear Channel Config */
|
|
hdma->Instance->CONFIG = 0x00000000;
|
|
|
|
if (hdma->Init.Data_Flow == DMA_DATA_FLOW_M2P)
|
|
{
|
|
hdma->Init.Request_ID <<= DMA_CHANNEL_CONFIG_DEST_PERIPH_POS;
|
|
}
|
|
else if (hdma->Init.Data_Flow == DMA_DATA_FLOW_P2M)
|
|
{
|
|
hdma->Init.Request_ID <<= DMA_CHANNEL_CONFIG_SRC_PERIPH_POS;
|
|
}
|
|
|
|
hdma->Instance->CONFIG = hdma->Init.Data_Flow | hdma->Init.Request_ID;
|
|
|
|
/* Config Channel Control */
|
|
|
|
hdma->Instance->CTRL = DMA_CHANNEL_CTRL_ITC;
|
|
|
|
/* Source or Desination address increase */
|
|
hdma->Instance->CTRL |= (hdma->Init.Desination_Inc | hdma->Init.Source_Inc);
|
|
/* Source or Desination date width */
|
|
hdma->Instance->CTRL |= (hdma->Init.Desination_Width | hdma->Init.Source_Width);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_DeInit
|
|
* Description : DMA De-initial with parameters.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
|
|
{
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
if (!IS_DMA_DATA_FLOW(hdma->Init.Data_Flow)) return HAL_ERROR;
|
|
if (!IS_DMA_REQUEST_ID(hdma->Init.Request_ID)) return HAL_ERROR;
|
|
if (!IS_DMA_SRC_WIDTH(hdma->Init.Source_Width)) return HAL_ERROR;
|
|
if (!IS_DMA_DST_WIDTH(hdma->Init.Desination_Width)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Reset DMA Module */
|
|
System_Module_Reset(RST_DMA);
|
|
|
|
/* Disable DMA Module */
|
|
System_Module_Disable(EN_DMA);
|
|
|
|
/* Disable Interrupt */
|
|
NVIC_ClearPendingIRQ(DMA_IRQn);
|
|
NVIC_DisableIRQ(DMA_IRQn);
|
|
|
|
hdma->DMA_IE_Callback = NULL;
|
|
hdma->DMA_ITC_Callback = NULL;
|
|
|
|
memset(&hdma->Init, 0, sizeof(hdma->Init));
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_NormalMode_Start
|
|
* Description : DMA transfer start.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_NormalMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
#endif
|
|
|
|
if (fu32_Size > 0xFFF)
|
|
{
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
/* Set source address and desination address */
|
|
hdma->Instance->SRC_ADDR = fu32_SrcAddr;
|
|
hdma->Instance->DEST_ADDR = fu32_DstAddr;
|
|
|
|
/* Set Transfer Size */
|
|
hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
|
|
/* DMA Channel Enable */
|
|
hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_NormalMode_Start_IT
|
|
* Description : DMA transfer start with interrupt.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_NormalMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Set source address and desination address */
|
|
hdma->Instance->SRC_ADDR = fu32_SrcAddr;
|
|
hdma->Instance->DEST_ADDR = fu32_DstAddr;
|
|
|
|
/* Set Transfer Size and enable LLI interrupt */
|
|
hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
// hdma->Instance->CTRL &=~(1<<31);
|
|
/* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
|
|
hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_CycleMode_Start
|
|
* Description : DMA Cycle transfer start.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_CycleMode_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
uint32_t lu32_Channel_Index;
|
|
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Get DMA Channel number */
|
|
lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
|
|
|
|
/* Set source address and desination address */
|
|
hdma->Instance->SRC_ADDR = fu32_SrcAddr;
|
|
hdma->Instance->DEST_ADDR = fu32_DstAddr;
|
|
|
|
/* Set Next Link */
|
|
hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
|
|
|
|
/* Set Transfer Size */
|
|
hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
|
|
/* The list point to oneself */
|
|
Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
|
|
Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
|
|
Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
|
|
Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
|
|
/* DMA Channel Enable */
|
|
hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_EN;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_CycleMode_Start_IT
|
|
* Description : DMA Cycle transfer start with interrupt.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_CycleMode_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
uint32_t lu32_Channel_Index;
|
|
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Get DMA Channel number */
|
|
lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
|
|
|
|
/* Set source address and desination address */
|
|
hdma->Instance->SRC_ADDR = fu32_SrcAddr;
|
|
hdma->Instance->DEST_ADDR = fu32_DstAddr;
|
|
|
|
/* Set Next Link */
|
|
hdma->Instance->LLI = (uint32_t)&Cycle_Channel[lu32_Channel_Index];
|
|
|
|
/* Set Transfer Size */
|
|
hdma->Instance->CTRL = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
|
|
/* The list point to oneself */
|
|
Cycle_Channel[lu32_Channel_Index].SrcAddr = fu32_SrcAddr;
|
|
Cycle_Channel[lu32_Channel_Index].DstAddr = fu32_DstAddr;
|
|
Cycle_Channel[lu32_Channel_Index].Next = &Cycle_Channel[lu32_Channel_Index];
|
|
Cycle_Channel[lu32_Channel_Index].Control = (hdma->Instance->CTRL & (~0xFFF)) | fu32_Size;
|
|
|
|
/* DMA Channel Enable and enable transfer error interrupt and transfer complete interrupt*/
|
|
hdma->Instance->CONFIG |= DMA_CHANNEL_CONFIG_ITC | DMA_CHANNEL_CONFIG_IE | DMA_CHANNEL_CONFIG_EN;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_Start
|
|
* Description : DMA transfer start.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
|
|
|
|
if (hdma->Init.Mode == DMA_NORMAL)
|
|
{
|
|
return HAL_DMA_NormalMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
|
|
}
|
|
else
|
|
{
|
|
return HAL_DMA_CycleMode_Start(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_Start_IT
|
|
* Description : DMA transfer start with interrupt.
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Input : fu32_SrcAddr: source address
|
|
* Input : fu32_DstAddr: desination address
|
|
* Input : fu32_Size: transfer size (This parameter can be a 12-bit Size)
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t fu32_SrcAddr, uint32_t fu32_DstAddr, uint32_t fu32_Size)
|
|
{
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_MODE(hdma->Init.Mode)) return HAL_ERROR;
|
|
|
|
if (hdma->Init.Mode == DMA_NORMAL)
|
|
{
|
|
return HAL_DMA_NormalMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
|
|
}
|
|
else
|
|
{
|
|
return HAL_DMA_CycleMode_Start_IT(hdma, fu32_SrcAddr, fu32_DstAddr, fu32_Size);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_Abort
|
|
* Description : Abort the DMA Transfer
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Output :
|
|
* Author : Chris_Kyle Data : 2020
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
|
|
{
|
|
uint32_t lu32_Channel_Index;
|
|
|
|
#if (USE_FULL_ASSERT == 1)
|
|
/* Check DMA Parameter */
|
|
if (!IS_DMA_ALL_INSTANCE(hdma->Instance)) return HAL_ERROR;
|
|
#endif
|
|
|
|
/* Get DMA Channel number */
|
|
lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
|
|
|
|
/* DMA Channel Disable */
|
|
hdma->Instance->CONFIG &= ~(1 << 0);
|
|
|
|
/* Clear TC ERR Falg */
|
|
DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
|
|
DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* Function : HAL_DMA_GetState
|
|
* Description : Returns the DMA state..
|
|
* Input : hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
* the configuration information for DMA module
|
|
* Output :
|
|
* Author : Data : 2021
|
|
**********************************************************************************/
|
|
HAL_StatusTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
|
|
{
|
|
uint32_t lu32_Channel_Index;
|
|
HAL_StatusTypeDef States = HAL_ERROR;
|
|
|
|
/* Get DMA Channel number */
|
|
lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;
|
|
|
|
/* Transfer complete interrupt */
|
|
if (DMA->RAW_INT_TC_STATUS & (1 << lu32_Channel_Index))
|
|
{
|
|
DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);
|
|
|
|
States = HAL_OK;
|
|
}
|
|
|
|
/* Transfer error interrupt */
|
|
if (DMA->RAW_INT_ERR_STATUS & (1 << lu32_Channel_Index))
|
|
{
|
|
DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);
|
|
|
|
States = HAL_ERROR;
|
|
}
|
|
|
|
return States;
|
|
}
|