LPCOpen Platform
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 "uart_18xx_43xx.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
40 
42 static __IO FlagStatus TxIntStat;
43 
44 /*****************************************************************************
45  * Public types/enumerations/variables
46  ****************************************************************************/
47 
48 /*****************************************************************************
49  * Private functions
50  ****************************************************************************/
51 
52 /* Get UART number based on selected UART */
54 {
55  if (UARTx == LPC_USART0) {
56  return UART_0;
57  }
58  else if (UARTx == LPC_UART1) {
59  return UART_1;
60  }
61  else if (UARTx == LPC_USART2) {
62  return UART_2;
63  }
64 
65  return UART_3;
66 }
67 
68 /* Determine UART clock based in selected UART */
70  CCU_CLK_T uartclk;
71 
72  /* Pick clock for uart BASED ON SELECTED uart */
73  if (UARTx == LPC_UART1) {
74  uartclk = CLK_MX_UART1;
75  }
76  if (UARTx == LPC_USART2) {
77  uartclk = CLK_MX_UART2;
78  }
79  if (UARTx == LPC_USART3) {
80  uartclk = CLK_MX_UART3;
81  }
82  else {
83  uartclk = CLK_MX_UART0;
84  }
85 
86  return uartclk;
87 }
88 
89 /*****************************************************************************
90  * Public functions
91  ****************************************************************************/
92 
93 /* Initializes the UARTx peripheral */
95 {
96  UART_ID_Type UARTPort = Chip_UART_Get_UARTNum(UARTx);
97 
98  /* Enable UART clocking. UART base clock(s) must already be enabled */
99  Chip_Clock_EnableOpts(Chip_UART_DetermineClk(UARTx), true, true, 1);
100 
101  IP_UART_Init(UARTx, UARTPort);
102 }
103 
104 /* De-initializes the UARTx peripheral */
106 {
107  UART_ID_Type UARTPort = Chip_UART_Get_UARTNum(UARTx);
108 
109  IP_UART_DeInit(UARTx, UARTPort);
110 
111  /* Disable UART clocking */
113 }
114 
115 /* Determines best dividers to get a target baud rate */
117 {
118  uint32_t uClk;
119 
120  /* Get UART clock rate */
122 
123  return IP_UART_SetBaud(UARTx, baudrate, uClk);
124 }
125 
126 /* Enable/Disable transmission on UART TxD pin */
128 {
129  UART_ID_Type UARTPort = Chip_UART_Get_UARTNum(UARTx);
130 
131  IP_UART_TxCmd(UARTx, UARTPort, NewState);
132 }
133 
134 /* Get Interrupt Stream Status */
136 {
137  uint32_t intsrc, tmp, tmp1;
139 
140  /* Determine the interrupt source */
141  intsrc = Chip_UART_IntGetStatus(UARTx);
142 
143  tmp = intsrc & UART_IIR_INTID_MASK;
144 
145  /* Receive Line Status */
146  if (tmp == UART_IIR_INTID_RLS) {
147  /* Check line status */
148  tmp1 = (uint32_t) Chip_UART_GetLineStatus(UARTx);
149  /* Mask out the Receive Ready and Transmit Holding empty status */
150  tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
152  /* If any error exist */
153  if (tmp1) {
154  return UART_ERROR;
155  }
156  }
157 
158  /* Receive Data Available or Character time-out */
159  if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)) {
160  ret |= READY_TO_RECEIVE;
161  }
162 
163  /* Transmit Holding Empty */
164  if (tmp == UART_IIR_INTID_THRE) {
165  ret |= READY_TO_SEND;
166  }
167  return ret;
168 }
169 
170 /* UART interrupt service routine */
172 {
173  uint8_t tmpc;
174  uint32_t rLen;
176  if (Sts == UART_ERROR) {
177  return; /* error */
178 
179  }
180  if (Sts & READY_TO_RECEIVE) { /* ready for Read Data */
181  while (1) {
182  /* Call UART read function in UART driver */
183  rLen = Chip_UART_Receive(UARTx, &tmpc, 1, NONE_BLOCKING);
184  /* If data received */
185  if (rLen) {
186  /* Check if buffer is more space
187  * If no more space, remaining character will be trimmed out
188  */
189  if (!__BUF_IS_FULL(rb.rx_head, rb.rx_tail)) {
190  rb.rx[rb.rx_head] = tmpc;
191  __BUF_INCR(rb.rx_head);
192  }
193  }
194  /* no more data */
195  else {
196  break;
197  }
198  }
199  }
200 
201  if (Sts & READY_TO_SEND) { /* ready for Write Data */
202  /* Disable THRE interrupt */
204 
205  /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
206  * of data or break whenever ring buffers are empty */
207  /* Wait until THR empty */
208  while (Chip_UART_CheckBusy(UARTx) == SET) ;
209 
210  while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
211  /* Move a piece of data into the transmit FIFO */
212  if (Chip_UART_Send(UARTx, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
213  /* Update transmit ring FIFO tail pointer */
214  __BUF_INCR(rb.tx_tail);
215  }
216  else {
217  break;
218  }
219  }
220 
221  /* If there is no more data to send, disable the transmit
222  interrupt - else enable it or keep it enabled */
223  if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
225  // Reset Tx Interrupt state
226  TxIntStat = RESET;
227  }
228  else {
229  /* Set Tx Interrupt state */
230  TxIntStat = SET;
232  }
233  }
234 }
235 
236 /* UART transmit function for interrupt mode (using ring buffers) */
237 uint32_t Chip_UART_Interrupt_Transmit(LPC_USART_Type *UARTx, uint8_t *txbuf, uint8_t buflen)
238 {
239  uint8_t *data = (uint8_t *) txbuf;
240  uint32_t bytes = 0;
241 
242  /* Temporarily lock out UART transmit interrupts during this
243  read so the UART transmit interrupt won't cause problems
244  with the index values */
246 
247  /* Loop until transmit run buffer is full or until n_bytes
248  expires */
249  while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head, rb.tx_tail))) {
250  /* Write data from buffer into ring buffer */
251  rb.tx[rb.tx_head] = *data;
252  data++;
253 
254  /* Increment head pointer */
255  __BUF_INCR(rb.tx_head);
256 
257  /* Increment data count and decrement buffer size count */
258  bytes++;
259  buflen--;
260  }
261 
262  /*
263  * Check if current Tx interrupt enable is reset,
264  * that means the Tx interrupt must be re-enabled
265  * due to call UART_IntTransmit() function to trigger
266  * this interrupt type
267  */
268  if (TxIntStat == RESET) {
269  // Disable THRE interrupt
271 
272  /* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
273  * of data or break whenever ring buffers are empty */
274  /* Wait until THR empty */
275  while (Chip_UART_CheckBusy(UARTx) == SET) ;
276 
277  while (!__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
278  /* Move a piece of data into the transmit FIFO */
279  if (Chip_UART_Send(UARTx, (uint8_t *) &rb.tx[rb.tx_tail], 1, NONE_BLOCKING)) {
280  /* Update transmit ring FIFO tail pointer */
281  __BUF_INCR(rb.tx_tail);
282  }
283  else {
284  break;
285  }
286  }
287 
288  /* If there is no more data to send, disable the transmit
289  interrupt - else enable it or keep it enabled */
290  if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
292  /* Reset Tx Interrupt state */
293  TxIntStat = RESET;
294  }
295  else {
296  /* Set Tx Interrupt state */
297  TxIntStat = SET;
299  }
300  }
301  /*
302  * Otherwise, re-enables Tx Interrupt
303  */
304  else {
306  }
307 
308  return bytes;
309 }
310 
311 /* UART read function for interrupt mode (using ring buffers) */
312 uint32_t Chip_UART_Interrupt_Receive(LPC_USART_Type *UARTx, uint8_t *rxbuf, uint8_t buflen)
313 {
314  uint8_t *data = (uint8_t *) rxbuf;
315  uint32_t bytes = 0;
316 
317  /* Temporarily lock out UART receive interrupts during this
318  read so the UART receive interrupt won't cause problems
319  with the index values */
321 
322  /* Loop until receive buffer ring is empty or
323  until max_bytes expires */
324  while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head, rb.rx_tail)))) {
325  /* Read data from ring buffer into user buffer */
326  *data = rb.rx[rb.rx_tail];
327  data++;
328 
329  /* Update tail pointer */
330  __BUF_INCR(rb.rx_tail);
331 
332  /* Increment data count and decrement buffer size count */
333  bytes++;
334  buflen--;
335  }
336 
337  /* Re-enable UART interrupts */
339 
340  return bytes;
341 }
342 
343 /* Reset Tx and Rx ring buffer (head and tail) */
345 {
346  TxIntStat = RESET;
347 
348  /* Reset ring buf head and tail idx */
349  __BUF_RESET(rb.rx_head);
350  __BUF_RESET(rb.rx_tail);
351  __BUF_RESET(rb.tx_head);
352  __BUF_RESET(rb.tx_tail);
353 }