8a0ae8a31e81abc3e20f9e70dececa0dcbc84106
[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
237         /* Check hw errors */
238         ser_handles[port]->status = status &
239                 (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
240
241         /* Process the IRQ */
242         if (status & BV(CR1_RXNEIE))
243         {
244                 uart_irq_rx(port);
245         }
246         if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
247         {
248                 uart_irq_tx(port);
249         }
250 }
251
252 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
253 {
254         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
255
256         /* Register the IRQ handler */
257         sysirq_setHandler(UARTDesc[port].irq, handler);
258
259         base->CR1 |= BV(CR1_RXNEIE);
260 }
261
262 static void stm32_uartIRQDisable(int port)
263 {
264         struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
265
266         base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
267 }
268
269
270 /* UART class definition */
271 #define UART_PORT(port)                  \
272         /* UART TX and RX buffers */ \
273         static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
274         static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE];      \
275                                                                                 \
276         /* UART interrupt handler */                                            \
277         static DECLARE_ISR(uart ## port ## _irq_handler)        \
278         {                                                                       \
279                 uart_common_irq_handler(USART ## port ## _PORT);        \
280         }                                                                       \
281                                                                                 \
282         /* UART public methods */ \
283         static void     uart ## port ## _txStart(struct SerialHardware *_hw) \
284         {                                                                                                                                \
285                 struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo;                \
286                 struct CM3Serial *hw = (struct CM3Serial *)_hw;                      \
287                 struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
288                 if (hw->sending)                                                \
289                         return;                                                 \
290                 stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo));    \
291                 if (!fifo_isempty(txfifo))                                      \
292                 {                                                               \
293                         hw->sending = true;      \
294                         base->CR1 |= BV(CR1_TXEIE); \
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 }