1 /******************************************************************************
2 * Filename: uart.c
3 * Revised: 2020-02-14 11:30:20 +0100 (Fri, 14 Feb 2020)
4 * Revision: 56760
5 *
6 * Description: Driver for the UART.
7 *
8 * Copyright (c) 2015 - 2017, Texas Instruments Incorporated
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * 1) Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * 2) Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 *
21 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38
39 #include "uart.h"
40
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48 #undef UARTFIFOLevelGet
49 #define UARTFIFOLevelGet NOROM_UARTFIFOLevelGet
50 #undef UARTConfigSetExpClk
51 #define UARTConfigSetExpClk NOROM_UARTConfigSetExpClk
52 #undef UARTConfigGetExpClk
53 #define UARTConfigGetExpClk NOROM_UARTConfigGetExpClk
54 #undef UARTDisable
55 #define UARTDisable NOROM_UARTDisable
56 #undef UARTCharGetNonBlocking
57 #define UARTCharGetNonBlocking NOROM_UARTCharGetNonBlocking
58 #undef UARTCharGet
59 #define UARTCharGet NOROM_UARTCharGet
60 #undef UARTCharPutNonBlocking
61 #define UARTCharPutNonBlocking NOROM_UARTCharPutNonBlocking
62 #undef UARTCharPut
63 #define UARTCharPut NOROM_UARTCharPut
64 #undef UARTIntRegister
65 #define UARTIntRegister NOROM_UARTIntRegister
66 #undef UARTIntUnregister
67 #define UARTIntUnregister NOROM_UARTIntUnregister
68 #endif
69
70 //*****************************************************************************
71 //
72 // Gets the FIFO level at which interrupts are generated
73 //
74 //*****************************************************************************
75 void
UARTFIFOLevelGet(uint32_t ui32Base,uint32_t * pui32TxLevel,uint32_t * pui32RxLevel)76 UARTFIFOLevelGet(uint32_t ui32Base, uint32_t *pui32TxLevel,
77 uint32_t *pui32RxLevel)
78 {
79 uint32_t ui32Temp;
80
81 // Check the arguments.
82 ASSERT(UARTBaseValid(ui32Base));
83
84 // Read the FIFO level register.
85 ui32Temp = HWREG(ui32Base + UART_O_IFLS);
86
87 // Extract the transmit and receive FIFO levels.
88 *pui32TxLevel = ui32Temp & UART_IFLS_TXSEL_M;
89 *pui32RxLevel = ui32Temp & UART_IFLS_RXSEL_M;
90 }
91
92 //*****************************************************************************
93 //
94 // Sets the configuration of a UART
95 //
96 //*****************************************************************************
97 void
UARTConfigSetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t ui32Baud,uint32_t ui32Config)98 UARTConfigSetExpClk(uint32_t ui32Base, uint32_t ui32UARTClk,
99 uint32_t ui32Baud, uint32_t ui32Config)
100 {
101 uint32_t ui32Div;
102
103 // Check the arguments.
104 ASSERT(UARTBaseValid(ui32Base));
105 ASSERT(ui32Baud != 0);
106
107 // Stop the UART.
108 UARTDisable(ui32Base);
109
110 // Compute the fractional baud rate divider.
111 ui32Div = (((ui32UARTClk * 8) / ui32Baud) + 1) / 2;
112
113 // Set the baud rate.
114 HWREG(ui32Base + UART_O_IBRD) = ui32Div / 64;
115 HWREG(ui32Base + UART_O_FBRD) = ui32Div % 64;
116
117 // Set parity, data length, and number of stop bits.
118 HWREG(ui32Base + UART_O_LCRH) = ui32Config;
119 }
120
121 //*****************************************************************************
122 //
123 // Gets the current configuration of a UART
124 //
125 //*****************************************************************************
126 void
UARTConfigGetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t * pui32Baud,uint32_t * pui32Config)127 UARTConfigGetExpClk(uint32_t ui32Base, uint32_t ui32UARTClk,
128 uint32_t *pui32Baud, uint32_t *pui32Config)
129 {
130 uint32_t ui32Int, ui32Frac;
131
132 // Check the arguments.
133 ASSERT(UARTBaseValid(ui32Base));
134
135 // Compute the baud rate.
136 ui32Int = HWREG(ui32Base + UART_O_IBRD);
137 ui32Frac = HWREG(ui32Base + UART_O_FBRD);
138 *pui32Baud = (ui32UARTClk * 4) / ((64 * ui32Int) + ui32Frac);
139
140 // Get the parity, data length, and number of stop bits.
141 *pui32Config = (HWREG(ui32Base + UART_O_LCRH) &
142 (UART_LCRH_SPS | UART_LCRH_WLEN_M | UART_LCRH_STP2 |
143 UART_LCRH_EPS | UART_LCRH_PEN));
144 }
145
146 //*****************************************************************************
147 //
148 // Disables transmitting and receiving
149 //
150 //*****************************************************************************
151 void
UARTDisable(uint32_t ui32Base)152 UARTDisable(uint32_t ui32Base)
153 {
154
155 // Check the arguments.
156 ASSERT(UARTBaseValid(ui32Base));
157
158 // Wait for end of TX.
159 while(HWREG(ui32Base + UART_O_FR) & UART_FR_BUSY)
160 {
161 }
162
163 // Disable the FIFO.
164 HWREG(ui32Base + UART_O_LCRH) &= ~(UART_LCRH_FEN);
165
166 // Disable the UART.
167 HWREG(ui32Base + UART_O_CTL) &= ~(UART_CTL_UARTEN | UART_CTL_TXE |
168 UART_CTL_RXE);
169 }
170
171 //*****************************************************************************
172 //
173 // Receives a character from the specified port
174 //
175 //*****************************************************************************
176 int32_t
UARTCharGetNonBlocking(uint32_t ui32Base)177 UARTCharGetNonBlocking(uint32_t ui32Base)
178 {
179 // Check the arguments.
180 ASSERT(UARTBaseValid(ui32Base));
181
182 // See if there are any characters in the receive FIFO.
183 if(!(HWREG(ui32Base + UART_O_FR) & UART_FR_RXFE))
184 {
185 // Read and return the next character.
186 return(HWREG(ui32Base + UART_O_DR));
187 }
188 else
189 {
190 // There are no characters, so return a failure.
191 return(-1);
192 }
193 }
194
195 //*****************************************************************************
196 //
197 // Waits for a character from the specified port
198 //
199 //*****************************************************************************
200 int32_t
UARTCharGet(uint32_t ui32Base)201 UARTCharGet(uint32_t ui32Base)
202 {
203 // Check the arguments.
204 ASSERT(UARTBaseValid(ui32Base));
205
206 // Wait until a char is available.
207 while(HWREG(ui32Base + UART_O_FR) & UART_FR_RXFE)
208 {
209 }
210
211 // Now get the character.
212 return(HWREG(ui32Base + UART_O_DR));
213 }
214
215 //*****************************************************************************
216 //
217 // Sends a character to the specified port
218 //
219 //*****************************************************************************
220 bool
UARTCharPutNonBlocking(uint32_t ui32Base,uint8_t ui8Data)221 UARTCharPutNonBlocking(uint32_t ui32Base, uint8_t ui8Data)
222 {
223 // Check the arguments.
224 ASSERT(UARTBaseValid(ui32Base));
225
226 // See if there is space in the transmit FIFO.
227 if(!(HWREG(ui32Base + UART_O_FR) & UART_FR_TXFF))
228 {
229 // Write this character to the transmit FIFO.
230 HWREG(ui32Base + UART_O_DR) = ui8Data;
231
232 // Success.
233 return(true);
234 }
235 else
236 {
237 // There is no space in the transmit FIFO, so return a failure.
238 return(false);
239 }
240 }
241
242 //*****************************************************************************
243 //
244 // Waits to send a character from the specified port
245 //
246 //*****************************************************************************
247 void
UARTCharPut(uint32_t ui32Base,uint8_t ui8Data)248 UARTCharPut(uint32_t ui32Base, uint8_t ui8Data)
249 {
250 // Check the arguments.
251 ASSERT(UARTBaseValid(ui32Base));
252
253 // Wait until space is available.
254 while(HWREG(ui32Base + UART_O_FR) & UART_FR_TXFF)
255 {
256 }
257
258 // Send the char.
259 HWREG(ui32Base + UART_O_DR) = ui8Data;
260 }
261
262 //*****************************************************************************
263 //
264 // Registers an interrupt handler for a UART interrupt
265 //
266 //*****************************************************************************
267 void
UARTIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))268 UARTIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
269 {
270 // Check the arguments.
271 ASSERT(UARTBaseValid(ui32Base));
272
273 // Register and enable the interrupt handler.
274 // (Doing the '& 0xFFFF' to catch both buffered and unbufferd offsets)
275 if (( ui32Base & 0xFFFF ) == ( UART0_BASE & 0xFFFF )) {
276 IntRegister(INT_UART0_COMB, pfnHandler);
277 IntEnable(INT_UART0_COMB);
278 } else {
279 IntRegister(INT_UART1_COMB, pfnHandler);
280 IntEnable(INT_UART1_COMB);
281 }
282 }
283
284 //*****************************************************************************
285 //
286 // Unregisters an interrupt handler for a UART interrupt
287 //
288 //*****************************************************************************
289 void
UARTIntUnregister(uint32_t ui32Base)290 UARTIntUnregister(uint32_t ui32Base)
291 {
292 // Check the arguments.
293 ASSERT(UARTBaseValid(ui32Base));
294
295 // Disable and unregister the interrupt.
296 // (Doing the '& 0xFFFF' to catch both buffered and unbufferd offsets)
297 if (( ui32Base & 0xFFFF ) == ( UART0_BASE & 0xFFFF )) {
298 IntDisable(INT_UART0_COMB);
299 IntUnregister(INT_UART0_COMB);
300 } else {
301 IntDisable(INT_UART1_COMB);
302 IntUnregister(INT_UART1_COMB);
303 }
304 }
305