1 /*
2 * @brief LPC15XX USART0 driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2013
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 licenser 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
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
46 /* Return UART clock ID from the UART register address */
getUARTClockID(LPC_USART_T * pUART)47 static CHIP_SYSCTL_CLOCK_T getUARTClockID(LPC_USART_T *pUART)
48 {
49 if (pUART == LPC_USART0) {
50 return SYSCTL_CLOCK_UART0;
51 }
52 else if (pUART == LPC_USART1) {
53 return SYSCTL_CLOCK_UART1;
54 }
55
56 return SYSCTL_CLOCK_UART2;
57 }
58
59 /*****************************************************************************
60 * Public functions
61 ****************************************************************************/
62
63 /* Initialize the UART peripheral */
Chip_UART_Init(LPC_USART_T * pUART)64 void Chip_UART_Init(LPC_USART_T *pUART)
65 {
66 /* Enable USART clock */
67 Chip_Clock_EnablePeriphClock(getUARTClockID(pUART));
68
69 /* UART reset */
70 if (pUART == LPC_USART0) {
71 /* Peripheral reset control to USART0 */
72 Chip_SYSCTL_PeriphReset(RESET_UART0);
73 }
74 else if (pUART == LPC_USART1) {
75 /* Peripheral reset control to USART1 */
76 Chip_SYSCTL_PeriphReset(RESET_UART1);
77 }
78 else {
79 /* Peripheral reset control to USART2 */
80 Chip_SYSCTL_PeriphReset(RESET_UART2);
81 }
82 }
83
84 /* Initialize the UART peripheral */
Chip_UART_DeInit(LPC_USART_T * pUART)85 void Chip_UART_DeInit(LPC_USART_T *pUART)
86 {
87 /* Disable USART clock */
88 Chip_Clock_DisablePeriphClock(getUARTClockID(pUART));
89 }
90
91 /* Transmit a byte array through the UART peripheral (non-blocking) */
Chip_UART_Send(LPC_USART_T * pUART,const void * data,int numBytes)92 int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes)
93 {
94 int sent = 0;
95 uint8_t *p8 = (uint8_t *) data;
96
97 /* Send until the transmit FIFO is full or out of bytes */
98 while ((sent < numBytes) &&
99 ((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0)) {
100 Chip_UART_SendByte(pUART, *p8);
101 p8++;
102 sent++;
103 }
104
105 return sent;
106 }
107
108 /* Transmit a byte array through the UART peripheral (blocking) */
Chip_UART_SendBlocking(LPC_USART_T * pUART,const void * data,int numBytes)109 int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes)
110 {
111 int pass, sent = 0;
112 uint8_t *p8 = (uint8_t *) data;
113
114 while (numBytes > 0) {
115 pass = Chip_UART_Send(pUART, p8, numBytes);
116 numBytes -= pass;
117 sent += pass;
118 p8 += pass;
119 }
120
121 return sent;
122 }
123
124 /* Read data through the UART peripheral (non-blocking) */
Chip_UART_Read(LPC_USART_T * pUART,void * data,int numBytes)125 int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes)
126 {
127 int readBytes = 0;
128 uint8_t *p8 = (uint8_t *) data;
129
130 /* Send until the transmit FIFO is full or out of bytes */
131 while ((readBytes < numBytes) &&
132 ((Chip_UART_GetStatus(pUART) & UART_STAT_RXRDY) != 0)) {
133 *p8 = Chip_UART_ReadByte(pUART);
134 p8++;
135 readBytes++;
136 }
137
138 return readBytes;
139 }
140
141 /* Read data through the UART peripheral (blocking) */
Chip_UART_ReadBlocking(LPC_USART_T * pUART,void * data,int numBytes)142 int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes)
143 {
144 int pass, readBytes = 0;
145 uint8_t *p8 = (uint8_t *) data;
146
147 while (readBytes < numBytes) {
148 pass = Chip_UART_Read(pUART, p8, numBytes);
149 numBytes -= pass;
150 readBytes += pass;
151 p8 += pass;
152 }
153
154 return readBytes;
155 }
156
157 /* Set baud rate for UART */
Chip_UART_SetBaud(LPC_USART_T * pUART,uint32_t baudrate)158 void Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate)
159 {
160 uint32_t baudRateGenerator;
161 baudRateGenerator = Chip_Clock_GetUARTBaseClockRate() / (16 * baudrate);
162 pUART->BRG = baudRateGenerator - 1; /* baud rate */
163 }
164
165 /* Set baud rate for UART using RTC32K oscillator */
Chip_UART_SetBaudWithRTC32K(LPC_USART_T * pUART,uint32_t baudrate)166 void Chip_UART_SetBaudWithRTC32K(LPC_USART_T *pUART, uint32_t baudrate)
167 {
168 /* Simple integer divide */
169 pUART->BRG = (Chip_Clock_GetRTCOscRate() / (3 * baudrate)) - 1;
170
171 pUART->CFG |= UART_MODE_32K;
172 }
173
174 /* UART receive-only interrupt handler for ring buffers */
Chip_UART_RXIntHandlerRB(LPC_USART_T * pUART,RINGBUFF_T * pRB)175 void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
176 {
177 /* New data will be ignored if data not popped in time */
178 while ((Chip_UART_GetStatus(pUART) & UART_STAT_RXRDY) != 0) {
179 uint8_t ch = Chip_UART_ReadByte(pUART);
180 RingBuffer_Insert(pRB, &ch);
181 }
182 }
183
184 /* UART transmit-only interrupt handler for ring buffers */
Chip_UART_TXIntHandlerRB(LPC_USART_T * pUART,RINGBUFF_T * pRB)185 void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
186 {
187 uint8_t ch;
188
189 /* Fill FIFO until full or until TX ring buffer is empty */
190 while (((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0) &&
191 RingBuffer_Pop(pRB, &ch)) {
192 Chip_UART_SendByte(pUART, ch);
193 }
194 }
195
196 /* Populate a transmit ring buffer and start UART transmit */
Chip_UART_SendRB(LPC_USART_T * pUART,RINGBUFF_T * pRB,const void * data,int count)197 uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int count)
198 {
199 uint32_t ret;
200 uint8_t *p8 = (uint8_t *) data;
201
202 /* Don't let UART transmit ring buffer change in the UART IRQ handler */
203 Chip_UART_IntDisable(pUART, UART_INTEN_TXRDY);
204
205 /* Move as much data as possible into transmit ring buffer */
206 ret = RingBuffer_InsertMult(pRB, p8, count);
207 Chip_UART_TXIntHandlerRB(pUART, pRB);
208
209 /* Add additional data to transmit ring buffer if possible */
210 ret += RingBuffer_InsertMult(pRB, (p8 + ret), (count - ret));
211
212 /* Enable UART transmit interrupt */
213 Chip_UART_IntEnable(pUART, UART_INTEN_TXRDY);
214
215 return ret;
216 }
217
218 /* Copy data from a receive ring buffer */
Chip_UART_ReadRB(LPC_USART_T * pUART,RINGBUFF_T * pRB,void * data,int bytes)219 int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes)
220 {
221 (void) pUART;
222
223 return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes);
224 }
225
226 /* UART receive/transmit interrupt handler for ring buffers */
Chip_UART_IRQRBHandler(LPC_USART_T * pUART,RINGBUFF_T * pRXRB,RINGBUFF_T * pTXRB)227 void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB)
228 {
229 /* Handle transmit interrupt if enabled */
230 if ((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0) {
231 Chip_UART_TXIntHandlerRB(pUART, pTXRB);
232
233 /* Disable transmit interrupt if the ring buffer is empty */
234 if (RingBuffer_IsEmpty(pTXRB)) {
235 Chip_UART_IntDisable(pUART, UART_INTEN_TXRDY);
236 }
237 }
238
239 /* Handle receive interrupt */
240 Chip_UART_RXIntHandlerRB(pUART, pRXRB);
241 }
242