1 /******************************************************************************
2 *  Filename:       uart.c
3 *  Revised:        2015-11-16 19:41:47 +0100 (Mon, 16 Nov 2015)
4 *  Revision:       45094
5 *
6 *  Description:    Driver for the UART.
7 *
8 *  Copyright (c) 2015, 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 <driverlib/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     //
82     // Check the arguments.
83     //
84     ASSERT(UARTBaseValid(ui32Base));
85 
86     //
87     // Read the FIFO level register.
88     //
89     ui32Temp = HWREG(ui32Base + UART_O_IFLS);
90 
91     //
92     // Extract the transmit and receive FIFO levels.
93     //
94     *pui32TxLevel = ui32Temp & UART_IFLS_TXSEL_M;
95     *pui32RxLevel = ui32Temp & UART_IFLS_RXSEL_M;
96 }
97 
98 //*****************************************************************************
99 //
100 //! Sets the configuration of a UART
101 //
102 //*****************************************************************************
103 void
UARTConfigSetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t ui32Baud,uint32_t ui32Config)104 UARTConfigSetExpClk(uint32_t ui32Base, uint32_t ui32UARTClk,
105                     uint32_t ui32Baud, uint32_t ui32Config)
106 {
107     uint32_t ui32Div;
108 
109     //
110     // Check the arguments.
111     //
112     ASSERT(UARTBaseValid(ui32Base));
113     ASSERT(ui32Baud != 0);
114 
115     //
116     // Stop the UART.
117     //
118     UARTDisable(ui32Base);
119 
120     //
121     // Compute the fractional baud rate divider.
122     //
123     ui32Div = (((ui32UARTClk * 8) / ui32Baud) + 1) / 2;
124 
125     //
126     // Set the baud rate.
127     //
128     HWREG(ui32Base + UART_O_IBRD) = ui32Div / 64;
129     HWREG(ui32Base + UART_O_FBRD) = ui32Div % 64;
130 
131     //
132     // Set parity, data length, and number of stop bits.
133     //
134     HWREG(ui32Base + UART_O_LCRH) = ui32Config;
135 }
136 
137 //*****************************************************************************
138 //
139 //! Gets the current configuration of a UART
140 //
141 //*****************************************************************************
142 void
UARTConfigGetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t * pui32Baud,uint32_t * pui32Config)143 UARTConfigGetExpClk(uint32_t ui32Base, uint32_t ui32UARTClk,
144                     uint32_t *pui32Baud, uint32_t *pui32Config)
145 {
146     uint32_t ui32Int, ui32Frac;
147 
148     //
149     // Check the arguments.
150     //
151     ASSERT(UARTBaseValid(ui32Base));
152 
153     //
154     // Compute the baud rate.
155     //
156     ui32Int = HWREG(ui32Base + UART_O_IBRD);
157     ui32Frac = HWREG(ui32Base + UART_O_FBRD);
158     *pui32Baud = (ui32UARTClk * 4) / ((64 * ui32Int) + ui32Frac);
159 
160     //
161     // Get the parity, data length, and number of stop bits.
162     //
163     *pui32Config = (HWREG(ui32Base + UART_O_LCRH) &
164                     (UART_LCRH_SPS | UART_LCRH_WLEN_M | UART_LCRH_STP2 |
165                      UART_LCRH_EPS | UART_LCRH_PEN));
166 }
167 
168 //*****************************************************************************
169 //
170 //! Disables transmitting and receiving
171 //
172 //*****************************************************************************
173 void
UARTDisable(uint32_t ui32Base)174 UARTDisable(uint32_t ui32Base)
175 {
176 
177     //
178     // Check the arguments.
179     //
180     ASSERT(UARTBaseValid(ui32Base));
181 
182     //
183     // Wait for end of TX.
184     //
185     while(HWREG(ui32Base + UART_O_FR) & UART_FR_BUSY)
186     {
187     }
188 
189     //
190     // Disable the FIFO.
191     //
192     HWREG(ui32Base + UART_O_LCRH) &= ~(UART_LCRH_FEN);
193 
194     //
195     // Disable the UART.
196     //
197     HWREG(ui32Base + UART_O_CTL) &= ~(UART_CTL_UARTEN | UART_CTL_TXE |
198                                       UART_CTL_RXE);
199 }
200 
201 //*****************************************************************************
202 //
203 //! Receives a character from the specified port
204 //
205 //*****************************************************************************
206 int32_t
UARTCharGetNonBlocking(uint32_t ui32Base)207 UARTCharGetNonBlocking(uint32_t ui32Base)
208 {
209     //
210     // Check the arguments.
211     //
212     ASSERT(UARTBaseValid(ui32Base));
213 
214     //
215     // See if there are any characters in the receive FIFO.
216     //
217     if(!(HWREG(ui32Base + UART_O_FR) & UART_FR_RXFE))
218     {
219         //
220         // Read and return the next character.
221         //
222         return(HWREG(ui32Base + UART_O_DR));
223     }
224     else
225     {
226         //
227         // There are no characters, so return a failure.
228         //
229         return(-1);
230     }
231 }
232 
233 //*****************************************************************************
234 //
235 //! Waits for a character from the specified port
236 //
237 //*****************************************************************************
238 int32_t
UARTCharGet(uint32_t ui32Base)239 UARTCharGet(uint32_t ui32Base)
240 {
241     //
242     // Check the arguments.
243     //
244     ASSERT(UARTBaseValid(ui32Base));
245 
246     //
247     // Wait until a char is available.
248     //
249     while(HWREG(ui32Base + UART_O_FR) & UART_FR_RXFE)
250     {
251     }
252 
253     //
254     // Now get the character.
255     //
256     return(HWREG(ui32Base + UART_O_DR));
257 }
258 
259 //*****************************************************************************
260 //
261 //! Sends a character to the specified port
262 //
263 //*****************************************************************************
264 bool
UARTCharPutNonBlocking(uint32_t ui32Base,uint8_t ui8Data)265 UARTCharPutNonBlocking(uint32_t ui32Base, uint8_t ui8Data)
266 {
267     //
268     // Check the arguments.
269     //
270     ASSERT(UARTBaseValid(ui32Base));
271 
272     //
273     // See if there is space in the transmit FIFO.
274     //
275     if(!(HWREG(ui32Base + UART_O_FR) & UART_FR_TXFF))
276     {
277         //
278         // Write this character to the transmit FIFO.
279         //
280         HWREG(ui32Base + UART_O_DR) = ui8Data;
281 
282         //
283         // Success.
284         //
285         return(true);
286     }
287     else
288     {
289         //
290         // There is no space in the transmit FIFO, so return a failure.
291         //
292         return(false);
293     }
294 }
295 
296 //*****************************************************************************
297 //
298 //! Waits to send a character from the specified port
299 //
300 //*****************************************************************************
301 void
UARTCharPut(uint32_t ui32Base,uint8_t ui8Data)302 UARTCharPut(uint32_t ui32Base, uint8_t ui8Data)
303 {
304     //
305     // Check the arguments.
306     //
307     ASSERT(UARTBaseValid(ui32Base));
308 
309     //
310     // Wait until space is available.
311     //
312     while(HWREG(ui32Base + UART_O_FR) & UART_FR_TXFF)
313     {
314     }
315 
316     //
317     // Send the char.
318     //
319     HWREG(ui32Base + UART_O_DR) = ui8Data;
320 }
321 
322 //*****************************************************************************
323 //
324 //! Registers an interrupt handler for a UART interrupt
325 //
326 //*****************************************************************************
327 void
UARTIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))328 UARTIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
329 {
330     //
331     // Check the arguments.
332     //
333     ASSERT(UARTBaseValid(ui32Base));
334 
335     //
336     // Register the interrupt handler.
337     //
338     IntRegister(INT_UART0_COMB, pfnHandler);
339 
340     //
341     // Enable the UART interrupt.
342     //
343     IntEnable(INT_UART0_COMB);
344 }
345 
346 //*****************************************************************************
347 //
348 //! Unregisters an interrupt handler for a UART interrupt
349 //
350 //*****************************************************************************
351 void
UARTIntUnregister(uint32_t ui32Base)352 UARTIntUnregister(uint32_t ui32Base)
353 {
354     //
355     // Check the arguments.
356     //
357     ASSERT(UARTBaseValid(ui32Base));
358 
359     //
360     // Disable the interrupt.
361     //
362     IntDisable(INT_UART0_COMB);
363 
364     //
365     // Unregister the interrupt handler.
366     //
367     IntUnregister(INT_UART0_COMB);
368 }
369