OpenMPTL - STM32 (common)
C++ Microprocessor Template Library
spi.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_SPI_HPP_INCLUDED
22 #define ARM_CORTEX_STM32_COMMON_SPI_HPP_INCLUDED
23 
24 #include <arch/rcc.hpp>
25 #include <arch/nvic.hpp>
26 #include <arch/reg/spi.hpp>
27 #include <type_traits>
28 
29 namespace mptl {
30 
31 template< unsigned _spi_no, typename system_clock_type >
33 {
34 public:
35 
36  static constexpr unsigned spi_no = _spi_no;
37  using SPIx = SPI<spi_no>;
38  using irq = irq::spi<spi_no>;
39 
40  using resources = rcc_spi_clock_resources<spi_no>;
41 
42  static constexpr unsigned clk_freq = (spi_no == 1 ? system_clock_type::pclk2_freq : system_clock_type::pclk1_freq );
43 
44 private:
45 
46  template<unsigned value>
47  struct data_size_impl {
48  static_assert(value == 8 || value == 16, "invalid data_size (supported values: 8, 16)");
49  using type = regval< typename SPIx::CR1::DFF,
50  ( value == 8 ? 0 :
51  value == 16 ? 1 : 0xff )
52  >;
53  };
54 
55 public: /* ------ configuration traits ------ */
56 
57  using master = reglist<
60  >;
61 
63 
64  struct clock_polarity {
67  };
68 
69  struct clock_phase {
72  };
73 
75 
76  struct data_direction {
81  >;
82  using two_lines_rx_only = reglist<
83  regval< typename SPIx::CR1::BIDIMODE, 0 >,
86  >;
87  using one_line_rx = reglist<
91  >;
92  using one_line_tx = reglist<
93  regval< typename SPIx::CR1::BIDIMODE, 1 >,
96  >;
97  };
98 
99  struct frame_format {
102  };
103 
104  /** Maximum frequency (hz, 0=maximum available) */
105  template<freq_t value>
106  using max_frequency = regval< typename SPIx::CR1::BR,
107  ( value == 0 ? 0 :
108  value >= clk_freq / 2 ? 0 :
109  value >= clk_freq / 4 ? 1 :
110  value >= clk_freq / 8 ? 2 :
111  value >= clk_freq / 16 ? 3 :
112  value >= clk_freq / 32 ? 4 :
113  value >= clk_freq / 64 ? 5 :
114  value >= clk_freq / 128 ? 6 :
115  7 )
116  >;
117 
118  /** 8 bit or 16 bit data size */
119  template<unsigned value>
120  using data_size = typename std::enable_if<
121  value == 8 || value == 16,
123  >::type;
124 
125 public: /* ------ static member functions ------ */
126 
127  /**
128  * Configure SPI register using Tp type traits.
129  *
130  * NOTE: make sure no communication is ongoing when calling this function.
131  */
132  template< typename... Tp >
133  static void configure(void) {
134  reglist< Tp... >::template strict_reset_to<
135  typename SPIx::CR1
136  >();
137  }
138 
139  /**
140  * Disable SPI, configure SPI register using Tp type traits, and enable SPI.
141  *
142  * NOTE: make sure no communication is ongoing when calling this function.
143  */
144  template< typename... Tp >
145  static void reconfigure(void) {
146  disable();
147  /* configure and enable SPI in one register write */
148  configure< typename SPIx::CR1::SPE, Tp... >();
149  }
150 
151  static void reset_crc(void) {
152  SPIx::CRCPR::reset();
153  }
154 
155  static void enable(void) {
156  SPIx::CR1::SPE::set();
157  }
158  static void disable(void) {
159  SPIx::CR1::SPE::clear();
160  }
161 
162  static void wait_transmit_empty(void) {
163  while(SPIx::SR::TXE::test() == false);
164  }
165  static void wait_receive_not_empty(void) {
166  while(SPIx::SR::RXNE::test() == false);
167  }
168  static void wait_not_busy(void) {
169  while(SPIx::SR::BSY::test());
170  }
171 
172  static void send(uint16_t data) {
173  SPIx::DR::store(data);
174  }
175 
176  static void send_blocking(uint16_t data) {
178  send(data);
179  }
180 
181  /** NOTE: return value depends on the data frame format (CR1::DFF, 8 or 16 bit) */
182  static typename SPIx::DR::value_type receive(void) {
183  return SPIx::DR::load();
184  }
185 
186  static typename SPIx::DR::value_type receive_blocking(void) {
188  return receive();
189  }
190 
191  static unsigned char writeread_blocking(uint16_t data) {
193  send(data);
195  return receive();
196  }
197 };
198 
199 } // namespace mptl
200 
201 #endif // ARM_CORTEX_STM32_COMMON_SPI_HPP_INCLUDED
static void enable(void)
Definition: spi.hpp:155
rcc_spi_clock_resources< spi_no > resources
Definition: spi.hpp:40
static constexpr unsigned spi_no
Definition: spi.hpp:36
static void wait_receive_not_empty(void)
Definition: spi.hpp:165
regval< typename SPIx::CR1::BR,(value==0 ? 0 :value >=clk_freq/2 ? 0 :value >=clk_freq/4 ? 1 :value >=clk_freq/8 ? 2 :value >=clk_freq/16 ? 3 :value >=clk_freq/32 ? 4 :value >=clk_freq/64 ? 5 :value >=clk_freq/128 ? 6 :7) > max_frequency
Maximum frequency (hz, 0=maximum available)
Definition: spi.hpp:116
static void wait_not_busy(void)
Definition: spi.hpp:168
static void send_blocking(uint16_t data)
Definition: spi.hpp:176
static void configure(void)
Configure SPI register using Tp type traits.
Definition: spi.hpp:133
static void send(uint16_t data)
Definition: spi.hpp:172
static constexpr unsigned clk_freq
Definition: spi.hpp:42
SPI< spi_no > SPIx
Definition: spi.hpp:37
static SPIx::DR::value_type receive(void)
NOTE: return value depends on the data frame format (CR1::DFF, 8 or 16 bit)
Definition: spi.hpp:182
static unsigned char writeread_blocking(uint16_t data)
Definition: spi.hpp:191
static void disable(void)
Definition: spi.hpp:158
static void wait_transmit_empty(void)
Definition: spi.hpp:162
static void reset_crc(void)
Definition: spi.hpp:151
Definition: spi.hpp:32
static SPIx::DR::value_type receive_blocking(void)
Definition: spi.hpp:186
static void reconfigure(void)
Disable SPI, configure SPI register using Tp type traits, and enable SPI.
Definition: spi.hpp:145
typename std::enable_if< value==8||value==16, regval< typename SPIx::CR1::DFF, value==16 ? 1 :0 > >::type data_size
8 bit or 16 bit data size
Definition: spi.hpp:123
irq::spi< spi_no > irq
Definition: spi.hpp:38