diff options
Diffstat (limited to 'embassy-stm32/src/xspi/mod.rs')
| -rw-r--r-- | embassy-stm32/src/xspi/mod.rs | 104 |
1 files changed, 59 insertions, 45 deletions
diff --git a/embassy-stm32/src/xspi/mod.rs b/embassy-stm32/src/xspi/mod.rs index 901569f64..466e1a9b4 100644 --- a/embassy-stm32/src/xspi/mod.rs +++ b/embassy-stm32/src/xspi/mod.rs | |||
| @@ -11,15 +11,15 @@ use embassy_embedded_hal::{GetConfig, SetConfig}; | |||
| 11 | use embassy_hal_internal::PeripheralType; | 11 | use embassy_hal_internal::PeripheralType; |
| 12 | pub use enums::*; | 12 | pub use enums::*; |
| 13 | 13 | ||
| 14 | use crate::dma::{word, ChannelAndRequest}; | 14 | use crate::dma::{ChannelAndRequest, word}; |
| 15 | use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; | 15 | use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; |
| 16 | use crate::mode::{Async, Blocking, Mode as PeriMode}; | 16 | use crate::mode::{Async, Blocking, Mode as PeriMode}; |
| 17 | use crate::pac::xspi::vals::*; | ||
| 18 | use crate::pac::xspi::Xspi as Regs; | 17 | use crate::pac::xspi::Xspi as Regs; |
| 18 | use crate::pac::xspi::vals::*; | ||
| 19 | #[cfg(xspim_v1)] | 19 | #[cfg(xspim_v1)] |
| 20 | use crate::pac::xspim::Xspim; | 20 | use crate::pac::xspim::Xspim; |
| 21 | use crate::rcc::{self, RccPeripheral}; | 21 | use crate::rcc::{self, RccPeripheral}; |
| 22 | use crate::{peripherals, Peri}; | 22 | use crate::{Peri, peripherals}; |
| 23 | 23 | ||
| 24 | /// XPSI driver config. | 24 | /// XPSI driver config. |
| 25 | #[derive(Clone, Copy)] | 25 | #[derive(Clone, Copy)] |
| @@ -420,9 +420,9 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { | |||
| 420 | return Err(XspiError::InvalidCommand); | 420 | return Err(XspiError::InvalidCommand); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | T::REGS.cr().modify(|w| { | 423 | T::REGS |
| 424 | w.set_fmode(0.into()); | 424 | .cr() |
| 425 | }); | 425 | .modify(|w| w.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into()))); |
| 426 | 426 | ||
| 427 | // Configure alternate bytes | 427 | // Configure alternate bytes |
| 428 | if let Some(ab) = command.alternate_bytes { | 428 | if let Some(ab) = command.alternate_bytes { |
| @@ -538,8 +538,8 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { | |||
| 538 | w.set_dmaen(false); | 538 | w.set_dmaen(false); |
| 539 | }); | 539 | }); |
| 540 | 540 | ||
| 541 | // self.configure_command(&transaction, Some(buf.len()))?; | 541 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 542 | self.configure_command(&transaction, Some(buf.len())).unwrap(); | 542 | self.configure_command(&transaction, Some(transfer_size_bytes))?; |
| 543 | 543 | ||
| 544 | let current_address = T::REGS.ar().read().address(); | 544 | let current_address = T::REGS.ar().read().address(); |
| 545 | let current_instruction = T::REGS.ir().read().instruction(); | 545 | let current_instruction = T::REGS.ir().read().instruction(); |
| @@ -578,7 +578,8 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { | |||
| 578 | w.set_dmaen(false); | 578 | w.set_dmaen(false); |
| 579 | }); | 579 | }); |
| 580 | 580 | ||
| 581 | self.configure_command(&transaction, Some(buf.len()))?; | 581 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 582 | self.configure_command(&transaction, Some(transfer_size_bytes))?; | ||
| 582 | 583 | ||
| 583 | T::REGS | 584 | T::REGS |
| 584 | .cr() | 585 | .cr() |
| @@ -1145,7 +1146,8 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1145 | // Wait for peripheral to be free | 1146 | // Wait for peripheral to be free |
| 1146 | while T::REGS.sr().read().busy() {} | 1147 | while T::REGS.sr().read().busy() {} |
| 1147 | 1148 | ||
| 1148 | self.configure_command(&transaction, Some(buf.len()))?; | 1149 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 1150 | self.configure_command(&transaction, Some(transfer_size_bytes))?; | ||
| 1149 | 1151 | ||
| 1150 | let current_address = T::REGS.ar().read().address(); | 1152 | let current_address = T::REGS.ar().read().address(); |
| 1151 | let current_instruction = T::REGS.ir().read().instruction(); | 1153 | let current_instruction = T::REGS.ir().read().instruction(); |
| @@ -1160,16 +1162,18 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1160 | T::REGS.ar().write(|v| v.set_address(current_address)); | 1162 | T::REGS.ar().write(|v| v.set_address(current_address)); |
| 1161 | } | 1163 | } |
| 1162 | 1164 | ||
| 1163 | let transfer = unsafe { | 1165 | for chunk in buf.chunks_mut(0xFFFF / W::size().bytes()) { |
| 1164 | self.dma | 1166 | let transfer = unsafe { |
| 1165 | .as_mut() | 1167 | self.dma |
| 1166 | .unwrap() | 1168 | .as_mut() |
| 1167 | .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) | 1169 | .unwrap() |
| 1168 | }; | 1170 | .read(T::REGS.dr().as_ptr() as *mut W, chunk, Default::default()) |
| 1171 | }; | ||
| 1169 | 1172 | ||
| 1170 | T::REGS.cr().modify(|w| w.set_dmaen(true)); | 1173 | T::REGS.cr().modify(|w| w.set_dmaen(true)); |
| 1171 | 1174 | ||
| 1172 | transfer.blocking_wait(); | 1175 | transfer.blocking_wait(); |
| 1176 | } | ||
| 1173 | 1177 | ||
| 1174 | finish_dma(T::REGS); | 1178 | finish_dma(T::REGS); |
| 1175 | 1179 | ||
| @@ -1185,21 +1189,24 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1185 | // Wait for peripheral to be free | 1189 | // Wait for peripheral to be free |
| 1186 | while T::REGS.sr().read().busy() {} | 1190 | while T::REGS.sr().read().busy() {} |
| 1187 | 1191 | ||
| 1188 | self.configure_command(&transaction, Some(buf.len()))?; | 1192 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 1193 | self.configure_command(&transaction, Some(transfer_size_bytes))?; | ||
| 1189 | T::REGS | 1194 | T::REGS |
| 1190 | .cr() | 1195 | .cr() |
| 1191 | .modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into()))); | 1196 | .modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into()))); |
| 1192 | 1197 | ||
| 1193 | let transfer = unsafe { | 1198 | for chunk in buf.chunks(0xFFFF / W::size().bytes()) { |
| 1194 | self.dma | 1199 | let transfer = unsafe { |
| 1195 | .as_mut() | 1200 | self.dma |
| 1196 | .unwrap() | 1201 | .as_mut() |
| 1197 | .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) | 1202 | .unwrap() |
| 1198 | }; | 1203 | .write(chunk, T::REGS.dr().as_ptr() as *mut W, Default::default()) |
| 1204 | }; | ||
| 1199 | 1205 | ||
| 1200 | T::REGS.cr().modify(|w| w.set_dmaen(true)); | 1206 | T::REGS.cr().modify(|w| w.set_dmaen(true)); |
| 1201 | 1207 | ||
| 1202 | transfer.blocking_wait(); | 1208 | transfer.blocking_wait(); |
| 1209 | } | ||
| 1203 | 1210 | ||
| 1204 | finish_dma(T::REGS); | 1211 | finish_dma(T::REGS); |
| 1205 | 1212 | ||
| @@ -1215,7 +1222,8 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1215 | // Wait for peripheral to be free | 1222 | // Wait for peripheral to be free |
| 1216 | while T::REGS.sr().read().busy() {} | 1223 | while T::REGS.sr().read().busy() {} |
| 1217 | 1224 | ||
| 1218 | self.configure_command(&transaction, Some(buf.len()))?; | 1225 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 1226 | self.configure_command(&transaction, Some(transfer_size_bytes))?; | ||
| 1219 | 1227 | ||
| 1220 | let current_address = T::REGS.ar().read().address(); | 1228 | let current_address = T::REGS.ar().read().address(); |
| 1221 | let current_instruction = T::REGS.ir().read().instruction(); | 1229 | let current_instruction = T::REGS.ir().read().instruction(); |
| @@ -1230,16 +1238,18 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1230 | T::REGS.ar().write(|v| v.set_address(current_address)); | 1238 | T::REGS.ar().write(|v| v.set_address(current_address)); |
| 1231 | } | 1239 | } |
| 1232 | 1240 | ||
| 1233 | let transfer = unsafe { | 1241 | for chunk in buf.chunks_mut(0xFFFF / W::size().bytes()) { |
| 1234 | self.dma | 1242 | let transfer = unsafe { |
| 1235 | .as_mut() | 1243 | self.dma |
| 1236 | .unwrap() | 1244 | .as_mut() |
| 1237 | .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) | 1245 | .unwrap() |
| 1238 | }; | 1246 | .read(T::REGS.dr().as_ptr() as *mut W, chunk, Default::default()) |
| 1247 | }; | ||
| 1239 | 1248 | ||
| 1240 | T::REGS.cr().modify(|w| w.set_dmaen(true)); | 1249 | T::REGS.cr().modify(|w| w.set_dmaen(true)); |
| 1241 | 1250 | ||
| 1242 | transfer.await; | 1251 | transfer.await; |
| 1252 | } | ||
| 1243 | 1253 | ||
| 1244 | finish_dma(T::REGS); | 1254 | finish_dma(T::REGS); |
| 1245 | 1255 | ||
| @@ -1255,21 +1265,25 @@ impl<'d, T: Instance> Xspi<'d, T, Async> { | |||
| 1255 | // Wait for peripheral to be free | 1265 | // Wait for peripheral to be free |
| 1256 | while T::REGS.sr().read().busy() {} | 1266 | while T::REGS.sr().read().busy() {} |
| 1257 | 1267 | ||
| 1258 | self.configure_command(&transaction, Some(buf.len()))?; | 1268 | let transfer_size_bytes = buf.len() * W::size().bytes(); |
| 1269 | self.configure_command(&transaction, Some(transfer_size_bytes))?; | ||
| 1259 | T::REGS | 1270 | T::REGS |
| 1260 | .cr() | 1271 | .cr() |
| 1261 | .modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into()))); | 1272 | .modify(|v| v.set_fmode(Fmode::from_bits(XspiMode::IndirectWrite.into()))); |
| 1262 | 1273 | ||
| 1263 | let transfer = unsafe { | 1274 | // TODO: implement this using a LinkedList DMA to offload the whole transfer off the CPU. |
| 1264 | self.dma | 1275 | for chunk in buf.chunks(0xFFFF / W::size().bytes()) { |
| 1265 | .as_mut() | 1276 | let transfer = unsafe { |
| 1266 | .unwrap() | 1277 | self.dma |
| 1267 | .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) | 1278 | .as_mut() |
| 1268 | }; | 1279 | .unwrap() |
| 1280 | .write(chunk, T::REGS.dr().as_ptr() as *mut W, Default::default()) | ||
| 1281 | }; | ||
| 1269 | 1282 | ||
| 1270 | T::REGS.cr().modify(|w| w.set_dmaen(true)); | 1283 | T::REGS.cr().modify(|w| w.set_dmaen(true)); |
| 1271 | 1284 | ||
| 1272 | transfer.await; | 1285 | transfer.await; |
| 1286 | } | ||
| 1273 | 1287 | ||
| 1274 | finish_dma(T::REGS); | 1288 | finish_dma(T::REGS); |
| 1275 | 1289 | ||
