stm32_rust_template/driver/spi/
stm32f407.rs1#[cfg(feature = "stm32f407")]
2extern crate alloc;
3
4use super::{BitOrder, Config, Event, FrameFormat, Mode, Result, SlaveSelectMode, Spi, Status};
5use crate::mcu::stm32f407::{self, spi::*};
6use crate::utils;
7use alloc::boxed::Box;
8use core::ops::FnMut;
9use core::ptr;
10
11const PCLK1_HZ: u32 = 16_000_000; const PCLK2_HZ: u32 = 16_000_000; pub struct SpiDriver<'a> {
18 regs: *mut RegisterBlock,
19 _callback: Option<Box<dyn FnMut(Event) + 'a>>,
20 config: Config,
21 data_count: u32,
22}
23
24impl<'a> SpiDriver<'a> {
25 pub fn new(spi_base_addr: u32, config: Config) -> Self {
26 Self {
27 regs: spi_base_addr as *mut RegisterBlock,
28 _callback: None,
29 config,
30 data_count: 0,
31 }
32 }
33
34 pub fn new_spi1(config: Config) -> Self {
36 Self::new(stm32f407::SPI1_BASEADDR, config)
37 }
38
39 pub fn new_spi2(config: Config) -> Self {
41 Self::new(stm32f407::SPI2_BASEADDR, config)
42 }
43
44 pub fn new_spi3(config: Config) -> Self {
46 Self::new(stm32f407::SPI3_BASEADDR, config)
47 }
48
49 fn regs(&self) -> &mut RegisterBlock {
50 unsafe { &mut *self.regs }
51 }
52
53 fn is_on_apb2(&self) -> bool {
54 let base = self.regs as u32;
55 base == stm32f407::SPI1_BASEADDR
56 }
57
58 fn get_flag_status(&self, flag_bit: u32) -> bool {
59 let sr = unsafe { ptr::read_volatile(&self.regs().sr) };
60 utils::read_bit(sr, flag_bit)
61 }
62
63 fn wait_txe(&self) {
64 while !self.get_flag_status(SR_TXE_POS) {}
65 }
66
67 fn wait_rxne(&self) {
68 while !self.get_flag_status(SR_RXNE_POS) {}
69 }
70
71 fn wait_not_busy(&self) {
72 while self.get_flag_status(SR_BSY_POS) {}
73 }
74
75 fn clear_ovr_flag(&mut self) {
76 let _ = unsafe { ptr::read_volatile(&self.regs().dr) };
78 let _ = unsafe { ptr::read_volatile(&self.regs().sr) };
79 }
80
81 fn configure_cr1(&mut self) -> u32 {
82 let mut cr1 = 0;
83
84 match self.config.mode {
86 Mode::Master => {
87 cr1 = utils::set_bit(cr1, CR1_MSTR_POS, true);
88 }
89 Mode::Slave => {
90 cr1 = utils::set_bit(cr1, CR1_MSTR_POS, false);
91 }
92 Mode::Inactive => {
93 return cr1;
95 }
96 }
97
98 match self.config.slave_select_mode {
100 SlaveSelectMode::MasterHwInput => {
101 cr1 = utils::set_bit(cr1, CR1_BIDIMODE_POS, true);
103 cr1 = utils::set_bit(cr1, CR1_BIDIOE_POS, false);
104 }
105 SlaveSelectMode::MasterHwOutput => {
106 cr1 = utils::set_bit(cr1, CR1_BIDIMODE_POS, false);
108 }
109 SlaveSelectMode::MasterSoftware => {
110 cr1 = utils::set_bit(cr1, CR1_BIDIMODE_POS, false);
112 cr1 = utils::set_bit(cr1, CR1_SSM_POS, true);
113 cr1 = utils::set_bit(cr1, CR1_SSI_POS, true);
114 }
115 SlaveSelectMode::MasterUnused => {
116 cr1 = utils::set_bit(cr1, CR1_BIDIMODE_POS, false);
118 }
119 SlaveSelectMode::SlaveHardware => {
120 cr1 = utils::set_bit(cr1, CR1_SSM_POS, false);
122 }
123 SlaveSelectMode::SlaveSoftware => {
124 cr1 = utils::set_bit(cr1, CR1_SSM_POS, true);
126 }
127 }
128
129 let pclk = if self.is_on_apb2() {
131 PCLK2_HZ
132 } else {
133 PCLK1_HZ
134 };
135 let br_div = match self.config.bus_speed_hz {
136 speed if speed >= pclk / 2 => CR1_BR_DIV2,
137 speed if speed >= pclk / 4 => CR1_BR_DIV4,
138 speed if speed >= pclk / 8 => CR1_BR_DIV8,
139 speed if speed >= pclk / 16 => CR1_BR_DIV16,
140 speed if speed >= pclk / 32 => CR1_BR_DIV32,
141 speed if speed >= pclk / 64 => CR1_BR_DIV64,
142 speed if speed >= pclk / 128 => CR1_BR_DIV128,
143 _ => CR1_BR_DIV256,
144 };
145 cr1 = utils::set_bits(cr1, br_div, CR1_BR_POS, CR1_BR_WIDTH);
146
147 match self.config.data_bits {
149 8 => {
150 cr1 = utils::set_bit(cr1, CR1_DFF_POS, false);
151 }
152 16 => {
153 cr1 = utils::set_bit(cr1, CR1_DFF_POS, true);
154 }
155 _ => {
156 return 0;
158 }
159 }
160
161 match self.config.frame_format {
163 FrameFormat::CPOL0_CPHA0 => {
164 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, false);
165 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, false);
166 }
167 FrameFormat::CPOL0_CPHA1 => {
168 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, false);
169 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, true);
170 }
171 FrameFormat::CPOL1_CPHA0 => {
172 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, true);
173 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, false);
174 }
175 FrameFormat::CPOL1_CPHA1 => {
176 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, true);
177 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, true);
178 }
179 FrameFormat::TI_SSI => {
180 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, false);
182 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, false);
183 }
184 FrameFormat::Microwire => {
185 cr1 = utils::set_bit(cr1, CR1_CPOL_POS, false);
187 cr1 = utils::set_bit(cr1, CR1_CPHA_POS, false);
188 }
189 }
190
191 match self.config.bit_order {
193 BitOrder::LSB_MSB => {
194 cr1 = utils::set_bit(cr1, CR1_LSBFIRST_POS, true);
195 }
196 BitOrder::MSB_LSB => {
197 cr1 = utils::set_bit(cr1, CR1_LSBFIRST_POS, false);
198 }
199 }
200
201 cr1
202 }
203
204 fn configure_cr2(&mut self) -> u32 {
205 let mut cr2 = 0;
206
207 if matches!(
209 self.config.slave_select_mode,
210 SlaveSelectMode::MasterHwOutput
211 ) {
212 cr2 = utils::set_bit(cr2, CR2_SSOE_POS, true);
213 }
214
215 match self.config.frame_format {
217 FrameFormat::TI_SSI => {
218 cr2 = utils::set_bit(cr2, CR2_FRF_POS, true);
219 }
220 _ => {
221 cr2 = utils::set_bit(cr2, CR2_FRF_POS, false);
222 }
223 }
224
225 cr2
226 }
227}
228
229impl<'a> Spi<'a> for SpiDriver<'a> {
230 fn initialize(&mut self, callback: impl FnMut(Event) + 'a) -> Result<()> {
231 self._callback = Some(Box::new(callback));
232
233 let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
237 cr1 = utils::set_bit(cr1, CR1_SPE_POS, false);
238 unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
239
240 let cr1_config = self.configure_cr1();
242 if cr1_config == 0 {
243 return Err(-1); }
245 unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1_config) };
246
247 let cr2_config = self.configure_cr2();
249 unsafe { ptr::write_volatile(&mut self.regs().cr2, cr2_config) };
250
251 let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
253 cr1 = utils::set_bit(cr1, CR1_SPE_POS, true);
254 unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
255
256 Ok(())
257 }
258
259 fn uninitialize(&mut self) -> Result<()> {
260 let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
261 cr1 = utils::set_bit(cr1, CR1_SPE_POS, false);
262 unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
263 self._callback = None;
264 Ok(())
265 }
266
267 fn configure(&mut self, config: &Config) -> Result<()> {
268 self.config = config.clone();
269
270 if let Some(callback) = self._callback.take() {
272 self.initialize(callback)?;
273 }
274
275 Ok(())
276 }
277
278 fn send(&mut self, data: &[u8]) -> Result<()> {
279 self.data_count = 0;
280
281 for &byte in data {
282 self.wait_txe();
283 unsafe { ptr::write_volatile(&mut self.regs().dr, byte as u32) };
284 self.data_count += 1;
285 }
286
287 self.wait_not_busy();
289
290 if let Some(cb) = &mut self._callback {
291 cb(Event::TRANSFER_COMPLETE);
292 }
293
294 Ok(())
295 }
296
297 fn receive(&mut self, data: &mut [u8]) -> Result<()> {
298 self.data_count = 0;
299
300 for b in data.iter_mut() {
302 self.wait_txe();
303 unsafe { ptr::write_volatile(&mut self.regs().dr, 0xFF) }; self.wait_rxne();
306 *b = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
307 self.data_count += 1;
308 }
309
310 if let Some(cb) = &mut self._callback {
311 cb(Event::TRANSFER_COMPLETE);
312 }
313
314 Ok(())
315 }
316
317 fn transfer(&mut self, data_out: &[u8], data_in: &mut [u8]) -> Result<()> {
318 if data_in.len() != data_out.len() {
319 return Err(-1);
320 }
321
322 self.data_count = 0;
323
324 for (i, &byte) in data_out.iter().enumerate() {
325 self.wait_txe();
326 unsafe { ptr::write_volatile(&mut self.regs().dr, byte as u32) };
327
328 self.wait_rxne();
329 data_in[i] = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
330 self.data_count += 1;
331 }
332
333 self.wait_not_busy();
335
336 if let Some(cb) = &mut self._callback {
337 cb(Event::TRANSFER_COMPLETE);
338 }
339
340 Ok(())
341 }
342
343 fn get_data_count(&self) -> u32 {
344 self.data_count
345 }
346
347 fn get_status(&self) -> Status {
348 let sr = unsafe { ptr::read_volatile(&self.regs().sr) };
349
350 Status {
351 busy: utils::read_bit(sr, SR_BSY_POS),
352 data_lost: utils::read_bit(sr, SR_OVR_POS),
353 mode_fault: utils::read_bit(sr, SR_MODF_POS),
354 }
355 }
356
357 fn control_slave_select(&mut self, active: bool) -> Result<()> {
358 if matches!(
360 self.config.slave_select_mode,
361 SlaveSelectMode::MasterSoftware
362 ) {
363 let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
364 cr1 = utils::set_bit(cr1, CR1_SSI_POS, active);
365 unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
366 Ok(())
367 } else {
368 Err(-2) }
370 }
371}