diff options
| -rw-r--r-- | embassy-stm32/build.rs | 33 | ||||
| -rw-r--r-- | embassy-stm32/src/ospi/mod.rs | 118 |
2 files changed, 151 insertions, 0 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 28c619c6b..966dce121 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -1054,6 +1054,30 @@ fn main() { | |||
| 1054 | (("octospi", "NCS"), quote!(crate::ospi::NSSPin)), | 1054 | (("octospi", "NCS"), quote!(crate::ospi::NSSPin)), |
| 1055 | (("octospi", "CLK"), quote!(crate::ospi::SckPin)), | 1055 | (("octospi", "CLK"), quote!(crate::ospi::SckPin)), |
| 1056 | (("octospi", "NCLK"), quote!(crate::ospi::NckPin)), | 1056 | (("octospi", "NCLK"), quote!(crate::ospi::NckPin)), |
| 1057 | (("octospim", "P1_IO0"), quote!(crate::ospi::D0Pin)), | ||
| 1058 | (("octospim", "P1_IO1"), quote!(crate::ospi::D1Pin)), | ||
| 1059 | (("octospim", "P1_IO2"), quote!(crate::ospi::D2Pin)), | ||
| 1060 | (("octospim", "P1_IO3"), quote!(crate::ospi::D3Pin)), | ||
| 1061 | (("octospim", "P1_IO4"), quote!(crate::ospi::D4Pin)), | ||
| 1062 | (("octospim", "P1_IO5"), quote!(crate::ospi::D5Pin)), | ||
| 1063 | (("octospim", "P1_IO6"), quote!(crate::ospi::D6Pin)), | ||
| 1064 | (("octospim", "P1_IO7"), quote!(crate::ospi::D7Pin)), | ||
| 1065 | (("octospim", "P1_DQS"), quote!(crate::ospi::DQSPin)), | ||
| 1066 | (("octospim", "P1_NCS"), quote!(crate::ospi::NSSPin)), | ||
| 1067 | (("octospim", "P1_CLK"), quote!(crate::ospi::SckPin)), | ||
| 1068 | (("octospim", "P1_NCLK"), quote!(crate::ospi::NckPin)), | ||
| 1069 | (("octospim", "P2_IO0"), quote!(crate::ospi::D0Pin)), | ||
| 1070 | (("octospim", "P2_IO1"), quote!(crate::ospi::D1Pin)), | ||
| 1071 | (("octospim", "P2_IO2"), quote!(crate::ospi::D2Pin)), | ||
| 1072 | (("octospim", "P2_IO3"), quote!(crate::ospi::D3Pin)), | ||
| 1073 | (("octospim", "P2_IO4"), quote!(crate::ospi::D4Pin)), | ||
| 1074 | (("octospim", "P2_IO5"), quote!(crate::ospi::D5Pin)), | ||
| 1075 | (("octospim", "P2_IO6"), quote!(crate::ospi::D6Pin)), | ||
| 1076 | (("octospim", "P2_IO7"), quote!(crate::ospi::D7Pin)), | ||
| 1077 | (("octospim", "P2_DQS"), quote!(crate::ospi::DQSPin)), | ||
| 1078 | (("octospim", "P2_NCS"), quote!(crate::ospi::NSSPin)), | ||
| 1079 | (("octospim", "P2_CLK"), quote!(crate::ospi::SckPin)), | ||
| 1080 | (("octospim", "P2_NCLK"), quote!(crate::ospi::NckPin)), | ||
| 1057 | (("tsc", "G1_IO1"), quote!(crate::tsc::G1IO1Pin)), | 1081 | (("tsc", "G1_IO1"), quote!(crate::tsc::G1IO1Pin)), |
| 1058 | (("tsc", "G1_IO2"), quote!(crate::tsc::G1IO2Pin)), | 1082 | (("tsc", "G1_IO2"), quote!(crate::tsc::G1IO2Pin)), |
| 1059 | (("tsc", "G1_IO3"), quote!(crate::tsc::G1IO3Pin)), | 1083 | (("tsc", "G1_IO3"), quote!(crate::tsc::G1IO3Pin)), |
| @@ -1111,6 +1135,15 @@ fn main() { | |||
| 1111 | peri = format_ident!("{}", pin.signal.replace('_', "")); | 1135 | peri = format_ident!("{}", pin.signal.replace('_', "")); |
| 1112 | } | 1136 | } |
| 1113 | 1137 | ||
| 1138 | // OCTOSPIM is special | ||
| 1139 | if p.name == "OCTOSPIM" { | ||
| 1140 | peri = format_ident!("{}", "OCTOSPI1"); | ||
| 1141 | g.extend(quote! { | ||
| 1142 | pin_trait_impl!(#tr, #peri, #pin_name, #af); | ||
| 1143 | }); | ||
| 1144 | peri = format_ident!("{}", "OCTOSPI2"); | ||
| 1145 | } | ||
| 1146 | |||
| 1114 | g.extend(quote! { | 1147 | g.extend(quote! { |
| 1115 | pin_trait_impl!(#tr, #peri, #pin_name, #af); | 1148 | pin_trait_impl!(#tr, #peri, #pin_name, #af); |
| 1116 | }) | 1149 | }) |
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 289bfa672..48a1ea5e6 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs | |||
| @@ -16,6 +16,8 @@ use crate::dma::{word, ChannelAndRequest}; | |||
| 16 | use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; | 16 | use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; |
| 17 | use crate::mode::{Async, Blocking, Mode as PeriMode}; | 17 | use crate::mode::{Async, Blocking, Mode as PeriMode}; |
| 18 | use crate::pac::octospi::{vals, Octospi as Regs}; | 18 | use crate::pac::octospi::{vals, Octospi as Regs}; |
| 19 | #[cfg(octospim_v1)] | ||
| 20 | use crate::pac::octospim::Octospim; | ||
| 19 | use crate::rcc::{self, RccPeripheral}; | 21 | use crate::rcc::{self, RccPeripheral}; |
| 20 | use crate::{peripherals, Peripheral}; | 22 | use crate::{peripherals, Peripheral}; |
| 21 | 23 | ||
| @@ -197,6 +199,83 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { | |||
| 197 | ) -> Self { | 199 | ) -> Self { |
| 198 | into_ref!(peri); | 200 | into_ref!(peri); |
| 199 | 201 | ||
| 202 | #[cfg(octospim_v1)] | ||
| 203 | { | ||
| 204 | // RCC for octospim should be enabled before writing register | ||
| 205 | #[cfg(stm32l4)] | ||
| 206 | crate::pac::RCC.ahb2smenr().modify(|w| w.set_octospimsmen(true)); | ||
| 207 | #[cfg(stm32u5)] | ||
| 208 | crate::pac::RCC.ahb2enr1().modify(|w| w.set_octospimen(true)); | ||
| 209 | #[cfg(not(any(stm32l4, stm32u5)))] | ||
| 210 | crate::pac::RCC.ahb3enr().modify(|w| w.set_iomngren(true)); | ||
| 211 | |||
| 212 | // Disable OctoSPI peripheral first | ||
| 213 | T::REGS.cr().modify(|w| { | ||
| 214 | w.set_en(false); | ||
| 215 | }); | ||
| 216 | |||
| 217 | // OctoSPI IO Manager has been enabled before | ||
| 218 | T::OCTOSPIM_REGS.cr().modify(|w| { | ||
| 219 | w.set_muxen(false); | ||
| 220 | w.set_req2ack_time(0xff); | ||
| 221 | }); | ||
| 222 | |||
| 223 | // Clear config | ||
| 224 | T::OCTOSPIM_REGS.p1cr().modify(|w| { | ||
| 225 | w.set_clksrc(false); | ||
| 226 | w.set_dqssrc(false); | ||
| 227 | w.set_ncssrc(false); | ||
| 228 | w.set_clken(false); | ||
| 229 | w.set_dqsen(false); | ||
| 230 | w.set_ncsen(false); | ||
| 231 | w.set_iolsrc(0); | ||
| 232 | w.set_iohsrc(0); | ||
| 233 | }); | ||
| 234 | |||
| 235 | T::OCTOSPIM_REGS.p1cr().modify(|w| { | ||
| 236 | let octospi_src = if T::OCTOSPI_IDX == 1 { false } else { true }; | ||
| 237 | w.set_ncsen(true); | ||
| 238 | w.set_ncssrc(octospi_src); | ||
| 239 | w.set_clken(true); | ||
| 240 | w.set_clksrc(octospi_src); | ||
| 241 | if dqs.is_some() { | ||
| 242 | w.set_dqsen(true); | ||
| 243 | w.set_dqssrc(octospi_src); | ||
| 244 | } | ||
| 245 | |||
| 246 | // Set OCTOSPIM IOL and IOH according to the index of OCTOSPI instance | ||
| 247 | if T::OCTOSPI_IDX == 1 { | ||
| 248 | w.set_iolen(true); | ||
| 249 | w.set_iolsrc(0); | ||
| 250 | // Enable IOH in octo and dual quad mode | ||
| 251 | if let OspiWidth::OCTO = width { | ||
| 252 | w.set_iohen(true); | ||
| 253 | w.set_iohsrc(0b01); | ||
| 254 | } else if dual_quad { | ||
| 255 | w.set_iohen(true); | ||
| 256 | w.set_iohsrc(0b00); | ||
| 257 | } else { | ||
| 258 | w.set_iohen(false); | ||
| 259 | w.set_iohsrc(0b00); | ||
| 260 | } | ||
| 261 | } else { | ||
| 262 | w.set_iolen(true); | ||
| 263 | w.set_iolsrc(0b10); | ||
| 264 | // Enable IOH in octo and dual quad mode | ||
| 265 | if let OspiWidth::OCTO = width { | ||
| 266 | w.set_iohen(true); | ||
| 267 | w.set_iohsrc(0b11); | ||
| 268 | } else if dual_quad { | ||
| 269 | w.set_iohen(true); | ||
| 270 | w.set_iohsrc(0b10); | ||
| 271 | } else { | ||
| 272 | w.set_iohen(false); | ||
| 273 | w.set_iohsrc(0b00); | ||
| 274 | } | ||
| 275 | } | ||
| 276 | }); | ||
| 277 | } | ||
| 278 | |||
| 200 | // System configuration | 279 | // System configuration |
| 201 | rcc::enable_and_reset::<T>(); | 280 | rcc::enable_and_reset::<T>(); |
| 202 | while T::REGS.sr().read().busy() {} | 281 | while T::REGS.sr().read().busy() {} |
| @@ -1056,11 +1135,25 @@ fn finish_dma(regs: Regs) { | |||
| 1056 | }); | 1135 | }); |
| 1057 | } | 1136 | } |
| 1058 | 1137 | ||
| 1138 | #[cfg(octospim_v1)] | ||
| 1139 | /// OctoSPI I/O manager instance trait. | ||
| 1140 | pub(crate) trait SealedOctospimInstance { | ||
| 1141 | const OCTOSPIM_REGS: Octospim; | ||
| 1142 | const OCTOSPI_IDX: u8; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | /// OctoSPI instance trait. | ||
| 1059 | pub(crate) trait SealedInstance { | 1146 | pub(crate) trait SealedInstance { |
| 1060 | const REGS: Regs; | 1147 | const REGS: Regs; |
| 1061 | } | 1148 | } |
| 1062 | 1149 | ||
| 1063 | /// OSPI instance trait. | 1150 | /// OSPI instance trait. |
| 1151 | #[cfg(octospim_v1)] | ||
| 1152 | #[allow(private_bounds)] | ||
| 1153 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral + SealedOctospimInstance {} | ||
| 1154 | |||
| 1155 | /// OSPI instance trait. | ||
| 1156 | #[cfg(not(octospim_v1))] | ||
| 1064 | #[allow(private_bounds)] | 1157 | #[allow(private_bounds)] |
| 1065 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} | 1158 | pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {} |
| 1066 | 1159 | ||
| @@ -1078,6 +1171,31 @@ pin_trait!(DQSPin, Instance); | |||
| 1078 | pin_trait!(NSSPin, Instance); | 1171 | pin_trait!(NSSPin, Instance); |
| 1079 | dma_trait!(OctoDma, Instance); | 1172 | dma_trait!(OctoDma, Instance); |
| 1080 | 1173 | ||
| 1174 | // Hard-coded the octospi index, for OCTOSPIM | ||
| 1175 | #[cfg(octospim_v1)] | ||
| 1176 | impl SealedOctospimInstance for peripherals::OCTOSPI1 { | ||
| 1177 | const OCTOSPIM_REGS: Octospim = crate::pac::OCTOSPIM; | ||
| 1178 | const OCTOSPI_IDX: u8 = 1; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | #[cfg(octospim_v1)] | ||
| 1182 | impl SealedOctospimInstance for peripherals::OCTOSPI2 { | ||
| 1183 | const OCTOSPIM_REGS: Octospim = crate::pac::OCTOSPIM; | ||
| 1184 | const OCTOSPI_IDX: u8 = 2; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | #[cfg(octospim_v1)] | ||
| 1188 | foreach_peripheral!( | ||
| 1189 | (octospi, $inst:ident) => { | ||
| 1190 | impl SealedInstance for peripherals::$inst { | ||
| 1191 | const REGS: Regs = crate::pac::$inst; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | impl Instance for peripherals::$inst {} | ||
| 1195 | }; | ||
| 1196 | ); | ||
| 1197 | |||
| 1198 | #[cfg(not(octospim_v1))] | ||
| 1081 | foreach_peripheral!( | 1199 | foreach_peripheral!( |
| 1082 | (octospi, $inst:ident) => { | 1200 | (octospi, $inst:ident) => { |
| 1083 | impl SealedInstance for peripherals::$inst { | 1201 | impl SealedInstance for peripherals::$inst { |
