source: rtems/c/src/lib/libbsp/arm/stm32f4/console/usart.c @ 228ece9

4.115
Last change on this file since 228ece9 was 228ece9, checked in by Sebastian Huber <sebastian.huber@…>, on 04/12/12 at 19:27:56

bsp/stm32f4: Add IO and RCC

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2012 Sebastian Huber.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#include <libchip/sersupp.h>
16
17#include <bsp.h>
18#include <bsp/io.h>
19#include <bsp/rcc.h>
20#include <bsp/irq.h>
21#include <bsp/usart.h>
22#include <bsp/stm32f4.h>
23
24static volatile stm32f4_usart *usart_get_regs(const console_tbl *ct)
25{
26  return (stm32f4_usart *) ct->ulCtrlPort1;
27}
28
29#if 0
30static rtems_vector_number usart_get_irq_number(const console_tbl *ct)
31{
32  return ct->ulIntVector;
33}
34#endif
35
36static const stm32f4_rcc_index usart_rcc_index [] = {
37  STM32F4_RCC_USART1,
38  STM32F4_RCC_USART2,
39  STM32F4_RCC_USART3,
40  STM32F4_RCC_UART4,
41  STM32F4_RCC_UART5,
42  STM32F4_RCC_USART6
43};
44
45static stm32f4_rcc_index usart_get_rcc_index(const console_tbl *ct)
46{
47  return usart_rcc_index [ct->ulCtrlPort2];
48}
49
50static const uint8_t usart_pclk_index [] = { 1, 0, 0, 0, 0, 1 };
51
52static const uint32_t usart_pclk_by_index [] = {
53  STM32F4_PCLK1,
54  STM32F4_PCLK2
55};
56
57static uint32_t usart_get_pclk(const console_tbl *ct)
58{
59  return usart_pclk_by_index [usart_pclk_index [ct->ulCtrlPort2]];
60}
61
62static uint32_t usart_get_baud(const console_tbl *ct)
63{
64  return ct->ulClock;
65}
66
67/*
68 * a = 8 * (2 - CR1[OVER8])
69 *
70 * usartdiv = div_mantissa + div_fraction / a
71 *
72 * baud = pclk / (a * usartdiv)
73 *
74 * usartdiv = pclk / (a * baud)
75 *
76 * Calculation in integer arithmetic:
77 *
78 * 1. div_mantissa = pclk / (a * baud)
79 *
80 * 2. div_fraction = pclk / (baud - a * div_mantissa)
81 */
82static uint32_t usart_get_bbr(
83  volatile stm32f4_usart *usart,
84  uint32_t pclk,
85  uint32_t baud
86)
87{
88  uint32_t a = 8 * (2 - ((usart->cr1 & STM32F4_USART_CR1_OVER8) != 0));
89  uint32_t div_mantissa_low = pclk / (a * baud);
90  uint32_t div_fraction_low = pclk / (baud - a * div_mantissa_low);
91  uint32_t div_mantissa_high;
92  uint32_t div_fraction_high;
93  uint32_t high_err;
94  uint32_t low_err;
95  uint32_t div_mantissa;
96  uint32_t div_fraction;
97
98  if (div_fraction_low < a - 1) {
99    div_mantissa_high = div_fraction_low;
100    div_fraction_high = div_fraction_low + 1;
101  } else {
102    div_mantissa_high = div_fraction_low + 1;
103    div_fraction_high = 0;
104  }
105
106  high_err = pclk - baud * (a * div_mantissa_high + div_fraction_high);
107  low_err = baud * (a * div_mantissa_low + div_fraction_low) - pclk;
108
109  if (low_err < high_err) {
110    div_mantissa = div_mantissa_low;
111    div_fraction = div_fraction_low;
112  } else {
113    div_mantissa = div_mantissa_high;
114    div_fraction = div_fraction_high;
115  }
116
117  return STM32F4_USART_BBR_DIV_MANTISSA(div_mantissa)
118    | STM32F4_USART_BBR_DIV_FRACTION(div_fraction);
119}
120
121#define USART_CFG(port, idx, altfunc) \
122  { \
123    .pin = STM32F4_GPIO_PIN(port, idx), \
124    .mode = STM32F4_GPIO_MODE_AF, \
125    .otype = STM32F4_GPIO_OTYPE_PUSH_PULL, \
126    .ospeed = STM32F4_GPIO_OSPEED_2_MHZ, \
127    .pupd = STM32F4_GPIO_PULL_UP, \
128    .af = altfunc \
129  }
130
131static const stm32f4_gpio_config usart_gpio_config [] [2] = {
132  {
133    USART_CFG(0, 9, STM32F4_GPIO_AF_USART1),
134    USART_CFG(0, 10, STM32F4_GPIO_AF_USART1)
135  }, {
136    USART_CFG(0, 2, STM32F4_GPIO_AF_USART2),
137    USART_CFG(0, 3, STM32F4_GPIO_AF_USART2)
138  }, {
139    USART_CFG(3, 8, STM32F4_GPIO_AF_USART3),
140    USART_CFG(3, 9, STM32F4_GPIO_AF_USART3)
141  }, {
142    USART_CFG(0, 1, STM32F4_GPIO_AF_UART4),
143    USART_CFG(0, 2, STM32F4_GPIO_AF_UART4)
144  }, {
145    USART_CFG(2, 11, STM32F4_GPIO_AF_UART5),
146    USART_CFG(2, 12, STM32F4_GPIO_AF_UART5)
147  }, {
148    USART_CFG(2, 6, STM32F4_GPIO_AF_USART6),
149    USART_CFG(2, 7, STM32F4_GPIO_AF_USART6)
150  }
151};
152
153static void usart_set_gpio_config(const console_tbl *ct)
154{
155  const stm32f4_gpio_config *config = usart_gpio_config [ct->ulCtrlPort2];
156
157  stm32f4_rcc_set_gpio_clock(config [0].pin, true);
158  stm32f4_gpio_set_config(&config [0]);
159  stm32f4_rcc_set_gpio_clock(config [1].pin, true);
160  stm32f4_gpio_set_config(&config [1]);
161}
162
163static void usart_initialize(int minor)
164{
165  const console_tbl *ct = Console_Port_Tbl [minor];
166  volatile stm32f4_usart *usart = usart_get_regs(ct);
167  uint32_t pclk = usart_get_pclk(ct);
168  uint32_t baud = usart_get_baud(ct);
169  stm32f4_rcc_index rcc_index = usart_get_rcc_index(ct);
170
171  stm32f4_rcc_set_clock(rcc_index, true);
172  usart_set_gpio_config(ct);
173
174  usart->cr1 = 0;
175  usart->cr2 = 0;
176  usart->cr3 = 0;
177  usart->bbr = usart_get_bbr(usart, pclk, baud);
178  usart->cr1 = STM32F4_USART_CR1_UE
179    | STM32F4_USART_CR1_TE
180    | STM32F4_USART_CR1_RE;
181}
182
183static int usart_first_open(int major, int minor, void *arg)
184{
185  rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
186  struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
187  const console_tbl *ct = Console_Port_Tbl [minor];
188  console_data *cd = &Console_Port_Data [minor];
189
190  cd->termios_data = tty;
191  rtems_termios_set_initial_baud(tty, ct->ulClock);
192
193  return 0;
194}
195
196static int usart_last_close(int major, int minor, void *arg)
197{
198  return 0;
199}
200
201static int usart_read_polled(int minor)
202{
203  const console_tbl *ct = Console_Port_Tbl [minor];
204  volatile stm32f4_usart *usart = usart_get_regs(ct);
205
206  if ((usart->sr & STM32F4_USART_SR_RXNE) != 0) {
207    return STM32F4_USART_DR_GET(usart->dr);
208  } else {
209    return -1;
210  }
211}
212
213static void usart_write_polled(int minor, char c)
214{
215  const console_tbl *ct = Console_Port_Tbl [minor];
216  volatile stm32f4_usart *usart = usart_get_regs(ct);
217
218  while ((usart->sr & STM32F4_USART_SR_TXE) == 0) {
219    /* Wait */
220  }
221
222  usart->dr = STM32F4_USART_DR(c);
223}
224
225static ssize_t usart_write_support_polled(
226  int minor,
227  const char *s,
228  size_t n
229)
230{
231  ssize_t i = 0;
232
233  for (i = 0; i < n; ++i) {
234    usart_write_polled(minor, s [i]);
235  }
236
237  return n;
238}
239
240static int usart_set_attributes(int minor, const struct termios *term)
241{
242  return -1;
243}
244
245console_fns stm32f4_usart_fns = {
246  .deviceProbe = libchip_serial_default_probe,
247  .deviceFirstOpen = usart_first_open,
248  .deviceLastClose = usart_last_close,
249  .deviceRead = usart_read_polled,
250  .deviceWrite = usart_write_support_polled,
251  .deviceInitialize = usart_initialize,
252  .deviceWritePolled = usart_write_polled,
253  .deviceSetAttributes = usart_set_attributes,
254  .deviceOutputUsesInterrupts = false
255};
Note: See TracBrowser for help on using the repository browser.