diff options
| -rw-r--r-- | embassy-stm32/build.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/can/bxcan.rs | 124 | ||||
| -rw-r--r-- | embassy-stm32/src/can/enums.rs | 30 | ||||
| -rw-r--r-- | embassy-stm32/src/can/util.rs | 117 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/g4.rs | 7 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/h.rs | 8 |
6 files changed, 173 insertions, 115 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 948ce3aff..414723573 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -449,7 +449,7 @@ fn main() { | |||
| 449 | // ======== | 449 | // ======== |
| 450 | // Generate RccPeripheral impls | 450 | // Generate RccPeripheral impls |
| 451 | 451 | ||
| 452 | let refcounted_peripherals = HashSet::from(["usart", "adc"]); | 452 | let refcounted_peripherals = HashSet::from(["usart", "adc", "can"]); |
| 453 | let mut refcount_statics = BTreeSet::new(); | 453 | let mut refcount_statics = BTreeSet::new(); |
| 454 | 454 | ||
| 455 | for p in METADATA.peripherals { | 455 | for p in METADATA.peripherals { |
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index cc87b2565..7e00eca6f 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -13,9 +13,12 @@ use crate::gpio::sealed::AFType; | |||
| 13 | use crate::interrupt::typelevel::Interrupt; | 13 | use crate::interrupt::typelevel::Interrupt; |
| 14 | use crate::pac::can::vals::{Ide, Lec}; | 14 | use crate::pac::can::vals::{Ide, Lec}; |
| 15 | use crate::rcc::RccPeripheral; | 15 | use crate::rcc::RccPeripheral; |
| 16 | use crate::time::Hertz; | ||
| 17 | use crate::{interrupt, peripherals, Peripheral}; | 16 | use crate::{interrupt, peripherals, Peripheral}; |
| 18 | 17 | ||
| 18 | pub mod enums; | ||
| 19 | use enums::*; | ||
| 20 | pub mod util; | ||
| 21 | |||
| 19 | /// Contains CAN frame and additional metadata. | 22 | /// Contains CAN frame and additional metadata. |
| 20 | /// | 23 | /// |
| 21 | /// Timestamp is available if `time` feature is enabled. | 24 | /// Timestamp is available if `time` feature is enabled. |
| @@ -93,23 +96,6 @@ pub struct Can<'d, T: Instance> { | |||
| 93 | can: bxcan::Can<BxcanInstance<'d, T>>, | 96 | can: bxcan::Can<BxcanInstance<'d, T>>, |
| 94 | } | 97 | } |
| 95 | 98 | ||
| 96 | /// CAN bus error | ||
| 97 | #[allow(missing_docs)] | ||
| 98 | #[derive(Debug)] | ||
| 99 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 100 | pub enum BusError { | ||
| 101 | Stuff, | ||
| 102 | Form, | ||
| 103 | Acknowledge, | ||
| 104 | BitRecessive, | ||
| 105 | BitDominant, | ||
| 106 | Crc, | ||
| 107 | Software, | ||
| 108 | BusOff, | ||
| 109 | BusPassive, | ||
| 110 | BusWarning, | ||
| 111 | } | ||
| 112 | |||
| 113 | /// Error returned by `try_read` | 99 | /// Error returned by `try_read` |
| 114 | #[derive(Debug)] | 100 | #[derive(Debug)] |
| 115 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 101 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -186,8 +172,15 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 186 | 172 | ||
| 187 | /// Set CAN bit rate. | 173 | /// Set CAN bit rate. |
| 188 | pub fn set_bitrate(&mut self, bitrate: u32) { | 174 | pub fn set_bitrate(&mut self, bitrate: u32) { |
| 189 | let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); | 175 | let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); |
| 190 | self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); | 176 | let sjw = u8::from(bit_timing.sync_jump_width) as u32; |
| 177 | let seg1 = u8::from(bit_timing.seg1) as u32; | ||
| 178 | let seg2 = u8::from(bit_timing.seg2) as u32; | ||
| 179 | let prescaler = u16::from(bit_timing.prescaler) as u32; | ||
| 180 | self.can | ||
| 181 | .modify_config() | ||
| 182 | .set_bit_timing((sjw - 1) << 24 | (seg1 - 1) << 16 | (seg2 - 1) << 20 | (prescaler - 1)) | ||
| 183 | .leave_disabled(); | ||
| 191 | } | 184 | } |
| 192 | 185 | ||
| 193 | /// Enables the peripheral and synchronizes with the bus. | 186 | /// Enables the peripheral and synchronizes with the bus. |
| @@ -302,97 +295,6 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 302 | } | 295 | } |
| 303 | } | 296 | } |
| 304 | 297 | ||
| 305 | const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> { | ||
| 306 | const BS1_MAX: u8 = 16; | ||
| 307 | const BS2_MAX: u8 = 8; | ||
| 308 | const MAX_SAMPLE_POINT_PERMILL: u16 = 900; | ||
| 309 | |||
| 310 | let periph_clock = periph_clock.0; | ||
| 311 | |||
| 312 | if can_bitrate < 1000 { | ||
| 313 | return None; | ||
| 314 | } | ||
| 315 | |||
| 316 | // Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG | ||
| 317 | // CAN in Automation, 2003 | ||
| 318 | // | ||
| 319 | // According to the source, optimal quanta per bit are: | ||
| 320 | // Bitrate Optimal Maximum | ||
| 321 | // 1000 kbps 8 10 | ||
| 322 | // 500 kbps 16 17 | ||
| 323 | // 250 kbps 16 17 | ||
| 324 | // 125 kbps 16 17 | ||
| 325 | let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 }; | ||
| 326 | |||
| 327 | // Computing (prescaler * BS): | ||
| 328 | // BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual | ||
| 329 | // BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified | ||
| 330 | // let: | ||
| 331 | // BS = 1 + BS1 + BS2 -- Number of time quanta per bit | ||
| 332 | // PRESCALER_BS = PRESCALER * BS | ||
| 333 | // ==> | ||
| 334 | // PRESCALER_BS = PCLK / BITRATE | ||
| 335 | let prescaler_bs = periph_clock / can_bitrate; | ||
| 336 | |||
| 337 | // Searching for such prescaler value so that the number of quanta per bit is highest. | ||
| 338 | let mut bs1_bs2_sum = max_quanta_per_bit - 1; | ||
| 339 | while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 { | ||
| 340 | if bs1_bs2_sum <= 2 { | ||
| 341 | return None; // No solution | ||
| 342 | } | ||
| 343 | bs1_bs2_sum -= 1; | ||
| 344 | } | ||
| 345 | |||
| 346 | let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32; | ||
| 347 | if (prescaler < 1) || (prescaler > 1024) { | ||
| 348 | return None; // No solution | ||
| 349 | } | ||
| 350 | |||
| 351 | // Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum. | ||
| 352 | // We need to find such values so that the sample point is as close as possible to the optimal value, | ||
| 353 | // which is 87.5%, which is 7/8. | ||
| 354 | // | ||
| 355 | // Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *) | ||
| 356 | // {{bs2 -> (1 + bs1)/7}} | ||
| 357 | // | ||
| 358 | // Hence: | ||
| 359 | // bs2 = (1 + bs1) / 7 | ||
| 360 | // bs1 = (7 * bs1_bs2_sum - 1) / 8 | ||
| 361 | // | ||
| 362 | // Sample point location can be computed as follows: | ||
| 363 | // Sample point location = (1 + bs1) / (1 + bs1 + bs2) | ||
| 364 | // | ||
| 365 | // Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one: | ||
| 366 | // - With rounding to nearest | ||
| 367 | // - With rounding to zero | ||
| 368 | let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first | ||
| 369 | let mut bs2 = bs1_bs2_sum - bs1; | ||
| 370 | core::assert!(bs1_bs2_sum > bs1); | ||
| 371 | |||
| 372 | let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16; | ||
| 373 | if sample_point_permill > MAX_SAMPLE_POINT_PERMILL { | ||
| 374 | // Nope, too far; now rounding to zero | ||
| 375 | bs1 = (7 * bs1_bs2_sum - 1) / 8; | ||
| 376 | bs2 = bs1_bs2_sum - bs1; | ||
| 377 | } | ||
| 378 | |||
| 379 | // Check is BS1 and BS2 are in range | ||
| 380 | if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) { | ||
| 381 | return None; | ||
| 382 | } | ||
| 383 | |||
| 384 | // Check if final bitrate matches the requested | ||
| 385 | if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) { | ||
| 386 | return None; | ||
| 387 | } | ||
| 388 | |||
| 389 | // One is recommended by DS-015, CANOpen, and DeviceNet | ||
| 390 | let sjw = 1; | ||
| 391 | |||
| 392 | // Pack into BTR register values | ||
| 393 | Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1)) | ||
| 394 | } | ||
| 395 | |||
| 396 | /// Split the CAN driver into transmit and receive halves. | 298 | /// Split the CAN driver into transmit and receive halves. |
| 397 | /// | 299 | /// |
| 398 | /// Useful for doing separate transmit/receive tasks. | 300 | /// Useful for doing separate transmit/receive tasks. |
diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs new file mode 100644 index 000000000..36139a45c --- /dev/null +++ b/embassy-stm32/src/can/enums.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | //! Enums shared between CAN controller types. | ||
| 2 | |||
| 3 | /// Bus error | ||
| 4 | #[derive(Debug)] | ||
| 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 6 | pub enum BusError { | ||
| 7 | /// Bit stuffing error - more than 5 equal bits | ||
| 8 | Stuff, | ||
| 9 | /// Form error - A fixed format part of a received message has wrong format | ||
| 10 | Form, | ||
| 11 | /// The message transmitted by the FDCAN was not acknowledged by another node. | ||
| 12 | Acknowledge, | ||
| 13 | /// Bit0Error: During the transmission of a message the device wanted to send a dominant level | ||
| 14 | /// but the monitored bus value was recessive. | ||
| 15 | BitRecessive, | ||
| 16 | /// Bit1Error: During the transmission of a message the device wanted to send a recessive level | ||
| 17 | /// but the monitored bus value was dominant. | ||
| 18 | BitDominant, | ||
| 19 | /// The CRC check sum of a received message was incorrect. The CRC of an | ||
| 20 | /// incoming message does not match with the CRC calculated from the received data. | ||
| 21 | Crc, | ||
| 22 | /// A software error occured | ||
| 23 | Software, | ||
| 24 | /// The FDCAN is in Bus_Off state. | ||
| 25 | BusOff, | ||
| 26 | /// The FDCAN is in the Error_Passive state. | ||
| 27 | BusPassive, | ||
| 28 | /// At least one of error counter has reached the Error_Warning limit of 96. | ||
| 29 | BusWarning, | ||
| 30 | } | ||
diff --git a/embassy-stm32/src/can/util.rs b/embassy-stm32/src/can/util.rs new file mode 100644 index 000000000..fcdbbad62 --- /dev/null +++ b/embassy-stm32/src/can/util.rs | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | //! Utility functions shared between CAN controller types. | ||
| 2 | |||
| 3 | use core::num::{NonZeroU16, NonZeroU8}; | ||
| 4 | |||
| 5 | /// Shared struct to represent bit timings used by calc_can_timings. | ||
| 6 | #[derive(Clone, Copy, Debug)] | ||
| 7 | pub struct NominalBitTiming { | ||
| 8 | /// Value by which the oscillator frequency is divided for generating the bit time quanta. The bit | ||
| 9 | /// time is built up from a multiple of this quanta. Valid values are 1 to 512. | ||
| 10 | pub prescaler: NonZeroU16, | ||
| 11 | /// Valid values are 1 to 128. | ||
| 12 | pub seg1: NonZeroU8, | ||
| 13 | /// Valid values are 1 to 255. | ||
| 14 | pub seg2: NonZeroU8, | ||
| 15 | /// Valid values are 1 to 128. | ||
| 16 | pub sync_jump_width: NonZeroU8, | ||
| 17 | } | ||
| 18 | |||
| 19 | /// Calculate nominal CAN bit timing based on CAN bitrate and periphial clock frequency | ||
| 20 | pub fn calc_can_timings(periph_clock: crate::time::Hertz, can_bitrate: u32) -> Option<NominalBitTiming> { | ||
| 21 | const BS1_MAX: u8 = 16; | ||
| 22 | const BS2_MAX: u8 = 8; | ||
| 23 | const MAX_SAMPLE_POINT_PERMILL: u16 = 900; | ||
| 24 | |||
| 25 | let periph_clock = periph_clock.0; | ||
| 26 | |||
| 27 | if can_bitrate < 1000 { | ||
| 28 | return None; | ||
| 29 | } | ||
| 30 | |||
| 31 | // Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG | ||
| 32 | // CAN in Automation, 2003 | ||
| 33 | // | ||
| 34 | // According to the source, optimal quanta per bit are: | ||
| 35 | // Bitrate Optimal Maximum | ||
| 36 | // 1000 kbps 8 10 | ||
| 37 | // 500 kbps 16 17 | ||
| 38 | // 250 kbps 16 17 | ||
| 39 | // 125 kbps 16 17 | ||
| 40 | let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 }; | ||
| 41 | |||
| 42 | // Computing (prescaler * BS): | ||
| 43 | // BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual | ||
| 44 | // BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified | ||
| 45 | // let: | ||
| 46 | // BS = 1 + BS1 + BS2 -- Number of time quanta per bit | ||
| 47 | // PRESCALER_BS = PRESCALER * BS | ||
| 48 | // ==> | ||
| 49 | // PRESCALER_BS = PCLK / BITRATE | ||
| 50 | let prescaler_bs = periph_clock / can_bitrate; | ||
| 51 | |||
| 52 | // Searching for such prescaler value so that the number of quanta per bit is highest. | ||
| 53 | let mut bs1_bs2_sum = max_quanta_per_bit - 1; | ||
| 54 | while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 { | ||
| 55 | if bs1_bs2_sum <= 2 { | ||
| 56 | return None; // No solution | ||
| 57 | } | ||
| 58 | bs1_bs2_sum -= 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32; | ||
| 62 | if (prescaler < 1) || (prescaler > 1024) { | ||
| 63 | return None; // No solution | ||
| 64 | } | ||
| 65 | |||
| 66 | // Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum. | ||
| 67 | // We need to find such values so that the sample point is as close as possible to the optimal value, | ||
| 68 | // which is 87.5%, which is 7/8. | ||
| 69 | // | ||
| 70 | // Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *) | ||
| 71 | // {{bs2 -> (1 + bs1)/7}} | ||
| 72 | // | ||
| 73 | // Hence: | ||
| 74 | // bs2 = (1 + bs1) / 7 | ||
| 75 | // bs1 = (7 * bs1_bs2_sum - 1) / 8 | ||
| 76 | // | ||
| 77 | // Sample point location can be computed as follows: | ||
| 78 | // Sample point location = (1 + bs1) / (1 + bs1 + bs2) | ||
| 79 | // | ||
| 80 | // Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one: | ||
| 81 | // - With rounding to nearest | ||
| 82 | // - With rounding to zero | ||
| 83 | let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first | ||
| 84 | let mut bs2 = bs1_bs2_sum - bs1; | ||
| 85 | core::assert!(bs1_bs2_sum > bs1); | ||
| 86 | |||
| 87 | let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16; | ||
| 88 | if sample_point_permill > MAX_SAMPLE_POINT_PERMILL { | ||
| 89 | // Nope, too far; now rounding to zero | ||
| 90 | bs1 = (7 * bs1_bs2_sum - 1) / 8; | ||
| 91 | bs2 = bs1_bs2_sum - bs1; | ||
| 92 | } | ||
| 93 | |||
| 94 | // Check is BS1 and BS2 are in range | ||
| 95 | if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) { | ||
| 96 | return None; | ||
| 97 | } | ||
| 98 | |||
| 99 | // Check if final bitrate matches the requested | ||
| 100 | if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) { | ||
| 101 | return None; | ||
| 102 | } | ||
| 103 | |||
| 104 | // One is recommended by DS-015, CANOpen, and DeviceNet | ||
| 105 | let sync_jump_width = core::num::NonZeroU8::new(1)?; | ||
| 106 | |||
| 107 | let seg1 = core::num::NonZeroU8::new(bs1)?; | ||
| 108 | let seg2 = core::num::NonZeroU8::new(bs2)?; | ||
| 109 | let nz_prescaler = core::num::NonZeroU16::new(prescaler as u16)?; | ||
| 110 | |||
| 111 | Some(NominalBitTiming { | ||
| 112 | sync_jump_width, | ||
| 113 | prescaler: nz_prescaler, | ||
| 114 | seg1, | ||
| 115 | seg2, | ||
| 116 | }) | ||
| 117 | } | ||
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index fca364c21..891f0490b 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs | |||
| @@ -3,8 +3,8 @@ use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; | |||
| 3 | use stm32_metapac::FLASH; | 3 | use stm32_metapac::FLASH; |
| 4 | 4 | ||
| 5 | pub use crate::pac::rcc::vals::{ | 5 | pub use crate::pac::rcc::vals::{ |
| 6 | Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, | 6 | Adcsel as AdcClockSource, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, |
| 7 | Pllr as PllR, Ppre as APBPrescaler, | 7 | Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler, |
| 8 | }; | 8 | }; |
| 9 | use crate::pac::{PWR, RCC}; | 9 | use crate::pac::{PWR, RCC}; |
| 10 | use crate::rcc::{set_freqs, Clocks}; | 10 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -87,6 +87,7 @@ pub struct Config { | |||
| 87 | pub clock_48mhz_src: Option<Clock48MhzSrc>, | 87 | pub clock_48mhz_src: Option<Clock48MhzSrc>, |
| 88 | pub adc12_clock_source: AdcClockSource, | 88 | pub adc12_clock_source: AdcClockSource, |
| 89 | pub adc345_clock_source: AdcClockSource, | 89 | pub adc345_clock_source: AdcClockSource, |
| 90 | pub fdcan_clock_source: FdCanClockSource, | ||
| 90 | 91 | ||
| 91 | pub ls: super::LsConfig, | 92 | pub ls: super::LsConfig, |
| 92 | } | 93 | } |
| @@ -104,6 +105,7 @@ impl Default for Config { | |||
| 104 | clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())), | 105 | clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())), |
| 105 | adc12_clock_source: Adcsel::DISABLE, | 106 | adc12_clock_source: Adcsel::DISABLE, |
| 106 | adc345_clock_source: Adcsel::DISABLE, | 107 | adc345_clock_source: Adcsel::DISABLE, |
| 108 | fdcan_clock_source: FdCanClockSource::PCLK1, | ||
| 107 | ls: Default::default(), | 109 | ls: Default::default(), |
| 108 | } | 110 | } |
| 109 | } | 111 | } |
| @@ -282,6 +284,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 282 | 284 | ||
| 283 | RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source)); | 285 | RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source)); |
| 284 | RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source)); | 286 | RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source)); |
| 287 | RCC.ccipr().modify(|w| w.set_fdcansel(config.fdcan_clock_source)); | ||
| 285 | 288 | ||
| 286 | let adc12_ck = match config.adc12_clock_source { | 289 | let adc12_ck = match config.adc12_clock_source { |
| 287 | AdcClockSource::DISABLE => None, | 290 | AdcClockSource::DISABLE => None, |
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 15b51a398..85e12637e 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs | |||
| @@ -6,6 +6,7 @@ use crate::pac::pwr::vals::Vos; | |||
| 6 | pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; | 6 | pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; |
| 7 | #[cfg(stm32h7)] | 7 | #[cfg(stm32h7)] |
| 8 | pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; | 8 | pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; |
| 9 | pub use crate::pac::rcc::vals::Fdcansel as FdCanClockSource; | ||
| 9 | pub use crate::pac::rcc::vals::{ | 10 | pub use crate::pac::rcc::vals::{ |
| 10 | Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, | 11 | Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, |
| 11 | Pllsrc as PllSource, Sw as Sysclk, | 12 | Pllsrc as PllSource, Sw as Sysclk, |
| @@ -212,6 +213,8 @@ pub struct Config { | |||
| 212 | 213 | ||
| 213 | pub per_clock_source: PerClockSource, | 214 | pub per_clock_source: PerClockSource, |
| 214 | pub adc_clock_source: AdcClockSource, | 215 | pub adc_clock_source: AdcClockSource, |
| 216 | pub fdcan_clock_source: FdCanClockSource, | ||
| 217 | |||
| 215 | pub timer_prescaler: TimerPrescaler, | 218 | pub timer_prescaler: TimerPrescaler, |
| 216 | pub voltage_scale: VoltageScale, | 219 | pub voltage_scale: VoltageScale, |
| 217 | pub ls: super::LsConfig, | 220 | pub ls: super::LsConfig, |
| @@ -248,6 +251,8 @@ impl Default for Config { | |||
| 248 | #[cfg(stm32h7)] | 251 | #[cfg(stm32h7)] |
| 249 | adc_clock_source: AdcClockSource::PER, | 252 | adc_clock_source: AdcClockSource::PER, |
| 250 | 253 | ||
| 254 | fdcan_clock_source: FdCanClockSource::from_bits(0), // HSE | ||
| 255 | |||
| 251 | timer_prescaler: TimerPrescaler::DefaultX2, | 256 | timer_prescaler: TimerPrescaler::DefaultX2, |
| 252 | voltage_scale: VoltageScale::Scale0, | 257 | voltage_scale: VoltageScale::Scale0, |
| 253 | ls: Default::default(), | 258 | ls: Default::default(), |
| @@ -585,7 +590,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 585 | 590 | ||
| 586 | RCC.ccipr5().modify(|w| { | 591 | RCC.ccipr5().modify(|w| { |
| 587 | w.set_ckpersel(config.per_clock_source); | 592 | w.set_ckpersel(config.per_clock_source); |
| 588 | w.set_adcdacsel(config.adc_clock_source) | 593 | w.set_adcdacsel(config.adc_clock_source); |
| 594 | w.set_fdcan1sel(config.fdcan_clock_source) | ||
| 589 | }); | 595 | }); |
| 590 | } | 596 | } |
| 591 | 597 | ||
