LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 
40 
42 static __IO FlagStatus TxIntStat;
43 
45 /*****************************************************************************
46  * Public types/enumerations/variables
47  ****************************************************************************/
48 
49 /*****************************************************************************
50  * Private functions
51  ****************************************************************************/
52 
53 /* Get UART number based on selected UART */
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 */
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 */
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 */
107 {
108  IP_UART_ID_T UARTPort = Chip_UART_Get_UARTNum(pUART);
109 
110  IP_UART_DeInit(pUART, UARTPort);
111 
112  /* Disable UART clocking */
114 }
115 
116 /* Determines best dividers to get a target baud rate */
118 {
119  uint32_t uClk;
120 
121  /* Get UART clock rate */
123 
124  return IP_UART_SetBaud(pUART, baudrate, uClk);
125 }
126 
127 /* Enable/Disable transmission on UART TxD pin */
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 */
137 {
138  uint32_t intsrc, tmp, tmp1;
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 \
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 */
180 {
181  uint8_t tmpc;
182  uint32_t rLen;
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 */
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)) {
232  // Reset Tx Interrupt state
233  TxIntStat = RESET;
234  }
235  else {
236  /* Set Tx Interrupt state */
237  TxIntStat = SET;
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
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 */
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 */
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
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)) {
321  /* Reset Tx Interrupt state */
322  TxIntStat = RESET;
323  }
324  else {
325  /* Set Tx Interrupt state */
326  TxIntStat = SET;
328  }
329  }
330  /*
331  * Otherwise, re-enables Tx Interrupt
332  */
333  else {
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 */
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 */
368 
369  return bytes;
370 }
371 
372 /* Reset Tx and Rx ring buffer (head and tail) */
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 */
388 {
389  (void) pUART;
390 
391  return ABsyncSts;
392 }