| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uart_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx UART chip driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
39 static UART_RingBuffer_T rb;
40
42 static __IO FlagStatus TxIntStat;
43
44 FlagStatus ABsyncSts = RESET;
45 /*****************************************************************************
46 * Public types/enumerations/variables
47 ****************************************************************************/
48
49 /*****************************************************************************
50 * Private functions
51 ****************************************************************************/
52
53 /* Get UART number based on selected UART */
54 static IP_UART_ID_T Chip_UART_Get_UARTNum(LPC_USART_T *pUART)
55 {
56 if (pUART == LPC_USART0) {
57 return UART_0;
58 }
59 else if (pUART == LPC_UART1) {
60 return UART_1;
61 }
62 else if (pUART == LPC_USART2) {
63 return UART_2;
64 }
65
66 return UART_3;
67 }
68
69 /* Determine UART clock based in selected UART */
70 static CHIP_CCU_CLK_T Chip_UART_DetermineClk(LPC_USART_T *pUART) {
71 CHIP_CCU_CLK_T uartclk;
72
73 /* Pick clock for uart BASED ON SELECTED uart */
74 if (pUART == LPC_UART1) {
75 uartclk = CLK_MX_UART1;
76 }
77 if (pUART == LPC_USART2) {
78 uartclk = CLK_MX_UART2;
79 }
80 if (pUART == LPC_USART3) {
81 uartclk = CLK_MX_UART3;
82 }
83 else {
84 uartclk = CLK_MX_UART0;
85 }
86
87 return uartclk;
88 }
89
90 /*****************************************************************************
91 * Public functions
92 ****************************************************************************/
93
94 /* Initializes the pUART peripheral */
95 void Chip_UART_Init(LPC_USART_T *pUART)
96 {
97 IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
98
99 /* Enable UART clocking. UART base clock(s) must already be enabled */
100 Chip_Clock_EnableOpts(Chip_UART_DetermineClk(pUART), true, true, 1);
101
102 IP_UART_Init(pUART, UARTPort);
103 }
104
105 /* De-initializes the pUART peripheral */
106 void Chip_UART_DeInit(LPC_USART_T *pUART)
107 {
108 IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
109
110 IP_UART_DeInit(pUART, UARTPort);
111
112 /* Disable UART clocking */
113 Chip_Clock_Disable(Chip_UART_DetermineClk(pUART));
114 }
115
116 /* Determines best dividers to get a target baud rate */
117 Status Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate)
118 {
119 uint32_t uClk;
120
121 /* Get UART clock rate */
122 uClk = Chip_Clock_GetRate(Chip_UART_DetermineClk(pUART));
123
124 return IP_UART_SetBaud(pUART, baudrate, uClk);
125 }
126
127 /* Enable/Disable transmission on UART TxD pin */
128 void Chip_UART_TxCmd(LPC_USART_T *pUART, FunctionalState NewState)
129 {
130 IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
131
132 IP_UART_TxCmd(pUART, UARTPort, NewState);
133 }
134
135 /* Get Interrupt Stream Status */
136 IP_UART_INT_STATUS_T Chip_UART_GetIntStatus(LPC_USART_T *pUART)
137 {
138 uint32_t intsrc, tmp, tmp1;
139 IP_UART_INT_STATUS_T ret = UART_INTSTS_ERROR;
140
141 /* Determine the interrupt source */
142 intsrc = Chip_UART_IntGetStatus(pUART);
143
144 tmp = intsrc & UART_IIR_INTID_MASK;
145
146 /* Receive Line Status */
147 if (tmp == UART_IIR_INTID_RLS) {
148 /* Check line status */
149 tmp1 = (uint32_t) Chip_UART_GetLineStatus(pUART);
150 /* Mask out the Receive Ready and Transmit Holding empty status */
151 tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
152 | UART_LSR_BI | UART_LSR_RXFE);
153 /* If any error exist */
154 if (tmp1) {
155 return UART_INTSTS_ERROR;
156 }
157 }
158
159 /* Receive Data Available or Character time-out */
160 if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)) {
161 ret |= UART_INTSTS_RTR;
162 }
163
164 /* Transmit Holding Empty */
165 if (tmp == UART_IIR_INTID_THRE) {
166 ret |= UART_INTSTS_RTS;
167 }
168
169 if (intsrc & UART_IIR_ABEO_INT) {
170 ret |= UART_INTSTS_ABEO;
171 }
172 else if (intsrc & UART_IIR_ABTO_INT) {
173 ret |= UART_INTSTS_ABTO;
174 }
175 return ret;
176 }
177
178 /* UART interrupt service routine */
179 void Chip_UART_Interrupt_Handler(LPC_USART_T *pUART)
180 {
181 uint8_t tmpc;
182 uint32_t rLen;
183 IP_UART_INT_STATUS_T Sts = Chip_UART_GetIntStatus(pUART);
184 if (Sts == UART_INTSTS_ERROR) {
185 return; /* error */
186 }
187 if (Sts & UART_INTSTS_RTR) { /* ready for Read Data */
188 while (1) {
189 /* Call UART read function in UART driver */
190 rLen = Chip_UART_Receive(pUART, &tmpc, 1, NONE_BLOCKING);
191 /* If data received */
192 if (rLen) {
193 /* Check if buffer is more space
194 * If no more space, remaining character will be trimmed out
195 */
196 if (!__BUF_IS_FULL(rb.rx_head, rb.rx_tail)) {
197 rb.rx[rb.rx_head] = tmpc;
198 __BUF_INCR(rb.rx_head);
199 }
200 }
201 /* no more data */
202 else {
203 break;
204 }
205 }
206 }
207
208 if (Sts & UART_INTSTS_RTS) { /* ready for Write Data */
209 /* Disable THRE interrupt */
210 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, DISABLE);
211
212 /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
213 * of data or break whenever ring buffers are empty */
214 /* Wait until THR empty */
215 while (Chip_UART_CheckBusy(pUART) == SET) {}
216
217 while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
218 /* Move a piece of data into the transmit FIFO */
219 if (Chip_UART_Send(pUART, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
220 /* Update transmit ring FIFO tail pointer */
221 __BUF_INCR(rb.tx_tail);
222 }
223 else {
224 break;
225 }
226 }
227
228 /* If there is no more data to send, disable the transmit
229 interrupt - else enable it or keep it enabled */
230 if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
231 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, DISABLE);
232 // Reset Tx Interrupt state
233 TxIntStat = RESET;
234 }
235 else {
236 /* Set Tx Interrupt state */
237 TxIntStat = SET;
238 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, ENABLE);
239 }
240 }
241
242 if (Sts & UART_INTSTS_ABEO) {
243 Chip_UART_ABClearIntPending(pUART, UART_INTSTS_ABEO);
244 }
245 if (Sts & UART_INTSTS_ABTO) {
246 Chip_UART_ABClearIntPending(pUART, UART_INTSTS_ABTO);
247 }
248 if (ABsyncSts == RESET) {
249 /* Interrupt caused by End of auto-baud */
250 if (Sts & UART_INTSTS_ABEO) {
251 // Disable AB interrupt
252 Chip_UART_IntConfig(pUART, UART_INTCFG_ABEO, DISABLE);
253 // Set Sync flag
254 ABsyncSts = SET;
255 }
256
257 /* Auto-Baudrate Time-Out interrupt (not implemented) */
258 if (Sts & UART_INTSTS_ABTO) {
259 /* Disable this interrupt - Add your code here */
260 Chip_UART_IntConfig(pUART, UART_INTCFG_ABTO, DISABLE);
261 }
262 }
263 }
264
265 /* UART transmit function for interrupt mode (using ring buffers) */
266 uint32_t Chip_UART_Interrupt_Transmit(LPC_USART_T *pUART, uint8_t *txbuf, uint8_t buflen)
267 {
268 uint8_t *data = (uint8_t *) txbuf;
269 uint32_t bytes = 0;
270
271 /* Temporarily lock out UART transmit interrupts during this
272 read so the UART transmit interrupt won't cause problems
273 with the index values */
274 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, DISABLE);
275
276 /* Loop until transmit run buffer is full or until n_bytes
277 expires */
278 while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head, rb.tx_tail))) {
279 /* Write data from buffer into ring buffer */
280 rb.tx[rb.tx_head] = *data;
281 data++;
282
283 /* Increment head pointer */
284 __BUF_INCR(rb.tx_head);
285
286 /* Increment data count and decrement buffer size count */
287 bytes++;
288 buflen--;
289 }
290
291 /*
292 * Check if current Tx interrupt enable is reset,
293 * that means the Tx interrupt must be re-enabled
294 * due to call UART_IntTransmit() function to trigger
295 * this interrupt type
296 */
297 if (TxIntStat == RESET) {
298 // Disable THRE interrupt
299 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, DISABLE);
300
301 /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
302 * of data or break whenever ring buffers are empty */
303 /* Wait until THR empty */
304 while (Chip_UART_CheckBusy(pUART) == SET) {}
305
306 while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
307 /* Move a piece of data into the transmit FIFO */
308 if (Chip_UART_Send(pUART, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
309 /* Update transmit ring FIFO tail pointer */
310 __BUF_INCR(rb.tx_tail);
311 }
312 else {
313 break;
314 }
315 }
316
317 /* If there is no more data to send, disable the transmit
318 interrupt - else enable it or keep it enabled */
319 if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
320 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, DISABLE);
321 /* Reset Tx Interrupt state */
322 TxIntStat = RESET;
323 }
324 else {
325 /* Set Tx Interrupt state */
326 TxIntStat = SET;
327 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, ENABLE);
328 }
329 }
330 /*
331 * Otherwise, re-enables Tx Interrupt
332 */
333 else {
334 Chip_UART_IntConfig(pUART, UART_INTCFG_THRE, ENABLE);
335 }
336
337 return bytes;
338 }
339
340 /* UART read function for interrupt mode (using ring buffers) */
341 uint32_t Chip_UART_Interrupt_Receive(LPC_USART_T *pUART, uint8_t *rxbuf, uint8_t buflen)
342 {
343 uint8_t *data = (uint8_t *) rxbuf;
344 uint32_t bytes = 0;
345
346 /* Temporarily lock out UART receive interrupts during this
347 read so the UART receive interrupt won't cause problems
348 with the index values */
349 Chip_UART_IntConfig(pUART, UART_INTCFG_RBR, DISABLE);
350
351 /* Loop until receive buffer ring is empty or
352 until max_bytes expires */
353 while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head, rb.rx_tail)))) {
354 /* Read data from ring buffer into user buffer */
355 *data = rb.rx[rb.rx_tail];
356 data++;
357
358 /* Update tail pointer */
359 __BUF_INCR(rb.rx_tail);
360
361 /* Increment data count and decrement buffer size count */
362 bytes++;
363 buflen--;
364 }
365
366 /* Re-enable UART interrupts */
367 Chip_UART_IntConfig(pUART, UART_INTCFG_RBR, ENABLE);
368
369 return bytes;
370 }
371
372 /* Reset Tx and Rx ring buffer (head and tail) */
373 void Chip_UART_InitRingBuffer(LPC_USART_T *pUART)
374 {
375 (void) pUART;
376
377 TxIntStat = RESET;
378
379 /* Reset ring buf head and tail idx */
380 __BUF_RESET(rb.rx_head);
381 __BUF_RESET(rb.rx_tail);
382 __BUF_RESET(rb.tx_head);
383 __BUF_RESET(rb.tx_tail);
384 }
385
386 /* UART interrupt service routine */
387 FlagStatus Chip_UART_GetABEOStatus(LPC_USART_T *pUART)
388 {
389 (void) pUART;
390
391 return ABsyncSts;
392 }