source: rtems/c/src/lib/libbsp/arm/stm32f4/console/usart.c @ 7afcb26

4.115
Last change on this file since 7afcb26 was e230fb4, checked in by Sebastian Huber <sebastian.huber@…>, on 03/29/12 at 19:23:14

bsp/stm32f4: New BSP

  • Property mode set to 100644
File size: 4.6 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/irq.h>
19#include <bsp/usart.h>
20#include <bsp/stm32f4.h>
21
22static volatile stm32f4_usart *usart_get_regs(const console_tbl *ct)
23{
24  return (stm32f4_usart *) ct->ulCtrlPort1;
25}
26
27#if 0
28static rtems_vector_number usart_get_irq_number(const console_tbl *ct)
29{
30  return ct->ulIntVector;
31}
32#endif
33
34static const uint8_t usart_pclk_index [] = { 1, 0, 0, 0, 0, 1 };
35
36static const uint32_t usart_pclk_by_index [] = {
37  STM32F4_PCLK1,
38  STM32F4_PCLK2
39};
40
41static uint32_t usart_get_pclk(const console_tbl *ct)
42{
43  return usart_pclk_by_index [usart_pclk_index [ct->ulCtrlPort2]];
44}
45
46static uint32_t usart_get_baud(const console_tbl *ct)
47{
48  return ct->ulClock;
49}
50
51/*
52 * a = 8 * (2 - CR1[OVER8])
53 *
54 * usartdiv = div_mantissa + div_fraction / a
55 *
56 * baud = pclk / (a * usartdiv)
57 *
58 * usartdiv = pclk / (a * baud)
59 *
60 * Calculation in integer arithmetic:
61 *
62 * 1. div_mantissa = pclk / (a * baud)
63 *
64 * 2. div_fraction = pclk / (baud - a * div_mantissa)
65 */
66static uint32_t usart_get_bbr(
67  volatile stm32f4_usart *usart,
68  uint32_t pclk,
69  uint32_t baud
70)
71{
72  uint32_t a = 8 * (2 - ((usart->cr1 & STM32F4_USART_CR1_OVER8) != 0));
73  uint32_t div_mantissa_low = pclk / (a * baud);
74  uint32_t div_fraction_low = pclk / (baud - a * div_mantissa_low);
75  uint32_t div_mantissa_high;
76  uint32_t div_fraction_high;
77  uint32_t high_err;
78  uint32_t low_err;
79  uint32_t div_mantissa;
80  uint32_t div_fraction;
81
82  if (div_fraction_low < a - 1) {
83    div_mantissa_high = div_fraction_low;
84    div_fraction_high = div_fraction_low + 1;
85  } else {
86    div_mantissa_high = div_fraction_low + 1;
87    div_fraction_high = 0;
88  }
89
90  high_err = pclk - baud * (a * div_mantissa_high + div_fraction_high);
91  low_err = baud * (a * div_mantissa_low + div_fraction_low) - pclk;
92
93  if (low_err < high_err) {
94    div_mantissa = div_mantissa_low;
95    div_fraction = div_fraction_low;
96  } else {
97    div_mantissa = div_mantissa_high;
98    div_fraction = div_fraction_high;
99  }
100
101  return STM32F4_USART_BBR_DIV_MANTISSA(div_mantissa)
102    | STM32F4_USART_BBR_DIV_FRACTION(div_fraction);
103}
104
105static void usart_initialize(int minor)
106{
107  const console_tbl *ct = Console_Port_Tbl [minor];
108  volatile stm32f4_usart *usart = usart_get_regs(ct);
109  uint32_t pclk = usart_get_pclk(ct);
110  uint32_t baud = usart_get_baud(ct);
111  volatile stm32f4_rcc *rcc = &STM32F4_RCC;
112
113  rcc->apb2enr |= STM32F4_RCC_APB2ENR_USART1_EN;
114
115  usart->cr1 = 0;
116  usart->cr2 = 0;
117  usart->cr3 = 0;
118  usart->bbr = usart_get_bbr(usart, pclk, baud);
119  usart->cr1 = STM32F4_USART_CR1_UE
120    | STM32F4_USART_CR1_TE
121    | STM32F4_USART_CR1_RE;
122}
123
124static int usart_first_open(int major, int minor, void *arg)
125{
126  rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
127  struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
128  const console_tbl *ct = Console_Port_Tbl [minor];
129  console_data *cd = &Console_Port_Data [minor];
130
131  cd->termios_data = tty;
132  rtems_termios_set_initial_baud(tty, ct->ulClock);
133
134  return 0;
135}
136
137static int usart_last_close(int major, int minor, void *arg)
138{
139  return 0;
140}
141
142static int usart_read_polled(int minor)
143{
144  const console_tbl *ct = Console_Port_Tbl [minor];
145  volatile stm32f4_usart *usart = usart_get_regs(ct);
146
147  if ((usart->sr & STM32F4_USART_SR_RXNE) != 0) {
148    return STM32F4_USART_DR_GET(usart->dr);
149  } else {
150    return -1;
151  }
152}
153
154static void usart_write_polled(int minor, char c)
155{
156  const console_tbl *ct = Console_Port_Tbl [minor];
157  volatile stm32f4_usart *usart = usart_get_regs(ct);
158
159  while ((usart->sr & STM32F4_USART_SR_TXE) == 0) {
160    /* Wait */
161  }
162
163  usart->dr = STM32F4_USART_DR(c);
164}
165
166static ssize_t usart_write_support_polled(
167  int minor,
168  const char *s,
169  size_t n
170)
171{
172  ssize_t i = 0;
173
174  for (i = 0; i < n; ++i) {
175    usart_write_polled(minor, s [i]);
176  }
177
178  return n;
179}
180
181static int usart_set_attributes(int minor, const struct termios *term)
182{
183  return -1;
184}
185
186console_fns stm32f4_usart_fns = {
187  .deviceProbe = libchip_serial_default_probe,
188  .deviceFirstOpen = usart_first_open,
189  .deviceLastClose = usart_last_close,
190  .deviceRead = usart_read_polled,
191  .deviceWrite = usart_write_support_polled,
192  .deviceInitialize = usart_initialize,
193  .deviceWritePolled = usart_write_polled,
194  .deviceSetAttributes = usart_set_attributes,
195  .deviceOutputUsesInterrupts = false
196};
Note: See TracBrowser for help on using the repository browser.