Clean up. Use defines instead magic numers.
[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;
76         uint32_t sysctl1;
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 = RCC_APB2_GPIOA,
89                 .sysctl1 = 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 = RCC_APB2_GPIOA,
97                 .sysctl1 = 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 = RCC_APB2_GPIOB,
105                 .sysctl1 = 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
153         /* Configure USART pins */
154         if (port == USART1_PORT)
155         {
156                 RCC->APB2ENR |=  gpio_uart[port].sysctl;
157                 RCC->APB2ENR |=  gpio_uart[port].sysctl1;
158         }
159         else
160         {
161                 RCC->APB1ENR |=  gpio_uart[port].sysctl;
162                 RCC->APB1ENR |=  gpio_uart[port].sysctl1;
163         }
164
165         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].tx_pin,
166                                 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
167
168         stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].rx_pin,
169                                 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
170
171         /* Clear control registry */
172         base->CR2 = 0; //CR2_CLEAR_MASK;
173         base->CR1 = 0; //CR1_CLEAR_MASK;
174         base->CR3 = 0; //CR3_CLEAR_MASK;
175         base->SR = 0;
176
177         /* Set serial param: 115.200 bps, no parity */
178         stm32_uartSetBaudRate(UARTDesc[port].base, 115200);
179         stm32_uartSetParity(UARTDesc[port].base, SER_PARITY_NONE);
180
181
182         /* Enable trasmision and receiver */
183         base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
184
185 }
186
187 static bool tx_sending(struct SerialHardware *_hw)
188 {
189         struct CM3Serial *hw = (struct CM3Serial *)_hw;
190         return hw->sending;
191 }
192
193 static void uart_irq_rx(int port)
194 {
195         struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
196         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
197         char c;
198
199         while (stm32_uartRxReady(UARTDesc[port].base))
200         {
201                 c = base->DR;
202                 if (fifo_isfull(rxfifo))
203                         ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
204                 else
205                         fifo_push(rxfifo, c);
206         }
207 }
208
209 static void uart_irq_tx(int port)
210 {
211         struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
212         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
213
214         if (fifo_isempty(txfifo))
215         {
216                 /*
217                  * Disable TX empty interrupts if there're no more
218                  * characters to transmit.
219                  */
220                 base->CR1 &= ~BV(CR1_TXEIE);
221                 UARTDesc[port].sending = false;
222         }
223         else
224         {
225                 base->DR = fifo_pop(txfifo);
226         }
227 }
228
229 static void uart_common_irq_handler(int port)
230 {
231         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
232         uint32_t status;
233
234         /* Read and clear the IRQ status */
235         status = base->SR;
236         /* Process the IRQ */
237         if (status & BV(CR1_RXNEIE))
238         {
239                 uart_irq_rx(port);
240         }
241         if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
242         {
243                 uart_irq_tx(port);
244         }
245 }
246
247 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
248 {
249         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
250
251         /* Register the IRQ handler */
252         sysirq_setHandler(UARTDesc[port].irq, handler);
253
254         base->CR1 |= BV(CR1_RXNEIE);
255 }
256
257 static void stm32_uartIRQDisable(int port)
258 {
259         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
260
261         base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
262 }
263
264
265 /* UART class definition */
266 #define UART_PORT(port)                  \
267         /* UART TX and RX buffers */ \
268         static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
269         static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE];      \
270                                                                                 \
271         /* UART interrupt handler */                                            \
272         static DECLARE_ISR(uart ## port ## _irq_handler)        \
273         {                                                                       \
274                 uart_common_irq_handler(USART ## port ## _PORT);        \
275         }                                                                       \
276                                                                                 \
277         /* UART public methods */ \
278         static void     uart ## port ## _txStart(struct SerialHardware *_hw) \
279         {                                                                                                                                \
280                 struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo;                \
281                 struct CM3Serial *hw = (struct CM3Serial *)_hw;                      \
282                 struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
283                 if (hw->sending)                                                \
284                         return;                                                 \
285                 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo));    \
286                 if (!fifo_isempty(txfifo))                                      \
287                 {                                                               \
288                         hw->sending = true;      \
289                         base->CR1 |= BV(CR1_TXEIE); \
290                 } \
291         }                                                                       \
292                                                                                 \
293         static void     uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
294                                                 unsigned long baud)             \
295         {                                                                       \
296                 stm32_uartSetBaudRate(USART## port ## _BASE, baud);             \
297         }                                                                       \
298                                                                                 \
299         static void     uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw),     \
300                                                 int parity)                     \
301         {                                                                       \
302                 stm32_uartSetParity(USART## port ## _BASE, parity);             \
303         }                                                                       \
304                                                                                 \
305         static void     uart ## port ## _cleanup(struct SerialHardware *_hw)                    \
306         {                                                                       \
307                 struct CM3Serial *hw = (struct CM3Serial *)_hw;                 \
308                 hw->sending = false; \
309                 stm32_uartIRQDisable(USART ## port ## _PORT);                                   \
310                 stm32_uartClear(USART## port ## _BASE);                         \
311                 stm32_uartDisable(USART## port ## _BASE);                       \
312         }                                                                       \
313                                                                                 \
314         static void     uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw),          \
315                                 UNUSED_ARG(struct Serial *, ser))               \
316         {                                                                       \
317                 stm32_uartInit(USART ## port ## _PORT);                                         \
318                 stm32_uartEnable(USART## port ## _BASE);                                \
319                 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler);              \
320         }                                                                       \
321                                                                                 \
322         /* UART operations */                                                   \
323         static const struct SerialHardwareVT USART ## port ## _VT =             \
324         {                                                                       \
325                 .init = uart ## port ## _init,                                  \
326                 .cleanup = uart ## port ## _cleanup,                            \
327                 .setBaudrate = uart ## port ## _setbaudrate,                    \
328                 .setParity = uart ## port ## _setparity,                        \
329                 .txStart = uart ## port ## _txStart,                            \
330                 .txSending = tx_sending,                                        \
331         };
332
333 /* UART port instances */
334 UART_PORT(1)
335 UART_PORT(2)
336 UART_PORT(3)
337
338 static struct CM3Serial UARTDesc[SER_CNT] =
339 {
340         {
341                 .hw = {
342                         .table = &USART1_VT,
343                         .txbuffer = uart1_txbuffer,
344                         .rxbuffer = uart1_rxbuffer,
345                         .txbuffer_size = sizeof(uart1_txbuffer),
346                         .rxbuffer_size = sizeof(uart1_rxbuffer),
347                 },
348                 .sending = false,
349                 .base = USART1_BASE,
350                 .irq = USART1_IRQHANDLER,
351         },
352         {
353                 .hw = {
354                         .table = &USART2_VT,
355                         .txbuffer = uart2_txbuffer,
356                         .rxbuffer = uart2_rxbuffer,
357                         .txbuffer_size = sizeof(uart2_txbuffer),
358                         .rxbuffer_size = sizeof(uart2_rxbuffer),
359                 },
360                 .sending = false,
361                 .base = USART2_BASE,
362                 .irq = USART2_IRQHANDLER,
363         },
364         {
365                 .hw = {
366                         .table = &USART3_VT,
367                         .txbuffer = uart3_txbuffer,
368                         .rxbuffer = uart3_rxbuffer,
369                         .txbuffer_size = sizeof(uart3_txbuffer),
370                         .rxbuffer_size = sizeof(uart3_rxbuffer),
371                 },
372                 .sending = false,
373                 .base = USART3_BASE,
374                 .irq = USART3_IRQHANDLER,
375         },
376 };
377
378 struct SerialHardware *ser_hw_getdesc(int port)
379 {
380         ASSERT(port >= 0 && port < SER_CNT);
381         return &UARTDesc[port].hw;
382 }