stm32f4xx/
spi.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use core::cell::Cell;
6use core::cmp;
7use kernel::utilities::leasable_buffer::SubSliceMut;
8use kernel::ErrorCode;
9
10use kernel::hil;
11use kernel::hil::gpio::Output;
12use kernel::hil::spi::{self, ClockPhase, ClockPolarity, SpiMasterClient};
13use kernel::platform::chip::ClockInterface;
14use kernel::utilities::cells::OptionalCell;
15use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
17use kernel::utilities::StaticRef;
18
19use crate::clocks::phclk;
20use crate::dma;
21use crate::dma::{Dma1, Dma1Peripheral};
22
23/// Serial peripheral interface
24#[repr(C)]
25pub struct SpiRegisters {
26    /// control register 1
27    cr1: ReadWrite<u32, CR1::Register>,
28    /// control register 2
29    cr2: ReadWrite<u32, CR2::Register>,
30    /// status register
31    sr: ReadWrite<u32, SR::Register>,
32    /// data register
33    dr: ReadWrite<u32, DR::Register>,
34    /// CRC polynomial register
35    crcpr: ReadWrite<u32>,
36    /// RX CRC register
37    rxcrcr: ReadOnly<u32>,
38    /// TX CRC register
39    txcrcr: ReadOnly<u32>,
40    /// I2S configuration register
41    i2scfgr: ReadWrite<u32, I2SCFGR::Register>,
42    /// I2S prescaler register
43    i2spr: ReadWrite<u32, I2SPR::Register>,
44}
45
46register_bitfields![u32,
47    CR1 [
48        /// Bidirectional data mode enable
49        BIDIMODE OFFSET(15) NUMBITS(1) [],
50        /// Output enable in bidirectional mode
51        BIDIOE OFFSET(14) NUMBITS(1) [],
52        /// Hardware CRC calculation enable
53        CRCEN OFFSET(13) NUMBITS(1) [],
54        /// CRC transfer next
55        CRCNEXT OFFSET(12) NUMBITS(1) [],
56        /// Data frame format
57        DFF OFFSET(11) NUMBITS(1) [],
58        /// Receive only
59        RXONLY OFFSET(10) NUMBITS(1) [],
60        /// Software slave management
61        SSM OFFSET(9) NUMBITS(1) [],
62        /// Internal slave select
63        SSI OFFSET(8) NUMBITS(1) [],
64        /// Frame format
65        LSBFIRST OFFSET(7) NUMBITS(1) [],
66        /// SPI enable
67        SPE OFFSET(6) NUMBITS(1) [],
68        /// Baud rate control
69        BR OFFSET(3) NUMBITS(3) [],
70        /// Master selection
71        MSTR OFFSET(2) NUMBITS(1) [],
72        /// Clock polarity
73        CPOL OFFSET(1) NUMBITS(1) [],
74        /// Clock phase
75        CPHA OFFSET(0) NUMBITS(1) []
76    ],
77    CR2 [
78        /// Tx buffer empty interrupt enable
79        TXEIE OFFSET(7) NUMBITS(1) [],
80        /// RX buffer not empty interrupt enable
81        RXNEIE OFFSET(6) NUMBITS(1) [],
82        /// Error interrupt enable
83        ERRIE OFFSET(5) NUMBITS(1) [],
84        /// Frame format
85        FRF OFFSET(4) NUMBITS(1) [],
86        /// SS output enable
87        SSOE OFFSET(2) NUMBITS(1) [],
88        /// Tx buffer DMA enable
89        TXDMAEN OFFSET(1) NUMBITS(1) [],
90        /// Rx buffer DMA enable
91        RXDMAEN OFFSET(0) NUMBITS(1) []
92    ],
93    SR [
94        /// TI frame format error
95        TIFRFE OFFSET(8) NUMBITS(1) [],
96        /// Busy flag
97        BSY OFFSET(7) NUMBITS(1) [],
98        /// Overrun flag
99        OVR OFFSET(6) NUMBITS(1) [],
100        /// Mode fault
101        MODF OFFSET(5) NUMBITS(1) [],
102        /// CRC error flag
103        CRCERR OFFSET(4) NUMBITS(1) [],
104        /// Underrun flag
105        UDR OFFSET(3) NUMBITS(1) [],
106        /// Channel side
107        CHSIDE OFFSET(2) NUMBITS(1) [],
108        /// Transmit buffer empty
109        TXE OFFSET(1) NUMBITS(1) [],
110        /// Receive buffer not empty
111        RXNE OFFSET(0) NUMBITS(1) []
112    ],
113    DR [
114        /// 8-bit data register
115        DR OFFSET(0) NUMBITS(8) []
116    ],
117    I2SCFGR [
118        /// I2S mode selection
119        I2SMOD OFFSET(11) NUMBITS(1) [],
120        /// I2S Enable
121        I2SE OFFSET(10) NUMBITS(1) [],
122        /// I2S configuration mode
123        I2SCFG OFFSET(8) NUMBITS(2) [],
124        /// PCM frame synchronization
125        PCMSYNC OFFSET(7) NUMBITS(1) [],
126        /// I2S standard selection
127        I2SSTD OFFSET(4) NUMBITS(2) [],
128        /// Steady state clock polarity
129        CKPOL OFFSET(3) NUMBITS(1) [],
130        /// Data length to be transferred
131        DATLEN OFFSET(1) NUMBITS(2) [],
132        /// Channel length (number of bits per audio channel)
133        CHLEN OFFSET(0) NUMBITS(1) []
134    ],
135    I2SPR [
136        /// Master clock output enable
137        MCKOE OFFSET(9) NUMBITS(1) [],
138        /// Odd factor for the prescaler
139        ODD OFFSET(8) NUMBITS(1) [],
140        /// I2S Linear prescaler
141        I2SDIV OFFSET(0) NUMBITS(8) []
142    ]
143];
144
145// for use by dma1
146pub(crate) fn get_address_dr(regs: StaticRef<SpiRegisters>) -> u32 {
147    core::ptr::addr_of!(regs.dr) as u32
148}
149
150pub const SPI3_BASE: StaticRef<SpiRegisters> =
151    unsafe { StaticRef::new(0x40003C00 as *const SpiRegisters) };
152
153pub struct Spi<'a> {
154    registers: StaticRef<SpiRegisters>,
155    clock: SpiClock<'a>,
156
157    // SPI slave support not yet implemented
158    master_client: OptionalCell<&'a dyn hil::spi::SpiMasterClient>,
159
160    tx_dma: OptionalCell<&'a dma::Stream<'a, Dma1<'a>>>,
161    tx_dma_pid: Dma1Peripheral,
162    rx_dma: OptionalCell<&'a dma::Stream<'a, Dma1<'a>>>,
163    rx_dma_pid: Dma1Peripheral,
164
165    dma_len: Cell<usize>,
166    transfers_in_progress: Cell<u8>,
167
168    active_slave: OptionalCell<&'a crate::gpio::Pin<'a>>,
169
170    active_after: Cell<bool>,
171}
172
173// for use by `set_dma`
174pub struct TxDMA<'a>(pub &'a dma::Stream<'a, Dma1<'a>>);
175pub struct RxDMA<'a>(pub &'a dma::Stream<'a, Dma1<'a>>);
176
177impl<'a> Spi<'a> {
178    pub const fn new(
179        base_addr: StaticRef<SpiRegisters>,
180        clock: SpiClock<'a>,
181        tx_dma_pid: Dma1Peripheral,
182        rx_dma_pid: Dma1Peripheral,
183    ) -> Spi<'a> {
184        Spi {
185            registers: base_addr,
186            clock,
187
188            master_client: OptionalCell::empty(),
189
190            tx_dma: OptionalCell::empty(),
191            tx_dma_pid,
192            rx_dma: OptionalCell::empty(),
193            rx_dma_pid,
194
195            dma_len: Cell::new(0),
196            transfers_in_progress: Cell::new(0),
197
198            active_slave: OptionalCell::empty(),
199
200            active_after: Cell::new(false),
201        }
202    }
203
204    pub fn is_enabled_clock(&self) -> bool {
205        self.clock.is_enabled()
206    }
207
208    pub fn enable_clock(&self) {
209        self.clock.enable();
210    }
211
212    pub fn disable_clock(&self) {
213        self.clock.disable();
214    }
215
216    pub fn set_dma(&self, tx_dma: TxDMA<'a>, rx_dma: RxDMA<'a>) {
217        self.tx_dma.set(tx_dma.0);
218        self.rx_dma.set(rx_dma.0);
219    }
220
221    pub fn handle_interrupt(&self) {
222        // Used only during debugging. Since we use DMA, we do not enable SPI
223        // interrupts during normal operations
224    }
225
226    fn set_active_slave(&self, slave_pin: &'a crate::gpio::Pin<'a>) {
227        self.active_slave.set(slave_pin);
228    }
229
230    fn set_cr<F>(&self, f: F)
231    where
232        F: FnOnce(),
233    {
234        self.registers.cr1.modify(CR1::SPE::CLEAR);
235        f();
236        self.registers.cr1.modify(CR1::SPE::SET);
237    }
238
239    // IdleLow  = CPOL = 0
240    // IdleHigh = CPOL = 1
241    fn set_polarity(&self, polarity: ClockPolarity) {
242        self.set_cr(|| match polarity {
243            ClockPolarity::IdleLow => self.registers.cr1.modify(CR1::CPOL::CLEAR),
244            ClockPolarity::IdleHigh => self.registers.cr1.modify(CR1::CPOL::SET),
245        });
246    }
247
248    fn get_polarity(&self) -> ClockPolarity {
249        if !self.registers.cr1.is_set(CR1::CPOL) {
250            ClockPolarity::IdleLow
251        } else {
252            ClockPolarity::IdleHigh
253        }
254    }
255
256    // SampleLeading  = CPHA = 0
257    // SampleTrailing = CPHA = 1
258    fn set_phase(&self, phase: ClockPhase) {
259        self.set_cr(|| match phase {
260            ClockPhase::SampleLeading => self.registers.cr1.modify(CR1::CPHA::CLEAR),
261            ClockPhase::SampleTrailing => self.registers.cr1.modify(CR1::CPHA::SET),
262        });
263    }
264
265    fn get_phase(&self) -> ClockPhase {
266        if !self.registers.cr1.is_set(CR1::CPHA) {
267            ClockPhase::SampleLeading
268        } else {
269            ClockPhase::SampleTrailing
270        }
271    }
272
273    fn enable_tx(&self) {
274        self.registers.cr2.modify(CR2::TXDMAEN::SET);
275    }
276
277    fn disable_tx(&self) {
278        self.registers.cr2.modify(CR2::TXDMAEN::CLEAR);
279    }
280
281    fn enable_rx(&self) {
282        self.registers.cr2.modify(CR2::RXDMAEN::SET);
283    }
284
285    fn disable_rx(&self) {
286        self.registers.cr2.modify(CR2::RXDMAEN::CLEAR);
287    }
288
289    fn read_write_bytes(
290        &self,
291        write_buffer: SubSliceMut<'static, u8>,
292        read_buffer: Option<SubSliceMut<'static, u8>>,
293    ) -> Result<
294        (),
295        (
296            ErrorCode,
297            SubSliceMut<'static, u8>,
298            Option<SubSliceMut<'static, u8>>,
299        ),
300    > {
301        self.active_slave.map(|p| {
302            p.clear();
303        });
304
305        let mut count: usize = write_buffer.len();
306        read_buffer
307            .as_ref()
308            .map(|buf| count = cmp::min(count, buf.len()));
309
310        self.dma_len.set(count);
311
312        self.transfers_in_progress.set(0);
313
314        read_buffer.map(|rx_buffer| {
315            self.transfers_in_progress
316                .set(self.transfers_in_progress.get() + 1);
317            self.rx_dma.map(move |dma| {
318                dma.do_transfer(rx_buffer);
319            });
320            self.enable_rx();
321        });
322
323        self.transfers_in_progress
324            .set(self.transfers_in_progress.get() + 1);
325        self.tx_dma.map(move |dma| {
326            dma.do_transfer(write_buffer);
327        });
328        self.enable_tx();
329
330        Ok(())
331    }
332}
333
334impl<'a> spi::SpiMaster<'a> for Spi<'a> {
335    type ChipSelect = &'a crate::gpio::Pin<'a>;
336
337    fn set_client(&self, client: &'a dyn SpiMasterClient) {
338        self.master_client.set(client);
339    }
340
341    fn init(&self) -> Result<(), ErrorCode> {
342        // enable error interrupt (used only for debugging)
343        // self.registers.cr2.modify(CR2::ERRIE::SET);
344
345        // 2 line unidirectional mode
346        // Select as master
347        // Software slave management
348        // 8 bit data frame format
349        // Enable
350        self.registers.cr1.modify(
351            CR1::BIDIMODE::CLEAR
352                + CR1::MSTR::SET
353                + CR1::SSM::SET
354                + CR1::SSI::SET
355                + CR1::DFF::CLEAR
356                + CR1::SPE::SET,
357        );
358        Ok(())
359    }
360
361    fn is_busy(&self) -> bool {
362        self.registers.sr.is_set(SR::BSY)
363    }
364
365    fn write_byte(&self, out_byte: u8) -> Result<(), ErrorCode> {
366        // loop till TXE (Transmit Buffer Empty) becomes 1
367        while !self.registers.sr.is_set(SR::TXE) {}
368
369        self.registers.dr.modify(DR::DR.val(out_byte as u32));
370        Ok(())
371    }
372
373    fn read_byte(&self) -> Result<u8, ErrorCode> {
374        self.read_write_byte(0)
375    }
376
377    fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode> {
378        match self.write_byte(val) {
379            Ok(()) => {
380                // loop till RXNE becomes 1
381                while !self.registers.sr.is_set(SR::RXNE) {}
382
383                Ok(self.registers.dr.read(DR::DR) as u8)
384            }
385            Err(e) => Err(e),
386        }
387    }
388
389    fn read_write_bytes(
390        &self,
391        write_buffer: SubSliceMut<'static, u8>,
392        read_buffer: Option<SubSliceMut<'static, u8>>,
393    ) -> Result<
394        (),
395        (
396            ErrorCode,
397            SubSliceMut<'static, u8>,
398            Option<SubSliceMut<'static, u8>>,
399        ),
400    > {
401        // If busy, don't start
402        if self.is_busy() {
403            return Err((ErrorCode::BUSY, write_buffer, read_buffer));
404        }
405
406        self.read_write_bytes(write_buffer, read_buffer)
407    }
408
409    /// We *only* support 1Mhz and 4MHz. If `rate` is set to any value other than
410    /// `1_000_000` or `4_000_000`, then this function panics.
411    fn set_rate(&self, rate: u32) -> Result<u32, ErrorCode> {
412        match rate {
413            1_000_000 => self.set_cr(|| {
414                // HSI is 16Mhz and Fpclk is also 16Mhz. 0b011 is Fpclk / 16
415                self.registers.cr1.modify(CR1::BR.val(0b011));
416            }),
417            4_000_000 => self.set_cr(|| {
418                // HSI is 16Mhz and Fpclk is also 16Mhz. 0b001 is Fpclk / 4
419                self.registers.cr1.modify(CR1::BR.val(0b001));
420            }),
421            _ => panic!("SPI rate must be 1_000_000 or 4_000_000"),
422        }
423        Ok(rate)
424    }
425
426    /// We *only* support 1Mhz and 4MHz. If we need to return any other value
427    /// than `1_000_000` or `4_000_000`, then this function panics.
428    fn get_rate(&self) -> u32 {
429        // HSI is 16Mhz and Fpclk is also 16Mhz
430        match self.registers.cr1.read(CR1::BR) {
431            0b011 => 1_000_000, // 0b011 is Fpclk / 16 => 1 MHz
432            0b001 => 4_000_000, // 0b001 is Fpclk / 4  => 4 MHz
433            _ => panic!("Current SPI rate not supported by tock OS!"),
434        }
435    }
436
437    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
438        self.set_polarity(polarity);
439        Ok(())
440    }
441
442    fn get_polarity(&self) -> ClockPolarity {
443        self.get_polarity()
444    }
445
446    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
447        self.set_phase(phase);
448        Ok(())
449    }
450
451    fn get_phase(&self) -> ClockPhase {
452        self.get_phase()
453    }
454
455    fn hold_low(&self) {
456        self.active_after.set(true);
457    }
458
459    fn release_low(&self) {
460        self.active_after.set(false);
461    }
462
463    fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode> {
464        self.set_active_slave(cs);
465        Ok(())
466    }
467}
468
469impl<'a> dma::StreamClient<'a, Dma1<'a>> for Spi<'a> {
470    fn transfer_done(&self, pid: Dma1Peripheral) {
471        if pid == self.tx_dma_pid {
472            self.disable_tx();
473        }
474
475        if pid == self.rx_dma_pid {
476            self.disable_rx();
477        }
478
479        self.transfers_in_progress
480            .set(self.transfers_in_progress.get() - 1);
481
482        if self.transfers_in_progress.get() == 0 {
483            if !self.active_after.get() {
484                self.active_slave.map(|p| {
485                    p.set();
486                });
487            }
488
489            let tx_buffer = self.tx_dma.and_then(|tx_dma| tx_dma.return_buffer());
490            let rx_buffer = self.rx_dma.and_then(|rx_dma| rx_dma.return_buffer());
491
492            let length = self.dma_len.get();
493            self.dma_len.set(0);
494
495            self.master_client.map(|client| {
496                tx_buffer.map(|t| {
497                    client.read_write_done(t, rx_buffer, Ok(length));
498                });
499            });
500        }
501    }
502}
503
504pub struct SpiClock<'a>(pub phclk::PeripheralClock<'a>);
505
506impl ClockInterface for SpiClock<'_> {
507    fn is_enabled(&self) -> bool {
508        self.0.is_enabled()
509    }
510
511    fn enable(&self) {
512        self.0.enable();
513    }
514
515    fn disable(&self) {
516        self.0.disable();
517    }
518}