diff options
| author | Ulf Lilleengen <[email protected]> | 2021-05-27 23:05:42 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2021-05-27 23:05:42 +0200 |
| commit | edec5833b3288d38469598e5e606750f5ed42b91 (patch) | |
| tree | eb5d5f1619ecd897227d5882abfe553fd940e6bf | |
| parent | c4ea7427faf08a69762bb81f329638ef90d12dc1 (diff) | |
Refactor SPI and fix write bug
* SPI write v2 was hanging in write due to an infinite loop
* SPI word write was not followed by a read back
The u8 and u16 write/read logic have been refactored into write_word and
read_word.
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v2.rs | 164 |
2 files changed, 59 insertions, 106 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 9bb8fb60f..72276535f 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -12,6 +12,7 @@ use crate::gpio::Pin; | |||
| 12 | pub enum Error { | 12 | pub enum Error { |
| 13 | Framing, | 13 | Framing, |
| 14 | Crc, | 14 | Crc, |
| 15 | ModeFault, | ||
| 15 | Overrun, | 16 | Overrun, |
| 16 | } | 17 | } |
| 17 | 18 | ||
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 393adc4e9..1c10ab1b5 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs | |||
| @@ -153,6 +153,54 @@ impl<'d, T: Instance> Drop for Spi<'d, T> { | |||
| 153 | } | 153 | } |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | trait Word {} | ||
| 157 | |||
| 158 | impl Word for u8 {} | ||
| 159 | impl Word for u16 {} | ||
| 160 | |||
| 161 | /// Write a single word blocking. Assumes word size have already been set. | ||
| 162 | fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { | ||
| 163 | loop { | ||
| 164 | let sr = unsafe { regs.sr().read() }; | ||
| 165 | if sr.ovr() { | ||
| 166 | return Err(Error::Overrun); | ||
| 167 | } else if sr.fre() { | ||
| 168 | return Err(Error::Framing); | ||
| 169 | } else if sr.modf() { | ||
| 170 | return Err(Error::ModeFault); | ||
| 171 | } else if sr.crcerr() { | ||
| 172 | return Err(Error::Crc); | ||
| 173 | } else if sr.txe() { | ||
| 174 | unsafe { | ||
| 175 | let dr = regs.dr().ptr() as *mut W; | ||
| 176 | ptr::write_volatile(dr, word); | ||
| 177 | } | ||
| 178 | return Ok(()); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | /// Read a single word blocking. Assumes word size have already been set. | ||
| 184 | fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> { | ||
| 185 | loop { | ||
| 186 | let sr = unsafe { regs.sr().read() }; | ||
| 187 | if sr.ovr() { | ||
| 188 | return Err(Error::Overrun); | ||
| 189 | } else if sr.modf() { | ||
| 190 | return Err(Error::ModeFault); | ||
| 191 | } else if sr.fre() { | ||
| 192 | return Err(Error::Framing); | ||
| 193 | } else if sr.crcerr() { | ||
| 194 | return Err(Error::Crc); | ||
| 195 | } else if sr.rxne() { | ||
| 196 | unsafe { | ||
| 197 | let dr = regs.dr().ptr() as *const W; | ||
| 198 | return Ok(ptr::read_volatile(dr)); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 156 | impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { | 204 | impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { |
| 157 | type Error = Error; | 205 | type Error = Error; |
| 158 | 206 | ||
| @@ -160,29 +208,9 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { | |||
| 160 | Self::set_word_size(WordSize::EightBit); | 208 | Self::set_word_size(WordSize::EightBit); |
| 161 | let regs = T::regs(); | 209 | let regs = T::regs(); |
| 162 | 210 | ||
| 163 | for (i, word) in words.iter().enumerate() { | 211 | for word in words.iter() { |
| 164 | while unsafe { !regs.sr().read().txe() } { | 212 | write_word(regs, *word)?; |
| 165 | // spin | 213 | let _: u8 = read_word(regs)?; |
| 166 | } | ||
| 167 | unsafe { | ||
| 168 | let dr = regs.dr().ptr() as *mut u8; | ||
| 169 | ptr::write_volatile(dr, *word); | ||
| 170 | } | ||
| 171 | loop { | ||
| 172 | let sr = unsafe { regs.sr().read() }; | ||
| 173 | if sr.fre() { | ||
| 174 | return Err(Error::Framing); | ||
| 175 | } | ||
| 176 | if sr.ovr() { | ||
| 177 | return Err(Error::Overrun); | ||
| 178 | } | ||
| 179 | if sr.crcerr() { | ||
| 180 | return Err(Error::Crc); | ||
| 181 | } | ||
| 182 | if !sr.txe() { | ||
| 183 | // loop waiting for TXE | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | 214 | } |
| 187 | 215 | ||
| 188 | Ok(()) | 216 | Ok(()) |
| @@ -196,43 +224,9 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> { | |||
| 196 | Self::set_word_size(WordSize::EightBit); | 224 | Self::set_word_size(WordSize::EightBit); |
| 197 | let regs = T::regs(); | 225 | let regs = T::regs(); |
| 198 | 226 | ||
| 199 | for (i, word) in words.iter_mut().enumerate() { | 227 | for word in words.iter_mut() { |
| 200 | while unsafe { !regs.sr().read().txe() } { | 228 | write_word(regs, *word)?; |
| 201 | // spin | 229 | *word = read_word(regs)?; |
| 202 | } | ||
| 203 | unsafe { | ||
| 204 | let dr = regs.dr().ptr() as *mut u8; | ||
| 205 | ptr::write_volatile(dr, *word); | ||
| 206 | } | ||
| 207 | loop { | ||
| 208 | let sr = unsafe { regs.sr().read() }; | ||
| 209 | if sr.rxne() { | ||
| 210 | break; | ||
| 211 | } | ||
| 212 | if sr.fre() { | ||
| 213 | return Err(Error::Framing); | ||
| 214 | } | ||
| 215 | if sr.ovr() { | ||
| 216 | return Err(Error::Overrun); | ||
| 217 | } | ||
| 218 | if sr.crcerr() { | ||
| 219 | return Err(Error::Crc); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | unsafe { | ||
| 223 | let dr = regs.dr().ptr() as *const u8; | ||
| 224 | *word = ptr::read_volatile(dr); | ||
| 225 | } | ||
| 226 | let sr = unsafe { regs.sr().read() }; | ||
| 227 | if sr.fre() { | ||
| 228 | return Err(Error::Framing); | ||
| 229 | } | ||
| 230 | if sr.ovr() { | ||
| 231 | return Err(Error::Overrun); | ||
| 232 | } | ||
| 233 | if sr.crcerr() { | ||
| 234 | return Err(Error::Crc); | ||
| 235 | } | ||
| 236 | } | 230 | } |
| 237 | 231 | ||
| 238 | Ok(words) | 232 | Ok(words) |
| @@ -247,28 +241,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> { | |||
| 247 | let regs = T::regs(); | 241 | let regs = T::regs(); |
| 248 | 242 | ||
| 249 | for word in words.iter() { | 243 | for word in words.iter() { |
| 250 | while unsafe { !regs.sr().read().txe() } { | 244 | write_word(regs, *word)?; |
| 251 | // spin | 245 | let _: u16 = read_word(regs)?; |
| 252 | } | ||
| 253 | unsafe { | ||
| 254 | let dr = regs.dr().ptr() as *mut u16; | ||
| 255 | ptr::write_volatile(dr, *word); | ||
| 256 | } | ||
| 257 | loop { | ||
| 258 | let sr = unsafe { regs.sr().read() }; | ||
| 259 | if sr.fre() { | ||
| 260 | return Err(Error::Framing); | ||
| 261 | } | ||
| 262 | if sr.ovr() { | ||
| 263 | return Err(Error::Overrun); | ||
| 264 | } | ||
| 265 | if sr.crcerr() { | ||
| 266 | return Err(Error::Crc); | ||
| 267 | } | ||
| 268 | if !sr.txe() { | ||
| 269 | // loop waiting for TXE | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | 246 | } |
| 273 | 247 | ||
| 274 | Ok(()) | 248 | Ok(()) |
| @@ -283,30 +257,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T> | |||
| 283 | let regs = T::regs(); | 257 | let regs = T::regs(); |
| 284 | 258 | ||
| 285 | for word in words.iter_mut() { | 259 | for word in words.iter_mut() { |
| 286 | while unsafe { !regs.sr().read().txe() } { | 260 | write_word(regs, *word)?; |
| 287 | // spin | 261 | *word = read_word(regs)?; |
| 288 | } | ||
| 289 | unsafe { | ||
| 290 | let dr = regs.dr().ptr() as *mut u16; | ||
| 291 | ptr::write_volatile(dr, *word); | ||
| 292 | } | ||
| 293 | while unsafe { !regs.sr().read().rxne() } { | ||
| 294 | // spin waiting for inbound to shift in. | ||
| 295 | } | ||
| 296 | unsafe { | ||
| 297 | let dr = regs.dr().ptr() as *const u16; | ||
| 298 | *word = ptr::read_volatile(dr); | ||
| 299 | } | ||
| 300 | let sr = unsafe { regs.sr().read() }; | ||
| 301 | if sr.fre() { | ||
| 302 | return Err(Error::Framing); | ||
| 303 | } | ||
| 304 | if sr.ovr() { | ||
| 305 | return Err(Error::Overrun); | ||
| 306 | } | ||
| 307 | if sr.crcerr() { | ||
| 308 | return Err(Error::Crc); | ||
| 309 | } | ||
| 310 | } | 262 | } |
| 311 | 263 | ||
| 312 | Ok(words) | 264 | Ok(words) |
