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