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()){} } }