//###########################################################################
//
// FILE:   dma_gsram_transfer_cpu01.c
//
// TITLE:  DMA GSRAM Transfer
//
//! \addtogroup cpu01_example_list
//! <h1>DMA GSRAM Transfer (dma_gsram_transfer)</h1>
//!
//!  This example uses one DMA channel to transfer data from a buffer in
//!  RAMGS0 to a buffer in RAMGS1. The example sets the DMA channel
//!  PERINTFRC bit repeatedly until the transfer of 16 bursts (where each
//!  burst is 8 16-bit words) has been completed. When the whole transfer is
//!  complete, it will trigger the DMA interrupt.
//!
//!  \b Watch \b Variables \n
//!  - \b sdata - Data to send
//!  - \b rdata - Received data
//!
//
//###########################################################################
// $TI Release: F2837xD Support Library v210 $
// $Release Date: Tue Nov  1 14:46:15 CDT 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

//
// Included Files
//
#include "F28x_Project.h"

//
// DMA data sections
//
#pragma DATA_SECTION(sdata, "ramgs0");  // map the TX data to memory
#pragma DATA_SECTION(rdata, "ramgs1");  // map the RX data to memory

//
// Defines
//
#define BURST       7       // write 7 to the register for a burst size of 8
#define TRANSFER    15      // [(MEM_BUFFER_SIZE/(BURST + 1)) - 1]

//
// Globals
//
Uint16 sdata[128];   // Send data buffer
Uint16 rdata[128];   // Receive data buffer
volatile Uint16 *DMADest;
volatile Uint16 *DMASource;
volatile Uint16 done;

//
// Function Prototypes
//
__interrupt void local_D_INTCH6_ISR(void);
void dma_init(void);
void error();

//
// Main
//
void main(void)
{
   Uint16 i;

//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
   InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
// InitGpio();  // Skipped for this example

//
// Step 3. Initialize PIE vector table:
// Disable and clear all CPU interrupts
//
   DINT;
   IER = 0x0000;
   IFR = 0x0000;

//
// Initialize PIE control registers to their default state:
// This function is found in the F2837xD_PieCtrl.c file.
//
   InitPieCtrl();

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
   InitPieVectTable();

//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
   EALLOW;  // This is needed to write to EALLOW protected registers
   PieVectTable.DMA_CH6_INT= &local_D_INTCH6_ISR;
   EDIS;    // This is needed to disable write to EALLOW protected registers

//
// Step 4. Initialize the Device Peripherals:
//
   dma_init();  // set up the dma

//
// Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)
//
   EALLOW;
   CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
   EDIS;

//
// Step 5. User specific code, enable interrupts:
// Initialize the data buffers
//
   for(i = 0; i < 128; i++)
   {
       sdata[i] = i;
       rdata[i] = 0;
   }

//
// Enable interrupts required for this example
//
   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
   PieCtrlRegs.PIEIER7.bit.INTx6 = 1;   // Enable PIE Group 7, INT 2 (DMA CH2)
   IER= M_INT7;                         // Enable CPU INT6
   EINT;                                // Enable Global Interrupts

   StartDMACH6();      // Start DMA channel

   done = 0;           // Test is not done yet

   while(!done)        // wait until the DMA transfer is complete
   {
       EALLOW;
       DmaRegs.CH6.CONTROL.bit.PERINTFRC = 1;
       EDIS;

       DELAY_US(1000);
   }

//
// When the DMA transfer is complete the program will stop here
//
   ESTOP0;
}

//
// error - Error Function which will halt the debugger
//
void error(void)
{
   asm("     ESTOP0");  //Test failed!! Stop!
    for (;;);
}

//
// dma_init - DMA setup for both TX and RX channels.
//
void dma_init()
{
    //
    // Refer to dma.c for the descriptions of the following functions.
    //

    //
    //Initialize DMA
    //
    DMAInitialize();

    DMASource = (volatile Uint16 *)sdata;
    DMADest = (volatile Uint16 *)rdata;

    //
    // configure DMA CH6
    //
    DMACH6AddrConfig(DMADest,DMASource);
    DMACH6BurstConfig(BURST,1,1);
    DMACH6TransferConfig(TRANSFER,1,1);
    DMACH6ModeConfig(0,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,
                     SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,
                     CHINT_END,CHINT_ENABLE);
}

//
// local_D_INTCH6_ISR - DMA Channel6 ISR
//
__interrupt void local_D_INTCH6_ISR(void)
{
    Uint16 i;

    EALLOW;  // NEED TO EXECUTE EALLOW INSIDE ISR !!!
    DmaRegs.CH6.CONTROL.bit.HALT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // ACK to receive more interrupts
                                            // from this PIE group
    EDIS;

    for( i = 0; i < 128; i++ )
    {
        //
        // check for data integrity
        //
        if (rdata[i] != i)
        {
            error();
        }
    }

    done = 1; // Test done.
    return;
}

//
// End of file
//
