LPC1768 - UART receive using DMA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1768 - UART receive using DMA

1,741 Views
tomasfrcek
Contributor III

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!

Labels (1)
0 Kudos
0 Replies