We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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()){} } }