Sprites, sprites, sprites
[hackover2013-badge-firmware.git] / core / uart / uart.c
1 /**************************************************************************/
2 /*!
3 @file uart.c
4 @author K. Townsend (microBuilder.eu)
5 @date 22 March 2010
6 @version 0.10
7
8 @section DESCRIPTION
9
10 Generic code for UART-based communication. Incoming text is stored
11 in a FIFO Queue for safer processing.
12
13 @section Example: Sending text via UART
14
15 @code
16 #include "core/cpu/cpu.h"
17 #include "core/uart/uart.h"
18 ...
19 #define UARTBUFFERSIZE 5
20 ...
21 cpuInit();
22 uartInit(57600);
23 ...
24 uint8_t uartBuffer[UARTBUFFERSIZE] = { 'T', 'e', 's', 't', '\n' };
25
26 // Send contents of uartBuffer
27 uartSend((uint8_t *)uartBuffer, UARTBUFFERSIZE);
28 @endcode
29
30 @section Example: Reading from UART
31
32 @code
33
34 #include "core/cpu/cpu.h"
35 #include "core/uart/uart.h"
36
37 cpuInit();
38 uartInit(57600);
39
40 // Get a reference to the UART control block
41 uart_pcb_t *pcb = uartGetPCB();
42
43 // Read any text available in the queue
44 while (uartRxBufferDataPending())
45 {
46 // Read the first available character
47 uint8_t c = uartRxBufferRead();
48
49 // read out the data in the buffer and echo it back to the host.
50 switch (c)
51 {
52 case '\r':
53 printf("\n\r");
54 break;
55 default:
56 printf("%c", c);
57 break;
58 }
59 }
60
61 #endcode
62
63 @section LICENSE
64
65 Software License Agreement (BSD License)
66
67 Copyright (c) 2010, microBuilder SARL
68 All rights reserved.
69
70 Redistribution and use in source and binary forms, with or without
71 modification, are permitted provided that the following conditions are met:
72 1. Redistributions of source code must retain the above copyright
73 notice, this list of conditions and the following disclaimer.
74 2. Redistributions in binary form must reproduce the above copyright
75 notice, this list of conditions and the following disclaimer in the
76 documentation and/or other materials provided with the distribution.
77 3. Neither the name of the copyright holders nor the
78 names of its contributors may be used to endorse or promote products
79 derived from this software without specific prior written permission.
80
81 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
82 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
83 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
84 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
85 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
86 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
87 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
88 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
89 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91 */
92 /**************************************************************************/
93
94 #include <string.h>
95
96 #include "uart.h"
97
98 #ifdef CFG_INTERFACE_UART
99 #include "core/cmd/cmd.h"
100 #endif
101
102 /**************************************************************************/
103 /*!
104 UART protocol control block, which is used to safely access the
105 RX FIFO buffer from elsewhere in the code. This should be accessed
106 through 'uartGetPCB()'.
107 */
108 /**************************************************************************/
109 static uart_pcb_t pcb;
110
111 /**************************************************************************/
112 /*!
113 IRQ to handle incoming data, etc.
114 */
115 /**************************************************************************/
116 void UART_IRQHandler(void)
117 {
118 uint8_t IIRValue, LSRValue;
119 uint8_t Dummy = Dummy;
120
121 IIRValue = UART_U0IIR;
122 IIRValue &= ~(UART_U0IIR_IntStatus_MASK); /* skip pending bit in IIR */
123 IIRValue &= UART_U0IIR_IntId_MASK; /* check bit 1~3, interrupt identification */
124
125 // 1.) Check receiver line status
126 if (IIRValue == UART_U0IIR_IntId_RLS)
127 {
128 LSRValue = UART_U0LSR;
129 // Check for errors
130 if (LSRValue & (UART_U0LSR_OE | UART_U0LSR_PE | UART_U0LSR_FE | UART_U0LSR_RXFE | UART_U0LSR_BI))
131 {
132 /* There are errors or break interrupt */
133 /* Read LSR will clear the interrupt */
134 pcb.status = LSRValue;
135 Dummy = UART_U0RBR; /* Dummy read on RX to clear interrupt, then bail out */
136 return;
137 }
138 // No error and receive data is ready
139 if (LSRValue & UART_U0LSR_RDR_DATA)
140 {
141 /* If no error on RLS, normal ready, save into the data buffer. */
142 /* Note: read RBR will clear the interrupt */
143 uartRxBufferWrite(UART_U0RBR);
144 }
145 }
146
147 // 2.) Check receive data available
148 else if (IIRValue == UART_U0IIR_IntId_RDA)
149 {
150 // Add incoming text to UART buffer
151 uartRxBufferWrite(UART_U0RBR);
152 }
153
154 // 3.) Check character timeout indicator
155 else if (IIRValue == UART_U0IIR_IntId_CTI)
156 {
157 /* Bit 9 as the CTI error */
158 pcb.status |= 0x100;
159 }
160
161 // 4.) Check THRE (transmit holding register empty)
162 else if (IIRValue == UART_U0IIR_IntId_THRE)
163 {
164 /* Check status in the LSR to see if valid data in U0THR or not */
165 LSRValue = UART_U0LSR;
166 if (LSRValue & UART_U0LSR_THRE)
167 {
168 pcb.pending_tx_data = 0;
169 }
170 else
171 {
172 pcb.pending_tx_data= 1;
173 }
174 }
175 return;
176 }
177
178 /**************************************************************************/
179 /*!
180 @brief Get a pointer to the UART's protocol control block, which can
181 be used to control the RX FIFO buffer and check whether UART
182 has already been initialised or not.
183
184 @section Example
185
186 @code
187 // Make sure that UART is initialised
188 uart_pcb_t *pcb = uartGetPCB();
189 if (!pcb->initialised)
190 {
191 uartInit(CFG_UART_BAUDRATE);
192 }
193 @endcode
194
195 */
196 /**************************************************************************/
197 uart_pcb_t *uartGetPCB()
198 {
199 return &pcb;
200 }
201
202 /**************************************************************************/
203 /*!
204 @brief Initialises UART at the specified baud rate.
205
206 @param[in] baudRate
207 The baud rate to use when configuring the UART.
208 */
209 /**************************************************************************/
210 void uartInit(uint32_t baudrate)
211 {
212 uint32_t fDiv;
213 uint32_t regVal;
214
215 NVIC_DisableIRQ(UART_IRQn);
216
217 // Clear protocol control blocks
218 memset(&pcb, 0, sizeof(uart_pcb_t));
219 pcb.pending_tx_data = 0;
220 uartRxBufferInit();
221
222 /* Set 1.6 UART RXD */
223 IOCON_PIO1_6 &= ~IOCON_PIO1_6_FUNC_MASK;
224 IOCON_PIO1_6 |= IOCON_PIO1_6_FUNC_UART_RXD;
225
226 /* Set 1.7 UART TXD */
227 IOCON_PIO1_7 &= ~IOCON_PIO1_7_FUNC_MASK;
228 IOCON_PIO1_7 |= IOCON_PIO1_7_FUNC_UART_TXD;
229
230 /* Enable UART clock */
231 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_UART);
232 SCB_UARTCLKDIV = SCB_UARTCLKDIV_DIV1; /* divided by 1 */
233
234 /* 8 bits, no Parity, 1 Stop bit */
235 UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
236 UART_U0LCR_Stop_Bit_Select_1Bits |
237 UART_U0LCR_Parity_Disabled |
238 UART_U0LCR_Parity_Select_OddParity |
239 UART_U0LCR_Break_Control_Disabled |
240 UART_U0LCR_Divisor_Latch_Access_Enabled);
241
242 /* Baud rate */
243 regVal = SCB_UARTCLKDIV;
244 fDiv = (((CFG_CPU_CCLK * SCB_SYSAHBCLKDIV)/regVal)/16)/baudrate;
245
246 UART_U0DLM = fDiv / 256;
247 UART_U0DLL = fDiv % 256;
248
249 /* Set DLAB back to 0 */
250 UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
251 UART_U0LCR_Stop_Bit_Select_1Bits |
252 UART_U0LCR_Parity_Disabled |
253 UART_U0LCR_Parity_Select_OddParity |
254 UART_U0LCR_Break_Control_Disabled |
255 UART_U0LCR_Divisor_Latch_Access_Disabled);
256
257 /* Enable and reset TX and RX FIFO. */
258 UART_U0FCR = (UART_U0FCR_FIFO_Enabled |
259 UART_U0FCR_Rx_FIFO_Reset |
260 UART_U0FCR_Tx_FIFO_Reset);
261
262 /* Read to clear the line status. */
263 regVal = UART_U0LSR;
264
265 /* Ensure a clean start, no data in either TX or RX FIFO. */
266 while (( UART_U0LSR & (UART_U0LSR_THRE|UART_U0LSR_TEMT)) != (UART_U0LSR_THRE|UART_U0LSR_TEMT) );
267 while ( UART_U0LSR & UART_U0LSR_RDR_DATA )
268 {
269 /* Dump data from RX FIFO */
270 regVal = UART_U0RBR;
271 }
272
273 /* Set the initialised flag in the protocol control block */
274 pcb.initialised = 1;
275 pcb.baudrate = baudrate;
276
277 /* Enable the UART Interrupt */
278 NVIC_EnableIRQ(UART_IRQn);
279 UART_U0IER = UART_U0IER_RBR_Interrupt_Enabled | UART_U0IER_RLS_Interrupt_Enabled;
280
281 return;
282 }
283
284 /**************************************************************************/
285 /*!
286 @brief Sends the contents of supplied text buffer over UART.
287
288 @param[in] bufferPtr
289 Pointer to the text buffer
290 @param[in] bufferPtr
291 The size of the text buffer
292
293 @section Example
294
295 @code
296 // Set 5-character text buffer
297 uint8_t uartBuffer[5] = { 'T', 'e', 's', 't', '\n' };
298 // Send contents of uartBuffer
299 uartSend((uint8_t *)uartBuffer, 5);
300 @endcode
301
302 */
303 /**************************************************************************/
304 void uartSend (uint8_t *bufferPtr, uint32_t length)
305 {
306 while (length != 0)
307 {
308 /* THRE status, contain valid data */
309 while ( !(UART_U0LSR & UART_U0LSR_THRE) );
310 UART_U0THR = *bufferPtr;
311
312 bufferPtr++;
313 length--;
314 }
315
316 return;
317 }
318
319 /**************************************************************************/
320 /*!
321 @brief Sends a single byte over UART.
322
323 @param[in] byte
324 Byte value to send
325
326 @section Example
327
328 @code
329 // Send 0xFF over UART
330 uartSendByte(0xFF);
331 // Send 'B' over UART (note single quotes)
332 uartSendByte('B');
333 @endcode
334
335 */
336 /**************************************************************************/
337 void uartSendByte (uint8_t byte)
338 {
339 /* THRE status, contain valid data */
340 while ( !(UART_U0LSR & UART_U0LSR_THRE) );
341 UART_U0THR = byte;
342
343 return;
344 }
345
346
347
This page took 0.066481 seconds and 5 git commands to generate.