/**
  ******************************************************************************
  * @file    main.c
  *
  * @brief   Тест базового режима авто-запрос DMA.
  *
  *          Пересылка 32-битных значений из массива в массив по нулевому каналу
  *          по программному запросу.
  *
  *          Компилятор: GCC ARM 4.9.3
  *          Среда: Qt Creator 3.4.2
  *
  * @author  НИИЭТ
  *             - Богдан Колбов (bkolbov), kolbov@niiet.ru
  * @date    18.11.2015
  *
  ******************************************************************************
  * @attention
  *
  * ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО
  * ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ
  * ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ
  * НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ
  * ПРЕДНАЗНАЧЕНО ДЛЯ ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЕЙ И НАПРАВЛЕНО ТОЛЬКО НА
  * ПРЕДОСТАВЛЕНИЕ ДОПОЛНИТЕЛЬНОЙ ИНФОРМАЦИИ О ПРОДУКТЕ, С ЦЕЛЬЮ СОХРАНИТЬ ВРЕМЯ
  * ПОТРЕБИТЕЛЮ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
  * ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА ПРЯМОЙ ИЛИ КОСВЕННЫЙ УЩЕРБ, ИЛИ
  * ПО ИНЫМ ТРЕБОВАНИЯМ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
  * ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
  *
  * <h2><center>&copy; 2015 ОАО "НИИЭТ"</center></h2>
  ******************************************************************************
  */

#include "niietcm4.h"
#include "retarget.h"

#define TRANSFERS_TOTAL    8

DMA_ConfigData_TypeDef DMA_CONFIGDATA __attribute__ ((aligned (1024)));

uint32_t array_src[TRANSFERS_TOTAL];
uint32_t array_dst[TRANSFERS_TOTAL];

volatile uint32_t irq_status = 0;

void SystemInit()
{
    /* DMA инициализация */
    /* Базовый указатель */
    DMA_BasePtrConfig((uint32_t)(&DMA_CONFIGDATA));
    /* Инициализация канала */
    DMA_ChannelInit_TypeDef DMA_ChannelInitStruct;
    DMA_ChannelStructInit(&DMA_ChannelInitStruct);
    DMA_ChannelInitStruct.DMA_SrcDataSize = DMA_DataSize_32;
    DMA_ChannelInitStruct.DMA_SrcDataInc = DMA_DataInc_32;
    DMA_ChannelInitStruct.DMA_DstDataSize = DMA_DataSize_32;
    DMA_ChannelInitStruct.DMA_DstDataInc = DMA_DataInc_32;
    DMA_ChannelInitStruct.DMA_ArbitrationRate = DMA_ArbitrationRate_8;
    DMA_ChannelInitStruct.DMA_TransfersTotal = TRANSFERS_TOTAL;
    DMA_ChannelInitStruct.DMA_Mode = DMA_Mode_Basic;
    DMA_ChannelInitStruct.DMA_SrcDataEndPtr = &(array_src[TRANSFERS_TOTAL-1]);
    DMA_ChannelInitStruct.DMA_DstDataEndPtr = &(array_dst[TRANSFERS_TOTAL-1]);
    DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[0], &DMA_ChannelInitStruct);

    /* Инициализация контроллера */
    DMA_Init_TypeDef DMA_InitStruct;
    DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.DMA_Channel = DMA_Channel_0;
    DMA_InitStruct.DMA_ChannelEnable = ENABLE;
    DMA_Init(&DMA_InitStruct);
    DMA_MasterEnableCmd(ENABLE);

    /* инициализация printf */
    retarget_init();

    /* NVIC init */
    NVIC_EnableIRQ(DMA_Stream0_IRQn);

    __enable_irq();
}

int main()
{
    /* инициализация массивов */
    for (uint32_t elem = 0; elem < TRANSFERS_TOTAL; elem++)
    {
        array_src[elem] = 0xDEADBEEF;
        array_dst[elem] = 0xCAFEBABE;
    }

    /* начинаем пересылку */
    DMA_SWRequestCmd(DMA_Channel_0);

    /* ждем пока dma выполняет запросы */
    while (irq_status != DMA_Channel_0);

    /* проверяем результаты */
    uint32_t check_error = 0;
    for (uint32_t elem = 0; elem < TRANSFERS_TOTAL; elem++)
    {
        if (array_src[elem] != array_dst[elem])
        {
            check_error = 1;
            break;
        }
    }

    if (check_error)
    {
        printf("Check results error.\n");
    }
    else
    {
        printf("All transfers done and checked. Success!\n");
    }

    while(1);
}

void DMA_Stream0_IRQHandler()
{
    irq_status |= DMA_Channel_0;
}
