4 * This file is part of BeRTOS.
6 * Bertos 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
33 * \brief STM32 UART interface driver.
35 * \author Daniele Basile <asterix@develer.com>
38 #include "ser_stm32.h"
40 #include "cfg/cfg_ser.h"
42 #include <cfg/macros.h> /* for BV() */
43 #include <cfg/debug.h>
45 #include <drv/gpio_stm32.h>
46 #include <drv/irq_cm3.h>
47 #include <drv/clock_stm32.h>
48 #include <drv/ser_p.h>
52 /* From the high-level serial driver */
53 extern struct Serial *ser_handles[SER_CNT];
57 struct SerialHardware hw;
58 volatile bool sending;
63 /* Forward declaration */
64 static struct CM3Serial UARTDesc[SER_CNT];
66 /* GPIO descriptor for UART pins */
69 /* GPIO base address register */
80 /* Table to retrieve GPIO pins configuration to work as UART pins */
81 static const struct gpio_uart_info gpio_uart[SER_CNT] =
86 .rx_pin = GPIO_USART1_RX_PIN,
87 .tx_pin = GPIO_USART1_TX_PIN,
88 .sysctl = RCC_APB2_GPIOA,
89 .sysctl1 = RCC_APB2_USART1,
94 .rx_pin = GPIO_USART2_RX_PIN,
95 .tx_pin = GPIO_USART2_TX_PIN,
96 .sysctl = RCC_APB2_GPIOA,
97 .sysctl1 = RCC_APB1_USART2,
102 .rx_pin = GPIO_USART3_RX_PIN,
103 .tx_pin = GPIO_USART3_TX_PIN,
104 .sysctl = RCC_APB2_GPIOB,
105 .sysctl1 = RCC_APB1_USART3,
109 #define USART1_PORT 0
110 #define USART2_PORT 1
111 #define USART3_PORT 2
113 void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
115 struct stm32_usart *_base = (struct stm32_usart *)base;
116 _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
119 void stm32_uartSetParity(uint32_t base, int parity)
121 struct stm32_usart *_base = (struct stm32_usart *)base;
123 /* USART_WORD_LEN_8B */
124 _base->CR1 &= ~BV(CR1_M);
128 case SER_PARITY_NONE:
129 _base->CR1 &= ~BV(CR1_PCE);
132 _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
134 case SER_PARITY_EVEN:
135 _base->CR1 |= BV(CR1_PCE);
136 _base->CR1 &= ~BV(CR1_PS);
144 void stm32_uartInit(int port)
146 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
148 kprintf("init port[%d]cnt[%d]\n", port, SER_CNT);
149 ASSERT(port >= 0 && port < SER_CNT);
151 /* Enable clocking on AFIO */
152 RCC->APB2ENR |= RCC_APB2_AFIO;
154 /* Configure USART pins */
155 if (port == USART1_PORT)
157 RCC->APB2ENR |= gpio_uart[port].sysctl;
158 RCC->APB2ENR |= gpio_uart[port].sysctl1;
162 RCC->APB1ENR |= gpio_uart[port].sysctl;
163 RCC->APB1ENR |= gpio_uart[port].sysctl1;
166 stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].tx_pin,
167 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
169 stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].rx_pin,
170 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
172 /* Clear control registry */
173 base->CR2 = 0; //CR2_CLEAR_MASK;
174 base->CR1 = 0; //CR1_CLEAR_MASK;
175 base->CR3 = 0; //CR3_CLEAR_MASK;
178 /* Set serial param: 115.200 bps, no parity */
179 stm32_uartSetBaudRate(UARTDesc[port].base, 115200);
180 stm32_uartSetParity(UARTDesc[port].base, SER_PARITY_NONE);
183 /* Enable trasmision and receiver */
184 base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
187 kprintf("INIT[%02x]\n", (uint8_t)base->SR); \
191 static bool tx_sending(struct SerialHardware *_hw)
193 struct CM3Serial *hw = (struct CM3Serial *)_hw;
197 static void uart_irq_rx(int port)
199 struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
200 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
203 while (stm32_uartRxReady(UARTDesc[port].base))
206 if (fifo_isfull(rxfifo))
207 ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
209 fifo_push(rxfifo, c);
213 static void uart_irq_tx(int port)
215 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
216 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
218 if (fifo_isempty(txfifo))
221 * Disable TX empty interrupts if there're no more
222 * characters to transmit.
225 UARTDesc[port].sending = false;
229 base->DR = fifo_pop(txfifo);
233 static void uart_common_irq_handler(int port)
235 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
238 /* Read and clear the IRQ status */
240 /* Process the IRQ */
245 if (status & (BV(7) | BV(6)))
251 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
253 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
255 /* Register the IRQ handler */
256 sysirq_setHandler(UARTDesc[port].irq, handler);
261 static void stm32_uartIRQDisable(int port)
263 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
265 base->CR1 &= ~(BV(5) | USART_FLAG_TXE);
269 /* UART class definition */
270 #define UART_PORT(port) \
271 /* UART TX and RX buffers */ \
272 static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
273 static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE]; \
275 /* UART interrupt handler */ \
276 static DECLARE_ISR(uart ## port ## _irq_handler) \
278 uart_common_irq_handler(USART ## port ## _PORT); \
281 /* UART public methods */ \
282 static void uart ## port ## _txStart(struct SerialHardware *_hw) \
284 struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo; \
285 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
286 struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
289 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo)); \
290 if (!fifo_isempty(txfifo)) \
292 kputs("tx_en_irq\n"); \
293 hw->sending = true; \
294 base->CR1 |= BV(7); \
298 static void uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
299 unsigned long baud) \
301 stm32_uartSetBaudRate(USART## port ## _BASE, baud); \
304 static void uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
307 stm32_uartSetParity(USART## port ## _BASE, parity); \
310 static void uart ## port ## _cleanup(struct SerialHardware *_hw) \
312 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
313 hw->sending = false; \
314 stm32_uartIRQDisable(USART ## port ## _PORT); \
315 stm32_uartClear(USART## port ## _BASE); \
316 stm32_uartDisable(USART## port ## _BASE); \
319 static void uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
320 UNUSED_ARG(struct Serial *, ser)) \
322 stm32_uartInit(USART ## port ## _PORT); \
323 stm32_uartEnable(USART## port ## _BASE); \
324 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler); \
327 /* UART operations */ \
328 static const struct SerialHardwareVT USART ## port ## _VT = \
330 .init = uart ## port ## _init, \
331 .cleanup = uart ## port ## _cleanup, \
332 .setBaudrate = uart ## port ## _setbaudrate, \
333 .setParity = uart ## port ## _setparity, \
334 .txStart = uart ## port ## _txStart, \
335 .txSending = tx_sending, \
338 /* UART port instances */
343 static struct CM3Serial UARTDesc[SER_CNT] =
348 .txbuffer = uart1_txbuffer,
349 .rxbuffer = uart1_rxbuffer,
350 .txbuffer_size = sizeof(uart1_txbuffer),
351 .rxbuffer_size = sizeof(uart1_rxbuffer),
355 .irq = USART1_IRQHANDLER,
360 .txbuffer = uart2_txbuffer,
361 .rxbuffer = uart2_rxbuffer,
362 .txbuffer_size = sizeof(uart2_txbuffer),
363 .rxbuffer_size = sizeof(uart2_rxbuffer),
367 .irq = USART2_IRQHANDLER,
372 .txbuffer = uart3_txbuffer,
373 .rxbuffer = uart3_rxbuffer,
374 .txbuffer_size = sizeof(uart3_txbuffer),
375 .rxbuffer_size = sizeof(uart3_rxbuffer),
379 .irq = USART3_IRQHANDLER,
383 struct SerialHardware *ser_hw_getdesc(int port)
385 ASSERT(port >= 0 && port < SER_CNT);
386 return &UARTDesc[port].hw;