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