Reformat. Clean up. Use more clear variable names.
[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         /* UART3 */
100         {
101                 .base = GPIOB_BASE,
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,
106         },
107 };
108
109 #define USART1_PORT                0
110 #define USART2_PORT                1
111 #define USART3_PORT                2
112
113 void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
114 {
115         struct stm32_usart *_base = (struct stm32_usart *)base;
116         _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
117 }
118
119 void stm32_uartSetParity(uint32_t base, int parity)
120 {
121         struct stm32_usart *_base = (struct stm32_usart *)base;
122
123         /*  USART_WORD_LEN_8B */
124         _base->CR1 &= ~BV(CR1_M);
125
126         switch(parity)
127         {
128         case SER_PARITY_NONE:
129                 _base->CR1 &= ~BV(CR1_PCE);
130                 break;
131         case SER_PARITY_ODD:
132                 _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
133                 break;
134         case SER_PARITY_EVEN:
135                 _base->CR1 |= BV(CR1_PCE);
136                 _base->CR1 &= ~BV(CR1_PS);
137                 break;
138         default:
139                 ASSERT(0);
140                 return;
141         }
142 }
143
144 void stm32_uartInit(int port)
145 {
146         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
147
148         ASSERT(port >= 0 && port < SER_CNT);
149
150         /* Enable clocking on AFIO */
151         RCC->APB2ENR |= RCC_APB2_AFIO;
152         RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
153
154         /* Configure USART pins */
155         if (port == USART1_PORT)
156         {
157                 RCC->APB2ENR |=  gpio_uart[port].sysctl_usart;
158         }
159         else
160         {
161                 RCC->APB1ENR |=  gpio_uart[port].sysctl_usart;
162         }
163
164         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].tx_pin,
165                                 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
166
167         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].rx_pin,
168                                 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
169
170         /* Clear control registry */
171         base->CR2 = 0;
172         base->CR1 = 0;
173         base->CR3 = 0;
174         base->SR = 0;
175
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);
179
180
181         /* Enable trasmision and receiver */
182         base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
183
184 }
185
186 static bool tx_sending(struct SerialHardware *_hw)
187 {
188         struct CM3Serial *hw = (struct CM3Serial *)_hw;
189         return hw->sending;
190 }
191
192 static void uart_irq_rx(int port)
193 {
194         struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
195         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
196         char c;
197
198         while (stm32_uartRxReady(UARTDesc[port].base))
199         {
200                 c = base->DR;
201                 if (fifo_isfull(rxfifo))
202                         ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
203                 else
204                         fifo_push(rxfifo, c);
205         }
206 }
207
208 static void uart_irq_tx(int port)
209 {
210         struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
211         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
212
213         if (fifo_isempty(txfifo))
214         {
215                 /*
216                  * Disable TX empty interrupts if there're no more
217                  * characters to transmit.
218                  */
219                 base->CR1 &= ~BV(CR1_TXEIE);
220                 UARTDesc[port].sending = false;
221         }
222         else
223         {
224                 base->DR = fifo_pop(txfifo);
225         }
226 }
227
228 static void uart_common_irq_handler(int port)
229 {
230         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
231         uint32_t status;
232
233         /* Read and clear the IRQ status */
234         status = base->SR;
235
236         /* Check hw errors */
237         ser_handles[port]->status = status &
238                 (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
239
240         /* Process the IRQ */
241         if (status & BV(CR1_RXNEIE))
242         {
243                 uart_irq_rx(port);
244         }
245         if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
246         {
247                 uart_irq_tx(port);
248         }
249 }
250
251 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
252 {
253         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
254
255         /* Register the IRQ handler */
256         sysirq_setHandler(UARTDesc[port].irq, handler);
257
258         base->CR1 |= BV(CR1_RXNEIE);
259 }
260
261 static void stm32_uartIRQDisable(int port)
262 {
263         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
264
265         base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
266 }
267
268
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];      \
274                                                                                 \
275         /* UART interrupt handler */                                            \
276         static DECLARE_ISR(uart ## port ## _irq_handler)        \
277         {                                                                       \
278                 uart_common_irq_handler(USART ## port ## _PORT);        \
279         }                                                                       \
280                                                                                 \
281         /* UART public methods */ \
282         static void     uart ## port ## _txStart(struct SerialHardware *_hw) \
283         {                                                                                                                                \
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; \
287                 if (hw->sending)                                                \
288                         return;                                                 \
289                 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo));    \
290                 if (!fifo_isempty(txfifo))                                      \
291                 {                                                               \
292                         hw->sending = true;      \
293                         base->CR1 |= BV(CR1_TXEIE); \
294                 } \
295         }                                                                       \
296                                                                                 \
297         static void     uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
298                                                 unsigned long baud)             \
299         {                                                                       \
300                 stm32_uartSetBaudRate(USART## port ## _BASE, baud);             \
301         }                                                                       \
302                                                                                 \
303         static void     uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw),     \
304                                                 int parity)                     \
305         {                                                                       \
306                 stm32_uartSetParity(USART## port ## _BASE, parity);             \
307         }                                                                       \
308                                                                                 \
309         static void     uart ## port ## _cleanup(struct SerialHardware *_hw)                    \
310         {                                                                       \
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);                       \
316         }                                                                       \
317                                                                                 \
318         static void     uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw),          \
319                                 UNUSED_ARG(struct Serial *, ser))               \
320         {                                                                       \
321                 stm32_uartInit(USART ## port ## _PORT);                                         \
322                 stm32_uartEnable(USART## port ## _BASE);                                \
323                 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler);              \
324         }                                                                       \
325                                                                                 \
326         /* UART operations */                                                   \
327         static const struct SerialHardwareVT USART ## port ## _VT =             \
328         {                                                                       \
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,                                        \
335         };
336
337 /* UART port instances */
338 UART_PORT(1)
339 UART_PORT(2)
340 UART_PORT(3)
341
342 static struct CM3Serial UARTDesc[SER_CNT] =
343 {
344         {
345                 .hw = {
346                         .table = &USART1_VT,
347                         .txbuffer = uart1_txbuffer,
348                         .rxbuffer = uart1_rxbuffer,
349                         .txbuffer_size = sizeof(uart1_txbuffer),
350                         .rxbuffer_size = sizeof(uart1_rxbuffer),
351                 },
352                 .sending = false,
353                 .base = USART1_BASE,
354                 .irq = USART1_IRQHANDLER,
355         },
356         {
357                 .hw = {
358                         .table = &USART2_VT,
359                         .txbuffer = uart2_txbuffer,
360                         .rxbuffer = uart2_rxbuffer,
361                         .txbuffer_size = sizeof(uart2_txbuffer),
362                         .rxbuffer_size = sizeof(uart2_rxbuffer),
363                 },
364                 .sending = false,
365                 .base = USART2_BASE,
366                 .irq = USART2_IRQHANDLER,
367         },
368         {
369                 .hw = {
370                         .table = &USART3_VT,
371                         .txbuffer = uart3_txbuffer,
372                         .rxbuffer = uart3_rxbuffer,
373                         .txbuffer_size = sizeof(uart3_txbuffer),
374                         .rxbuffer_size = sizeof(uart3_rxbuffer),
375                 },
376                 .sending = false,
377                 .base = USART3_BASE,
378                 .irq = USART3_IRQHANDLER,
379         },
380 };
381
382 struct SerialHardware *ser_hw_getdesc(int port)
383 {
384         ASSERT(port >= 0 && port < SER_CNT);
385         return &UARTDesc[port].hw;
386 }