| 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
usart_001.c
Go to the documentation of this file.
1 /*
2 * @brief UART/USART registers and control functions
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 "usart_001.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
46 /*****************************************************************************
47 * Public functions
48 ****************************************************************************/
49
50 /* Initializes the UARTx peripheral according to the specified parameters in
51 the UART_ConfigStruct */
52 void IP_UART_Init(IP_USART_001_T *pUART, IP_UART_ID_T UARTPort)
53 {
54 volatile uint32_t tmp;
55 (void) tmp; /* For use warnings only */
56
57 /* FIFOs are empty */
58 pUART->FCR = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS);
59 /* Disable FIFO */
60 // pUART->FCR = 0;
61 /* Dummy reading */
62 while (pUART->LSR & UART_LSR_RDR) {
63 tmp = pUART->RBR;
64 }
65 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X) || defined(CHIP_LPC18XX) || defined(CHIP_LPC43XX)
66 switch (UARTPort) {
67 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
68 case 4:
69 #else
70 case 0:
71 case 2:
72 case 3:
73 #endif
74 pUART->TER2 = UART_TER2_TXEN;
75 /* Wait for current transmit complete */
76 while (!(pUART->LSR & UART_LSR_THRE)) {}
77 /* Disable Tx */
78 pUART->TER2 = 0;
79 break;
80
81 default:
82 break;
83 }
84 #else
85 pUART->TER1 = UART_TER1_TXEN;
86 /* Wait for current transmit complete */
87 while (!(pUART->LSR & UART_LSR_THRE)) {}
88 /* Disable Tx */
89 pUART->TER1 = 0;
90 #endif
91 /* Disable interrupt */
92 pUART->IER = 0;
93 /* Set LCR to default state */
94 pUART->LCR = 0;
95 /* Set ACR to default state */
96 pUART->ACR = 0;
97 #if defined(CHIP_LPC175X_6X) || defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
98 if ((UARTPort == 1) || (UARTPort == 4)) {
99 /* Set RS485 control to default state */
100 pUART->RS485CTRL = 0;
101 /* Set RS485 delay timer to default state */
102 pUART->RS485DLY = 0;
103 /* Set RS485 addr match to default state */
104 pUART->RS485ADRMATCH = 0;
105 }
106 #else
107 /* Set RS485 control to default state */
108 pUART->RS485CTRL = 0;
109 /* Set RS485 delay timer to default state */
110 pUART->RS485DLY = 0;
111 /* Set RS485 addr match to default state */
112 pUART->RS485ADRMATCH = 0;
113 #endif
114
115 #if defined(CHIP_LPC175X_6X) || defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X) || defined(CHIP_LPC18XX) || \
116 defined(CHIP_LPC43XX)
117 if (UARTPort == 1) {
118 #endif
119 /* Set Modem Control to default state */
120 pUART->MCR = 0;
121 /*Dummy Reading to Clear Status */
122 tmp = pUART->MSR;
123 #if defined(CHIP_LPC175X_6X) || defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X) || defined(CHIP_LPC18XX) || \
124 defined(CHIP_LPC43XX)
125 }
126
127 #endif
128
129 /* Dummy reading */
130 tmp = pUART->LSR;
131 /* Set Line Control register ---------------------------- */
132 // pUART->LCR = UART_DATABIT_8 | /* Default: 8N1 */
133 // UART_STOPBIT_1 |
134 // UART_PARITY_NONE;
135 pUART->FDR = 0x10; /* No fractional divider */
136 }
137
138 /* De-initializes the UARTx peripheral registers to their default reset values */
139 void IP_UART_DeInit(IP_USART_001_T *pUART, IP_UART_ID_T UARTPort)
140 {
141 /* For debug mode */
142
143 IP_UART_TxCmd(pUART, UARTPort, DISABLE);
144
145 switch (UARTPort) {
146 default:
147 break;
148 }
149 }
150
151 // FIXME - this function doesn't work correctly and is too big
152 /* Determines best dividers to get a target clock rate */
153 Status IP_UART_SetBaud(IP_USART_001_T *pUART, uint32_t baudrate, uint32_t uClk)
154 {
155 Status errorStatus = ERROR;
156
157 uint32_t d, m, bestd, bestm, tmp;
158 uint64_t best_divisor, divisor;
159 uint32_t current_error, best_error;
160 uint32_t recalcbaud;
161
162 /* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
163 * The formula is :
164 * BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
165 * It involves floating point calculations. That's the reason the formulae are adjusted with
166 * Multiply and divide method.*/
167 /* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
168 * 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
169 best_error = 0xFFFFFFFF;/* Worst case */
170 bestd = 0;
171 bestm = 0;
172 best_divisor = 0;
173 for (m = 1; m <= 15; m++) {
174 for (d = 0; d < m; d++) {
175 divisor = ((uint64_t) uClk << 28) * m / (baudrate * (m + d));
176 current_error = divisor & 0xFFFFFFFF;
177
178 tmp = divisor >> 32;
179
180 /* Adjust error */
181 if (current_error > ((uint32_t) 1 << 31)) {
182 current_error = -current_error;
183 tmp++;
184 }
185
186 if (( tmp < 1) || ( tmp > 65536) ) {/* Out of range */
187 continue;
188 }
189
190 if ( current_error < best_error) {
191 best_error = current_error;
192 best_divisor = tmp;
193 bestd = d;
194 bestm = m;
195 if (best_error == 0) {
196 break;
197 }
198 }
199 } /* end of inner for loop */
200
201 if (best_error == 0) {
202 break;
203 }
204 } /* end of outer for loop */
205
206 if (best_divisor == 0) {
207 return ERROR; /* can not find best match */
208
209 }
210 recalcbaud = (uClk >> 4) * bestm / (best_divisor * (bestm + bestd));
211
212 /* reuse best_error to evaluate baud error */
213 if (baudrate > recalcbaud) {
214 best_error = baudrate - recalcbaud;
215 }
216 else {best_error = recalcbaud - baudrate; }
217
218 best_error = best_error * 100 / baudrate;
219
220 if (best_error < UART_ACCEPTED_BAUDRATE_ERROR) {
221 pUART->LCR |= UART_LCR_DLAB_EN;
222 // FIXME - this is not how DLL and DLM work - they do not add
223 pUART->DLM = UART_LOAD_DLM(best_divisor);
224 pUART->DLL = UART_LOAD_DLL(best_divisor);
225 /* Then reset DLAB bit */
226 pUART->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
227 pUART->FDR = (UART_FDR_MULVAL(bestm) \
228 | UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
229 errorStatus = SUCCESS;
230 }
231
232 return errorStatus;
233 }
234
235 /* Configure data width, parity mode and stop bits */
236 void IP_UART_ConfigData(IP_USART_001_T *pUART,
237 IP_UART_DATABIT_T Databits,
238 IP_UART_PARITY_T Parity,
239 IP_UART_STOPBIT_T Stopbits)
240 {
241 uint32_t tmp = (pUART->LCR & (UART_LCR_DLAB_EN | UART_LCR_BREAK_EN)) & UART_LCR_BITMASK;
242 tmp |= (uint32_t) Databits | (uint32_t) Parity | (uint32_t) Stopbits;
243 pUART->LCR = (uint8_t) (tmp & UART_LCR_BITMASK);
244 }
245
246 /* UART Send/Recieve functions -------------------------------------------------*/
247 /* Transmit a single data through UART peripheral */
248 Status IP_UART_SendByte(IP_USART_001_T *pUART, uint8_t data)
249 {
250 if (!(pUART->LSR & UART_LSR_THRE)) {
251 return ERROR;
252 }
253 pUART->THR = data & UART_THR_MASKBIT;
254 return SUCCESS;
255 }
256
257 /* Receive a single data from UART peripheral */
258 Status IP_UART_ReceiveByte(IP_USART_001_T *pUART, uint8_t *Data)
259 {
260 if (!(pUART->LSR & UART_LSR_RDR)) {
261 return ERROR;
262 }
263 *Data = (uint8_t) (pUART->RBR & UART_RBR_MASKBIT);
264 return SUCCESS;
265 }
266
267 /* Send a block of data via UART peripheral */
268 uint32_t IP_UART_Send(IP_USART_001_T *pUART, uint8_t *txbuf, uint32_t buflen, TRANSFER_BLOCK_T flag)
269 {
270 uint32_t bToSend, bSent, timeOut; // , fifo_cnt;
271 uint8_t *pChar = txbuf;
272
273 bToSend = buflen;
274
275 /* blocking mode */
276 if (flag == BLOCKING) {
277 bSent = 0;
278 while (bToSend) {
279 timeOut = UART_BLOCKING_TIMEOUT;
280 /* Wait for THR empty with timeout */
281 while (!(IP_UART_SendByte(pUART, *pChar))) {
282 if (timeOut == 0) {
283 break;
284 }
285 timeOut--;
286 }
287 /* Time out! */
288 if (timeOut == 0) {
289 break;
290 }
291 pChar++;
292 bToSend--;
293 bSent++;
294 }
295 }
296 /* None blocking mode */
297 else {
298 bSent = 0;
299 while (bToSend) {
300 if (!(IP_UART_SendByte(pUART, *pChar))) {
301 break;
302 }
303 pChar++;
304 bToSend--;
305 bSent++;
306 }
307 }
308 return bSent;
309 }
310
311 /* Receive a block of data via UART peripheral */
312 uint32_t IP_UART_Receive(IP_USART_001_T *pUART, uint8_t *rxbuf, uint32_t buflen, TRANSFER_BLOCK_T flag)
313 {
314 uint32_t bToRecv, bRecv, timeOut;
315 uint8_t *pChar = rxbuf;
316
317 bToRecv = buflen;
318
319 /* Blocking mode */
320 if (flag == BLOCKING) {
321 bRecv = 0;
322 while (bToRecv) {
323 timeOut = UART_BLOCKING_TIMEOUT;
324 while (!(IP_UART_ReceiveByte(pUART, pChar))) {
325 if (timeOut == 0) {
326 break;
327 }
328 timeOut--;
329 }
330 /* Time out! */
331 if (timeOut == 0) {
332 break;
333 }
334 pChar++;
335 bToRecv--;
336 bRecv++;
337 }
338 }
339 /* None blocking mode */
340 else {
341 bRecv = 0;
342 while (bToRecv) {
343 if (!(IP_UART_ReceiveByte(pUART, pChar))) {
344 break;
345 }
346 else {
347 pChar++;
348 bRecv++;
349 bToRecv--;
350 }
351 }
352 }
353 return bRecv;
354 }
355
356 /* Enable or disable specified UART interrupt */
357 void IP_UART_IntConfig(IP_USART_001_T *pUART, IP_UART_INT_T UARTIntCfg, FunctionalState NewState)
358 {
359 uint32_t tmp = 0;
360
361 switch (UARTIntCfg) {
362 case UART_INTCFG_RBR:
363 tmp = UART_IER_RBRINT_EN;
364 break;
365
366 case UART_INTCFG_THRE:
367 tmp = UART_IER_THREINT_EN;
368 break;
369
370 case UART_INTCFG_RLS:
371 tmp = UART_IER_RLSINT_EN;
372 break;
373
374 case UART_INTCFG_MS:
375 tmp = UART_IER_MSINT_EN;
376 break;
377
378 case UART_INTCFG_CTS:
379 tmp = UART_IER_CTSINT_EN;
380 break;
381
382 case UART_INTCFG_ABEO:
383 tmp = UART_IER_ABEOINT_EN;
384 break;
385
386 case UART_INTCFG_ABTO:
387 tmp = UART_IER_ABTOINT_EN;
388 break;
389 }
390
391 if (NewState == ENABLE) {
392 pUART->IER |= tmp;
393 }
394 else {
395
396 pUART->IER &= (~tmp) & UART_IER_BITMASK;
397
398 }
399 }
400
401 /* Get Source Interrupt */
402 uint32_t IP_UART_IntGetStatus(IP_USART_001_T *pUART)
403 {
404 return (pUART->IIR) & UART_IIR_BITMASK;
405 }
406
407 /* Force BREAK character on UART line, output pin UARTx TXD is forced to logic 0 */
408 void IP_UART_ForceBreak(IP_USART_001_T *pUART)
409 {
410 pUART->LCR |= UART_LCR_BREAK_EN;
411 }
412
413 /* Get current value of Line Status register in UART peripheral */
414 uint8_t IP_UART_GetLineStatus(IP_USART_001_T *pUART)
415 {
416 return (pUART->LSR) & UART_LSR_BITMASK;
417 }
418
419 /* Check whether if UART is busy or not */
420 FlagStatus IP_UART_CheckBusy(IP_USART_001_T *pUART)
421 {
422 if (pUART->LSR & UART_LSR_TEMT) {
423 return RESET;
424 }
425 else {
426 return SET;
427 }
428 }
429
430 /* Enable/Disable transmission on UART TxD pin */
431 void IP_UART_TxCmd(IP_USART_001_T *pUART, IP_UART_ID_T UARTPort, FunctionalState NewState)
432 {
433 if (NewState == ENABLE) {
434 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X) || defined(CHIP_LPC18XX) || defined(CHIP_LPC43XX)
435 switch (UARTPort) {
436 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
437 case 4:
438 #else
439 case 0:
440 case 2:
441 case 3:
442 #endif
443 pUART->TER2 = UART_TER2_TXEN;
444 break;
445
446 default:
447 break;
448 }
449 #else
450 pUART->TER1 = UART_TER1_TXEN;
451 #endif
452 }
453 else {
454 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X) || defined(CHIP_LPC18XX) || defined(CHIP_LPC43XX)
455 switch (UARTPort) {
456 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
457 case 4:
458 #else
459 case 0:
460 case 2:
461 case 3:
462 #endif
463 pUART->TER2 &= (~UART_TER2_TXEN) & UART_TER2_BITMASK;
464 break;
465
466 default:
467 break;
468 }
469 #else
470 pUART->TER1 &= (~UART_TER1_TXEN) & UART_TER1_BITMASK;
471 #endif
472 }
473 }
474
475 /* UART FIFO functions ----------------------------------------------------------*/
476 /* Configure FIFO function on selected UART peripheral */
477 void IP_UART_FIFOConfig(IP_USART_001_T *pUART, UART_FIFO_CFG_T *FIFOCfg)
478 {
479 uint8_t tmp = 0;
480
481 tmp |= UART_FCR_FIFO_EN;
482 switch (FIFOCfg->FIFO_Level) {
483 case UART_FIFO_TRGLEV0:
484 tmp |= UART_FCR_TRG_LEV0;
485 break;
486
487 case UART_FIFO_TRGLEV1:
488 tmp |= UART_FCR_TRG_LEV1;
489 break;
490
491 case UART_FIFO_TRGLEV2:
492 tmp |= UART_FCR_TRG_LEV2;
493 break;
494
495 case UART_FIFO_TRGLEV3:
496 default:
497 tmp |= UART_FCR_TRG_LEV3;
498 break;
499 }
500
501 if (FIFOCfg->FIFO_ResetTxBuf == ENABLE) {
502 tmp |= UART_FCR_TX_RS;
503 }
504 if (FIFOCfg->FIFO_ResetRxBuf == ENABLE) {
505 tmp |= UART_FCR_RX_RS;
506 }
507 if (FIFOCfg->FIFO_DMAMode == ENABLE) {
508 tmp |= UART_FCR_DMAMODE_SEL;
509 }
510
511 /* write to FIFO control register */
512 pUART->FCR = tmp & UART_FCR_BITMASK;
513 }
514
515 /* Fills each UART_FIFOInitStruct member with its default value */
516 void IP_UART_FIFOConfigStructInit(UART_FIFO_CFG_T *UART_FIFOInitStruct)
517 {
518 UART_FIFOInitStruct->FIFO_DMAMode = DISABLE;
519 UART_FIFOInitStruct->FIFO_Level = UART_FIFO_TRGLEV0;
520 UART_FIFOInitStruct->FIFO_ResetRxBuf = ENABLE;
521 UART_FIFOInitStruct->FIFO_ResetTxBuf = ENABLE;
522 }
523
524 /* Start/Stop Auto Baudrate activity */
525 void IP_UART_ABCmd(IP_USART_001_T *pUART, UART_AB_CFG_T *ABConfigStruct, FunctionalState NewState)
526 {
527 if (NewState == ENABLE) {
528 /* Clear DLL and DLM value */
529 pUART->LCR |= UART_LCR_DLAB_EN;
530 pUART->DLL = 0;
531 pUART->DLM = 0;
532 pUART->LCR &= ~UART_LCR_DLAB_EN;
533
534 /* FDR value must be reset to default value */
535 pUART->FDR = 0x10;
536
537 if (ABConfigStruct->ABMode == UART_AUTOBAUD_MODE1) {
538 pUART->ACR = UART_ACR_START | UART_ACR_MODE;
539 }
540
541 if (ABConfigStruct->AutoRestart == ENABLE) {
542 pUART->ACR = UART_ACR_START | UART_ACR_AUTO_RESTART;
543 }
544 }
545 else {
546 pUART->ACR = 0;
547 }
548 }
549
550 /* Clear Autobaud Interrupt Pending */
551 void IP_UART_ABClearIntPending(IP_USART_001_T *pUART, IP_UART_INT_STATUS_T ABIntType)
552 {
553 pUART->ACR |= ABIntType;
554 }