lpcware

LPC1768: DMA channel is always asserted (UART RX)

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by LuukvanderBiezen on Wed Dec 05 03:13:51 MST 2012
Hi everyone,

I'm currently creating a DMA module on a LPC1768. In my software I want to be able to assign the first free DMA channel (starting at channel 0) automatically for the datatransfer. My software searches for the first unused channel using the DMA Enabled Channel register (DMACEnbldChns). Currently I'm using DMA with UART2 and it works when I use fixed DMA channels (e.g. channel 0 for UART TX and channel 2 for UART RX). I can transfer data to and receive data from the PC. The automatic assignment of the DMA channels works for UART TX but for UART RX it doesn't.

My problem is that the DMA channel that is assigned to UART RX is normally asserted (channel active). When transferring data the channel is de-asserted. When I'm using UART2 TX the channel is normally de-asserted and is asserted when transferring data. So when I want to do several datatransfers in a row the software assigns all channels to UART RX, because the DMA channel that is assigned to UART2 RX stays active.

I've searched in the datasheet, user manual, technical reference manuals (PL011 and PL080) and on the internet but couldn't find helpful information. Is anyone familiar with this 'problem'? Is there an easy solution for this problem, or do I have to assign a fixed channel for every UART RX? Can anyone please help me?!


Software (fixed channel):

bool DmaDataReceive(TDmaMode DmaMode, dmaRequestPeripheral dmaReq, char * DataPtr, uns32 DataLength)   // dmaReq = UART2, dmaMode = dmaModeP2M
{
   uns8                                    DmaChannelNumber = 2;
   char                                    SourcePeripheral = DmaConnNrRcv[dmaReq];  
   uns32                                   SourceAddress = DmaPeripheralAddress[dmaReq];

   DmaChannel = (LPC_GPDMACH_TypeDef *) GpdmaChannel[DmaChannelNumber];

   // Clear any pending interrupts on the channel to be used
   LPC_GPDMA->DMACIntTCClear = (1<<DmaChannelNumber);
   LPC_GPDMA->DMACIntErrClr = (1<<DmaChannelNumber);

   if (DmaMode == dmaModeP2M)
   {
      DmaChannel->DMACCSrcAddr = SourceAddress;               // LPC_UART2_BASE
      DmaChannel->DMACCDestAddr = (uns32) DataPtr;
      DmaChannel->DMACCLLI = 0;    // no next data packet
      DmaChannel->DMACCControl = (DmaChCtrl_TransferSize(0x10)) |  // DataLength
                                 (DmaChCtrl_SrcBurstSize(DmaBurstSize_1)) |
                                 (DmaChCtrl_DestBurstSize(DmaBurstSize_1)) |
                                 (DmaChCtrl_SrcTransferWidth(DmaTransferWidth_Byte)) |
                                 (DmaChCtrl_DestTransferWidth(DmaTransferWidth_Byte)) |
                                 (DmaChCtrl_DestInc) |
                                 (DmaChCtrl_TCIntEn);
      DmaChannel->DMACCConfig = (DmaChCfg_E) |
                                (DmaChCfg_SrcPeripheral(SourcePeripheral)|      // DMA_UART2_RX
                                (DmaChCfg_TransferType(DmaMode)) |
                                (DmaChCfg_IntErr) |
                                (DmaChCfg_IntTC));
   }
}

I'm currently not doing anything in the ISR except:

DMA_IRQHandler
{  
   regVal = LPC_GPDMA->DMACIntTCStat;
   if (regVal)
   {
      LPC_GPDMA->DMACIntTCClear = regVal;
   }
   regVal = LPC_GPDMA->DMACIntErrStat;
   if (regVal)
   {
      LPC_GPDMA->DMACIntErrClr = regVal;
   }
}

Outcomes