1 /****************************************************************************
4 * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *************************************************************************** */
23 /***************************************************************************** */
25 /***************************************************************************** */
26 /* UART driver for the integrated UARTs of the LPC82x.
27 * Refer to LPC82x documentation (UM10800.pdf) for more information.
30 /* All three UARTs are available, UART numbers are in the range 0 - 2 */
32 #include "core/system.h"
34 #include "lib/string.h"
35 #include "lib/utils.h"
36 #include "lib/errno.h"
37 #include "drivers/serial.h"
42 struct lpc_usart* regs;
50 volatile uint8_t out_buff[SERIAL_OUT_BUFF_SIZE];
51 volatile uint32_t sending; /* Actual sending position in out buffer */
52 /* This lock only prevents multiple calls to serial_write() to execute simultaneously */
53 volatile uint32_t out_lock;
54 volatile uint32_t out_length; /* actual position to add in out buffer */
57 void (*rx_callback)(uint8_t); /* Possible RX callback */
61 static struct uart_device uarts[NUM_UARTS] = {
64 .regs = (struct lpc_usart*)LPC_UART_0,
66 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
71 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485),
72 .current_mode = SERIAL_MODE_UART,
76 .regs = (struct lpc_usart*)LPC_UART_1,
78 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
83 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485),
84 .current_mode = SERIAL_MODE_UART,
88 .regs = (struct lpc_usart*)LPC_UART_2,
90 .config = (LPC_UART_8BIT | LPC_UART_NO_PAR | LPC_UART_1STOP),
95 .capabilities = (SERIAL_CAP_UART | SERIAL_CAP_RS485),
96 .current_mode = SERIAL_MODE_UART,
100 static void uart_check_rx(struct uart_device* uart, uint32_t intr)
102 if (intr & LPC_UART_ST_RX_READY) {
103 uint8_t data = uart->regs->rx_data;
104 if (uart->rx_callback != NULL) {
105 /* Call the Rx callback */
106 uart->rx_callback(data);
109 uart->regs->tx_data = data;
112 /* FIXME : handle RX erors */
115 static void uart_check_tx(struct uart_device* uart, uint32_t intr)
117 /* We are currently sending, send next char */
118 if (intr & LPC_UART_ST_TX_READY) {
119 if (uart->out_buff && uart->sending && (uart->out_length > uart->sending)) {
120 uart->regs->tx_data = uart->out_buff[uart->sending];
124 uart->regs->inten_clear = LPC_UART_ST_TX_READY;
129 /* Generic UART handler */
130 static void UART_Handler(struct uart_device* uart)
132 uint32_t intr = uart->regs->status;
134 uart_check_rx(uart, intr);
135 uart_check_tx(uart, intr);
136 /* Clear all flags */
137 uart->regs->status = LPC_UART_ST_CLEAR;
142 void UART_0_Handler(void)
144 UART_Handler(&uarts[0]);
146 void UART_1_Handler(void)
148 UART_Handler(&uarts[1]);
150 void UART_2_Handler(void)
152 UART_Handler(&uarts[2]);
156 /* Start sending buffer content */
157 static void uart_start_sending(uint32_t uart_num)
159 struct uart_device* uart = &uarts[uart_num];
161 if (!uart->sending && (uart->out_length != 0)) {
163 uart->regs->tx_data = uart->out_buff[0];
164 /* Activate only LPC_UART_ST_TX_READY in order to prevent multiple calls to
165 * the interrupt handler, which will cause data loss */
166 uart->regs->inten_set = (LPC_UART_ST_TX_READY);
171 /****************************************************************************** */
172 /* Serial send byte - quick function with almost no tests.
173 * If the uart is not sending, the byte is placed directly in the data buffer and
174 * the call returns 0.
175 * Else, the call returns -EBUSY and nothing is sent.
177 int serial_send_quickbyte(uint32_t uart_num, uint8_t data)
179 struct uart_device* uart = &uarts[uart_num];
180 if (!uart->sending) {
181 uart->regs->tx_data = data;
188 /***************************************************************************** */
191 * Try to send at most "length" characters from "buf" on the requested uart.
192 * Returns a negative value on error, or number of characters copied into output buffer,
193 * witch may be less than requested "length"
194 * Possible errors: requested uart does not exists (-EINVAL) or unable to acquire uart
197 * Warning for Real Time : This implementation will block if there's already a
198 * transmission ongoing.
200 int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
202 struct uart_device* uart = NULL;
204 if (uart_num >= NUM_UARTS)
207 uart = &uarts[uart_num];
209 if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
213 /* If UART is sending wait for buffer empty */
214 /* FIXME : be smart for OS, call scheduler or return */
215 while (uart->sending != 0) {
216 /* If interrupt are masked, check for tx ourselves */
217 if (get_priority_mask() != 0) {
218 uart_check_tx(uart, uart->regs->status);
222 if (length > SERIAL_OUT_BUFF_SIZE) {
223 length = SERIAL_OUT_BUFF_SIZE;
225 memcpy((void*)uart->out_buff, buf, length);
226 uart->out_length = length;
229 uart_start_sending(uart_num);
231 /* Release the lock */
232 sync_lock_release(&uart->out_lock);
238 /***************************************************************************** */
241 * Wait until all characters have been sent
242 * Returns -EINVAL on error, 0 on success.
243 * Possible errors: requested uart does not exists or unable to acquire uart lock.
245 * Warning for Real Time : This implementation will block if there's already a
246 * transmission ongoing.
248 int serial_flush(uint32_t uart_num)
250 struct uart_device* uart = NULL;
252 if (uart_num >= NUM_UARTS)
255 uart = &uarts[uart_num];
257 /* Active wait for message to be sent. If interrupts are
258 * disabled, call the UART handler while waiting. */
259 while (uart->sending) {
260 if (get_priority_mask() == 0) {
261 uart_check_tx(uart, uart->regs->status);
269 /***************************************************************************** */
270 /* UART Setup : private part : Clocks, Pins, Power and Mode */
272 /* UART Clock Setup */
273 /* Note : for all uarts we use full peripheral clock.
274 * The common uart clock is the main_clock divided by UARTCLKDIV (which we set to 1)
275 * The uart pclk (U_PCLK) is common uart clock divided by (1 + mult/div)
276 * - Documentation states that div must be 256 (uart_common_fclk_div = 0xFF)
277 * - In order to get the closest value for 115200 bauds, the mult value is 22, which
278 * provides a 11050360 Hz clock with a 12Mhz system clock (ideal value would be
279 * 11059200 Hz). Then the uart specific baud rate generator divisor can be set to 6
280 * (BRGVAL = 5) in order to get the 1843200 Hz clock which is 16x the 115200 baud
281 * rate (oversampling of 16).
282 * Depending on the main clock frequency, other values can be achieved by selecting
283 * the right baud rate generator divisor (BRGVAL).
284 * - In order to get the closest value for 1500000 bauds (1.5Mbauds) the mult value
285 * should be 128 and the main clock set to 36MHz, which gives a 24MHz uart pclk.
286 * A baud rate generator divisor of 1 (BRGVAL = 0) would then provide a 1.5MHz baudrate
287 * with 16x oversampling.
289 enum uart_speed_types {
292 LPC_UART_CLK_HIGH_SPEED,
294 static uint8_t uart_speed_type = LPC_UART_CLK_NONE;
295 static int uart_clk_on(uint32_t uart_num, uint32_t baudrate)
297 struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
298 struct lpc_usart* uart_regs = uarts[uart_num].regs; /* Get the right registers */
300 /* clk_mult is the 12MHz multiplier which gives the main clock freq */
301 uint8_t clk_mult = (get_main_clock() / (12 * 1000 * 1000));
303 /* Save baudrate value */
304 uarts[uart_num].baudrate = baudrate;
306 /* Configure common UART clock */
307 sys_config->uart_clk_div = 0x01; /* Do not divide peripheral clock for uarts */
308 sys_config->uart_common_fclk_div = 0xFF; /* divider value must be 256 */
309 if (baudrate <= 230400) {
310 if (uart_speed_type == LPC_UART_CLK_HIGH_SPEED) {
313 sys_config->uart_common_fclk_mult = 22; /* Closest value to get 115200 baudrate */
314 /* Get the divider value */
315 div = (691200 * clk_mult) / baudrate; /* 691200 is (11059200 / 16) */
316 uart_regs->baudrate_gen = (div - 1);
317 uart_speed_type = LPC_UART_CLK_COMMON;
319 if (uart_speed_type == LPC_UART_CLK_COMMON) {
322 sys_config->uart_common_fclk_mult = 128; /* Value to get 1500000 baudrate */
323 uart_speed_type = LPC_UART_CLK_HIGH_SPEED;
324 uart_regs->baudrate_gen = 0;
328 static void uart_clk_off(uint32_t uart_num)
330 /* Erase saved baudrate */
331 uarts[uart_num].baudrate = 0;
334 static void uart_setup(uint32_t uart_num)
336 struct lpc_usart* uart_regs = uarts[uart_num].regs; /* Get the right registers */
337 /* Set up UART mode */
338 uart_regs->config = (uarts[uart_num].config | LPC_UART_ENABLE);
339 uart_regs->control = 0;
340 /* Clear the Status Register */
341 uart_regs->status = LPC_UART_ST_CLEAR;
342 /* Enable UART Interrupt */
343 uart_regs->inten_set = LPC_UART_ST_RX_READY;
346 /* Change UART configuration (number of data, parity and stop bits).
347 * config is usually a mask of LPC_UART_xBIT (x = 5..8), LPC_UART_xSTOP (x = 1..2)
348 * and one of LPC_UART_NO_PAR, LPC_UART_ODD_PAR or LPC_UART_EVEN_PAR.
350 int uart_set_config(uint8_t uart_num, uint32_t config)
352 struct uart_device* uart = NULL;
354 if (uart_num >= NUM_UARTS)
356 uart = &uarts[uart_num];
357 uart->config = config;
364 uint32_t power_offset;
366 static struct uart_def uart_defs[NUM_UARTS] = {
367 { UART0_IRQ, LPC_SYS_ABH_CLK_CTRL_UART0 },
368 { UART1_IRQ, LPC_SYS_ABH_CLK_CTRL_UART1 },
369 { UART2_IRQ, LPC_SYS_ABH_CLK_CTRL_UART2 },
372 /***************************************************************************** */
373 /* Public access to UART setup */
375 /* Allow any change to the main clock to be forwarded to us */
376 void uart_clk_update(void)
379 for (i = 0; i < NUM_UARTS; i++) {
380 if (uarts[i].baudrate != 0) {
381 uart_clk_on(i, uarts[i].baudrate);
386 /* Change uart mode to RS485
387 * return -ENODEV when the device does not support RS485 mode.
389 int uart_set_mode_rs485(uint32_t uart_num, uint32_t control, uint8_t addr, uint8_t delay)
391 struct uart_device* uart = NULL;
392 struct lpc_usart* uart_regs = NULL;
393 if (uart_num >= NUM_UARTS)
395 uart = &uarts[uart_num];
396 uart_regs = uart->regs; /* Get the right registers */
398 if (!(uart->capabilities & SERIAL_CAP_RS485)) {
402 /* Set current mode */
403 uart->current_mode = SERIAL_MODE_RS485;
404 uart_regs->config = 0; /* FIXME */
405 uart_regs->control = 0; /* FIXME */
406 uart_regs->address = LPC_RS485_ADDR(addr);
411 /* Do we need to allow setting of other parameters ? (Other than 8n1) */
412 int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
414 struct uart_def* uartdef = NULL;
417 if (uart_num >= NUM_UARTS)
419 uartdef = &uart_defs[uart_num];
420 uarts[uart_num].rx_callback = rx_callback;
422 NVIC_DisableIRQ( uartdef->irq );
424 subsystem_power(uartdef->power_offset, 1);
425 /* Setup clock acording to baudrate */
426 status = uart_clk_on(uart_num, baudrate);
428 uart_setup(uart_num);
429 /* Enable interrupts back on */
430 NVIC_EnableIRQ( uartdef->irq );
435 void uart_off(uint32_t uart_num)
437 struct uart_def* uartdef = NULL;
438 if (uart_num >= NUM_UARTS)
440 uartdef = &uart_defs[uart_num];
442 NVIC_DisableIRQ( uartdef->irq );
443 uart_clk_off(uart_num);
445 subsystem_power(uartdef->power_offset, 0);
446 uarts[uart_num].rx_callback = NULL;
447 uarts[uart_num].regs->config = 0;