This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Enable DMA in LPC1768

I am Modifying the example of CMSIS Driver USART program. when I am debugging the program DMA is not Enable in GPDMA configuration.

LPC_GPDMA->DMACConfig = GPDMA_CONFIG_E; while ((LPC_GPDMA->DMACConfig & GPDMA_CONFIG_E) == 0);

The control is not coming out of while loop. Can anyone help me in this as I am new to ARM Cortex-M3.

#include "Driver_USART.h"

void initial_USART0(void);
extern ARM_DRIVER_USART Driver_USART0;

int main(void)
{
        initial_USART0();
        Driver_USART0.Send("ABCDEF",7);

        while(1);

}

void initial_USART0(void)
{
        int32_t status=0;
        status = Driver_USART0.Initialize(NULL);
        status = Driver_USART0.PowerControl(ARM_POWER_FULL);

        // configure to UART mode: 8 bits, no parity, 1 stop bit, no flow control, 9600 bps
        status = Driver_USART0.Control(ARM_USART_MODE_ASYNCHRONOUS |
        ARM_USART_DATA_BITS_8 |
        ARM_USART_PARITY_NONE |
        ARM_USART_STOP_BITS_1 |
        ARM_USART_FLOW_CONTROL_NONE, 9600);
        status = Driver_USART0.Control(ARM_USART_MODE_ASYNCHRONOUS, 9600);
        // enable TX output
        status = Driver_USART0.Control(ARM_USART_CONTROL_TX, 1);
        // disable RX output
        status = Driver_USART0.Control(ARM_USART_CONTROL_RX, 1);
}

Regards
Arvin

  • I know you were asking about the drivers, but I ran into problems with them too.

    Here is how I rolled my own. Note: This is hard coded to use UART0 and DMA Channel 5 for TX (RX isn't using DMA in this example) (Also, no interrupts, UART or DMA, I didn't need them).

    I created a class called Serial in a header file (Serial.h):

    class Serial
    {
            public:
                    Serial();
                    Serial(int BaudRate); // Constructor
    
                    // Initialize the Serial Port with specified Baud
                    void SetBaud(int BaudRate);
                    bool Readable(void);
                    char Read(void);
                    bool Writable(void);
                    void Write(char Byte);
                    void Write(char *Data, int Length);
    
            private:
                    static const int DMA_UART0_RXChannel = 0x04; // Use Channel 4 for RX
                    static const int DMA_UART0_TXChannel = 0x05; // Use Channel 5 for TX
            // Helper Functions
                    void ConfigureUART0(int BaudRate);
            // End Helper Functions
    }; // End Serial Class
    

    Code for the class (Serial.cpp)

    #include "LPC17xx.h"
    
    // Public Functions
    // Constructor
    Serial::Serial()
    {
            ConfigureUART0(9600);
    }
    Serial::Serial(int BaudRate)
    {
            ConfigureUART0(BaudRate);
    }
    // End Constructor
    void Serial::SetBaud(int BaudRate)
    {
            int PeripheralClockDivider = 0;
            int PeripheralClock = 0;
            int FrequencyBasedBaud = 0;
            /* By default, the PCLKSELx value is zero, thus, the PCLK for
            all the peripherals is 1/4 of the SystemFrequency. */
            // Enable Baud Changes
            LPC_UART0->LCR |= 1 << 7;              // enable baud changes (divisor latch)
    
            /* Bit 6~7 is for UART0 */
            PeripheralClockDivider = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
            SystemCoreClockUpdate();
            switch (PeripheralClockDivider)
            {
            case 0x00:
            default:
                    PeripheralClock = SystemCoreClock / 4;
                    break;
            case 0x01:
                    PeripheralClock = SystemCoreClock;
                    break;
            case 0x02:
                    PeripheralClock = SystemCoreClock / 2;
                    break;
            case 0x03:
                    PeripheralClock = SystemCoreClock / 8;
                    break;
            }
            FrequencyBasedBaud = (PeripheralClock / 16) / BaudRate;
            LPC_UART0->DLM = FrequencyBasedBaud / 256;
            LPC_UART0->DLL = FrequencyBasedBaud % 256;
            LPC_UART0->LCR &= ~(1 << 7);               // enable baud changes (divisor latch)
    }
    bool Serial::Readable(void)
    {
            return (LPC_UART0->LSR & (0x1));
    }
    bool Serial::Writable(void)
    {
            return ((LPC_UART0->LSR & 0x20) && !(LPC_GPDMACH5->DMACCConfig & 1));
    }
    void Serial::Write(char Byte)
    {
            while (!(Writable()));  // Wait for existing transfers to complete
            LPC_UART0->THR = Byte;       //Load new data
    }
    char Serial::Read(void)
    {
            if (Readable()){        //While RBR is not empty!
                    return LPC_UART0->RBR;
            }
            return 0x00;
    }
    void Serial::Write(char *Data, int Length)
    {
            while (!Writable()); // Wait for existing transfers to complete
    
            LPC_UART0->FCR |= 1 << 3; // Enable DMA Transfers on the UART
            LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&Data[0];
            LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&(LPC_UART0->THR);
            LPC_GPDMACH0->DMACCLLI = 0; // linked lists for ch0
            LPC_GPDMACH0->DMACCControl = Length   // transfer size (0 - 11)
                    | (0 << 12)               // source burst size (12 - 14) = 1
                    | (0 << 15)               // destination burst size (15 - 17) = 1
                    | (0 << 18)               // source width (18 - 20) = 8 bit
                    | (0 << 21)               // destination width (21 - 23) = 8 bit
                    | (0 << 24)               // source AHB select (24) = AHB 0
                    | (0 << 25)               // destination AHB select (25) = AHB 0
                    | (1 << 26)               // source increment (26) = increment
                    | (0 << 27)               // destination increment (27) = no increment
                    | (0 << 28)               // mode select (28) = access in user mode
                    | (0 << 29)               // (29) = access not bufferable
                    | (0 << 30)               // (30) = access not cacheable
                    | (0 << 31);              // terminal count interrupt disabled
    
            LPC_GPDMACH0->DMACCConfig = 1                // channel enabled (0)
                    | (0 << 1)                // source peripheral (1 - 5) = none
                    | (8 << 6)                // destination peripheral (6 - 10) = UART0 TX
                    | (1 << 11)               // flow control (11 - 13) = mem to per
                    | (0 << 14)               // (14) = mask out error interrupt
                    | (0 << 15)               // (15) = mask out terminal count interrupt
                    | (0 << 16)               // (16) = no locked transfers
                    | (0 << 18);      // (27) = no HALT
    }
    
    // End Public Functions
    // Private Functions
    // End Private Functions
    // Helper Functions
    // End Helper Functions
    void Serial::ConfigureUART0(int BaudRate)
    {
            // Power up the DMA
            LPC_SC->PCONP |= 1 << 29;
            LPC_GPDMA->DMACConfig = 1;
    
            // Configure UART0
            LPC_PINCON->PINSEL0 &= ~0x000000F0;
            LPC_PINCON->PINSEL0 |= 0x00000050;  // RxD0 is P0.3 and TxD0 is P0.2
    
            SetBaud(BaudRate);                              // Default to 9600 Baud
            LPC_UART0->LCR = 0x03;               // 8 bits, no Parity, 1 Stop bit
            LPC_UART0->FCR = 0x07;               // Enable and reset TX and RX FIFO.
    }
    // End Private Functions
    

    Then to use the DMA to transfer data:

    Serial SerialPort(115200);
    void SendDMAData(bool Block)
    {
            char DataToSend[] = "DMA Large Transfer\r\n";
            SerialPort.Write(characters, 22);
    
            if(Block)
            {
                    while (!SerialPort.Writable()){}
            }
    }