Add serial module.
[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         kprintf("init port[%d]cnt[%d]\n", port, SER_CNT);
149         ASSERT(port >= 0 && port < SER_CNT);
150
151         /* Enable clocking on AFIO */
152         RCC->APB2ENR |= RCC_APB2_AFIO;
153
154         /* Configure USART pins */
155         if (port == USART1_PORT)
156         {
157                 RCC->APB2ENR |=  gpio_uart[port].sysctl;
158                 RCC->APB2ENR |=  gpio_uart[port].sysctl1;
159         }
160         else
161         {
162                 RCC->APB1ENR |=  gpio_uart[port].sysctl;
163                 RCC->APB1ENR |=  gpio_uart[port].sysctl1;
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; //CR2_CLEAR_MASK;
174         base->CR1 = 0; //CR1_CLEAR_MASK;
175         base->CR3 = 0; //CR3_CLEAR_MASK;
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         kprintf("INIT[%02x]\n", (uint8_t)base->SR); \
188
189 }
190
191 static bool tx_sending(struct SerialHardware *_hw)
192 {
193         struct CM3Serial *hw = (struct CM3Serial *)_hw;
194         return hw->sending;
195 }
196
197 static void uart_irq_rx(int port)
198 {
199         struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
200         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
201         char c;
202
203         while (stm32_uartRxReady(UARTDesc[port].base))
204         {
205                 c = base->DR;
206                 if (fifo_isfull(rxfifo))
207                         ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
208                 else
209                         fifo_push(rxfifo, c);
210         }
211 }
212
213 static void uart_irq_tx(int port)
214 {
215         struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
216         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
217
218         if (fifo_isempty(txfifo))
219         {
220                 /*
221                  * Disable TX empty interrupts if there're no more
222                  * characters to transmit.
223                  */
224                 base->CR1 &= ~BV(7);
225                 UARTDesc[port].sending = false;
226         }
227         else
228         {
229                 base->DR = fifo_pop(txfifo);
230         }
231 }
232
233 static void uart_common_irq_handler(int port)
234 {
235         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
236         uint32_t status;
237
238         /* Read and clear the IRQ status */
239         status = base->SR;
240         /* Process the IRQ */
241         if (status & BV(5))
242         {
243                 uart_irq_rx(port);
244         }
245         if (status & (BV(7) | BV(6)))
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(5);
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(5) | 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                         kputs("tx_en_irq\n"); \
293                         hw->sending = true;      \
294                         base->CR1 |= BV(7); \
295                 } \
296         }                                                                       \
297                                                                                 \
298         static void     uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
299                                                 unsigned long baud)             \
300         {                                                                       \
301                 stm32_uartSetBaudRate(USART## port ## _BASE, baud);             \
302         }                                                                       \
303                                                                                 \
304         static void     uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw),     \
305                                                 int parity)                     \
306         {                                                                       \
307                 stm32_uartSetParity(USART## port ## _BASE, parity);             \
308         }                                                                       \
309                                                                                 \
310         static void     uart ## port ## _cleanup(struct SerialHardware *_hw)                    \
311         {                                                                       \
312                 struct CM3Serial *hw = (struct CM3Serial *)_hw;                 \
313                 hw->sending = false; \
314                 stm32_uartIRQDisable(USART ## port ## _PORT);                                   \
315                 stm32_uartClear(USART## port ## _BASE);                         \
316                 stm32_uartDisable(USART## port ## _BASE);                       \
317         }                                                                       \
318                                                                                 \
319         static void     uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw),          \
320                                 UNUSED_ARG(struct Serial *, ser))               \
321         {                                                                       \
322                 stm32_uartInit(USART ## port ## _PORT);                                         \
323                 stm32_uartEnable(USART## port ## _BASE);                                \
324                 stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler);              \
325         }                                                                       \
326                                                                                 \
327         /* UART operations */                                                   \
328         static const struct SerialHardwareVT USART ## port ## _VT =             \
329         {                                                                       \
330                 .init = uart ## port ## _init,                                  \
331                 .cleanup = uart ## port ## _cleanup,                            \
332                 .setBaudrate = uart ## port ## _setbaudrate,                    \
333                 .setParity = uart ## port ## _setparity,                        \
334                 .txStart = uart ## port ## _txStart,                            \
335                 .txSending = tx_sending,                                        \
336         };
337
338 /* UART port instances */
339 UART_PORT(1)
340 UART_PORT(2)
341 UART_PORT(3)
342
343 static struct CM3Serial UARTDesc[SER_CNT] =
344 {
345         {
346                 .hw = {
347                         .table = &USART1_VT,
348                         .txbuffer = uart1_txbuffer,
349                         .rxbuffer = uart1_rxbuffer,
350                         .txbuffer_size = sizeof(uart1_txbuffer),
351                         .rxbuffer_size = sizeof(uart1_rxbuffer),
352                 },
353                 .sending = false,
354                 .base = USART1_BASE,
355                 .irq = USART1_IRQHANDLER,
356         },
357         {
358                 .hw = {
359                         .table = &USART2_VT,
360                         .txbuffer = uart2_txbuffer,
361                         .rxbuffer = uart2_rxbuffer,
362                         .txbuffer_size = sizeof(uart2_txbuffer),
363                         .rxbuffer_size = sizeof(uart2_rxbuffer),
364                 },
365                 .sending = false,
366                 .base = USART2_BASE,
367                 .irq = USART2_IRQHANDLER,
368         },
369         {
370                 .hw = {
371                         .table = &USART3_VT,
372                         .txbuffer = uart3_txbuffer,
373                         .rxbuffer = uart3_rxbuffer,
374                         .txbuffer_size = sizeof(uart3_txbuffer),
375                         .rxbuffer_size = sizeof(uart3_rxbuffer),
376                 },
377                 .sending = false,
378                 .base = USART3_BASE,
379                 .irq = USART3_IRQHANDLER,
380         },
381 };
382
383 struct SerialHardware *ser_hw_getdesc(int port)
384 {
385         ASSERT(port >= 0 && port < SER_CNT);
386         return &UARTDesc[port].hw;
387 }