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 */
76 uint32_t sysctl_usart;
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_gpio = RCC_APB2_GPIOA,
89 .sysctl_usart = RCC_APB2_USART1,
94 .rx_pin = GPIO_USART2_RX_PIN,
95 .tx_pin = GPIO_USART2_TX_PIN,
96 .sysctl_gpio = RCC_APB2_GPIOA,
97 .sysctl_usart = RCC_APB1_USART2,
99 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
103 .rx_pin = GPIO_USART3_RX_PIN,
104 .tx_pin = GPIO_USART3_TX_PIN,
105 .sysctl_gpio = RCC_APB2_GPIOB,
106 .sysctl_usart = RCC_APB1_USART3,
111 #define USART1_PORT 0
112 #define USART2_PORT 1
113 #define USART3_PORT 2
115 void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
117 struct stm32_usart *_base = (struct stm32_usart *)base;
118 _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
121 void stm32_uartSetParity(uint32_t base, int parity)
123 struct stm32_usart *_base = (struct stm32_usart *)base;
125 /* USART_WORD_LEN_8B */
126 _base->CR1 &= ~BV(CR1_M);
130 case SER_PARITY_NONE:
131 _base->CR1 &= ~BV(CR1_PCE);
134 _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
136 case SER_PARITY_EVEN:
137 _base->CR1 |= BV(CR1_PCE);
138 _base->CR1 &= ~BV(CR1_PS);
146 void stm32_uartInit(int port)
148 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
150 ASSERT(port >= 0 && port < SER_CNT);
152 /* Enable clocking on AFIO */
153 RCC->APB2ENR |= RCC_APB2_AFIO;
154 RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
156 /* Configure USART pins */
157 if (port == USART1_PORT)
159 RCC->APB2ENR |= gpio_uart[port].sysctl_usart;
163 RCC->APB1ENR |= gpio_uart[port].sysctl_usart;
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 */
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));
188 static bool tx_sending(struct SerialHardware *_hw)
190 struct CM3Serial *hw = (struct CM3Serial *)_hw;
194 static void uart_irq_rx(int port)
196 struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
197 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
200 while (stm32_uartRxReady(UARTDesc[port].base))
203 if (fifo_isfull(rxfifo))
204 ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
206 fifo_push(rxfifo, c);
210 static void uart_irq_tx(int port)
212 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
213 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
215 if (fifo_isempty(txfifo))
218 * Disable TX empty interrupts if there're no more
219 * characters to transmit.
221 base->CR1 &= ~BV(CR1_TXEIE);
222 UARTDesc[port].sending = false;
226 base->DR = fifo_pop(txfifo);
230 static void uart_common_irq_handler(int port)
232 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
235 /* Read and clear the IRQ status */
238 /* Check hw errors */
239 ser_handles[port]->status = status &
240 (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
242 /* Process the IRQ */
243 if (status & BV(CR1_RXNEIE))
247 if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
253 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
255 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
257 /* Register the IRQ handler */
258 sysirq_setHandler(UARTDesc[port].irq, handler);
260 base->CR1 |= BV(CR1_RXNEIE);
263 static void stm32_uartIRQDisable(int port)
265 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
267 base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
271 /* UART class definition */
272 #define UART_PORT(port) \
273 /* UART TX and RX buffers */ \
274 static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
275 static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE]; \
277 /* UART interrupt handler */ \
278 static DECLARE_ISR(uart ## port ## _irq_handler) \
280 uart_common_irq_handler(USART ## port ## _PORT); \
283 /* UART public methods */ \
284 static void uart ## port ## _txStart(struct SerialHardware *_hw) \
286 struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo; \
287 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
288 struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
291 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo)); \
292 if (!fifo_isempty(txfifo)) \
294 hw->sending = true; \
295 base->CR1 |= BV(CR1_TXEIE); \
299 static void uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
300 unsigned long baud) \
302 stm32_uartSetBaudRate(USART## port ## _BASE, baud); \
305 static void uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
308 stm32_uartSetParity(USART## port ## _BASE, parity); \
311 static void uart ## port ## _cleanup(struct SerialHardware *_hw) \
313 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
314 hw->sending = false; \
315 stm32_uartIRQDisable(USART ## port ## _PORT); \
316 stm32_uartClear(USART## port ## _BASE); \
317 stm32_uartDisable(USART## port ## _BASE); \
320 static void uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
321 UNUSED_ARG(struct Serial *, ser)) \
323 stm32_uartInit(USART ## port ## _PORT); \
324 stm32_uartEnable(USART## port ## _BASE); \
325 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler); \
328 /* UART operations */ \
329 static const struct SerialHardwareVT USART ## port ## _VT = \
331 .init = uart ## port ## _init, \
332 .cleanup = uart ## port ## _cleanup, \
333 .setBaudrate = uart ## port ## _setbaudrate, \
334 .setParity = uart ## port ## _setparity, \
335 .txStart = uart ## port ## _txStart, \
336 .txSending = tx_sending, \
339 /* UART port instances */
342 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
346 static struct CM3Serial UARTDesc[SER_CNT] =
351 .txbuffer = uart1_txbuffer,
352 .rxbuffer = uart1_rxbuffer,
353 .txbuffer_size = sizeof(uart1_txbuffer),
354 .rxbuffer_size = sizeof(uart1_rxbuffer),
358 .irq = USART1_IRQHANDLER,
363 .txbuffer = uart2_txbuffer,
364 .rxbuffer = uart2_rxbuffer,
365 .txbuffer_size = sizeof(uart2_txbuffer),
366 .rxbuffer_size = sizeof(uart2_rxbuffer),
370 .irq = USART2_IRQHANDLER,
372 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
376 .txbuffer = uart3_txbuffer,
377 .rxbuffer = uart3_rxbuffer,
378 .txbuffer_size = sizeof(uart3_txbuffer),
379 .rxbuffer_size = sizeof(uart3_rxbuffer),
383 .irq = USART3_IRQHANDLER,
388 struct SerialHardware *ser_hw_getdesc(int port)
390 ASSERT(port >= 0 && port < SER_CNT);
391 return &UARTDesc[port].hw;