Refactor to use new protocol module and sipo.
[bertos.git] / bertos / cpu / cortex-m3 / drv / ser_stm32.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
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.
10  *
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.
15  *
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
19  *
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.
28  *
29  * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief STM32 UART interface driver.
34  *
35  * \author Daniele Basile <asterix@develer.com>
36  */
37
38 #include "ser_stm32.h"
39
40 #include "cfg/cfg_ser.h"
41
42 #include <cfg/macros.h> /* for BV() */
43 #include <cfg/debug.h>
44
45 #include <drv/gpio_stm32.h>
46 #include <drv/irq_cm3.h>
47 #include <drv/clock_stm32.h>
48 #include <drv/ser_p.h>
49 #include <drv/ser.h>
50
51
52 /* From the high-level serial driver */
53 extern struct Serial *ser_handles[SER_CNT];
54
55 struct CM3Serial
56 {
57         struct SerialHardware hw;
58         volatile bool sending;
59         uint32_t base;
60         sysirq_t irq;
61 };
62
63 /* Forward declaration */
64 static struct CM3Serial UARTDesc[SER_CNT];
65
66 /* GPIO descriptor for UART pins */
67 struct gpio_uart_info
68 {
69         /* GPIO base address register */
70         uint32_t base;
71         /* Pin(s) bitmask */
72         uint32_t rx_pin;
73         uint32_t tx_pin;
74         /* Sysctl */
75         uint32_t sysctl_gpio;
76         uint32_t sysctl_usart;
77
78 };
79
80 /* Table to retrieve GPIO pins configuration to work as UART pins */
81 static const struct gpio_uart_info gpio_uart[SER_CNT] =
82 {
83         /* UART1 */
84         {
85                 .base = GPIOA_BASE,
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,
90         },
91         /* UART2 */
92         {
93                 .base = GPIOA_BASE,
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,
98         },
99 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
100         /* UART3 */
101         {
102                 .base = GPIOB_BASE,
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,
107         },
108 #endif
109 };
110
111 #define USART1_PORT                0
112 #define USART2_PORT                1
113 #define USART3_PORT                2
114
115 void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
116 {
117         struct stm32_usart *_base = (struct stm32_usart *)base;
118         _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
119 }
120
121 void stm32_uartSetParity(uint32_t base, int parity)
122 {
123         struct stm32_usart *_base = (struct stm32_usart *)base;
124
125         /*  USART_WORD_LEN_8B */
126         _base->CR1 &= ~BV(CR1_M);
127
128         switch(parity)
129         {
130         case SER_PARITY_NONE:
131                 _base->CR1 &= ~BV(CR1_PCE);
132                 break;
133         case SER_PARITY_ODD:
134                 _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
135                 break;
136         case SER_PARITY_EVEN:
137                 _base->CR1 |= BV(CR1_PCE);
138                 _base->CR1 &= ~BV(CR1_PS);
139                 break;
140         default:
141                 ASSERT(0);
142                 return;
143         }
144 }
145
146 void stm32_uartInit(int port)
147 {
148         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
149
150         ASSERT(port >= 0 && port < SER_CNT);
151
152         /* Enable clocking on AFIO */
153         RCC->APB2ENR |= RCC_APB2_AFIO;
154         RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
155
156         /* Configure USART pins */
157         if (port == USART1_PORT)
158         {
159                 RCC->APB2ENR |=  gpio_uart[port].sysctl_usart;
160         }
161         else
162         {
163                 RCC->APB1ENR |=  gpio_uart[port].sysctl_usart;
164         }
165
166         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].tx_pin,
167                                 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
168
169         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].rx_pin,
170                                 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
171
172         /* Clear control registry */
173         base->CR2 = 0;
174         base->CR1 = 0;
175         base->CR3 = 0;
176         base->SR = 0;
177
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);
181
182
183         /* Enable trasmision and receiver */
184         base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
185
186 }
187
188 static bool tx_sending(struct SerialHardware *_hw)
189 {
190         struct CM3Serial *hw = (struct CM3Serial *)_hw;
191         return hw->sending;
192 }
193
194 static void uart_irq_rx(int port)
195 {
196         struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
197         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
198         char c;
199
200         while (stm32_uartRxReady(UARTDesc[port].base))
201         {
202                 c = base->DR;
203                 if (fifo_isfull(rxfifo))
204                         ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
205                 else
206                         fifo_push(rxfifo, c);
207         }
208 }
209
210 static void uart_irq_tx(int port)
211 {
212         struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
213         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
214
215         if (fifo_isempty(txfifo))
216         {
217                 /*
218                  * Disable TX empty interrupts if there're no more
219                  * characters to transmit.
220                  */
221                 base->CR1 &= ~BV(CR1_TXEIE);
222                 UARTDesc[port].sending = false;
223         }
224         else
225         {
226                 base->DR = fifo_pop(txfifo);
227         }
228 }
229
230 static void uart_common_irq_handler(int port)
231 {
232         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
233         uint32_t status;
234
235         /* Read and clear the IRQ status */
236         status = base->SR;
237
238         /* Check hw errors */
239         ser_handles[port]->status = status &
240                 (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
241
242         /* Process the IRQ */
243         if (status & BV(CR1_RXNEIE))
244         {
245                 uart_irq_rx(port);
246         }
247         if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
248         {
249                 uart_irq_tx(port);
250         }
251 }
252
253 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
254 {
255         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
256
257         /* Register the IRQ handler */
258         sysirq_setHandler(UARTDesc[port].irq, handler);
259
260         base->CR1 |= BV(CR1_RXNEIE);
261 }
262
263 static void stm32_uartIRQDisable(int port)
264 {
265         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
266
267         base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
268 }
269
270
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];      \
276                                                                                 \
277         /* UART interrupt handler */                                            \
278         static DECLARE_ISR(uart ## port ## _irq_handler)        \
279         {                                                                       \
280                 uart_common_irq_handler(USART ## port ## _PORT);        \
281         }                                                                       \
282                                                                                 \
283         /* UART public methods */ \
284         static void     uart ## port ## _txStart(struct SerialHardware *_hw) \
285         {                                                                                                                                \
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; \
289                 if (hw->sending)                                                \
290                         return;                                                 \
291                 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo));    \
292                 if (!fifo_isempty(txfifo))                                      \
293                 {                                                               \
294                         hw->sending = true;      \
295                         base->CR1 |= BV(CR1_TXEIE); \
296                 } \
297         }                                                                       \
298                                                                                 \
299         static void     uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
300                                                 unsigned long baud)             \
301         {                                                                       \
302                 stm32_uartSetBaudRate(USART## port ## _BASE, baud);             \
303         }                                                                       \
304                                                                                 \
305         static void     uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw),     \
306                                                 int parity)                     \
307         {                                                                       \
308                 stm32_uartSetParity(USART## port ## _BASE, parity);             \
309         }                                                                       \
310                                                                                 \
311         static void     uart ## port ## _cleanup(struct SerialHardware *_hw)                    \
312         {                                                                       \
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);                       \
318         }                                                                       \
319                                                                                 \
320         static void     uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw),          \
321                                 UNUSED_ARG(struct Serial *, ser))               \
322         {                                                                       \
323                 stm32_uartInit(USART ## port ## _PORT);                                         \
324                 stm32_uartEnable(USART## port ## _BASE);                                \
325                 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler);              \
326         }                                                                       \
327                                                                                 \
328         /* UART operations */                                                   \
329         static const struct SerialHardwareVT USART ## port ## _VT =             \
330         {                                                                       \
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,                                        \
337         };
338
339 /* UART port instances */
340 UART_PORT(1)
341 UART_PORT(2)
342 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
343 UART_PORT(3)
344 #endif
345
346 static struct CM3Serial UARTDesc[SER_CNT] =
347 {
348         {
349                 .hw = {
350                         .table = &USART1_VT,
351                         .txbuffer = uart1_txbuffer,
352                         .rxbuffer = uart1_rxbuffer,
353                         .txbuffer_size = sizeof(uart1_txbuffer),
354                         .rxbuffer_size = sizeof(uart1_rxbuffer),
355                 },
356                 .sending = false,
357                 .base = USART1_BASE,
358                 .irq = USART1_IRQHANDLER,
359         },
360         {
361                 .hw = {
362                         .table = &USART2_VT,
363                         .txbuffer = uart2_txbuffer,
364                         .rxbuffer = uart2_rxbuffer,
365                         .txbuffer_size = sizeof(uart2_txbuffer),
366                         .rxbuffer_size = sizeof(uart2_rxbuffer),
367                 },
368                 .sending = false,
369                 .base = USART2_BASE,
370                 .irq = USART2_IRQHANDLER,
371         },
372 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
373         {
374                 .hw = {
375                         .table = &USART3_VT,
376                         .txbuffer = uart3_txbuffer,
377                         .rxbuffer = uart3_rxbuffer,
378                         .txbuffer_size = sizeof(uart3_txbuffer),
379                         .rxbuffer_size = sizeof(uart3_rxbuffer),
380                 },
381                 .sending = false,
382                 .base = USART3_BASE,
383                 .irq = USART3_IRQHANDLER,
384         },
385 #endif
386 };
387
388 struct SerialHardware *ser_hw_getdesc(int port)
389 {
390         ASSERT(port >= 0 && port < SER_CNT);
391         return &UARTDesc[port].hw;
392 }