示例#1
0
文件: memmem.c 项目: havardh/bitless
void setupDMAInput( void ) 
{
  cbADC.cbFunc = adcCb;
  cbADC.userPtr = NULL;

  DMA_CfgChannel_TypeDef chnlCfg;
  chnlCfg.highPri = true;
  chnlCfg.enableInt = true;
  chnlCfg.select = DMAREQ_ADC0_SCAN;
  chnlCfg.cb = &cbADC;
  DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg);

  DMA_CfgDescr_TypeDef descrCfg;
  descrCfg.dstInc = dmaDataInc2;
  descrCfg.srcInc = dmaDataIncNone;
  descrCfg.size   = dmaDataSize2;
  descrCfg.hprot  = 0;
  DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg);
  DMA_CfgDescr(DMA_CHANNEL_ADC, false, &descrCfg);

  DMA_ActivatePingPong(DMA_CHANNEL_ADC,
                       false,
                       sourceP,
                       (void*)((uint32_t) &(ADC0->SCANDATA)),
                       N - 1,
                       sourceS,
                       (void*)((uint32_t) &(ADC0->SCANDATA)),
                       N - 1);

  bufferPrimary = true;
	
}
/***************************************************************************//**
* @brief
*   Configure ADC and DMA for this application.
*******************************************************************************/
static void guitarADCConfig(void)
{
  DMA_CfgDescr_TypeDef   descrCfg;
  DMA_CfgChannel_TypeDef chnlCfg;
  ADC_Init_TypeDef       init     = ADC_INIT_DEFAULT;
  ADC_InitScan_TypeDef   scanInit = ADC_INITSCAN_DEFAULT;

  /* Configure DMA usage by ADC */

  cbInData.cbFunc  = guitarDMAInCb;
  cbInData.userPtr = NULL;

  /* Set up high pri channel with callback with request from ADC scan complete. */ 
  chnlCfg.highPri   = true; 
  chnlCfg.enableInt = true;
  chnlCfg.select    = DMAREQ_ADC0_SCAN;
  chnlCfg.cb        = &cbInData;
  DMA_CfgChannel(GUITAR_DMA_AUDIO_IN, &chnlCfg);

  /* Configure datasize, increment and primary, alternate structure for pingpong. */
  descrCfg.dstInc  = dmaDataInc2;
  descrCfg.srcInc  = dmaDataIncNone;
  descrCfg.size    = dmaDataSize2;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr(GUITAR_DMA_AUDIO_IN, true, &descrCfg);
  DMA_CfgDescr(GUITAR_DMA_AUDIO_IN, false, &descrCfg);

  DMA_ActivatePingPong(GUITAR_DMA_AUDIO_IN,
                       false,
                       guitarAudioInBuffer1,
                       (void *)((uint32_t) &(ADC0->SCANDATA)),
                       (GUITAR_AUDIO_BUFFER_SAMPLES * 2) - 1,
                       guitarAudioInBuffer2,
                       (void *)((uint32_t) &(ADC0->SCANDATA)),
                       (GUITAR_AUDIO_BUFFER_SAMPLES * 2) - 1);

  /* Configure ADC */

  /* Keep warm due to "high" frequency sampling */
  init.warmUpMode = adcWarmupKeepADCWarm;
  /* Init common issues for both single conversion and scan mode */
  /* 0 means, figure out the base frequency based on current cmu config. */
  init.timebase = ADC_TimebaseCalc(0); 
  /* Calculate necessary prescaler to get 4MHz adc clock with current cmu configuration. */
  init.prescale = ADC_PrescaleCalc(4000000, 0); 
  /* Sample potentiometer by tailgating in order to not disturb fixed rate */
  /* audio sampling. */
  init.tailgate = true;
  ADC_Init(ADC0, &init);

  /* Init for scan sequence use (audio in right/left channels). */
  scanInit.prsSel    = adcPRSSELCh0;
  scanInit.prsEnable = true;
  scanInit.reference = adcRefVDD;
  scanInit.input     = ADC_SCANCTRL_INPUTMASK_CH6 | ADC_SCANCTRL_INPUTMASK_CH7;
  ADC_InitScan(ADC0, &scanInit);
}
示例#3
0
文件: memmem.c 项目: havardh/bitless
static void ADCConfig(void)
{
  DMA_CfgDescr_TypeDef   descrCfg;
  DMA_CfgChannel_TypeDef chnlCfg;
  ADC_Init_TypeDef       init     = ADC_INIT_DEFAULT;
  ADC_InitScan_TypeDef   scanInit = ADC_INITSCAN_DEFAULT;

  /* Configure DMA usage by ADC */

  cbInData.cbFunc  = adcCb;
  cbInData.userPtr = NULL;

  chnlCfg.highPri   = true;
  chnlCfg.enableInt = true;
  chnlCfg.select    = DMAREQ_ADC0_SCAN;
  chnlCfg.cb        = &cbInData;
  DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg);

  descrCfg.dstInc  = dmaDataInc2;
  descrCfg.srcInc  = dmaDataIncNone;
  descrCfg.size    = dmaDataSize2;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg);
  DMA_CfgDescr(DMA_CHANNEL_ADC, false, &descrCfg);

  DMA_ActivatePingPong(DMA_CHANNEL_ADC,
                       false,
                       sourceP,
                       (void *)((uint32_t) &(ADC0->SCANDATA)),
                       N - 1,
                       sourceS,
                       (void *)((uint32_t) &(ADC0->SCANDATA)),
                       N - 1);

  /* Indicate starting with primary in-buffer (according to above DMA setup) */
  bufferPrimary = true;

  /* Configure ADC */

  /* Keep warm due to "high" frequency sampling */
  init.warmUpMode = adcWarmupKeepADCWarm;
  /* Init common issues for both single conversion and scan mode */
  init.timebase = ADC_TimebaseCalc(0);
  init.prescale = ADC_PrescaleCalc(4000000, 0);
  /* Sample potentiometer by tailgating in order to not disturb fixed rate */
  /* audio sampling. */
  init.tailgate = true;
  ADC_Init(ADC0, &init);

  /* Init for scan sequence use (audio in right/left channels). */
  scanInit.prsSel    = adcPRSSELCh0;
  scanInit.prsEnable = true;
  scanInit.reference = adcRefVDD;
  scanInit.input     = ADC_SCANCTRL_INPUTMASK_CH6 | ADC_SCANCTRL_INPUTMASK_CH7;
  ADC_InitScan(ADC0, &scanInit);
}
示例#4
0
文件: memmem.c 项目: havardh/bitless
static void DACConfig(void)
{
  DMA_CfgDescr_TypeDef    descrCfg;
  DMA_CfgChannel_TypeDef  chnlCfg;
  DAC_Init_TypeDef        dacInit   = DAC_INIT_DEFAULT;
  DAC_InitChannel_TypeDef dacChInit = DAC_INITCHANNEL_DEFAULT;

  /* Notice: Audio out buffers are by default filled with 0, since */
  /* uninitialized data; no need to clear explicitly. */

  /* Configure DAC */

  /* Init common DAC issues */
  dacInit.reference = dacRefVDD;
  DAC_Init(DAC0, &dacInit);

  /* Start with "no" signal out */
  DAC0->COMBDATA = 0x0;

  /* Init channels, equal config for both channels. */
  dacChInit.enable    = true;
  dacChInit.prsSel    = dacPRSSELCh0;
  dacChInit.prsEnable = true;
  DAC_InitChannel(DAC0, &dacChInit, 0); /* Right channel */
  DAC_InitChannel(DAC0, &dacChInit, 1); /* Left channel */

  /* Configure DMA usage by DAC */

  cbOutData.cbFunc  = dacCb;
  cbOutData.userPtr = NULL;

  chnlCfg.highPri   = true;
  chnlCfg.enableInt = true;
  chnlCfg.select    = DMAREQ_DAC0_CH0;
  chnlCfg.cb        = &cbOutData;
  DMA_CfgChannel(DMA_CHANNEL_DAC, &chnlCfg);

  descrCfg.dstInc  = dmaDataIncNone;
  descrCfg.srcInc  = dmaDataInc4;
  descrCfg.size    = dmaDataSize4;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_DAC, true, &descrCfg);
  DMA_CfgDescr(DMA_CHANNEL_DAC, false, &descrCfg);

  DMA_ActivatePingPong(DMA_CHANNEL_DAC,
                       false,
                       (void *)((uint32_t) &(DAC0->COMBDATA)),
                       sourceP,
                       N - 1,
                       (void *)((uint32_t) &(DAC0->COMBDATA)),
                       sourceS,
                       N - 1);
}
/**************************************************************************//**
 * @brief Configure DMA in basic mode for both TX and RX to/from USART
 *****************************************************************************/
void setupDma(void)
{
  /* Initialization structs */
  DMA_Init_TypeDef        dmaInit;
  DMA_CfgChannel_TypeDef  rxChnlCfg;
  DMA_CfgDescr_TypeDef    rxDescrCfg;
  DMA_CfgChannel_TypeDef  txChnlCfg;
  DMA_CfgDescr_TypeDef    txDescrCfg;
  
  /* Initializing the DMA */
  dmaInit.hprot        = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
  
  /* Setup call-back function */  
  dmaCallbackSpi.cbFunc  = transferComplete;
  dmaCallbackSpi.userPtr = NULL;
  
  /*** Setting up RX DMA ***/

  /* Setting up channel */
  rxChnlCfg.highPri   = false;
  rxChnlCfg.enableInt = true;
  rxChnlCfg.select    = DMAREQ_USART1_RXDATAV;
  rxChnlCfg.cb        = &dmaCallbackSpi;
  DMA_CfgChannel(DMA_CHANNEL_RX, &rxChnlCfg);

  /* Setting up channel descriptor */
  rxDescrCfg.dstInc  = dmaDataInc1;
  rxDescrCfg.srcInc  = dmaDataIncNone;
  rxDescrCfg.size    = dmaDataSize1;
  rxDescrCfg.arbRate = dmaArbitrate1;
  rxDescrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_RX, true, &rxDescrCfg);
  
  /*** Setting up TX DMA ***/

  /* Setting up channel */
  txChnlCfg.highPri   = false;
  txChnlCfg.enableInt = true;
  txChnlCfg.select    = DMAREQ_USART1_TXBL;
  txChnlCfg.cb        = &dmaCallbackSpi;
  DMA_CfgChannel(DMA_CHANNEL_TX, &txChnlCfg);

  /* Setting up channel descriptor */
  txDescrCfg.dstInc  = dmaDataIncNone;
  txDescrCfg.srcInc  = dmaDataInc1;
  txDescrCfg.size    = dmaDataSize1;
  txDescrCfg.arbRate = dmaArbitrate1;
  txDescrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_TX, true, &txDescrCfg);
}
示例#6
0
/*****************************************************************************
 * @brief Configure DMA to send and receive over I2C
 *****************************************************************************/
void dmaInit(void)
{
  CMU_ClockEnable(cmuClock_DMA, true);  
  
  DMA_Init_TypeDef        dmaInit;
  DMA_CfgChannel_TypeDef  txChannelConfig;
  DMA_CfgDescr_TypeDef    txDescriptorConfig;
  DMA_CfgChannel_TypeDef  rxChannelConfig;
  DMA_CfgDescr_TypeDef    rxDescriptorConfig;
  
  /* Initializing the DMA */
  dmaInit.hprot        = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
  
  /* Setup call-back function */  
  dmaCallback.cbFunc  = transferComplete;
  dmaCallback.userPtr = NULL;

  /* Setting up TX channel */
  txChannelConfig.highPri   = false;
  txChannelConfig.enableInt = true;
  txChannelConfig.select    = DMAREQ_I2C0_TXBL;
  txChannelConfig.cb        = &dmaCallback;
  DMA_CfgChannel(DMA_CHANNEL_I2C_TX, &txChannelConfig);

  /* Setting up TX channel descriptor */
  txDescriptorConfig.dstInc  = dmaDataIncNone;
  txDescriptorConfig.srcInc  = dmaDataInc1;
  txDescriptorConfig.size    = dmaDataSize1;
  txDescriptorConfig.arbRate = dmaArbitrate1;
  txDescriptorConfig.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_I2C_TX, true, &txDescriptorConfig);
  
  /* Setting up RX channel */
  rxChannelConfig.highPri   = false;
  rxChannelConfig.enableInt = true;
  rxChannelConfig.select    = DMAREQ_I2C0_RXDATAV;
  rxChannelConfig.cb        = &dmaCallback;
  DMA_CfgChannel(DMA_CHANNEL_I2C_RX, &rxChannelConfig);

  /* Setting up RX channel descriptor */
  rxDescriptorConfig.dstInc  = dmaDataInc1;
  rxDescriptorConfig.srcInc  = dmaDataIncNone;
  rxDescriptorConfig.size    = dmaDataSize1;
  rxDescriptorConfig.arbRate = dmaArbitrate1;
  rxDescriptorConfig.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_I2C_RX, true, &rxDescriptorConfig);
}
示例#7
0
文件: accel.c 项目: havardh/bitless
/***************************************************************************//**
 * @brief
 *   Configure DMA usage for this application.
 *******************************************************************************/
static void accelDMAConfig(void)
{
  DMA_Init_TypeDef dmaInit;
  DMA_CfgDescr_TypeDef descrCfg;
  DMA_CfgChannel_TypeDef chnlCfg;

  /* Configure general DMA issues */
  dmaInit.hprot = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);

  /* Configure DMA channel used */
  chnlCfg.highPri = false;
  chnlCfg.enableInt = false;
  chnlCfg.select = DMAREQ_ADC0_SCAN;
  chnlCfg.cb = NULL;
  DMA_CfgChannel(ACCEL_DMA_CHANNEL, &chnlCfg);

  descrCfg.dstInc = dmaDataInc4;
  descrCfg.srcInc = dmaDataIncNone;
  descrCfg.size = dmaDataSize4;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot = 0;
  DMA_CfgDescr(ACCEL_DMA_CHANNEL, true, &descrCfg);
}
示例#8
0
extern void DMA_enter_DefaultMode_from_RESET(void) {
	DMA_Init_TypeDef       dmaInit;
	DMA_CfgDescr_TypeDef   descrCfg;
	DMA_CfgChannel_TypeDef chnlCfg;

	/* DMA控制器配置 */
	dmaInit.hprot        = 0;
	dmaInit.controlBlock = dmaControlBlock;
	DMA_Init(&dmaInit);

	/* DMA通道配置 */
	chnlCfg.highPri   = false;
	chnlCfg.enableInt = false;
	chnlCfg.select    = DMAREQ_ADC0_SCAN;
	chnlCfg.cb        = NULL;
	DMA_CfgChannel(DMA_CHANNEL, &chnlCfg);

	/* DMA通道描述符配置 */
	descrCfg.dstInc  = dmaDataInc4;
	descrCfg.srcInc  = dmaDataIncNone;
	descrCfg.size    = dmaDataSize4;
	descrCfg.arbRate = dmaArbitrate1;
	descrCfg.hprot   = 0;
	DMA_CfgDescr(DMA_CHANNEL, true, &descrCfg);
}
示例#9
0
void usart2_dma_init(void)
{
  /* Initialization structs */
  DMA_CfgChannel_TypeDef  rxChnlCfg;
  DMA_CfgDescr_TypeDef    rxDescrCfg;
  DMA_CfgChannel_TypeDef  txChnlCfg;
  DMA_CfgDescr_TypeDef    txDescrCfg;

  /* Setup call-back function */
  cb.cbFunc  = &transferComplete;
  cb.userPtr = NULL;

  /*** Setting up RX DMA ***/

  /* Setting up channel */
  rxChnlCfg.highPri   = false;
  rxChnlCfg.enableInt = true;
  rxChnlCfg.select    = DMAREQ_USART2_RXDATAV;
  rxChnlCfg.cb        = &cb;
  DMA_CfgChannel(DMA_CHANNEL_RX, &rxChnlCfg);

  /* Setting up channel descriptor */
  rxDescrCfg.dstInc  = dmaDataInc1;
  rxDescrCfg.srcInc  = dmaDataIncNone;
  rxDescrCfg.size    = dmaDataSize1;
  rxDescrCfg.arbRate = dmaArbitrate1;
  rxDescrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_RX, true, &rxDescrCfg);

  /*** Setting up TX DMA ***/

  /* Setting up channel */
  txChnlCfg.highPri   = false;
  txChnlCfg.enableInt = true;
  txChnlCfg.select    = DMAREQ_USART2_TXBL;
  txChnlCfg.cb        = &cb;
  DMA_CfgChannel(DMA_CHANNEL_TX, &txChnlCfg);

  /* Setting up channel descriptor */
  txDescrCfg.dstInc  = dmaDataIncNone;
  txDescrCfg.srcInc  = dmaDataIncNone;
  txDescrCfg.size    = dmaDataSize1;
  txDescrCfg.arbRate = dmaArbitrate1;
  txDescrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_TX, true, &txDescrCfg);
}
示例#10
0
/**  
  * Configure DMA to send part of, or the entire frame buffer over SPI
  * to the memory LCD. Rectangle copy is used because it can transfer
  * the entire frame in one DMA cycle. 
  * (In addition, the extra padding bits needed because emWin v5.16 does 
  * not handle a 144 px width correctly are skipped by rectangle copy
  * by setting the width to 144 px and stride to 160 px.) 
  */
void configRectangleCopy(USART_TypeDef *usart)
{
  DMA_CfgChannel_TypeDef   channelConfig;
  DMA_CfgDescr_TypeDef     descriptorConfig;

  /* Setting callback function */  
  dmaCallback.cbFunc = transferComplete;
  dmaCallback.userPtr = NULL;

  /* Setting up channel */
  channelConfig.highPri   = false;                /* No high priority */
  channelConfig.enableInt = true;                 /* Enable interrupt */
  
  /* Select USARTx peripheral */
  if ( usart == USART0 ) {
    channelConfig.select = DMAREQ_USART0_TXBL;   
  } else if ( usart == USART1 ) {
    channelConfig.select = DMAREQ_USART1_TXBL;   
  } else if ( usart == USART2 ) {
    channelConfig.select = DMAREQ_USART2_TXBL; 
  }
  
  channelConfig.cb        = &dmaCallback;         /* Callback routine */
  DMA_CfgChannel(DMA_CHANNEL, &channelConfig);

  /* Configure descriptor */
  descriptorConfig.dstInc   = dmaDataIncNone;     /* Do not increase destination */
  descriptorConfig.srcInc   = dmaDataInc2;        /* Increase source by 2 bytes */
  descriptorConfig.size     = dmaDataSize2;       /* Element size is 2 bytes */
  descriptorConfig.arbRate  = dmaArbitrate1;      /* Arbiratrate after each transfer */
  descriptorConfig.hprot    = 0;                  /* Non-privileged access */
  
  /* Configure the LOOP0 register for 2D copy */
  DMA_CfgLoop_TypeDef loopConfig;
  loopConfig.enable = false;
  loopConfig.nMinus1 = FRAME_BUFFER_WIDTH/16-1;  /* Number of elements (-1) to transfer */
  DMA_CfgLoop(DMA_CHANNEL, &loopConfig);
  
  /* Configure the RECT0 register for 2D copy */
  DMA_CfgRect_TypeDef rectConfig;
  rectConfig.dstStride = 0;
  rectConfig.srcStride = FRAME_BUFFER_STRIDE / 8; /* Width of the total frame buffer, in bytes */
  rectConfig.height = 128;
  DMA_CfgRect(DMA_CHANNEL, &rectConfig);
  
  /* Create the descriptor */
  DMA_CfgDescr(DMA_CHANNEL, true, &descriptorConfig); 
}
示例#11
0
/**************************************************************************//**
 * @brief Flash transfer function
 * This function sets up the DMA transfer
 *****************************************************************************/
void performFlashTransfer(void)
{
  /* Setting call-back function */
  DMA_CB_TypeDef cb[DMA_CHAN_COUNT];
  cb[DMA_CHANNEL_FLASH].cbFunc = flashTransferComplete;

  /* usrPtr can be used to send data to the callback function,
   * but this is not used here, which is indicated by the NULL pointer */
  cb[DMA_CHANNEL_FLASH].userPtr = NULL;

  /* Setting up channel */
  DMA_CfgChannel_TypeDef chnlCfg;
  chnlCfg.highPri   = false;
  chnlCfg.enableInt = true;
  chnlCfg.select    = 0;
  chnlCfg.cb        = &(cb[DMA_CHANNEL_FLASH]);
  DMA_CfgChannel(DMA_CHANNEL_FLASH, &chnlCfg);

  /* Setting up channel descriptor */
  DMA_CfgDescr_TypeDef descrCfg;
  descrCfg.dstInc  = dmaDataInc1;
  descrCfg.srcInc  = dmaDataInc1;
  descrCfg.size    = dmaDataSize1;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_FLASH, true, &descrCfg);

  /* Setting flag to indicate that transfer is in progress
   * will be cleared by call-back function */
  flashTransferActive = true;

  DMA_ActivateBasic(DMA_CHANNEL_FLASH,
                    true,
                    false,
                    (void *) &ramBuffer,
                    (void *) &flashData,
                    FLASHDATA_SIZE - 1);

  /* Entering EM1 to wait for completion (the DMA requires EM1) */
  while (flashTransferActive)
  {
    EMU_EnterEM1();
  }
}
示例#12
0
/**************************************************************************//**
 * @brief Configure DMA for ADC RAM Transfer
 *****************************************************************************/
void setupDma(void)
{
  DMA_Init_TypeDef        dmaInit;
  DMA_CfgChannel_TypeDef  chnlCfg;
  DMA_CfgDescr_TypeDef    descrCfg;
  
  /* Initializing the DMA */
  dmaInit.hprot        = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
    
  /* Setting up call-back function */  
  cb.cbFunc  = transferComplete;
  cb.userPtr = NULL;

  /* Setting up channel */
  chnlCfg.highPri   = false;
  chnlCfg.enableInt = true;
  chnlCfg.select    = DMAREQ_ADC0_SINGLE;
  chnlCfg.cb        = &cb;
  DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg);

  /* Setting up channel descriptor */
  descrCfg.dstInc  = dmaDataInc2;
  descrCfg.srcInc  = dmaDataIncNone;
  descrCfg.size    = dmaDataSize2;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg);
    
  /* Setting flag to indicate that transfer is in progress
   * will be cleared by call-back function. */
  transferActive = true;
  
  /* Starting transfer. Using Basic since every transfer must be initiated
   * by the ADC. */
  DMA_ActivateBasic(DMA_CHANNEL_ADC,
                    true,
                    false,
                    (void *)ramBufferAdcData,
                    (void *)&(ADC0->SINGLEDATA),
                    ADCSAMPLES - 1);
}
示例#13
0
/***************************************************************************//**
* @brief
*   Initialize the specified USART unit
*
* @details
*
* @note
*
* @param[in] device
*   Pointer to device descriptor
*
* @param[in] unitNumber
*   Unit number
*
* @param[in] location
*   Pin location number
*
* @param[in] flag
*   Configuration flag
*
* @param[in] dmaChannel
*   DMA channel number for TX
*
* @param[in] console
*   Indicate if using as console
*
* @return
*   Pointer to USART device
******************************************************************************/
static struct efm32_usart_device_t *rt_hw_usart_unit_init(
    rt_device_t device,
    rt_uint8_t  unitNumber,
    rt_uint8_t  location,
    rt_uint32_t flag,
    rt_uint32_t dmaChannel,
    rt_uint8_t  config)
{
    struct efm32_usart_device_t     *usart;
    struct efm32_usart_dma_mode_t   *dma_mode;
    DMA_CB_TypeDef                  *callback;
    CMU_Clock_TypeDef               usartClock;
    rt_uint32_t                     txDmaSelect;
    GPIO_Port_TypeDef               port_tx, port_rx, port_clk, port_cs;
    rt_uint32_t                     pin_tx, pin_rx, pin_clk, pin_cs;
    efm32_irq_hook_init_t           hook;

    do
    {
        /* Allocate device */
        usart = rt_malloc(sizeof(struct efm32_usart_device_t));
        if (usart == RT_NULL)
        {
            usart_debug("USART%d err: no mem\n", usart->unit);
            break;
        }
        usart->counter  = 0;
        usart->unit     = unitNumber;
        usart->state    = config;
        usart->tx_mode  = RT_NULL;
        usart->rx_mode  = RT_NULL;

        /* Allocate TX */
        dma_mode = RT_NULL;
        if (flag & RT_DEVICE_FLAG_DMA_TX)
        {
            usart->tx_mode = dma_mode = rt_malloc(sizeof(struct efm32_usart_dma_mode_t));
            if (dma_mode == RT_NULL)
            {
                usart_debug("USART%d err: no mem for DMA TX\n", usart->unit);
                break;
            }
            dma_mode->dma_channel = dmaChannel;
        }

        /* Allocate RX */
        if (flag & RT_DEVICE_FLAG_INT_RX)
        {
            usart->rx_mode = rt_malloc(sizeof(struct efm32_usart_int_mode_t));
            if (usart->rx_mode == RT_NULL)
            {
                usart_debug("USART%d err: no mem for INT RX\n", usart->unit);
                break;
            }
        }

        /* Initialization */
#if defined(UART_PRESENT)
        if ((!(config & USART_STATE_ASYNC_ONLY) && (unitNumber >= USART_COUNT)) || \
                ((config & USART_STATE_ASYNC_ONLY) && (unitNumber >= UART_COUNT)))
#else
        if (unitNumber >= USART_COUNT)
#endif
        {
            break;
        }
        switch (unitNumber)
        {
        case 0:
#if defined(UART_PRESENT)
            if (config & USART_STATE_ASYNC_ONLY)
            {
                usart->usart_device = UART0;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_UART0;
                txDmaSelect         = DMAREQ_UART0_TXBL;
                port_tx             = AF_UART0_TX_PORT(location);
                pin_tx              = AF_UART0_TX_PIN(location);
                port_rx             = AF_UART0_RX_PORT(location);
                pin_rx              = AF_UART0_RX_PIN(location);
            }
            else
#endif
            {
                usart->usart_device = USART0;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_USART0;
                txDmaSelect         = DMAREQ_USART0_TXBL;
                port_tx             = AF_USART0_TX_PORT(location);
                pin_tx              = AF_USART0_TX_PIN(location);
                port_rx             = AF_USART0_RX_PORT(location);
                pin_rx              = AF_USART0_RX_PIN(location);
                port_clk            = AF_USART0_CLK_PORT(location);
                pin_clk             = AF_USART0_CLK_PIN(location);
                port_cs             = AF_USART0_CS_PORT(location);
                pin_cs              = AF_USART0_CS_PIN(location);
            }
            break;
#if ((defined(USART_PRESENT) && (USART_COUNT > 1)) || \
    (defined(UART_PRESENT) && (UART_COUNT > 1)))
        case 1:
#if (defined(UART_PRESENT) && (UART_COUNT > 1))
            if (config & USART_STATE_ASYNC_ONLY)
            {
                usart->usart_device = UART1;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_UART1;
                txDmaSelect         = DMAREQ_UART1_TXBL;
                port_tx             = AF_UART1_TX_PORT(location);
                pin_tx              = AF_UART1_TX_PIN(location);
                port_rx             = AF_UART1_RX_PORT(location);
                pin_rx              = AF_UART1_RX_PIN(location);
            }
            else
#endif
            {
                usart->usart_device = USART1;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_USART1;
                txDmaSelect         = DMAREQ_USART1_TXBL;
                port_tx             = AF_USART1_TX_PORT(location);
                pin_tx              = AF_USART1_TX_PIN(location);
                port_rx             = AF_USART1_RX_PORT(location);
                pin_rx              = AF_USART1_RX_PIN(location);
                port_clk            = AF_USART1_CLK_PORT(location);
                pin_clk             = AF_USART1_CLK_PIN(location);
                port_cs             = AF_USART1_CS_PORT(location);
                pin_cs              = AF_USART1_CS_PIN(location);
            }
            break;
#endif
#if ((defined(USART_PRESENT) && (USART_COUNT > 2)) || \
    (defined(UART_PRESENT) && (UART_COUNT > 2)))
        case 2:
#if (defined(UART_PRESENT) && (UART_COUNT > 2))
            if (config & USART_STATE_ASYNC_ONLY)
            {
                usart->usart_device = UART2;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_UART2;
                txDmaSelect         = DMAREQ_UART2_TXBL;
                port_tx             = AF_UART2_TX_PORT(location);
                pin_tx              = AF_UART2_TX_PIN(location);
                port_rx             = AF_UART2_RX_PORT(location);
                pin_rx              = AF_UART2_RX_PIN(location);
            }
            else
#endif
            {
                usart->usart_device = USART2;
                usartClock          = (CMU_Clock_TypeDef)cmuClock_USART2;
                txDmaSelect         = DMAREQ_USART2_TXBL;
                port_tx             = AF_USART2_TX_PORT(location);
                pin_tx              = AF_USART2_TX_PIN(location);
                port_rx             = AF_USART2_RX_PORT(location);
                pin_rx              = AF_USART2_RX_PIN(location);
                port_clk            = AF_USART2_CLK_PORT(location);
                pin_clk             = AF_USART2_CLK_PIN(location);
                port_cs             = AF_USART2_CS_PORT(location);
                pin_cs              = AF_USART2_CS_PIN(location);
            }
            break;
#endif
        default:
            break;
        }

        /* Enable USART clock */
        CMU_ClockEnable(usartClock, true);

        /* Config GPIO */
        GPIO_PinModeSet(
            port_tx,
            pin_tx,
            gpioModePushPull,
            0);
        GPIO_PinModeSet(
            port_rx,
            pin_rx,
            gpioModeInputPull,
            1);
        if (config & USART_STATE_SYNC)
        {
            GPIO_PinModeSet(
                port_clk,
                pin_clk,
                gpioModePushPull,
                0);
        }
        if (config & USART_STATE_AUTOCS)
        {
            GPIO_PinModeSet(
                port_cs,
                pin_cs,
                gpioModePushPull,
                1);
        }

        /* Config interrupt and NVIC */
        if (flag & RT_DEVICE_FLAG_INT_RX)
        {
            hook.type       = efm32_irq_type_usart;
            hook.unit       = unitNumber * 2 + 1;
#if defined(UART_PRESENT)
            if (config & USART_STATE_ASYNC_ONLY)
            {
                hook.unit += USART_COUNT * 2;
            }
#endif
            hook.cbFunc     = rt_hw_usart_rx_isr;
            hook.userPtr    = device;
            efm32_irq_hook_register(&hook);
        }

        /* Config DMA */
        if (flag & RT_DEVICE_FLAG_DMA_TX)
        {
            DMA_CfgChannel_TypeDef  chnlCfg;
            DMA_CfgDescr_TypeDef    descrCfg;

            hook.type           = efm32_irq_type_dma;
            hook.unit           = dmaChannel;
            hook.cbFunc         = rt_hw_usart_dma_tx_isr;
            hook.userPtr        = device;
            efm32_irq_hook_register(&hook);

            callback = (DMA_CB_TypeDef *)rt_malloc(sizeof(DMA_CB_TypeDef));
            if (callback == RT_NULL)
            {
                usart_debug("USART%d err: no mem for callback\n", usart->unit);
                break;
            }
            callback->cbFunc    = DMA_IRQHandler_All;
            callback->userPtr   = RT_NULL;
            callback->primary   = 0;

            /* Setting up DMA channel */
            chnlCfg.highPri     = false;    /* Can't use with peripherals */
            chnlCfg.enableInt   = true;     /* Interrupt for callback function */
            chnlCfg.select      = txDmaSelect;
            chnlCfg.cb          = callback;
            DMA_CfgChannel(dmaChannel, &chnlCfg);

            /* Setting up DMA channel descriptor */
            descrCfg.dstInc     = dmaDataIncNone;
            descrCfg.srcInc     = dmaDataInc1;
            descrCfg.size       = dmaDataSize1;
            descrCfg.arbRate    = dmaArbitrate1;
            descrCfg.hprot      = 0;
            DMA_CfgDescr(dmaChannel, true, &descrCfg);
        }

        /* Init specified USART unit */
        if (config & USART_STATE_SYNC)
        {
            USART_InitSync_TypeDef init_sync = USART_INITSYNC_DEFAULT;

            init_sync.enable        = usartEnable;
            init_sync.refFreq       = 0;
            init_sync.baudrate      = SPI_BAUDRATE;
            if (config & USART_STATE_9BIT)
            {
                init_sync.databits  = usartDatabits9;
            }
            else
            {
                init_sync.databits  = usartDatabits8;
            }
            if (config & USART_STATE_MASTER)
            {
                init_sync.master    = true;
            }
            else
            {
                init_sync.master    = false;
            }
            init_sync.msbf          = true;

            switch (USART_CLK_MODE_GET(config))
            {
            case 0:
                init_sync.clockMode = usartClockMode0;
                break;
            case 1:
                init_sync.clockMode = usartClockMode1;
                break;
            case 2:
                init_sync.clockMode = usartClockMode2;
                break;
            case 3:
                init_sync.clockMode = usartClockMode3;
                break;
            }
            USART_InitSync(usart->usart_device, &init_sync);
        }
        else
        {
            USART_InitAsync_TypeDef init_async = USART_INITASYNC_DEFAULT;

            init_async.enable       = usartEnable;
            init_async.refFreq      = 0;
            init_async.baudrate     = UART_BAUDRATE;
            init_async.oversampling = USART_CTRL_OVS_X4;
            init_async.databits     = USART_FRAME_DATABITS_EIGHT;
            init_async.parity       = USART_FRAME_PARITY_NONE;
            init_async.stopbits     = USART_FRAME_STOPBITS_ONE;
            USART_InitAsync(usart->usart_device, &init_async);
        }

        /* Enable RX and TX pins and set location */
        usart->usart_device->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | \
                                     (location << _USART_ROUTE_LOCATION_SHIFT);
        if (config & USART_STATE_SYNC)
        {
            usart->usart_device->ROUTE |= USART_ROUTE_CLKPEN;
        }
        if (config & USART_STATE_AUTOCS)
        {
            usart->usart_device->ROUTE |= USART_ROUTE_CSPEN;
            if (config & USART_STATE_MASTER)
            {
                usart->usart_device->CTRL |= USART_CTRL_AUTOCS;
            }
        }

        /* Clear RX/TX buffers */
        usart->usart_device->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;

        return usart;
    } while(0);

    if (usart->rx_mode)
    {
        rt_free(usart->rx_mode);
    }
    if (usart->tx_mode)
    {
        rt_free(usart->tx_mode);
    }
    if (usart)
    {
        rt_free(usart);
    }
    if (callback)
    {
        rt_free(callback);
    }

#if defined(UART_PRESENT)
    if (config & USART_STATE_ASYNC_ONLY)
    {
        usart_debug("UART%d err: init failed!\n", unitNumber);
    }
    else
#endif
    {
        usart_debug("USART%d err: init failed!\n", unitNumber);
    }
    return RT_NULL;
}
/*
 * Function Name: DMA_setup
 * Description: Setup DMA channels for ADC,TX,RX
 */
void DMA_Setup(void)
{

    DMA_CfgChannel_TypeDef  chnlCfg_adc;
    DMA_CfgDescr_TypeDef    descrCfg_adc;
    DMA_CfgChannel_TypeDef  chnlCfg_rx;
    DMA_CfgDescr_TypeDef    descrCfg_rx;
    DMA_CfgChannel_TypeDef  chnlCfg_tx;
    DMA_CfgDescr_TypeDef    descrCfg_tx;

    /* Setting up call-back function */
    cb.cbFunc  = DMA_CallBack;
    cb.userPtr = NULL;

    /* Setting up ADC channel */
    chnlCfg_adc.highPri   = DMA_PRIORITY_ADC;
    chnlCfg_adc.enableInt = true;
    chnlCfg_adc.select    = DMAREQ_ADC0_SINGLE;
    chnlCfg_adc.cb        = &cb;
    DMA_CfgChannel(DMA_CHANNEL_ADC, &chnlCfg_adc);

    /* Setting up ADC channel descriptor */
    descrCfg_adc.dstInc  = dmaDataInc2;
    descrCfg_adc.srcInc  = dmaDataIncNone;
    descrCfg_adc.size    = dmaDataSize2;
    descrCfg_adc.arbRate = DMA_ARBITRATE_ADC;
    descrCfg_adc.hprot   = 0;
    DMA_CfgDescr(DMA_CHANNEL_ADC, true, &descrCfg_adc);

    /* Starting DMA transfer using Basic since every transfer must be initiated by the ADC. */
       DMA_ActivateBasic(DMA_CHANNEL_ADC, true, false, (void *)ADC_Buffer, (void *)&(ADC0->SINGLEDATA), ADC_SAMPLES - 1);

    /* Setting up Rx channel */
    chnlCfg_rx.highPri   = DMA_PRIORITY_RX;
    chnlCfg_rx.enableInt = true;
    chnlCfg_rx.select    = DMAREQ_LEUART0_RXDATAV;
    chnlCfg_rx.cb        = &cb;
    DMA_CfgChannel(DMA_CHANNEL_RX, &chnlCfg_rx);

    /* Setting up Rx channel descriptor */
    descrCfg_rx.dstInc  = dmaDataInc1;
    descrCfg_rx.srcInc  = dmaDataIncNone;
    descrCfg_rx.size    = dmaDataSize1;
    descrCfg_rx.arbRate = DMA_ARBITRATE_RX;
    descrCfg_rx.hprot   = 0;
    DMA_CfgDescr(DMA_CHANNEL_RX, true, &descrCfg_rx);

    /* Setting up Tx channel */
    chnlCfg_tx.highPri   = DMA_PRIORITY_TX;
    chnlCfg_tx.enableInt = true;
    chnlCfg_tx.select    = DMAREQ_LEUART0_TXBL;
    chnlCfg_tx.cb        = &cb;
    DMA_CfgChannel(DMA_CHANNEL_TX, &chnlCfg_tx);

    /* Setting up Tx channel descriptor */
    descrCfg_tx.dstInc  = dmaDataIncNone;
    descrCfg_tx.srcInc  = dmaDataInc1;
    descrCfg_tx.size    = dmaDataSize1;
    descrCfg_tx.arbRate = DMA_ARBITRATE_TX;
    descrCfg_tx.hprot   = 0;
    DMA_CfgDescr(DMA_CHANNEL_TX, true, &descrCfg_tx);

}
示例#15
0
文件: memmem.c 项目: havardh/bitless
void setupDMAOutput( void ) 
{
	cbDAC.cbFunc = dacCb;
  cbDAC.userPtr = NULL;

  DMA_CfgChannel_TypeDef chnlCfg = {
    .highPri = true,
    .enableInt = true,
    .select = DMAREQ_DAC0_CH0,
    .cb = &cbDAC
  };
  DMA_CfgChannel(DMA_CHANNEL_DAC, &chnlCfg);
  
  DMA_CfgDescr_TypeDef descrCfg = {
    .dstInc = dmaDataIncNone,
    .srcInc = dmaDataInc4,
    .size = dmaDataSize4,
    .hprot = 0
  };
  DMA_CfgDescr(DMA_CHANNEL_DAC, true, &descrCfg);
  DMA_CfgDescr(DMA_CHANNEL_DAC, false, &descrCfg);
  
  DMA_ActivatePingPong(DMA_CHANNEL_DAC, false,
                       (void*)((uint32_t) &DAC0->COMBDATA), sourceP, N - 1,
                       (void*)((uint32_t) &DAC0->COMBDATA), sourceS, N - 1);

}

/*
 * Sets up the DMA to copy from src to dst0 and dst1 with the pattern:
 *
 * src:  | 1, 2, 3, 4, ... |
 * dst0: | 1, 3, ...  |
 * dst1: | 2, 4, ...  |
 */
void setupDMASplit(void)
{
	DMA_Init_TypeDef dmaInit;
	dmaInit.hprot = 0;
	dmaInit.controlBlock = dmaControlBlock;
	DMA_Init(&dmaInit);

	DMA_CfgChannel_TypeDef chnlCfgLeft;
	chnlCfgLeft.highPri   = false;
	chnlCfgLeft.enableInt = true;
	chnlCfgLeft.select    = 0;
	chnlCfgLeft.cb        = NULL; //&cbInLeft;
	DMA_CfgChannel(DMA_CHANNEL_IN_LEFT, &chnlCfgLeft);

	DMA_CfgChannel_TypeDef chnlCfgRight;
	chnlCfgRight.highPri   = false;
	chnlCfgRight.enableInt = true;
	chnlCfgRight.select    = 0;
	chnlCfgRight.cb        = NULL; //&cbInRight;
	DMA_CfgChannel(DMA_CHANNEL_IN_RIGHT, &chnlCfgRight);

	DMA_CfgDescr_TypeDef descrCfg;
	descrCfg.dstInc  = dmaDataInc2;
	descrCfg.srcInc  = dmaDataInc4;
	descrCfg.size    = dmaDataSize2;
	descrCfg.arbRate = dmaArbitrate1;
	descrCfg.hprot   = 0;
	DMA_CfgDescr(DMA_CHANNEL_IN_LEFT, true, &descrCfg);
	DMA_CfgDescr(DMA_CHANNEL_IN_RIGHT, false, &descrCfg);

	DMA_ActivateAuto(DMA_CHANNEL_IN_LEFT, true, left, source, N - 1);
	DMA_ActivateAuto(DMA_CHANNEL_IN_RIGHT, false, right, (char*)source+sizeof(uint16_t), N - 1);
}

/*
 * Sets up the DMA to copy from src0 and src1 to dst with the pattern:
 *
 * src0: | 1, 3, ...  |
 * src1: | 2, 4, ...  |
 * dst:  | 1, 2, 3, 4, ... |
 */
void setupDMAMerge(void)
{

	DMA_CfgChannel_TypeDef chnlCfgLeft;
	chnlCfgLeft.highPri   = false;
	chnlCfgLeft.enableInt = true;
	chnlCfgLeft.select    = 0;
	chnlCfgLeft.cb        = NULL; //&cbOutLeft;
	DMA_CfgChannel(DMA_CHANNEL_OUT_LEFT, &chnlCfgLeft);

	DMA_CfgChannel_TypeDef chnlCfgRight;
	chnlCfgRight.highPri   = false;
	chnlCfgRight.enableInt = true;
	chnlCfgRight.select    = 0;
	chnlCfgRight.cb        = NULL; //&cbOutRight;
	DMA_CfgChannel(DMA_CHANNEL_OUT_RIGHT, &chnlCfgRight);

	DMA_CfgDescr_TypeDef descrCfg;
	descrCfg.dstInc  = dmaDataInc4;
	descrCfg.srcInc  = dmaDataInc2;
	descrCfg.size    = dmaDataSize2;
	descrCfg.arbRate = dmaArbitrate1;
	descrCfg.hprot   = 0;
	DMA_CfgDescr(DMA_CHANNEL_OUT_LEFT, true, &descrCfg);
	DMA_CfgDescr(DMA_CHANNEL_OUT_RIGHT, false, &descrCfg);

	DMA_ActivateAuto(DMA_CHANNEL_OUT_LEFT, true, destination, left, N - 1);
	DMA_ActivateAuto(DMA_CHANNEL_OUT_RIGHT, false, (char*)destination+sizeof(uint16_t), right, N - 1);
}
示例#16
0
/***************************************************************************//**
 * @brief
 *   Configure ADC usage for this application.
 *******************************************************************************/
static void preampADCConfig(void)
{
  DMA_CfgDescr_TypeDef descrCfg;
  DMA_CfgChannel_TypeDef chnlCfg;
  ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
  ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
  ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;

  /* Configure DMA usage by ADC */

  cbInData.cbFunc = preampDMAInCb;
  cbInData.userPtr = NULL;

  chnlCfg.highPri = true;
  chnlCfg.enableInt = true;
  chnlCfg.select = DMAREQ_ADC0_SCAN;
  chnlCfg.cb = &cbInData;
  DMA_CfgChannel(PREAMP_DMA_AUDIO_IN, &chnlCfg);

  descrCfg.dstInc = dmaDataInc2;
  descrCfg.srcInc = dmaDataIncNone;
  descrCfg.size = dmaDataSize2;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot = 0;
  DMA_CfgDescr(PREAMP_DMA_AUDIO_IN, true, &descrCfg);
  DMA_CfgDescr(PREAMP_DMA_AUDIO_IN, false, &descrCfg);

  DMA_ActivatePingPong(PREAMP_DMA_AUDIO_IN,
                       false,
                       preampAudioInBuffer1,
                       (void *)((uint32_t)&(ADC0->SCANDATA)),
                       (PREAMP_AUDIO_BUFFER_SIZE * 2) - 1,
                       preampAudioInBuffer2,
                       (void *)((uint32_t)&(ADC0->SCANDATA)),
                       (PREAMP_AUDIO_BUFFER_SIZE * 2) - 1);

  /* Indicate starting with primary in-buffer (according to above DMA setup) */
  preampProcessPrimary = true;

  /* Configure ADC */

  /* Keep warm due to "high" frequency sampling */
  init.warmUpMode = adcWarmupKeepADCWarm;
  /* Init common issues for both single conversion and scan mode */
  init.timebase = ADC_TimebaseCalc(0);
  init.prescale = ADC_PrescaleCalc(4000000, 0);
  /* Sample potentiometer by tailgating in order to not disturb fixed rate */
  /* audio sampling. */
  init.tailgate = true;
  ADC_Init(ADC0, &init);

  /* Init for single conversion use (potentiometer). */
  singleInit.reference = adcRefVDD;
  singleInit.input = adcSingleInpCh5; /* According to DVK HW design */
  singleInit.resolution = adcRes8Bit; /* Use at least 8 bit since unlinear voltage */
  ADC_InitSingle(ADC0, &singleInit);

  /* Init for scan sequence use (audio in right/left channels). */
  scanInit.prsSel = adcPRSSELCh0;
  scanInit.prsEnable = true;
  scanInit.reference = adcRefVDD;
  scanInit.input = ADC_SCANCTRL_INPUTMASK_CH0 | ADC_SCANCTRL_INPUTMASK_CH1;
  ADC_InitScan(ADC0, &scanInit);
}
示例#17
0
/***************************************************************************//**
 * @brief
 *  Start a UDMA transfer.
 ******************************************************************************/
static Ecode_t StartTransfer( DmaMode_t             mode,
                              DmaDirection_t        direction,
                              unsigned int          channelId,
                              DMADRV_PeripheralSignal_t
                                                    peripheralSignal,
                              void                  *buf0,
                              void                  *buf1,
                              void                  *buf2,
                              bool                  bufInc,
                              int                   len,
                              DMADRV_DataSize_t     size,
                              DMADRV_Callback_t     callback,
                              void                  *cbUserParam )
{
  ChTable_t *ch;
  DMA_CfgChannel_TypeDef chCfg;
  DMA_CfgDescr_TypeDef   descrCfg;

  if ( !initialized )
  {
    return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
  }

  if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
       || ( buf0 == NULL )
       || ( buf1 == NULL )
       || ( len > DMADRV_MAX_XFER_COUNT )
       || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
  {
    return ECODE_EMDRV_DMADRV_PARAM_ERROR;
  }

  ch = &chTable[ channelId ];
  if ( ch->allocated == false )
  {
    return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
  }

  /* Setup the interrupt callback routine. */
  if ( mode == dmaModeBasic )
  {
    dmaCallBack[ channelId ].cbFunc  = DmaBasicCallback;
  }
  else
  {
    dmaCallBack[ channelId ].cbFunc  = DmaPingPongCallback;
  }
  dmaCallBack[ channelId ].userPtr = NULL;

  /* Setup the channel */
  chCfg.highPri = false;              /* Can't use hi pri with peripherals. */

  /* Interrupt needed ? */
  if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
  {
    chCfg.enableInt = true;
  }
  else
  {
    chCfg.enableInt = false;
  }
  chCfg.select = peripheralSignal;
  chCfg.cb     = &dmaCallBack[ channelId ];
  DMA_CfgChannel( channelId, &chCfg );

  /* Setup channel descriptor. */
  if ( direction == dmaDirectionMemToPeripheral )
  {
    if ( bufInc )
    {
      if ( size == dmadrvDataSize1 )
      {
        descrCfg.srcInc = dmaDataInc1;
      }
      else if ( size == dmadrvDataSize2 )
      {
        descrCfg.srcInc = dmaDataInc2;
      }
      else /* dmadrvDataSize4 */
      {
        descrCfg.srcInc = dmaDataInc4;
      }
    }
    else
    {
      descrCfg.srcInc = dmaDataIncNone;
    }
    descrCfg.dstInc = dmaDataIncNone;
  }
  else
  {
    if ( bufInc )
    {
      if ( size == dmadrvDataSize1 )
      {
        descrCfg.dstInc = dmaDataInc1;
      }
      else if ( size == dmadrvDataSize2 )
      {
        descrCfg.dstInc = dmaDataInc2;
      }
      else /* dmadrvDataSize4 */
      {
        descrCfg.dstInc = dmaDataInc4;
      }
    }
    else
    {
      descrCfg.dstInc = dmaDataIncNone;
    }
    descrCfg.srcInc = dmaDataIncNone;
  }
  descrCfg.size    = (DMA_DataSize_TypeDef)size;
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;
  DMA_CfgDescr( channelId, true, &descrCfg );
  if ( mode == dmaModePingPong )
  {
    DMA_CfgDescr( channelId, false, &descrCfg );
  }

  ch->callback      = callback;
  ch->userParam     = cbUserParam;
  ch->callbackCount = 0;
  ch->length        = len;

  DMA->IFC = 1 << channelId;

  /* Start DMA cycle. */
  if ( mode == dmaModeBasic )
  {
    DMA_ActivateBasic( channelId, true, false, buf0, buf1, len - 1 );
  }
  else
  {
    if ( direction == dmaDirectionMemToPeripheral )
    {
      DMA_ActivatePingPong( channelId,
                            false,
                            buf0,                             /* dest */
                            buf1,                             /* src  */
                            len - 1,
                            buf0,                             /* dest */
                            buf2,                             /* src  */
                            len - 1);
    }
    else
    {
      DMA_ActivatePingPong( channelId,
                            false,
                            buf0,                             /* dest */
                            buf2,                             /* src  */
                            len - 1,
                            buf1,                             /* dest */
                            buf2,                             /* src  */
                            len - 1);
    }
  }

  return ECODE_EMDRV_DMADRV_OK;
}
/**************************************************************************//**
 * @brief
 *   Setup DMA in ping pong mode
 * @details
 *   The DMA is set up to transfer data from memory to the DAC, triggered by
 *   PRS (which in turn is triggered by the TIMER). When the DMA finishes,
 *   it will trigger the callback (PingPongTransferComplete).
 *****************************************************************************/
void DMA_setup(void)
{
  /* DMA configuration structs */
  DMA_Init_TypeDef       dmaInit;
  DMA_CfgChannel_TypeDef chnlCfg;
  DMA_CfgDescr_TypeDef   descrCfg;
  ramBufferTX0Zeros[0] = 0;
  /* Initializing the DMA */
  dmaInit.hprot        = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);

  /* Set the interrupt callback routine */
  DMAcallBackTX.cbFunc = PingPongTransferCompleteTX;

  /* Callback doesn't need userpointer */
  DMAcallBackTX.userPtr = NULL;

  /* Setting up channel */
  chnlCfg.highPri   = false; /* Can't use with peripherals */
  chnlCfg.enableInt = true;  /* Interrupt needed when buffers are used */

  chnlCfg.select = DMAREQ_USART2_TXBL;

  chnlCfg.cb = &DMAcallBackTX;
  DMA_CfgChannel(0, &chnlCfg);  // Enable TX DMA Channel
  /* Set the interrupt callback routine */
  DMAcallBackRX.cbFunc = PingPongTransferCompleteRX;

  /* Callback doesn't need userpointer */
  DMAcallBackRX.userPtr = NULL;

  /* Setting up channel */
  chnlCfg.highPri   = false; /* Can't use with peripherals */
  chnlCfg.enableInt = true;  /* Interrupt needed when buffers are used */

  /* channel 0 and 1 will need data at the same time,
   * can use channel 0 as trigger */

  chnlCfg.select = DMAREQ_USART2_RXDATAV;

  chnlCfg.cb = &DMAcallBackRX;
  DMA_CfgChannel(1, &chnlCfg);
  /* Setting up channel descriptor */
  /* Destination is DAC/USART register and doesn't move */
  descrCfg.dstInc = dmaDataIncNone;

  descrCfg.srcInc = dmaDataIncNone;
  descrCfg.size   = dmaDataSize1;

  /* We have time to arbitrate again for each sample */
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;

  /* Configure both primary and secondary descriptor alike */
  DMA_CfgDescr(0, true, &descrCfg);
  DMA_CfgDescr(0, false, &descrCfg);

  /* Setting up channel descriptor */
  /* Destination is DAC/USART register and doesn't move */
  descrCfg.dstInc = dmaDataInc1;

  descrCfg.srcInc = dmaDataIncNone;
  descrCfg.size   = dmaDataSize1;

  /* We have time to arbitrate again for each sample */
  descrCfg.arbRate = dmaArbitrate1;
  descrCfg.hprot   = 0;

  /* Configure both primary and secondary descriptor alike */
  DMA_CfgDescr(1, true, &descrCfg);
  DMA_CfgDescr(1, false, &descrCfg);

  /* Enabling PingPong Transfer*/
  DMA_ActivatePingPong(0,
                       false,
                             (void *) & (USART2->TXDATA),
                       (void *) &ramBufferTX0Zeros,
                       (2 * BUFFERSIZE) - 1,
                       (void *) &(USART2->TXDATA),
                       (void *) &ramBufferTX1Zeros,
                       (2 * BUFFERSIZE) - 1);
  /* Enabling PingPong Transfer*/
  DMA_ActivatePingPong(1,
                       false,
                       (void *) &ramBufferDacData0Stereo,
                             (void *) & (USART2->RXDATA),
                       (2 * BUFFERSIZE) - 1,
                       (void *) &ramBufferDacData1Stereo,
                       (void *) &(USART2->RXDATA),
                       (2 * BUFFERSIZE) - 1);
}