2 INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART0 and UART1.
4 This file contains all the serial port components that can be compiled to
5 either ARM or THUMB mode. Components that must be compiled to ARM mode are
6 contained in serialISR.c.
22 // Demo application includes
28 // Constants to setup and access the UART
30 #define serWANTED_CLOCK_SCALING ((unsigned portLONG) 16)
33 // Constants to setup and access the VIC
35 #define serINVALID_QUEUE ((xQueueHandle) 0)
36 #define serHANDLE ((xComPortHandle) 1)
37 #define serNO_BLOCK ((portTickType) 0)
40 // Queues used to hold received characters, and characters waiting to be transmitted
42 static xQueueHandle xRX0Queue;
43 static xQueueHandle xTX0Queue;
44 static xQueueHandle xRX1Queue;
45 static xQueueHandle xTX1Queue;
48 // Communication flag between the interrupt service routine and serial API
50 static volatile portLONG *plTHREEmpty;
51 static volatile portLONG *plTHREEmpty1;
56 xComPortHandle uartInit (portCHAR pxPort, unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength)
58 unsigned portLONG ulDivisor;
59 unsigned portLONG ulWantedClock;
60 xComPortHandle xReturn = serHANDLE;
66 uartISRCreateQueues (0, uxQueueLength, &xRX0Queue, &xTX0Queue, &plTHREEmpty);
68 if ((xRX0Queue != serINVALID_QUEUE) &&
69 (xTX0Queue != serINVALID_QUEUE) &&
70 (ulWantedBaud != (unsigned portLONG) 0)
73 portENTER_CRITICAL ();
76 SCB_PCONP |= SCB_PCONP_PCUART0;
79 // Setup the baud rate: Calculate the divisor value
81 ulWantedClock = ulWantedBaud * serWANTED_CLOCK_SCALING;
82 ulDivisor = configCPU_CLOCK_HZ / ulWantedClock;
85 // Set the DLAB bit so we can access the divisor
87 UART0_LCR |= UART_LCR_DLAB;
92 UART0_DLL = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff);
94 UART0_DLM = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff);
97 // Turn on the FIFO's and clear the buffers
99 UART0_FCR = UART_FCR_EN | UART_FCR_CLR;
102 // Setup transmission format
104 UART0_LCR = UART_LCR_NOPAR | UART_LCR_1STOP | UART_LCR_8BITS;
107 // Setup the VIC for the UART
109 VIC_IntSelect &= ~VIC_IntSelect_UART0;
110 VIC_VectAddr2 = (portLONG) uartISR0;
111 VIC_VectCntl2 = VIC_VectCntl_ENABLE | VIC_Channel_UART0;
112 VIC_IntEnable = VIC_IntEnable_UART0;
115 // Enable UART0 interrupts
117 UART0_IER |= UART_IER_EI;
120 portEXIT_CRITICAL ();
123 xReturn = (xComPortHandle) 0;
129 uartISRCreateQueues (1, uxQueueLength, &xRX1Queue, &xTX1Queue, &plTHREEmpty1);
131 if ((xRX1Queue != serINVALID_QUEUE) &&
132 (xTX1Queue != serINVALID_QUEUE) &&
133 (ulWantedBaud != (unsigned portLONG) 0)
136 portENTER_CRITICAL ();
139 SCB_PCONP |= SCB_PCONP_PCUART1;
142 // Setup the baud rate: Calculate the divisor value
144 ulWantedClock = ulWantedBaud * serWANTED_CLOCK_SCALING;
145 ulDivisor = configCPU_CLOCK_HZ / ulWantedClock;
148 // Set the DLAB bit so we can access the divisor
150 UART1_LCR |= UART_LCR_DLAB;
155 UART1_DLL = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff);
157 UART1_DLM = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff);
160 // Turn on the FIFO's and clear the buffers
162 UART1_FCR = UART_FCR_EN | UART_FCR_CLR;
165 // Setup transmission format
167 UART1_LCR = UART_LCR_NOPAR | UART_LCR_1STOP | UART_LCR_8BITS;
170 // Setup the VIC for the UART
172 VIC_IntSelect &= ~VIC_IntSelect_UART1;
173 VIC_VectAddr3 = (portLONG) uartISR1;
174 VIC_VectCntl3 = VIC_VectCntl_ENABLE | VIC_Channel_UART1;
175 VIC_IntEnable = VIC_IntEnable_UART1;
178 // Enable UART0 interrupts//
180 UART1_IER |= UART_IER_EI;
183 portEXIT_CRITICAL ();
186 xReturn = (xComPortHandle) 0;
194 signed portBASE_TYPE uartGetChar (portCHAR pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime)
199 // Get the next character from the buffer. Return false if no characters are available, or arrive before xBlockTime expires
203 if (xQueueReceive (xRX0Queue, pcRxedChar, xBlockTime))
211 // Get the next character from the buffer. Return false if no characters are available, or arrive before xBlockTime expires
215 if (xQueueReceive (xRX1Queue, pcRxedChar, xBlockTime))
229 void uartPutString (portCHAR pxPort, const signed portCHAR * const pcString, portTickType xBlockTime)
231 signed portCHAR *pxNext;
233 pxNext = (signed portCHAR *) pcString;
237 uartPutChar (pxPort, *pxNext, xBlockTime);
245 signed portBASE_TYPE uartPutChar (portCHAR pxPort, signed portCHAR cOutChar, portTickType xBlockTime)
247 signed portBASE_TYPE xReturn = 0;
253 portENTER_CRITICAL ();
257 // Is there space to write directly to the UART?
259 if (*plTHREEmpty == (portLONG) pdTRUE)
261 *plTHREEmpty = pdFALSE;
262 UART0_THR = cOutChar;
268 // We cannot write directly to the UART, so queue the character. Block for a maximum of
269 // xBlockTime if there is no space in the queue.
271 xReturn = xQueueSend (xTX0Queue, &cOutChar, xBlockTime);
274 // Depending on queue sizing and task prioritisation: While we were blocked waiting to post
275 // interrupts were not disabled. It is possible that the serial ISR has emptied the Tx queue,
276 // in which case we need to start the Tx off again.
278 if ((*plTHREEmpty == (portLONG) pdTRUE) && (xReturn == pdPASS))
280 xQueueReceive (xTX0Queue, &cOutChar, serNO_BLOCK);
281 *plTHREEmpty = pdFALSE;
282 UART0_THR = cOutChar;
287 portEXIT_CRITICAL ();
293 portENTER_CRITICAL ();
297 // Is there space to write directly to the UART?
299 if (*plTHREEmpty1 == (portLONG) pdTRUE)
301 *plTHREEmpty1 = pdFALSE;
302 UART1_THR = cOutChar;
308 // We cannot write directly to the UART, so queue the character. Block for a maximum of
309 // xBlockTime if there is no space in the queue.
311 xReturn = xQueueSend (xTX1Queue, &cOutChar, xBlockTime);
314 // Depending on queue sizing and task prioritisation: While we were blocked waiting to post
315 // interrupts were not disabled. It is possible that the serial ISR has emptied the Tx queue,
316 // in which case we need to start the Tx off again.
318 if ((*plTHREEmpty1 == (portLONG) pdTRUE) && (xReturn == pdPASS))
320 xQueueReceive (xTX1Queue, &cOutChar, serNO_BLOCK);
321 *plTHREEmpty1 = pdFALSE;
322 UART1_THR = cOutChar;
327 portEXIT_CRITICAL ();
342 void uart0GetRxQueue (xQueueHandle *qh)
347 void uart1GetRxQueue (xQueueHandle *qh)