LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 */
53 {
54  volatile uint32_t tmp;
55  (void) tmp; /* For use warnings only */
56 
57  /* FIFOs are empty */
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 */
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 */
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) \
229  errorStatus = SUCCESS;
230  }
231 
232  return errorStatus;
233 }
234 
235 /* Configure data width, parity mode and stop bits */
237  IP_UART_DATABIT_T Databits,
238  IP_UART_PARITY_T Parity,
239  IP_UART_STOPBIT_T Stopbits)
240 {
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 */
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 */
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 */
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 */
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 */
409 {
410  pUART->LCR |= UART_LCR_BREAK_EN;
411 }
412 
413 /* Get current value of Line Status register in UART peripheral */
415 {
416  return (pUART->LSR) & UART_LSR_BITMASK;
417 }
418 
419 /* Check whether if UART is busy or not */
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 */
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 */
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 */
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) {
543  }
544  }
545  else {
546  pUART->ACR = 0;
547  }
548 }
549 
550 /* Clear Autobaud Interrupt Pending */
552 {
553  pUART->ACR |= ABIntType;
554 }