@@ -54,7 +54,7 @@ struct control_register1
54
54
// / Frame Format
55
55
// / 0: msb transmitted first
56
56
// / 1: lsb tranmitted first
57
- static constexpr auto frame_format = bit_mask::from<7 >();
57
+ static constexpr auto lsb_first = bit_mask::from<7 >();
58
58
59
59
// / internal slave select
60
60
static constexpr auto internal_slave_select = bit_mask::from<8 >();
@@ -65,40 +65,37 @@ struct control_register1
65
65
66
66
// / Recieve only
67
67
// / 0: Full Duplex, 1: Output disable
68
- [[maybe_unused]] static constexpr auto rx_only = bit_mask::from<10 >();
68
+ static constexpr auto rx_only = bit_mask::from<10 >();
69
69
70
70
// / Data frame format
71
71
// / 0: 8-bits, 1: 16-bit
72
- [[maybe_unused]] static constexpr auto data_frame_format =
73
- bit_mask::from<11 >();
72
+ static constexpr auto data_frame_format = bit_mask::from<11 >();
74
73
75
74
// / CRC transfer next
76
75
// / 0: No CRC phase, 1: transfer CRC next
77
- [[maybe_unused]] static constexpr auto crc_transfer_next =
78
- bit_mask::from<12 >();
76
+ static constexpr auto crc_transfer_next = bit_mask::from<12 >();
79
77
80
78
// / CRC enable
81
79
// / 0: disable, 1: enable
82
- [[maybe_unused]] static constexpr auto crc_enable = bit_mask::from<13 >();
80
+ static constexpr auto crc_enable = bit_mask::from<13 >();
83
81
84
82
// / Output enable in bidirectional mode
85
83
// / 0: output disabled, 1: output enable
86
84
static constexpr auto bidirectional_output_enable = bit_mask::from<14 >();
87
85
88
86
// / Bidirectional data mode enable
89
87
// / 0: full-duplex, 1: half-duplex
90
- [[maybe_unused]] static constexpr auto bidirectional_mode_enable =
91
- bit_mask::from<15 >();
88
+ static constexpr auto bidirectional_mode_enable = bit_mask::from<15 >();
92
89
};
93
90
94
91
// / SPI Control Register 2
95
92
struct control_register2
96
93
{
97
94
// / Rx buffer DMA enable
98
- [[maybe_unused]] static constexpr auto rx_dma_enable = bit_mask::from<0 >();
95
+ static constexpr auto rx_dma_enable = bit_mask::from<0 >();
99
96
100
97
// / Tx buffer DMA enable
101
- [[maybe_unused]] static constexpr auto tx_dma_enable = bit_mask::from<1 >();
98
+ static constexpr auto tx_dma_enable = bit_mask::from<1 >();
102
99
103
100
// / Slave select output enable
104
101
// / 0: use a GPIO, 1: use the NSS pin
@@ -109,16 +106,13 @@ struct control_register2
109
106
static constexpr auto frame_format = bit_mask::from<4 >();
110
107
111
108
// / Error interupt enable
112
- [[maybe_unused]] static constexpr auto error_interrupt_enable =
113
- bit_mask::from<5 >();
109
+ static constexpr auto error_interrupt_enable = bit_mask::from<5 >();
114
110
115
111
// / Rx buffer empty interrupt enable
116
- [[maybe_unused]] static constexpr auto rx_buffer_empty_interrupt_enable =
117
- bit_mask::from<6 >();
112
+ static constexpr auto rx_buffer_empty_interrupt_enable = bit_mask::from<6 >();
118
113
119
114
// / Tx buffer empty interrupt enable
120
- [[maybe_unused]] static constexpr auto tx_buffer_empty_interrupt_enable =
121
- bit_mask::from<7 >();
115
+ static constexpr auto tx_buffer_empty_interrupt_enable = bit_mask::from<7 >();
122
116
};
123
117
124
118
// / SPI Status Register
@@ -131,8 +125,8 @@ struct status_register
131
125
static constexpr auto tx_buffer_empty = bit_mask::from<1 >();
132
126
133
127
// / Channel side (i2s only)
134
- // / 0: left has been transmitted/recieved
135
- // / 1: right has been transmitted/recieved
128
+ // / 0: left has been transmitted/received
129
+ // / 1: right has been transmitted/received
136
130
[[maybe_unused]] static constexpr auto i2s_channel_side = bit_mask::from<2 >();
137
131
138
132
// / Underrun flag
@@ -190,19 +184,20 @@ spi::spi(hal::unsafe, void* p_peripheral_address)
190
184
191
185
spi::~spi ()
192
186
{
187
+ auto & reg = to_reg (m_peripheral_address);
188
+ bit_modify (reg.cr1 ).clear <control_register1::enable>();
193
189
}
194
190
195
191
void spi::configure (hal::spi::settings const & p_settings,
196
192
hal::hertz p_peripheral_clock_speed)
197
193
{
198
- auto & reg = to_reg (m_peripheral_address) ;
194
+ using namespace hal ::literals ;
199
195
200
- // Set SPI to master mode by clearing
201
- bit_modify (reg.cr1 ).set (control_register1::master_selection);
196
+ auto & reg = to_reg (m_peripheral_address);
202
197
203
- using namespace hal ::literals;
204
198
auto const clock_divider = p_peripheral_clock_speed / p_settings.clock_rate ;
205
199
auto prescaler = static_cast <std::uint16_t >(clock_divider);
200
+
206
201
if (prescaler <= 1 ) {
207
202
prescaler = 2 ;
208
203
} else if (prescaler > 256 ) {
@@ -213,25 +208,33 @@ void spi::configure(hal::spi::settings const& p_settings,
213
208
if (std::has_single_bit (prescaler)) {
214
209
baud_control--;
215
210
}
216
- bit_modify (reg.cr1 )
217
- .insert <control_register1::baud_rate_control>(baud_control)
218
- .insert <control_register1::clock_phase>(
219
- p_settings.data_valid_on_trailing_edge )
220
- .insert <control_register1::clock_polarity>(p_settings.clock_idles_high )
221
- .set <control_register1::bidirectional_output_enable>()
222
- .set <control_register1::software_slave_management>()
223
- .set <control_register1::internal_slave_select>()
224
- .clear <control_register1::frame_format>();
225
211
226
212
bit_modify (reg.cr2 )
213
+ .clear <control_register2::rx_dma_enable>()
214
+ .clear <control_register2::tx_dma_enable>()
215
+ // We set `slave_select_output_enable` because it is required for master
216
+ // mode to work.
227
217
.set <control_register2::slave_select_output_enable>()
228
- .clear <control_register2::frame_format>();
229
-
230
- bit_modify (reg.cr1 ).set <control_register1::master_selection>();
218
+ .clear <control_register2::frame_format>()
219
+ .clear <control_register2::error_interrupt_enable>()
220
+ .clear <control_register2::rx_buffer_empty_interrupt_enable>()
221
+ .clear <control_register2::tx_buffer_empty_interrupt_enable>();
231
222
232
223
bit_modify (reg.cr1 )
233
- .set <control_register1::enable>()
234
- .clear <control_register1::internal_slave_select>();
224
+ .clear <control_register1::rx_only>()
225
+ .clear <control_register1::crc_transfer_next>()
226
+ .clear <control_register1::data_frame_format>()
227
+ .clear <control_register1::crc_enable>()
228
+ .clear <control_register1::lsb_first>()
229
+ .clear <control_register1::bidirectional_mode_enable>()
230
+ .clear <control_register1::bidirectional_output_enable>()
231
+ .insert <control_register1::baud_rate_control>(baud_control)
232
+ .insert <control_register1::clock_phase>(p_settings.clock_phase )
233
+ .insert <control_register1::clock_polarity>(p_settings.clock_polarity )
234
+ .set <control_register1::internal_slave_select>() // same as disabled
235
+ .set <control_register1::software_slave_management>()
236
+ .set <control_register1::master_selection>()
237
+ .set <control_register1::enable>();
235
238
}
236
239
237
240
void spi::transfer (std::span<hal::byte const > p_data_out,
@@ -250,7 +253,7 @@ void spi::transfer(std::span<hal::byte const> p_data_out,
250
253
// The stm's spi driver needs to be internally told that it is selecting a
251
254
// device before it will emit anything on the pins. This will control the NSS
252
255
// pin if it is selected, otherwise, its just an internal enable signal.
253
- bit_modify (reg.cr1 ).set <control_register1::internal_slave_select>();
256
+ bit_modify (reg.cr1 ).clear <control_register1::internal_slave_select>();
254
257
255
258
for (size_t index = 0 ; index < max_length; index++) {
256
259
hal::byte byte = 0 ;
@@ -277,7 +280,7 @@ void spi::transfer(std::span<hal::byte const> p_data_out,
277
280
}
278
281
}
279
282
280
- bit_modify (reg.cr1 ).clear <control_register1::internal_slave_select>();
283
+ bit_modify (reg.cr1 ).set <control_register1::internal_slave_select>();
281
284
282
285
// Wait for bus activity to cease before leaving the function
283
286
while (busy (reg)) {
0 commit comments