
/******************************************************************************
*@file  : app.c
*@brief : application
******************************************************************************/

#include "app.h"   


#define    DMA_TRANSFER_BUF_SIZE    ( 40 )
#define    DMA_NODE_NUM			    ( 8 )

__attribute__ ((aligned (4))) uint8_t g_srcBuf[DMA_NODE_NUM][DMA_TRANSFER_BUF_SIZE];
__attribute__ ((aligned (4))) uint8_t g_destBuf[DMA_NODE_NUM][DMA_TRANSFER_BUF_SIZE];

__attribute__ ((aligned (4))) DMA_LinkTypeDef g_node[DMA_NODE_NUM];

volatile uint32_t g_TransferComplete = 0;

DMA_HandleTypeDef DMA1_Ch1Handle;

void DMATransferComplete(DMA_HandleTypeDef *hmda1);

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t i;
    uint32_t j;
    uint32_t Error;
    DMA_LinkInitTypeDef DMA_LinkInit;
    
	BSP_LED_Init();
	
	BSP_LED_On();
    HAL_Delay(500);
    
	__HAL_RCC_DMA1_CLK_ENABLE();
	
	DMA1_Ch1Handle.Instance          = DMA1_Channel0;
	DMA1_Ch1Handle.Init.Mode         = DMA_MODE_NORMAL;
	DMA1_Ch1Handle.Init.DataFlow     = DMA_DATAFLOW_M2M;
	DMA1_Ch1Handle.Init.ReqID        = DMA1_REG_M2M;
	DMA1_Ch1Handle.Init.SrcInc       = DMA_SRCINC_ENABLE;
	DMA1_Ch1Handle.Init.DestInc      = DMA_DESTINC_ENABLE;
	DMA1_Ch1Handle.Init.SrcWidth     = DMA_SRCWIDTH_BYTE;
	DMA1_Ch1Handle.Init.DestWidth    = DMA_DESTWIDTH_BYTE;
	DMA1_Ch1Handle.Init.SrcBurst     = DMA_SRCBURST_4;
	DMA1_Ch1Handle.Init.DestBurst    = DMA_DESTBURST_4;
	
	HAL_DMA_Init(&DMA1_Ch1Handle);
	
	/* 初始化 源buf、目标buf */
	for (i = 0; i < DMA_NODE_NUM; i++)
	{
		for (j = 0; j < DMA_TRANSFER_BUF_SIZE; j++)
		{
			g_srcBuf[i][j] = j & 0xffu;
		}
	}
	
	memset((void *)g_destBuf, 0, sizeof(g_destBuf));
	
	/* 初始化 发送链表；注：初始化链表前，需先初始化DMA */
	
	for (i = 0; i < DMA_NODE_NUM; i++)
	{
		if (i == (DMA_NODE_NUM - 1))
            DMA_LinkInit.RawInt = DMA_RAWINT_ENABLE;
        else
            DMA_LinkInit.RawInt = DMA_RAWINT_DISABLE;
        DMA_LinkInit.SrcInc = DMA_SRCINC_ENABLE;
        DMA_LinkInit.DestInc = DMA_DESTINC_ENABLE;
        DMA_LinkInit.SrcWidth = DMA_SRCWIDTH_BYTE;
        DMA_LinkInit.DestWidth = DMA_DESTWIDTH_BYTE;
        DMA_LinkInit.SrcBurst = DMA_SRCBURST_4;
        DMA_LinkInit.DestBurst = DMA_DESTBURST_4;
        DMA_LinkInit.SrcAddr = (uint32_t)g_srcBuf[i];
        DMA_LinkInit.DestAddr = (uint32_t)g_destBuf[i];
        DMA_LinkInit.Size = DMA_TRANSFER_BUF_SIZE;
		DMA_LinkInit.Next = 0u;
		HAL_DMA_InitLink(&g_node[i], &DMA_LinkInit);
	}
	
	for (i = 0; i < (DMA_NODE_NUM - 1); i++)
	{
		HAL_DMA_SetLinkNext(&g_node[i], &g_node[i + 1]);
	}
	
    HAL_DMA_RegisterCallback(&DMA1_Ch1Handle, DMA_XFER_CPLT_CB_ID, DMATransferComplete);
    
	/* 设置中断  */
	__HAL_DMA_CLEAR_HFTC_IT_FLAG(&DMA1_Ch1Handle);
	__HAL_DMA_CLEAR_TC_IT_FLAG(&DMA1_Ch1Handle);
	__HAL_DMA_CLEAR_ERR_IT_FLAG(&DMA1_Ch1Handle);
	
	__HAL_DMA_ENABLE_TC_IT(&DMA1_Ch1Handle);
	
	NVIC_ClearPendingIRQ(DMA1_IRQn);
	NVIC_SetPriority(DMA1_IRQn, 0);
	NVIC_EnableIRQ(DMA1_IRQn);
	
    g_TransferComplete = 0;
    
    /* DMA 链表传输  */
	HAL_DMA_Start_Link(&DMA1_Ch1Handle, &g_node[0]);
	
	while (g_TransferComplete == 0u)
    {
    };
	
	Error = 0;
	for (i = 0; i < DMA_NODE_NUM; i++)
	{
        if (memcmp((void *)&g_srcBuf[i][0], (void *)&g_destBuf[i][0], DMA_TRANSFER_BUF_SIZE) != 0)
        {
            Error = 1;
        }
	}
	
	if (Error == 0)
	{
		printfS("test result: successful!\r\n");
	}
	else
	{
		printfS("test result: failed!\r\n");
	}
	
    while(1)
    {
		if (Error == 0)
		{
			BSP_LED_Toggle();
		}
		else
		{
			BSP_LED_Off();
		}
		HAL_Delay(500);
    };
}

void DMATransferComplete(DMA_HandleTypeDef *hdma1)
{
    UNUSED(hdma1);
    
    g_TransferComplete = 1;
}
