OpenMPTL - STM32 (common)
C++ Microprocessor Template Library
usart.hpp
Go to the documentation of this file.
1 /*
2  * OpenMPTL - C++ Microprocessor Template Library
3  *
4  * Copyright (C) 2012-2017 Axel Burri <axel@tty0.ch>
5  *
6  * This program 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef ARM_CORTEX_STM32_COMMON_USART_HPP_INCLUDED
22 #define ARM_CORTEX_STM32_COMMON_USART_HPP_INCLUDED
23 
24 #include <arch/nvic.hpp>
25 #include <arch/rcc.hpp>
26 #include <arch/reg/usart.hpp>
27 #include <type_traits>
28 
29 namespace mptl {
30 
31 template< unsigned _usart_no, typename system_clock_type >
33 {
34  static_assert((_usart_no >= 1) && (_usart_no <= 3), "invalid USART number");
35  static_assert(_usart_no != 1, "usart 1 is not yet supported, sorry...");
36 
38 
39 public:
40  static constexpr unsigned usart_no = _usart_no;
41 
42  using USARTx = USART<usart_no>;
43 
44  using irq = irq::usart<usart_no>;
45 
46  using resources = rcc_usart_clock_resources<usart_no>;
47 
48 private:
49 
50  template<unsigned value>
51  struct baud_rate_impl {
52  static constexpr unsigned pclk = (usart_no == 1 ? system_clock_type::pclk2_freq : system_clock_type::pclk1_freq );
53  static constexpr unsigned div = (pclk * 25) / (4 * value);
54  static constexpr unsigned mant = div / 100;
55  static constexpr unsigned fraq = ((div - (mant * 100)) * 16 + 50) / 100;
56 
57  using type = typename USARTx::BRR::template merge<
60  >::type;
61  };
62 
63  template<unsigned value>
64  struct word_length_impl {
65  static_assert((value == 8) || (value == 9), "illegal word_length (supported values: 8, 9)");
67  };
68 
69  template<unsigned a, unsigned b = 0>
70  struct stop_bits_impl {
71  static_assert(((a == 1) && (b == 0)) ||
72  ((a == 0) && (b == 5)) ||
73  ((a == 2) && (b == 0)) ||
74  ((a == 1) && (b == 5)),
75  "illegal stop_bits (supported values: 1, 0.5, 2, 1.5)");
76 
77  template<typename usart>
78  using type = regval< typename USARTx::CR2::STOP,
79  ((a == 1) && (b == 0)) ? 0 :
80  ((a == 0) && (b == 5)) ? 1 :
81  ((a == 2) && (b == 0)) ? 2 :
82  ((a == 1) && (b == 5)) ? 3 : 0xff
83  >;
84  };
85 
86 public: /* ------ configuration traits ------ */
87 
90 
91  template<unsigned value>
92  using baud_rate = typename baud_rate_impl<value>::type;
93 
94  template<unsigned value>
96 
97  struct parity
98  {
99  using even = reglist<
102  >;
103  using odd = reglist<
104  regval< typename USARTx::CR1::PCE, 1 >,
106  >;
107  using disabled = reglist<
110  >;
111  };
112 
113  template<unsigned a, unsigned b = 0>
115 
117 
118  struct clock_polarity {
121  };
122 
123  struct clock_phase {
124  /** The first clock transition is the first data capture edge. */
126 
127  /** The second clock transition is the first data capture edge. */
129  };
130 
132 
133  struct flow_control {
136  };
137 
138 
139  static typename USARTx::BRR::value_type baud_to_brr(unsigned baud_rate) {
140  unsigned pclk = (_usart_no == 1 ? system_clock_type::pclk2_freq : system_clock_type::pclk1_freq );
141  unsigned div = (pclk * 25) / (4 * baud_rate);
142  unsigned mant = div / 100;
143  unsigned fraq = ((div - (mant * 100)) * 16 + 50) / 100;
144 
145  return (mant << 4) | (fraq & 0x0f);
146  };
147 
148 
149 public: /* ------ static member functions ------ */
150 
151  /**
152  * Configure USART register using Tp type traits.
153  *
154  * NOTE: make sure no communication is ongoing when calling this function.
155  */
156  template< typename... Tp >
157  static void configure(void) {
158  reglist< Tp... >::template strict_reset_to<
159  typename USARTx::CR1,
160  typename USARTx::CR2,
161  typename USARTx::CR3,
162  typename USARTx::BRR
163  >();
164  }
165 
166  /**
167  * Set the BRR register to the value corresponding to the baud_rate
168  * provided.
169  *
170  * NOTE: make sure no communication is ongoing when calling this function.
171  */
172  static void set_baudrate(unsigned value) {
173  USARTx::BRR::store(baud_to_brr(value));
174  }
175 
176  static void send(typename USARTx::DR::value_type data) {
177  /* Implicitely clears the TXE bit in the SR register. */
178  // assert((data & 0x01ff) == data);
179  USARTx::DR::store(data);
180  }
181  static typename USARTx::DR::value_type receive(void) {
182  /* Implicitely clears the RXNE bit in the SR register. */
183  /* When receiving the parity enabled, the value read in the MSB */
184  /* bit is the received parity bit. */
185  return USARTx::DR::load();
186  }
187 
188  static void enable(void) {
189  USARTx::CR1::UE::set();
190  }
191  static void disable(void) {
192  USARTx::CR1::UE::clear();
193  }
194 
195  static void enable_interrupt(bool rxne, /**< read data register not empty interrupt */
196  bool txe = false, /**< transmitter data register empty interrupt */
197  bool pe = false, /**< parity error interrupt */
198  bool tc = false, /**< transmission complete interrupt */
199  bool idle = false) /**< idle interrupt */
200  {
201  auto cr1 = USARTx::CR1::load();
202  if(rxne) cr1 |= USARTx::CR1::RXNEIE::value;
203  if(txe) cr1 |= USARTx::CR1::TXEIE::value;
204  if(pe) cr1 |= USARTx::CR1::PEIE::value;
205  if(tc) cr1 |= USARTx::CR1::TCIE::value;
206  if(idle) cr1 |= USARTx::CR1::IDLEIE::value;
207  USARTx::CR1::store(cr1);
208  }
209 
210  static void disable_interrupt(bool rxne, /**< read data register not empty interrupt */
211  bool txe = false, /**< transmitter data register empty interrupt */
212  bool pe = false, /**< parity error interrupt */
213  bool tc = false, /**< transmission complete interrupt */
214  bool idle = false) /**< idle interrupt */
215  {
216  auto cr1 = USARTx::CR1::load();
217  if(rxne) cr1 &= ~USARTx::CR1::RXNEIE::value;
218  if(txe) cr1 &= ~USARTx::CR1::TXEIE::value;
219  if(pe) cr1 &= ~USARTx::CR1::PEIE::value;
220  if(tc) cr1 &= ~USARTx::CR1::TCIE::value;
221  if(idle) cr1 &= ~USARTx::CR1::IDLEIE::value;
222  USARTx::CR1::store(cr1);
223  }
224 
225  static void enable_tx_interrupt(void) { USARTx::CR1::TXEIE::set(); }
226  static void disable_tx_interrupt(void) { USARTx::CR1::TXEIE::clear(); }
227 };
228 
229 } // namespace mptl
230 
231 #endif // ARM_CORTEX_STM32_COMMON_USART_HPP_INCLUDED
irq::usart< usart_no > irq
Definition: usart.hpp:44
static void configure(void)
Configure USART register using Tp type traits.
Definition: usart.hpp:157
USART< usart_no > USARTx
Definition: usart.hpp:42
static void disable_interrupt(bool rxne, bool txe=false, bool pe=false, bool tc=false, bool idle=false)
Definition: usart.hpp:210
typename stop_bits_impl< a, b >::type stop_bits
Definition: usart.hpp:114
static void enable_interrupt(bool rxne, bool txe=false, bool pe=false, bool tc=false, bool idle=false)
Definition: usart.hpp:195
Definition: usart.hpp:97
static constexpr unsigned usart_no
Definition: usart.hpp:40
rcc_usart_clock_resources< usart_no > resources
Definition: usart.hpp:46
static void enable_tx_interrupt(void)
Definition: usart.hpp:225
typename word_length_impl< value >::type word_length
Definition: usart.hpp:95
static void send(typename USARTx::DR::value_type data)
Definition: usart.hpp:176
static USARTx::DR::value_type receive(void)
Definition: usart.hpp:181
static void set_baudrate(unsigned value)
Set the BRR register to the value corresponding to the baud_rate provided.
Definition: usart.hpp:172
static void disable(void)
Definition: usart.hpp:191
typename baud_rate_impl< value >::type baud_rate
Definition: usart.hpp:92
static void enable(void)
Definition: usart.hpp:188
Definition: usart.hpp:32
Definition: usart.hpp:123
static void disable_tx_interrupt(void)
Definition: usart.hpp:226
static USARTx::BRR::value_type baud_to_brr(unsigned baud_rate)
Definition: usart.hpp:139