LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uart_17xx_40xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC17xx/40xx 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 
40 
42 static __IO FlagStatus TxIntStat;
43 
45 
46 /*****************************************************************************
47  * Public types/enumerations/variables
48  ****************************************************************************/
49 
50 /*****************************************************************************
51  * Private functions
52  ****************************************************************************/
53 
54 /* Get UART number based on selected UART */
56 {
57  if (pUART == LPC_UART0) {
58  return UART_0;
59  }
60  else if (pUART == LPC_UART1) {
61  return UART_1;
62  }
63  else if (pUART == LPC_UART2) {
64  return UART_2;
65  }
66  else if (pUART == LPC_UART3) {
67  return UART_3;
68  }
69 
70  return UART_4;
71 }
72 
73 /* Determine UART clock based in selected UART */
75  CHIP_SYSCTL_CLOCK_T uartclk;
76 
77  /* Pick clock for uart BASED ON SELECTED uart */
78  if (pUART == LPC_UART1) {
79  uartclk = SYSCTL_CLOCK_UART1;
80  }
81  else if (pUART == LPC_UART2) {
82  uartclk = SYSCTL_CLOCK_UART2;
83  }
84  else if (pUART == LPC_UART3) {
85  uartclk = SYSCTL_CLOCK_UART3;
86  }
87 #if !defined(CHIP_LPC175X_6X)
88  else if (pUART == LPC_UART4) {
89  uartclk = SYSCTL_CLOCK_UART4;
90  }
91 #endif
92  else {
93  uartclk = SYSCTL_CLOCK_UART0;
94  }
95  return uartclk;
96 }
97 
99 #if !defined(CHIP_LPC175X_6X)
101 #else
102  /* Pick clock for uart BASED ON SELECTED uart */
103  if (pUART == LPC_UART1) {
104  return Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_UART1);
105  }
106  else if (pUART == LPC_UART2) {
107  return Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_UART2);
108  }
109  else if (pUART == LPC_UART3) {
110  return Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_UART3);
111  }
112  else {
113  return Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_UART0);
114  }
115 #endif
116 }
117 
118 /*****************************************************************************
119  * Public functions
120  ****************************************************************************/
121 
122 /* Initializes the pUART peripheral */
124 {
125  IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
126 
127  /* Enable UART clocking. UART base clock(s) must already be enabled */
129 
130  IP_UART_Init(pUART, UARTPort);
131 }
132 
133 /* De-initializes the pUART peripheral */
135 {
136  IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
137 
138  IP_UART_DeInit(pUART, UARTPort);
139 
140  /* Disable UART clocking */
142 }
143 
144 /* Determines best dividers to get a target baud rate */
146 {
147  uint32_t uClk;
148 
149  /* Get UART clock rate */
150  uClk = Chip_UART_GetClockRate(pUART);
151 
152  return IP_UART_SetBaud(pUART, baudrate, uClk);
153 }
154 
155 /* Enable/Disable transmission on UART TxD pin */
157 {
158  IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
159 
160  IP_UART_TxCmd(pUART, UARTPort, NewState);
161 }
162 
163 /* Get Interrupt Stream Status */
165 {
166  uint32_t intsrc, tmp, tmp1;
168 
169  /* Determine the interrupt source */
170  intsrc = Chip_UART_IntGetStatus(pUART);
171 
172  tmp = intsrc & UART_IIR_INTID_MASK;
173 
174  /* Receive Line Status */
175  if (tmp == UART_IIR_INTID_RLS) {
176  /* Check line status */
177  tmp1 = (uint32_t) Chip_UART_GetLineStatus(pUART);
178  /* Mask out the Receive Ready and Transmit Holding empty status */
179  tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
181  /* If any error exist */
182  if (tmp1) {
183  return UART_INTSTS_ERROR;
184  }
185  }
186 
187  /* Receive Data Available or Character time-out */
188  if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)) {
189  ret |= UART_INTSTS_RTR;
190  }
191 
192  /* Transmit Holding Empty */
193  if (tmp == UART_IIR_INTID_THRE) {
194  ret |= UART_INTSTS_RTS;
195  }
196 
197  if (intsrc & UART_IIR_ABEO_INT) {
198  ret |= UART_INTSTS_ABEO;
199  }
200  else if (intsrc & UART_IIR_ABTO_INT) {
201  ret |= UART_INTSTS_ABTO;
202  }
203  return ret;
204 }
205 
206 /* UART interrupt service routine */
208 {
209  uint8_t tmpc;
210  uint32_t rLen;
212  if (Sts == UART_INTSTS_ERROR) {
213  return; /* error */
214  }
215  if (Sts & UART_INTSTS_RTR) { /* ready for Read Data */
216  while (1) {
217  /* Call UART read function in UART driver */
218  rLen = Chip_UART_Receive(pUART, &tmpc, 1, NONE_BLOCKING);
219  /* If data received */
220  if (rLen) {
221  /* Check if buffer is more space
222  * If no more space, remaining character will be trimmed out
223  */
224  if (!__BUF_IS_FULL(rb.rx_head, rb.rx_tail)) {
225  rb.rx[rb.rx_head] = tmpc;
226  __BUF_INCR(rb.rx_head);
227  }
228  }
229  /* no more data */
230  else {
231  break;
232  }
233  }
234  }
235 
236  if (Sts & UART_INTSTS_RTS) { /* ready for Write Data */
237  /* Disable THRE interrupt */
239 
240  /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
241  * of data or break whenever ring buffers are empty */
242  /* Wait until THR empty */
243  while (Chip_UART_CheckBusy(pUART) == SET) {}
244 
245  while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
246  /* Move a piece of data into the transmit FIFO */
247  if (Chip_UART_Send(pUART, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
248  /* Update transmit ring FIFO tail pointer */
249  __BUF_INCR(rb.tx_tail);
250  }
251  else {
252  break;
253  }
254  }
255 
256  /* If there is no more data to send, disable the transmit
257  interrupt - else enable it or keep it enabled */
258  if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
260  // Reset Tx Interrupt state
261  TxIntStat = RESET;
262  }
263  else {
264  /* Set Tx Interrupt state */
265  TxIntStat = SET;
267  }
268  }
269 
270  if (Sts & UART_INTSTS_ABEO) {
271  Chip_UART_ABClearIntPending(pUART, UART_INTSTS_ABEO);
272  }
273  if (Sts & UART_INTSTS_ABTO) {
274  Chip_UART_ABClearIntPending(pUART, UART_INTSTS_ABTO);
275  }
276  if (ABsyncSts == RESET) {
277  /* Interrupt caused by End of auto-baud */
278  if (Sts & UART_INTSTS_ABEO) {
279  // Disable AB interrupt
281  // Set Sync flag
282  ABsyncSts = SET;
283  }
284 
285  /* Auto-Baudrate Time-Out interrupt (not implemented) */
286  if (Sts & UART_INTSTS_ABTO) {
287  /* Disable this interrupt - Add your code here */
289  }
290  }
291 }
292 
293 /* UART transmit function for interrupt mode (using ring buffers) */
294 uint32_t Chip_UART_Interrupt_Transmit(LPC_USART_T *pUART, uint8_t *txbuf, uint8_t buflen)
295 {
296  uint8_t *data = (uint8_t *) txbuf;
297  uint32_t bytes = 0;
298 
299  /* Temporarily lock out UART transmit interrupts during this
300  read so the UART transmit interrupt won't cause problems
301  with the index values */
303 
304  /* Loop until transmit run buffer is full or until n_bytes
305  expires */
306  while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head, rb.tx_tail))) {
307  /* Write data from buffer into ring buffer */
308  rb.tx[rb.tx_head] = *data;
309  data++;
310 
311  /* Increment head pointer */
312  __BUF_INCR(rb.tx_head);
313 
314  /* Increment data count and decrement buffer size count */
315  bytes++;
316  buflen--;
317  }
318 
319  /*
320  * Check if current Tx interrupt enable is reset,
321  * that means the Tx interrupt must be re-enabled
322  * due to call UART_IntTransmit() function to trigger
323  * this interrupt type
324  */
325  if (TxIntStat == RESET) {
326  // Disable THRE interrupt
328 
329  /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
330  * of data or break whenever ring buffers are empty */
331  /* Wait until THR empty */
332  while (Chip_UART_CheckBusy(pUART) == SET) {}
333 
334  while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
335  /* Move a piece of data into the transmit FIFO */
336  if (Chip_UART_Send(pUART, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
337  /* Update transmit ring FIFO tail pointer */
338  __BUF_INCR(rb.tx_tail);
339  }
340  else {
341  break;
342  }
343  }
344 
345  /* If there is no more data to send, disable the transmit
346  interrupt - else enable it or keep it enabled */
347  if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
349  /* Reset Tx Interrupt state */
350  TxIntStat = RESET;
351  }
352  else {
353  /* Set Tx Interrupt state */
354  TxIntStat = SET;
356  }
357  }
358  /*
359  * Otherwise, re-enables Tx Interrupt
360  */
361  else {
363  }
364 
365  return bytes;
366 }
367 
368 /* UART read function for interrupt mode (using ring buffers) */
369 uint32_t Chip_UART_Interrupt_Receive(LPC_USART_T *pUART, uint8_t *rxbuf, uint8_t buflen)
370 {
371  uint8_t *data = (uint8_t *) rxbuf;
372  uint32_t bytes = 0;
373 
374  /* Temporarily lock out UART receive interrupts during this
375  read so the UART receive interrupt won't cause problems
376  with the index values */
378 
379  /* Loop until receive buffer ring is empty or
380  until max_bytes expires */
381  while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head, rb.rx_tail)))) {
382  /* Read data from ring buffer into user buffer */
383  *data = rb.rx[rb.rx_tail];
384  data++;
385 
386  /* Update tail pointer */
387  __BUF_INCR(rb.rx_tail);
388 
389  /* Increment data count and decrement buffer size count */
390  bytes++;
391  buflen--;
392  }
393 
394  /* Re-enable UART interrupts */
396 
397  return bytes;
398 }
399 
400 /* Reset Tx and Rx ring buffer (head and tail) */
402 {
403  (void) pUART;
404 
405  TxIntStat = RESET;
406 
407  /* Reset ring buf head and tail idx */
408  __BUF_RESET(rb.rx_head);
409  __BUF_RESET(rb.rx_tail);
410  __BUF_RESET(rb.tx_head);
411  __BUF_RESET(rb.tx_tail);
412 }
413 
414 /* UART interrupt service routine */
416 {
417  (void) pUART;
418 
419  return ABsyncSts;
420 }