AnsweredAssumed Answered

LPC1768 - UART receive using DMA

Question asked by Tomas Frcek on Nov 26, 2018

Hello,

 

I have firmware with functional UART implementation, using UART interrupt to receive chars. I want to use the DMA for both receiving and transmitting. I started with the receiving part, this is my code:

 

volatile uint32_t rx_char;

void InitUARTWithDMA(void)

{

   // Power and clock for UART2.

   LPC_SC->PCONP |= 1 << 24;
   LPC_SC->PCLKSEL1 &= ~(3 << 16);

 

   // UART2 Rx and Tx pins.

   LPC_PINCON->PINSEL0 &= ~(0xF << 20);
   LPC_PINCON->PINSEL0 |= 5 << 20;

   LPC_PINCON->PINMODE0 &= ~(0xF << 20);

 

   // Reset TX and RX FIFO, enable FIFO and DMA.
   LPC_UART2->FCR = 0xF;

 

   // 8 bits, no Parity, 1 Stop bit, Enable access to DLL, DLM for baud rate setup.
   LPC_UART2->LCR = 0x83;

 

   // 9600 baud

   LPC_UART2->DLM = 0x00000000;
   LPC_UART2->DLL = 0x0000006C;
   LPC_UART2->FDR = 0x00000021; 

 

   // DLAB = 0. When I enable the UART interrupt after this line, it works.
   LPC_UART2->LCR &= ~(1 << 7);  

 

   // Power the DMA.

   LPC_SC->PCONP |= 0x1 << 29;

 

   // Enable DMA, little endian.
   LPC_GPDMA->DMACConfig = 0x00000001;

 

   // Clear interrupts for all channels.
   LPC_GPDMA->DMACIntTCClear = 0x000000FF;
   LPC_GPDMA->DMACIntErrClr = 0x000000FF;

 

   // UART Receive Buffer Register - source of the DMA channel.
   LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&LPC_UART2->RBR;

 

   // Global variable - destination of the DMA channel.
   LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&rx_char;

 

   // Linked list set to 0x0.
   LPC_GPDMACH0->DMACCLLI = 0x00000000;

 

   // Transfer size not set, because UART module controls the data flow. Terminal count interrupt enable.

   LPC_GPDMACH0->DMACCControl = 1U << 31;

 

   // Activates DMA channel, transfer type 'peripheral (UART2 Tx) >> memory'.
   LPC_GPDMACH0->DMACCConfig = 0x1 | (0xD << 1) | (0x2 << 11) | (0x1 << 14) | (0x1 << 15);

 

   // Register interrupt.

   NVIC_ClearPendingIRQ(DMA_IRQn);

   NVIC_EnableIRQ(DMA_IRQn);

}

 

void DMA_IRQHandler(void)

{

   if ((LPC_GPDMA->DMACIntStat & 0x1) != 0x0)

   {

      // DMA channel 0.

      if ((LPC_GPDMA->DMACIntTCStat & 0x1) != 0x0)

      {

         // Terminal count interrupt.

         // Work with 'rx_char' variable.

         LPC_GPDMA->DMACIntTCClear = 0x1;

      }

   }

}

 

But the DMA interrupt routine is never encountered, even though I send data on UART from the PC terminal. Any obvious reasons why this shouldn't work? This is my first use of the DMA module, so I'm sure there must be some stupid mistake...

 

Thanks!

Outcomes