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