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

#include "app.h" 

#define    DMA_TRANSFER_BUF_SIZE    ( 12U )
#define    DMA_NODE_NUM			    ( 8 )

__attribute__ ((aligned (4)))	uint8_t g_src_buf[DMA_NODE_NUM][DMA_TRANSFER_BUF_SIZE];
__attribute__ ((aligned (4)))	uint8_t g_dest_buf[DMA_NODE_NUM][DMA_TRANSFER_BUF_SIZE];

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

volatile uint32_t g_transfer_complete;
volatile uint32_t g_transfer_error;

DMA_InitTypeDef DMA_InitStruct = {0};

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t i;
    uint32_t j;
    DMA_LinkInitTypeDef Link_InitStruct = {0};
    
	printfS("SPL DMA Demo: M2M List\r\n");
	printfS("\r\n");
    
	BSP_LED_Init();
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    
	for (i = 0; i < DMA_NODE_NUM; i++)
	{
		for (j = 0; j < DMA_TRANSFER_BUF_SIZE; j++)
		{
			g_src_buf[i][j] = j & 0xffu;
			g_dest_buf[i][j] = 0;
		}
	}
    
	for (i = 0; i < DMA_NODE_NUM; i++)
	{
		if (i == (DMA_NODE_NUM - 1))
            Link_InitStruct.RawInt = DMA_RAWINT_ENABLE;
        else
            Link_InitStruct.RawInt = DMA_RAWINT_DISABLE;
        
        Link_InitStruct.SrcInc = DMA_SRCINC_ENABLE;
        Link_InitStruct.DestInc = DMA_DESTINC_ENABLE;
        Link_InitStruct.SrcWidth = DMA_SRCWIDTH_BYTE;
        Link_InitStruct.DestWidth = DMA_DESTWIDTH_BYTE;
        Link_InitStruct.SrcBurst = DMA_SRCBURST_1;
        Link_InitStruct.DestBurst = DMA_DESTBURST_1;
        Link_InitStruct.SrcAddr = (uint32_t)g_src_buf[i];
        Link_InitStruct.DestAddr = (uint32_t)g_dest_buf[i];
        Link_InitStruct.Size = DMA_TRANSFER_BUF_SIZE;
		Link_InitStruct.Next = 0u;
        
		DMA_LinkConfig(&g_node[i], &Link_InitStruct);
	}
	
	for (i = 0; i < (DMA_NODE_NUM - 1); i++)
	{
        g_node[i].Next = &g_node[i + 1];
	}
    
    __RCC_DMA1_CLK_ENABLE();
    DMA_DeInit(DMA1_Channel0);
    
    DMA_InitStruct.DataFlow    = DMA_DATAFLOW_M2M;
    DMA_InitStruct.ReqID       = DMA1_REQ0_M2M;
    
    DMA_LinkInit(DMA1_Channel0, &DMA_InitStruct, &g_node[0]);
    
    DMA_ClearFlag(DMA1_Channel0, DMA_FLAG_RTC);
    DMA_ITConfig(DMA1_Channel0, DMA_IT_TC | DMA_IT_ERR, ENABLE);
    
    NVIC_ClearPendingIRQ(DMA1_IRQn);
    NVIC_SetPriority(DMA1_IRQn, 0x00);
    NVIC_EnableIRQ(DMA1_IRQn);
    
	printfS("DMA linked list transmission, %u nodes in total, start.\r\n", DMA_NODE_NUM);
    
    g_transfer_complete = 0;
    g_transfer_error = 0;
    
    DMA_Cmd(DMA1_Channel0, ENABLE);
    
    while ((g_transfer_complete == 0) && (g_transfer_error == 0));
    
    if (g_transfer_complete)
    {
        g_transfer_complete = 0;
        printfS("DMA transfer completed.\r\n");
        
        for (i=0; i<DMA_NODE_NUM; i++)
        {
            if (memcmp((void *)g_src_buf[i], (void *)g_dest_buf[i], DMA_TRANSFER_BUF_SIZE) == 0)
            {
                printfS("Node %u data comparison succeeded.\r\n", i);
            }
            else
            {
                printfS("Node %u data comparison failed.\r\n", i);
            }
        }
    }
    if (g_transfer_error)
    {
        g_transfer_error = 0;
        
        printfS("DMA transmission error.\r\n");
    }
    
    while(1)
    {
        BSP_LED_Toggle();
		DelayMs(500);
    };
}

void DMA1CH0_Transfer_Complete(void)
{
    g_transfer_complete = 1;
}

void DMA1CH0_Transfer_Error(void)
{
    g_transfer_error = 1;
}

