]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X/serial_api.c
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_NXP / TARGET_LPC81X / serial_api.c
1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 // math.h required for floating point operations for baud rate calculation
17 #include "mbed_assert.h"
18 #include <math.h>
19 #include <string.h>
20
21 #include "serial_api.h"
22 #include "cmsis.h"
23 #include "pinmap.h"
24 #include "mbed_error.h"
25
26 /******************************************************************************
27 * INITIALIZATION
28 ******************************************************************************/
29 #define UART_NUM 3
30
31 static const SWM_Map SWM_UART_TX[] = {
32 {0, 0},
33 {1, 8},
34 {2, 16},
35 };
36
37 static const SWM_Map SWM_UART_RX[] = {
38 {0, 8},
39 {1, 16},
40 {2, 24},
41 };
42
43 static const SWM_Map SWM_UART_RTS[] = {
44 {0, 16},
45 {1, 24},
46 {3, 0},
47 };
48
49 static const SWM_Map SWM_UART_CTS[] = {
50 {0, 24},
51 {2, 0},
52 {3, 8}
53 };
54
55 // bit flags for used UARTs
56 static unsigned char uart_used = 0;
57 static int get_available_uart(void) {
58 int i;
59 for (i=0; i<3; i++) {
60 if ((uart_used & (1 << i)) == 0)
61 return i;
62 }
63 return -1;
64 }
65
66 #define UART_EN (0x01<<0)
67
68 #define CTS_DELTA (0x01<<5)
69 #define RXBRK (0x01<<10)
70 #define DELTA_RXBRK (0x01<<11)
71
72 #define RXRDY (0x01<<0)
73 #define TXRDY (0x01<<2)
74
75 #define TXBRKEN (0x01<<1)
76 #define CTSEN (0x01<<9)
77
78 static uint32_t UARTSysClk;
79
80 static uint32_t serial_irq_ids[UART_NUM] = {0};
81 static uart_irq_handler irq_handler;
82
83 int stdio_uart_inited = 0;
84 serial_t stdio_uart;
85
86 void serial_init(serial_t *obj, PinName tx, PinName rx) {
87 int is_stdio_uart = 0;
88
89 int uart_n = get_available_uart();
90 if (uart_n == -1) {
91 error("No available UART");
92 }
93 obj->index = uart_n;
94 obj->uart = (LPC_USART_TypeDef *)(LPC_USART0_BASE + (0x4000 * uart_n));
95 uart_used |= (1 << uart_n);
96
97 const SWM_Map *swm;
98 uint32_t regVal;
99
100 swm = &SWM_UART_TX[uart_n];
101 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
102 LPC_SWM->PINASSIGN[swm->n] = regVal | (tx << swm->offset);
103
104 swm = &SWM_UART_RX[uart_n];
105 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
106 LPC_SWM->PINASSIGN[swm->n] = regVal | (rx << swm->offset);
107
108 /* uart clock divided by 1 */
109 LPC_SYSCON->UARTCLKDIV = 1;
110
111 /* disable uart interrupts */
112 NVIC_DisableIRQ((IRQn_Type)(UART0_IRQn + uart_n));
113
114 /* Enable UART clock */
115 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << (14 + uart_n));
116
117 /* Peripheral reset control to UART, a "1" bring it out of reset. */
118 LPC_SYSCON->PRESETCTRL &= ~(0x1 << (3 + uart_n));
119 LPC_SYSCON->PRESETCTRL |= (0x1 << (3 + uart_n));
120
121 // Derive UART Clock from MainClock
122 UARTSysClk = MainClock / LPC_SYSCON->UARTCLKDIV;
123
124 // set default baud rate and format
125 serial_baud (obj, 9600);
126 serial_format(obj, 8, ParityNone, 1);
127
128 /* Clear all status bits. */
129 obj->uart->STAT = CTS_DELTA | DELTA_RXBRK;
130
131 /* enable uart interrupts */
132 NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + uart_n));
133
134 /* Enable UART interrupt */
135 // obj->uart->INTENSET = RXRDY | TXRDY | DELTA_RXBRK;
136
137 /* Enable UART */
138 obj->uart->CFG |= UART_EN;
139
140 is_stdio_uart = ((tx == USBTX) && (rx == USBRX));
141
142 if (is_stdio_uart) {
143 stdio_uart_inited = 1;
144 memcpy(&stdio_uart, obj, sizeof(serial_t));
145 }
146 }
147
148 void serial_free(serial_t *obj) {
149 uart_used &= ~(1 << obj->index);
150 serial_irq_ids[obj->index] = 0;
151 }
152
153 // serial_baud
154 // set the baud rate, taking in to account the current SystemFrequency
155 void serial_baud(serial_t *obj, int baudrate) {
156 /* Integer divider:
157 BRG = UARTSysClk/(Baudrate * 16) - 1
158
159 Frational divider:
160 FRG = ((UARTSysClk / (Baudrate * 16 * (BRG + 1))) - 1)
161
162 where
163 FRG = (LPC_SYSCON->UARTFRDADD + 1) / (LPC_SYSCON->UARTFRDSUB + 1)
164
165 (1) The easiest way is set SUB value to 256, -1 encoded, thus SUB
166 register is 0xFF.
167 (2) In ADD register value, depending on the value of UartSysClk,
168 baudrate, BRG register value, and SUB register value, be careful
169 about the order of multiplier and divider and make sure any
170 multiplier doesn't exceed 32-bit boundary and any divider doesn't get
171 down below one(integer 0).
172 (3) ADD should be always less than SUB.
173 */
174 obj->uart->BRG = UARTSysClk / 16 / baudrate - 1;
175
176 LPC_SYSCON->UARTFRGDIV = 0xFF;
177 LPC_SYSCON->UARTFRGMULT = ( ((UARTSysClk / 16) * (LPC_SYSCON->UARTFRGDIV + 1)) /
178 (baudrate * (obj->uart->BRG + 1))
179 ) - (LPC_SYSCON->UARTFRGDIV + 1);
180
181 }
182
183 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
184 // 0: 1 stop bits, 1: 2 stop bits
185 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2));
186 MBED_ASSERT((data_bits > 6) && (data_bits < 10)); // 0: 7 data bits ... 2: 9 data bits
187 MBED_ASSERT((parity == ParityNone) || (parity == ParityEven) || (parity == ParityOdd));
188 stop_bits -= 1;
189 data_bits -= 7;
190
191 int paritysel;
192 switch (parity) {
193 case ParityNone: paritysel = 0; break;
194 case ParityEven: paritysel = 2; break;
195 case ParityOdd : paritysel = 3; break;
196 default:
197 break;
198 }
199
200 obj->uart->CFG = (data_bits << 2)
201 | (paritysel << 4)
202 | (stop_bits << 6);
203 }
204
205 /******************************************************************************
206 * INTERRUPTS HANDLING
207 ******************************************************************************/
208 static inline void uart_irq(uint32_t iir, uint32_t index) {
209 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
210 SerialIrq irq_type;
211 switch (iir) {
212 case 1: irq_type = TxIrq; break;
213 case 2: irq_type = RxIrq; break;
214 default: return;
215 }
216
217 if (serial_irq_ids[index] != 0)
218 irq_handler(serial_irq_ids[index], irq_type);
219 }
220
221 void uart0_irq() {uart_irq((LPC_USART0->STAT & (1 << 2)) ? 2 : 1, 0);}
222 void uart1_irq() {uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 1);}
223 void uart2_irq() {uart_irq((LPC_USART2->STAT & (1 << 2)) ? 2 : 1, 2);}
224
225 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
226 irq_handler = handler;
227 serial_irq_ids[obj->index] = id;
228 }
229
230 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
231 IRQn_Type irq_n = (IRQn_Type)0;
232 uint32_t vector = 0;
233 switch ((int)obj->uart) {
234 case LPC_USART0_BASE: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
235 case LPC_USART1_BASE: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
236 case LPC_USART2_BASE: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
237 }
238
239 if (enable) {
240 obj->uart->INTENSET = (1 << ((irq == RxIrq) ? 0 : 2));
241 NVIC_SetVector(irq_n, vector);
242 NVIC_EnableIRQ(irq_n);
243 } else { // disable
244 int all_disabled = 0;
245 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
246 obj->uart->INTENSET &= ~(1 << ((irq == RxIrq) ? 0 : 2));
247 all_disabled = (obj->uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0;
248 if (all_disabled)
249 NVIC_DisableIRQ(irq_n);
250 }
251 }
252
253 /******************************************************************************
254 * READ/WRITE
255 ******************************************************************************/
256 int serial_getc(serial_t *obj) {
257 while (!serial_readable(obj));
258 return obj->uart->RXDATA;
259 }
260
261 void serial_putc(serial_t *obj, int c) {
262 while (!serial_writable(obj));
263 obj->uart->TXDATA = c;
264 }
265
266 int serial_readable(serial_t *obj) {
267 return obj->uart->STAT & RXRDY;
268 }
269
270 int serial_writable(serial_t *obj) {
271 return obj->uart->STAT & TXRDY;
272 }
273
274 void serial_clear(serial_t *obj) {
275 // [TODO]
276 }
277
278 void serial_pinout_tx(PinName tx) {
279
280 }
281
282 void serial_break_set(serial_t *obj) {
283 obj->uart->CTRL |= TXBRKEN;
284 }
285
286 void serial_break_clear(serial_t *obj) {
287 obj->uart->CTRL &= ~TXBRKEN;
288 }
289
290 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
291 const SWM_Map *swm_rts, *swm_cts;
292 uint32_t regVal_rts, regVal_cts;
293
294 swm_rts = &SWM_UART_RTS[obj->index];
295 swm_cts = &SWM_UART_CTS[obj->index];
296 regVal_rts = LPC_SWM->PINASSIGN[swm_rts->n] & ~(0xFF << swm_rts->offset);
297 regVal_cts = LPC_SWM->PINASSIGN[swm_cts->n] & ~(0xFF << swm_cts->offset);
298
299 if (FlowControlNone == type) {
300 LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (0xFF << swm_rts->offset);
301 LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (0xFF << swm_cts->offset);
302 obj->uart->CFG &= ~CTSEN;
303 return;
304 }
305 if ((FlowControlRTS == type || FlowControlRTSCTS == type) && (rxflow != NC)) {
306 LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (rxflow << swm_rts->offset);
307 if (FlowControlRTS == type) {
308 LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (0xFF << swm_cts->offset);
309 obj->uart->CFG &= ~CTSEN;
310 }
311 }
312 if ((FlowControlCTS == type || FlowControlRTSCTS == type) && (txflow != NC)) {
313 LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (txflow << swm_cts->offset);
314 obj->uart->CFG |= CTSEN;
315 if (FlowControlCTS == type) {
316 LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (0xFF << swm_rts->offset);
317 }
318 }
319 }
320
Imprint / Impressum