1 | //uart.c
|
2 | #include <NXP\iolpc2103.h>
|
3 | #include <stdlib.h>
|
4 | #include <intrinsics.h>
|
5 | #include "main.h"
|
6 | #include "uart.h"
|
7 | #include "interrupts.h"
|
8 | #include <yfuns.h>
|
9 |
|
10 | /** local definitions **/
|
11 | #define UART_FIFO_SIZE 200
|
12 |
|
13 | typedef struct _UartFifo_t
|
14 | {
|
15 | uint32_t PushIndx;
|
16 | uint32_t PopIndx;
|
17 | uint8_t Buffer[UART_FIFO_SIZE];
|
18 | } UartFifo_t, *pUartFifo_t;
|
19 |
|
20 | pUartFifo_t pUart0RxFifo; // Pointer to a FIFO Buffer of the UART0 Receive
|
21 | pUartFifo_t pUart0TxFifo; // Pointer to a FIFO Buffer of the UART0 Transmit
|
22 |
|
23 | // Hold UART0 Events (PE, BI, FE, OE)
|
24 | UartLineEvents_t Uart0LineEvents;
|
25 |
|
26 | /*************************************************************************
|
27 | * Function Name: FifoPush
|
28 | * Parameters: pUartFifo_t Fifo, uint8_t Data
|
29 | *
|
30 | * Return: uint8_t
|
31 | *
|
32 | * Description: Push a char in a FIFO. Return 1 when push is successful
|
33 | * or 0 when the FIFO is full.
|
34 | *
|
35 | *************************************************************************/
|
36 | static uint8_t FifoPush(pUartFifo_t Fifo, uint8_t Data)
|
37 | {
|
38 | uint32_t IndxTmp;
|
39 |
|
40 | // calculate next push index
|
41 | IndxTmp = Fifo->PushIndx + 1;
|
42 | IndxTmp = IndxTmp % UART_FIFO_SIZE;
|
43 |
|
44 | // Check FIFO state
|
45 | if (IndxTmp == Fifo->PopIndx)
|
46 | {
|
47 | // The FIFO is full
|
48 | return(0);
|
49 | }
|
50 | // Push the data
|
51 | Fifo->Buffer[Fifo->PushIndx] = Data;
|
52 | // Updating the push's index
|
53 | Fifo->PushIndx = IndxTmp;
|
54 | return(1);
|
55 | }
|
56 |
|
57 | /*************************************************************************
|
58 | * Function Name: FifoPop
|
59 | * Parameters: pUartFifo_t Fifo, uint8_t Data
|
60 | *
|
61 | * Return: uint8_t
|
62 | *
|
63 | * Description: Pop a char from a FIFO. Return 1 when pop is successful
|
64 | * or 0 when the FIFO is empty.
|
65 | *
|
66 | *************************************************************************/
|
67 | static uint8_t FifoPop(pUartFifo_t Fifo, uint8_t* pData)
|
68 | {
|
69 | uint32_t IndxTmp;
|
70 | // Check FIFO state
|
71 | if (Fifo->PushIndx == Fifo->PopIndx)
|
72 | {
|
73 | // The FIFO is empty
|
74 | return(0);
|
75 | }
|
76 | // Calculate the next pop index
|
77 | IndxTmp = Fifo->PopIndx + 1;
|
78 | IndxTmp = IndxTmp % UART_FIFO_SIZE;
|
79 | // Pop the data
|
80 | *pData = Fifo->Buffer[Fifo->PopIndx];
|
81 | // Updating of the pop's index
|
82 | Fifo->PopIndx = IndxTmp;
|
83 | return(1);
|
84 | }
|
85 |
|
86 | /*************************************************************************
|
87 | * Function Name: Uart0Isr
|
88 | * Parameters: none
|
89 | *
|
90 | * Return: none
|
91 | *
|
92 | * Description: UART 0 interrupt routine
|
93 | *
|
94 | *************************************************************************/
|
95 | static
|
96 | void uart0_isr(void)
|
97 | {
|
98 | uint32_t UartIntId = U0IIR, LineStatus, Counter;
|
99 | uint8_t Data;
|
100 | // Recognize the interrupt event
|
101 | switch (UartIntId & 0xF)
|
102 | {
|
103 | case RLS_INTR_ID: // Receive Line Status
|
104 | case CDI_INTR_ID: // Character Time-out Indicator
|
105 | case RDA_INTR_ID: // Receive Data Available
|
106 | // Read the line state of the UART
|
107 | LineStatus = U0LSR;
|
108 | do
|
109 | {
|
110 | if(LineStatus & RLS_OverrunError)
|
111 | {
|
112 | // Overrun Error
|
113 | Uart0LineEvents.bOE = 1;
|
114 | }
|
115 | Data = U0RBR;
|
116 | if (LineStatus & RLS_BreakInterruptr)
|
117 | {
|
118 | // Break Indicator
|
119 | Uart0LineEvents.bBI = 1;
|
120 | }
|
121 | else if (LineStatus & RLS_FramingError)
|
122 | {
|
123 | // Framing Error
|
124 | Uart0LineEvents.bFE = 1;
|
125 | }
|
126 | else if (LineStatus & RLS_ParityError)
|
127 | {
|
128 | // Parity Error
|
129 | Uart0LineEvents.bPE = 1;
|
130 | }
|
131 | // Push a new data into the receiver buffer
|
132 | if(!FifoPush(pUart0RxFifo,Data))
|
133 | {
|
134 | // the FIFO is full
|
135 | Uart0LineEvents.bOE = 1;
|
136 | break;
|
137 | }
|
138 | // Read the line state of the UART
|
139 | LineStatus = U0LSR;
|
140 | }
|
141 | while(LineStatus & RLS_ReceiverDataReady); // Is the hardware FIFO empty?
|
142 | break;
|
143 | case THRE_INTR_ID: // THRE Interrupt
|
144 | // Tx UART FIFO size - 1
|
145 | // Fill whole hardware transmit FIFO
|
146 | for (Counter = 15; Counter; --Counter)
|
147 | {
|
148 | // Pop a data from the transmit buffer
|
149 | if(!FifoPop(pUart0TxFifo,&Data))
|
150 | {
|
151 | // The tx software FIFO is empty
|
152 | break;
|
153 | }
|
154 | U0THR = Data;
|
155 | }
|
156 | break;
|
157 | }
|
158 | }
|
159 |
|
160 | /*************************************************************************
|
161 | * Function Name: UartInit
|
162 | * Parameters: UartNum_t Uart, uint32_t IrqSlot, UartMode_t UartMode
|
163 | *
|
164 | * Return: uint8_t
|
165 | *
|
166 | * Description: Init UART
|
167 | *
|
168 | *************************************************************************/
|
169 | uint8_t uart0_init(uint32_t Baudrate, uint32_t IrqSlot)
|
170 | {
|
171 | volatile uint8_t Tmp;
|
172 |
|
173 | pUart0RxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
|
174 | if(!pUart0RxFifo)
|
175 | {
|
176 | return(0);
|
177 | }
|
178 | pUart0TxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
|
179 | if(!pUart0TxFifo)
|
180 | {
|
181 | free(pUart0RxFifo);
|
182 | return(0);
|
183 | }
|
184 | // Init receive and transmit FIFOs
|
185 | pUart0RxFifo->PopIndx = pUart0RxFifo->PushIndx = 0;
|
186 | pUart0TxFifo->PopIndx = pUart0TxFifo->PushIndx = 0;
|
187 |
|
188 | PCONP_bit.PCUART0 = 1; // Enable UART0
|
189 | PINSEL0_bit.P0_0 = 1; //Uart TX function select
|
190 | PINSEL0_bit.P0_1 = 1; //Uart RX function select
|
191 |
|
192 | U0LCR = 0x03; // Word Length =8, no parity , 1 stop
|
193 | U0FDR_bit.MULVAL = 1; //set fractional divider register multiplier to 1
|
194 | U0FDR_bit.DIVADDVAL = 0; //disable fractional divider (this should change for other baudrates
|
195 |
|
196 | U0LCR_bit.DLAB = 1; //Devisor Latch Access enabled
|
197 | U0DLL = ((PCLK/16)/Baudrate)%256; //configure divisor latch register lsb..
|
198 | U0DLM = ((PCLK/16)/Baudrate)/256; //..and msb
|
199 | U0LCR_bit.DLAB = 0; //Clear Devisor Latch Access bit
|
200 | U0FCR = 0x03;//0x7; // Enable and Clear the UART0 FIFO, Set RX FIFO interrupt level - 1 char
|
201 |
|
202 | U0TER_bit.TXEN = 1; // Transmit enable
|
203 | Tmp = U0IER; // Clear pending interrupts
|
204 | U0IER = 0x07; // enable RBR Interrupt, THRE Interrupt, RX Line Status Interrupt
|
205 |
|
206 | Install_IRQ(VIC_UART0, uart0_isr, IrqSlot); //Install Interrupt
|
207 | return(1);
|
208 | }
|
209 |
|
210 |
|
211 | /*************************************************************************
|
212 | * Function Name: uart0_read
|
213 | * Parameters: uint8_t* pBuffer, uint32_t BufferSize
|
214 | *
|
215 | * Return: uint32_t
|
216 | *
|
217 | * Description: Read received data from UART0.
|
218 | * Return number of readied characters
|
219 | *
|
220 | *************************************************************************/
|
221 | uint32_t uart0_read(uint8_t* pBuffer, uint32_t BufferSize)
|
222 | {
|
223 | uint32_t Count;
|
224 | for (Count = 0; Count < BufferSize; ++Count)
|
225 | {
|
226 | if(!FifoPop(pUart0RxFifo,pBuffer+Count))
|
227 | {
|
228 | break;
|
229 | }
|
230 | }
|
231 | return(Count);
|
232 | }
|
233 |
|
234 | /*************************************************************************
|
235 | * Function Name: UartWrite
|
236 | * Parameters: UartNum_t Uart, uint8_t* pBuffer, uint32_t BufferSize
|
237 | *
|
238 | * Return: uint32_t
|
239 | *
|
240 | * Description: Write a data to UART. Return number of successful
|
241 | * transmitted bytes
|
242 | *
|
243 | *************************************************************************/
|
244 | uint32_t uart0_write(uint8_t* pBuffer, uint32_t BufferSize)
|
245 | {
|
246 | uint32_t Count = 0;
|
247 |
|
248 | if(BufferSize != 0)
|
249 | {
|
250 | volatile uint8_t* pUartTxReg;
|
251 | __disable_interrupt();
|
252 | //TX FIFO is empty
|
253 | if((pUart0TxFifo->PushIndx == pUart0TxFifo->PopIndx))
|
254 | {
|
255 | pUartTxReg = (uint8_t*)&U0THR;
|
256 | if(U0LSR_bit.THRE)
|
257 | {
|
258 | *pUartTxReg = *pBuffer;
|
259 | ++Count;
|
260 | }
|
261 | }
|
262 | for ( ; Count < BufferSize; ++Count)
|
263 | {
|
264 | if(!FifoPush(pUart0TxFifo,*(pBuffer+Count)))
|
265 | {
|
266 | break;
|
267 | }
|
268 | }
|
269 | __enable_interrupt();
|
270 | }
|
271 | return(Count);
|
272 | }
|
273 |
|
274 | /*************************************************************************
|
275 | * Function Name: uart0_getUartLineEvents
|
276 | * Parameters:
|
277 | *
|
278 | * Return: UartLineEvents_t
|
279 | *
|
280 | * Description: Get Uart Line events (PE, OE, FE, BI)
|
281 | *
|
282 | *************************************************************************/
|
283 | UartLineEvents_t uart0_getUartLineEvents()
|
284 | {
|
285 | UartLineEvents_t LineEvents;
|
286 | LineEvents.Data = Uart0LineEvents.Data;
|
287 | return(LineEvents);
|
288 | }
|