66use stm32f0xx_hal:: { pac, prelude:: * , rcc:: Rcc } ;
77
88pub struct SpiPeripheral < const RXC : usize , const TXC : usize > {
9+ /// Our PAC object for register access
910 dev : pac:: SPI1 ,
1011 /// A space for bytes received from the host
1112 rx_buffer : [ u8 ; RXC ] ,
@@ -23,6 +24,9 @@ pub struct SpiPeripheral<const RXC: usize, const TXC: usize> {
2324}
2425
2526impl < const RXC : usize , const TXC : usize > SpiPeripheral < RXC , TXC > {
27+ const MODE : embedded_hal:: spi:: Mode = embedded_hal:: spi:: MODE_0 ;
28+
29+ /// Construct a new driver
2630 pub fn new < SCKPIN , MISOPIN , MOSIPIN > (
2731 dev : pac:: SPI1 ,
2832 pins : ( SCKPIN , MISOPIN , MOSIPIN ) ,
@@ -35,24 +39,53 @@ impl<const RXC: usize, const TXC: usize> SpiPeripheral<RXC, TXC> {
3539 {
3640 defmt:: info!( "pclk = {}" , rcc. clocks. pclk( ) . 0 , ) ;
3741
38- let mode = embedded_hal:: spi:: MODE_0 ;
39-
4042 // Set SPI up in Controller mode. This will cause the HAL to enable the clocks and power to the IP block.
4143 // It also checks the pins are OK.
42- let spi_controller = stm32f0xx_hal:: spi:: Spi :: spi1 ( dev, pins, mode, 8_000_000u32 . hz ( ) , rcc) ;
44+ let spi_controller =
45+ stm32f0xx_hal:: spi:: Spi :: spi1 ( dev, pins, Self :: MODE , 8_000_000u32 . hz ( ) , rcc) ;
4346 // Now disassemble the driver so we can set it into Controller mode instead
4447 let ( dev, _pins) = spi_controller. release ( ) ;
4548
49+ let mut spi = SpiPeripheral {
50+ dev,
51+ rx_buffer : [ 0u8 ; RXC ] ,
52+ rx_idx : 0 ,
53+ tx_buffer : [ 0u8 ; TXC ] ,
54+ tx_idx : 0 ,
55+ tx_ready : 0 ,
56+ is_done : false ,
57+ } ;
58+
59+ spi. config ( Self :: MODE ) ;
60+
61+ // Empty the receive register
62+ while spi. has_rx_data ( ) {
63+ let _ = spi. raw_read ( ) ;
64+ }
65+
66+ // Enable the SPI device
67+ spi. stop ( ) ;
68+ spi. dev . cr1 . write ( |w| {
69+ // Enable the peripheral
70+ w. spe ( ) . enabled ( ) ;
71+ w
72+ } ) ;
73+
74+ spi
75+ }
76+
77+ /// Set up the registers
78+ fn config ( & mut self , mode : embedded_hal:: spi:: Mode ) {
4679 // We are following DM00043574, Section 30.5.1 Configuration of SPI
4780
4881 // 1. Disable SPI
49- dev. cr1 . modify ( |_r, w| {
82+ self . dev . cr1 . modify ( |_r, w| {
5083 w. spe ( ) . disabled ( ) ;
5184 w
5285 } ) ;
5386
5487 // 2. Write to the SPI_CR1 register. Apologies for the outdated terminology.
55- dev. cr1 . write ( |w| {
88+ self . dev . cr1 . write ( |w| {
5689 // 2a. Configure the serial clock baud rate (ignored in peripheral mode)
5790 w. br ( ) . div2 ( ) ;
5891 // 2b. Configure the CPHA and CPOL bits.
@@ -83,7 +116,7 @@ impl<const RXC: usize, const TXC: usize> SpiPeripheral<RXC, TXC> {
83116 } ) ;
84117
85118 // 3. Write to SPI_CR2 register
86- dev. cr2 . write ( |w| {
119+ self . dev . cr2 . write ( |w| {
87120 // 3a. Configure the DS[3:0] bits to select the data length for the transfer (0b111 = 8-bit words).
88121 unsafe { w. ds ( ) . bits ( 0b111 ) } ;
89122 // 3b. Disable hard-output on the CS pin (ignored in Master mode)
@@ -109,31 +142,6 @@ impl<const RXC: usize, const TXC: usize> SpiPeripheral<RXC, TXC> {
109142 // 4. SPI_CRCPR - not required
110143
111144 // 5. DMA registers - not required
112-
113- let mut spi = SpiPeripheral {
114- dev,
115- rx_buffer : [ 0u8 ; RXC ] ,
116- rx_idx : 0 ,
117- tx_buffer : [ 0u8 ; TXC ] ,
118- tx_idx : 0 ,
119- tx_ready : 0 ,
120- is_done : false ,
121- } ;
122-
123- // Empty the receive register
124- while spi. has_rx_data ( ) {
125- let _ = spi. raw_read ( ) ;
126- }
127-
128- // Enable the SPI device
129- spi. stop ( ) ;
130- spi. dev . cr1 . write ( |w| {
131- // Enable the peripheral
132- w. spe ( ) . enabled ( ) ;
133- w
134- } ) ;
135-
136- spi
137145 }
138146
139147 /// Enable the SPI peripheral (i.e. when CS goes low)
@@ -160,6 +168,41 @@ impl<const RXC: usize, const TXC: usize> SpiPeripheral<RXC, TXC> {
160168 } ) ;
161169 }
162170
171+ /// Fully reset the SPI peripheral
172+ pub fn reset ( & mut self , _rcc : & mut stm32f0xx_hal:: rcc:: Rcc ) {
173+ self . dev . cr1 . write ( |w| {
174+ // Disable the peripheral
175+ w. spe ( ) . disabled ( ) ;
176+ w
177+ } ) ;
178+
179+ // Reset the IP manually. This is OK as we have exclusive access to the
180+ // RCC peripheral. But sadly the RCC peripheral doesn't let us reset
181+ // anything (it assumes it can handle it all internally).
182+ let reset_reg = 0x4002_100C as * mut u32 ;
183+ let spi1_bit = 1 << 12 ;
184+ unsafe {
185+ * reset_reg |= spi1_bit;
186+ * reset_reg &= !( spi1_bit) ;
187+ }
188+
189+ // Reconfigure
190+ self . config ( Self :: MODE ) ;
191+
192+ // Empty the receive register
193+ while self . has_rx_data ( ) {
194+ let _ = self . raw_read ( ) ;
195+ }
196+
197+ // Enable the SPI device and leave it idle
198+ self . stop ( ) ;
199+ self . dev . cr1 . write ( |w| {
200+ // Enable the peripheral
201+ w. spe ( ) . enabled ( ) ;
202+ w
203+ } ) ;
204+ }
205+
163206 /// Does the RX FIFO have any data in it?
164207 fn has_rx_data ( & self ) -> bool {
165208 self . dev . sr . read ( ) . rxne ( ) . is_not_empty ( )
0 commit comments