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 if (!uart->sending) {
110 uart->regs->tx_data = data;
114 /* FIXME : handle RX erors */
117 static void uart_check_tx(struct uart_device* uart, uint32_t intr)
119 /* We are currently sending, send next char */
120 if (intr & LPC_UART_ST_TX_READY) {
121 if (uart->sending && (uart->out_length > uart->sending)) {
122 uart->regs->tx_data = uart->out_buff[uart->sending++];
125 uart->regs->inten_clear = LPC_UART_ST_TX_READY;
130 /* Generic UART handler */
131 static void UART_Handler(struct uart_device* uart)
133 uint32_t intr = uart->regs->status;
135 uart_check_rx(uart, intr);
136 uart_check_tx(uart, intr);
137 /* Clear all flags */
138 uart->regs->status = LPC_UART_ST_CLEAR;
143 void UART_0_Handler(void)
145 UART_Handler(&uarts[0]);
147 void UART_1_Handler(void)
149 UART_Handler(&uarts[1]);
151 void UART_2_Handler(void)
153 UART_Handler(&uarts[2]);
157 /* Start sending buffer content */
158 static void uart_start_sending(uint32_t uart_num)
160 struct uart_device* uart = &uarts[uart_num];
162 if (!uart->sending && (uart->out_length != 0)) {
164 uart->regs->tx_data = uart->out_buff[0];
165 /* Activate only LPC_UART_ST_TX_READY in order to prevent multiple calls to
166 * the interrupt handler, which will cause data loss */
167 uart->regs->inten_set = (LPC_UART_ST_TX_READY);
172 /****************************************************************************** */
173 /* Serial send byte - quick function with almost no tests.
174 * If the uart is not sending, the byte is placed directly in the data buffer and
175 * the call returns 0.
176 * Else, the call returns -EBUSY and nothing is sent.
178 int serial_send_quickbyte(uint32_t uart_num, uint8_t data)
180 struct uart_device* uart = &uarts[uart_num];
181 if (!uart->sending) {
182 uart->regs->tx_data = data;
189 /***************************************************************************** */
192 * Try to send at most "length" characters from "buf" on the requested uart.
193 * Returns a negative value on error, or number of characters copied into output buffer,
194 * witch may be less than requested "length"
195 * Possible errors: requested uart does not exists (-EINVAL) or unable to acquire uart
198 * Warning for Real Time : This implementation will block if there's already a
199 * transmission ongoing.
201 int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
203 struct uart_device* uart = NULL;
205 if (uart_num >= NUM_UARTS)
208 uart = &uarts[uart_num];
210 if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
214 /* If UART is sending wait for buffer empty */
215 /* FIXME : be smart for OS, call scheduler or return */
216 while (uart->sending != 0) {
217 /* If interrupt are masked, check for tx ourselves */
218 if (get_priority_mask() != 0) {
219 uart_check_tx(uart, uart->regs->status);
223 if (length > SERIAL_OUT_BUFF_SIZE) {
224 length = SERIAL_OUT_BUFF_SIZE;
226 memcpy((void*)uart->out_buff, buf, length);
227 uart->out_length = length;
230 uart_start_sending(uart_num);
232 /* Release the lock */
233 sync_lock_release(&uart->out_lock);
239 /***************************************************************************** */
242 * Wait until all characters have been sent
243 * Returns -EINVAL on error, 0 on success.
244 * Possible errors: requested uart does not exists or unable to acquire uart lock.
246 * Warning for Real Time : This implementation will block if there's already a
247 * transmission ongoing.
249 int serial_flush(uint32_t uart_num)
251 struct uart_device* uart = NULL;
253 if (uart_num >= NUM_UARTS)
256 uart = &uarts[uart_num];
258 /* Active wait for message to be sent. If interrupts are
259 * disabled, call the UART handler while waiting. */
260 while (uart->sending) {
261 if (get_priority_mask() == 0) {
262 uart_check_tx(uart, uart->regs->status);
270 /***************************************************************************** */
271 /* UART Setup : private part : Clocks, Pins, Power and Mode */
273 /* UART Clock Setup */
274 /* Note : for all uarts we use full peripheral clock.
275 * The common uart clock is the main_clock divided by UARTCLKDIV (which we set to 1)
276 * The uart pclk (U_PCLK) is common uart clock divided by (1 + mult/div)
277 * - Documentation states that div must be 256 (uart_common_fclk_div = 0xFF)
278 * - In order to get the closest value for 115200 bauds, the mult value is 22, which
279 * provides a 11050360 Hz clock with a 12Mhz system clock (ideal value would be
280 * 11059200 Hz). Then the uart specific baud rate generator divisor can be set to 6
281 * (BRGVAL = 5) in order to get the 1843200 Hz clock which is 16x the 115200 baud
282 * rate (oversampling of 16).
283 * Depending on the main clock frequency, other values can be achieved by selecting
284 * the right baud rate generator divisor (BRGVAL).
285 * - In order to get the closest value for 1500000 bauds (1.5Mbauds) the mult value
286 * should be 128 and the main clock set to 36MHz, which gives a 24MHz uart pclk.
287 * A baud rate generator divisor of 1 (BRGVAL = 0) would then provide a 1.5MHz baudrate
288 * with 16x oversampling.
290 enum uart_speed_types {
293 LPC_UART_CLK_HIGH_SPEED,
295 static uint8_t uart_speed_type = LPC_UART_CLK_NONE;
296 static int uart_clk_on(uint32_t uart_num, uint32_t baudrate)
298 struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
299 struct lpc_usart* uart_regs = uarts[uart_num].regs; /* Get the right registers */
301 /* clk_mult is the 12MHz multiplier which gives the main clock freq */
302 uint8_t clk_mult = (get_main_clock() / (12 * 1000 * 1000));
304 /* Save baudrate value */
305 uarts[uart_num].baudrate = baudrate;
307 /* Configure common UART clock */
308 sys_config->uart_clk_div = 0x01; /* Do not divide peripheral clock for uarts */
309 sys_config->uart_common_fclk_div = 0xFF; /* divider value must be 256 */
310 if (baudrate <= 230400) {
311 if (uart_speed_type == LPC_UART_CLK_HIGH_SPEED) {
314 sys_config->uart_common_fclk_mult = 22; /* Closest value to get 115200 baudrate */
315 /* Get the divider value */
316 div = (691200 * clk_mult) / baudrate; /* 691200 is (11059200 / 16) */
317 uart_regs->baudrate_gen = (div - 1);
318 uart_speed_type = LPC_UART_CLK_COMMON;
320 if (uart_speed_type == LPC_UART_CLK_COMMON) {
323 sys_config->uart_common_fclk_mult = 128; /* Value to get 1500000 baudrate */
324 uart_speed_type = LPC_UART_CLK_HIGH_SPEED;
325 uart_regs->baudrate_gen = 0;
329 static void uart_clk_off(uint32_t uart_num)
331 /* Erase saved baudrate */
332 uarts[uart_num].baudrate = 0;
335 static void uart_setup(uint32_t uart_num)
337 struct lpc_usart* uart_regs = uarts[uart_num].regs; /* Get the right registers */
338 /* Set up UART mode */
339 uart_regs->config = (uarts[uart_num].config | LPC_UART_ENABLE);
340 uart_regs->control = 0;
341 /* Clear the Status Register */
342 uart_regs->status = LPC_UART_ST_CLEAR;
343 /* Enable UART Interrupt */
344 uart_regs->inten_set = LPC_UART_ST_RX_READY;
347 /* Change UART configuration (number of data, parity and stop bits).
348 * config is usually a mask of LPC_UART_xBIT (x = 5..8), LPC_UART_xSTOP (x = 1..2)
349 * and one of LPC_UART_NO_PAR, LPC_UART_ODD_PAR or LPC_UART_EVEN_PAR.
351 int uart_set_config(uint8_t uart_num, uint32_t config)
353 struct uart_device* uart = NULL;
355 if (uart_num >= NUM_UARTS)
357 uart = &uarts[uart_num];
358 uart->config = config;
365 uint32_t power_offset;
367 static struct uart_def uart_defs[NUM_UARTS] = {
368 { UART0_IRQ, LPC_SYS_ABH_CLK_CTRL_UART0 },
369 { UART1_IRQ, LPC_SYS_ABH_CLK_CTRL_UART1 },
370 { UART2_IRQ, LPC_SYS_ABH_CLK_CTRL_UART2 },
373 /***************************************************************************** */
374 /* Public access to UART setup */
376 /* Allow any change to the main clock to be forwarded to us */
377 void uart_clk_update(void)
380 for (i = 0; i < NUM_UARTS; i++) {
381 if (uarts[i].baudrate != 0) {
382 uart_clk_on(i, uarts[i].baudrate);
387 /* Change uart mode to RS485
388 * return -ENODEV when the device does not support RS485 mode.
390 int uart_set_mode_rs485(uint32_t uart_num, uint32_t control, uint8_t addr, uint8_t delay)
392 struct uart_device* uart = NULL;
393 struct lpc_usart* uart_regs = NULL;
394 if (uart_num >= NUM_UARTS)
396 uart = &uarts[uart_num];
397 uart_regs = uart->regs; /* Get the right registers */
399 if (!(uart->capabilities & SERIAL_CAP_RS485)) {
403 /* Set current mode */
404 uart->current_mode = SERIAL_MODE_RS485;
405 uart_regs->config = 0; /* FIXME */
406 uart_regs->control = 0; /* FIXME */
407 uart_regs->address = LPC_RS485_ADDR(addr);
412 /* Do we need to allow setting of other parameters ? (Other than 8n1) */
413 int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
415 struct uart_def* uartdef = NULL;
418 if (uart_num >= NUM_UARTS)
420 uartdef = &uart_defs[uart_num];
421 uarts[uart_num].rx_callback = rx_callback;
423 NVIC_DisableIRQ( uartdef->irq );
425 subsystem_power(uartdef->power_offset, 1);
426 /* Setup clock acording to baudrate */
427 status = uart_clk_on(uart_num, baudrate);
429 uart_setup(uart_num);
430 /* Enable interrupts back on */
431 NVIC_EnableIRQ( uartdef->irq );
436 void uart_off(uint32_t uart_num)
438 struct uart_def* uartdef = NULL;
439 if (uart_num >= NUM_UARTS)
441 uartdef = &uart_defs[uart_num];
443 NVIC_DisableIRQ( uartdef->irq );
444 uart_clk_off(uart_num);
446 subsystem_power(uartdef->power_offset, 0);
447 uarts[uart_num].rx_callback = NULL;
448 uarts[uart_num].regs->config = 0;