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,
102 .rx_pin = GPIO_USART3_RX_PIN,
103 .tx_pin = GPIO_USART3_TX_PIN,
104 .sysctl_gpio = RCC_APB2_GPIOB,
105 .sysctl_usart = 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 ASSERT(port >= 0 && port < SER_CNT);
150 /* Enable clocking on AFIO */
151 RCC->APB2ENR |= RCC_APB2_AFIO;
152 RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
154 /* Configure USART pins */
155 if (port == USART1_PORT)
157 RCC->APB2ENR |= gpio_uart[port].sysctl_usart;
161 RCC->APB1ENR |= gpio_uart[port].sysctl_usart;
164 stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].tx_pin,
165 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
167 stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].rx_pin,
168 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
170 /* Clear control registry */
176 /* Set serial param: 115.200 bps, no parity */
177 stm32_uartSetBaudRate(UARTDesc[port].base, 115200);
178 stm32_uartSetParity(UARTDesc[port].base, SER_PARITY_NONE);
181 /* Enable trasmision and receiver */
182 base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
186 static bool tx_sending(struct SerialHardware *_hw)
188 struct CM3Serial *hw = (struct CM3Serial *)_hw;
192 static void uart_irq_rx(int port)
194 struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
195 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
198 while (stm32_uartRxReady(UARTDesc[port].base))
201 if (fifo_isfull(rxfifo))
202 ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
204 fifo_push(rxfifo, c);
208 static void uart_irq_tx(int port)
210 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
211 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
213 if (fifo_isempty(txfifo))
216 * Disable TX empty interrupts if there're no more
217 * characters to transmit.
219 base->CR1 &= ~BV(CR1_TXEIE);
220 UARTDesc[port].sending = false;
224 base->DR = fifo_pop(txfifo);
228 static void uart_common_irq_handler(int port)
230 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
233 /* Read and clear the IRQ status */
236 /* Check hw errors */
237 ser_handles[port]->status = status &
238 (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
240 /* Process the IRQ */
241 if (status & BV(CR1_RXNEIE))
245 if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
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);
258 base->CR1 |= BV(CR1_RXNEIE);
261 static void stm32_uartIRQDisable(int port)
263 struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
265 base->CR1 &= ~(BV(CR1_RXNEIE) | 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 hw->sending = true; \
293 base->CR1 |= BV(CR1_TXEIE); \
297 static void uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
298 unsigned long baud) \
300 stm32_uartSetBaudRate(USART## port ## _BASE, baud); \
303 static void uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
306 stm32_uartSetParity(USART## port ## _BASE, parity); \
309 static void uart ## port ## _cleanup(struct SerialHardware *_hw) \
311 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
312 hw->sending = false; \
313 stm32_uartIRQDisable(USART ## port ## _PORT); \
314 stm32_uartClear(USART## port ## _BASE); \
315 stm32_uartDisable(USART## port ## _BASE); \
318 static void uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
319 UNUSED_ARG(struct Serial *, ser)) \
321 stm32_uartInit(USART ## port ## _PORT); \
322 stm32_uartEnable(USART## port ## _BASE); \
323 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler); \
326 /* UART operations */ \
327 static const struct SerialHardwareVT USART ## port ## _VT = \
329 .init = uart ## port ## _init, \
330 .cleanup = uart ## port ## _cleanup, \
331 .setBaudrate = uart ## port ## _setbaudrate, \
332 .setParity = uart ## port ## _setparity, \
333 .txStart = uart ## port ## _txStart, \
334 .txSending = tx_sending, \
337 /* UART port instances */
342 static struct CM3Serial UARTDesc[SER_CNT] =
347 .txbuffer = uart1_txbuffer,
348 .rxbuffer = uart1_rxbuffer,
349 .txbuffer_size = sizeof(uart1_txbuffer),
350 .rxbuffer_size = sizeof(uart1_rxbuffer),
354 .irq = USART1_IRQHANDLER,
359 .txbuffer = uart2_txbuffer,
360 .rxbuffer = uart2_rxbuffer,
361 .txbuffer_size = sizeof(uart2_txbuffer),
362 .rxbuffer_size = sizeof(uart2_rxbuffer),
366 .irq = USART2_IRQHANDLER,
371 .txbuffer = uart3_txbuffer,
372 .rxbuffer = uart3_rxbuffer,
373 .txbuffer_size = sizeof(uart3_txbuffer),
374 .rxbuffer_size = sizeof(uart3_rxbuffer),
378 .irq = USART3_IRQHANDLER,
382 struct SerialHardware *ser_hw_getdesc(int port)
384 ASSERT(port >= 0 && port < SER_CNT);
385 return &UARTDesc[port].hw;