diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 1fbb3883b1..6f3672c3c1 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -635,8 +635,8 @@ impl Config { } fn validate(&self) -> Result<(), ConfigError> { - // Max supported frequency is 80Mhz - if self.frequency > HertzU32::MHz(80) { + // Maximum supported frequency is 80Mhz, minimum is about 70khz. + if self.frequency < HertzU32::kHz(70) || self.frequency > HertzU32::MHz(80) { return Err(ConfigError::UnsupportedFrequency); } Ok(()) @@ -1056,8 +1056,12 @@ where /// Change the bus configuration. /// /// # Errors. - /// If frequency passed in config exceeds 80Mhz, a corresponding - /// [`ConfigError`] variant will be returned. + /// If frequency passed in config exceeds 80Mhz or is below 70kHz, a + /// corresponding [`ConfigError`] variant will be returned. If the user + /// has specified in the configuration that they want frequency to + /// correspond exactly or with some percentage of deviation to the + /// desired value, and the driver cannot reach this speed - an error + /// will also be returned. pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { self.driver().apply_config(config) } diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index c2d2349252..bd8b545076 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -272,7 +272,8 @@ pub enum BaudrateTolerance { /// Accept the closest achievable baud rate without restriction. #[default] Closest, - /// Require an exact match, otherwise return an error. + /// In this setting, the deviation of only 1% from the desired baud value is + /// tolerated. Exact, /// Allow a certain percentage of deviation. ErrorPercent(u8), @@ -288,6 +289,7 @@ pub struct Config { baudrate: u32, /// Determines how close to the desired baud rate value the driver should /// set the baud rate. + #[builder_lite(skip_setter)] baudrate_tolerance: BaudrateTolerance, /// Number of data bits in each frame (5, 6, 7, or 8 bits). data_bits: DataBits, @@ -346,6 +348,19 @@ impl Default for RxConfig { } impl Config { + /// Set the baudrate tolerance of the UART configuration. + pub fn with_baudrate_tolerance(mut self, tolerance: BaudrateTolerance) -> Self { + self.baudrate_tolerance = match tolerance { + BaudrateTolerance::Exact => BaudrateTolerance::Exact, + BaudrateTolerance::Closest => BaudrateTolerance::Closest, + BaudrateTolerance::ErrorPercent(percentage) => { + assert!(percentage > 0 && percentage <= 100); + BaudrateTolerance::ErrorPercent(percentage) + } + }; + + self + } /// Calculates the total symbol length in bits based on the configured /// data bits, parity, and stop bits. fn symbol_length(&self) -> u8 { @@ -1214,7 +1229,10 @@ where /// # Errors. /// Errors will be returned in the cases described in /// [`UartRx::apply_config`] and if baud rate passed in config exceeds - /// 5MBaud or is equal to zero. + /// 5MBaud or is equal to zero. If the user has specified in the + /// configuration that they want baudrate to correspond exactly or with some + /// percentage of deviation to the desired value, and the driver cannot + /// reach this speed - an error will also be returned. pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { self.rx.apply_config(config)?; self.tx.apply_config(config)?; @@ -2459,8 +2477,15 @@ impl Info { let actual_baud = self.get_baudrate(clk); match config.baudrate_tolerance { - BaudrateTolerance::Exact if actual_baud != config.baudrate => { - return Err(ConfigError::UnachievableBaudrate) + BaudrateTolerance::Exact => { + let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs() + * 100) + / actual_baud as u64; + // We tolerate deviation of 1% from the desired baud value, as it never will be + // exactly the same + if deviation > 1 as u64 { + return Err(ConfigError::UnachievableBaudrate); + } } BaudrateTolerance::ErrorPercent(percent) => { let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs() @@ -2544,8 +2569,15 @@ impl Info { let actual_baud = self.get_baudrate(clk); match config.baudrate_tolerance { - BaudrateTolerance::Exact if actual_baud != config.baudrate => { - return Err(ConfigError::UnachievableBaudrate) + BaudrateTolerance::Exact => { + let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs() + * 100) + / actual_baud as u64; + // We tolerate deviation of 1% from the desired baud value, as it never will be + // exactly the same + if deviation > 1 as u64 { + return Err(ConfigError::UnachievableBaudrate); + } } BaudrateTolerance::ErrorPercent(percent) => { let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs() @@ -2583,8 +2615,15 @@ impl Info { let actual_baud = self.get_baudrate(clk); match config.baudrate_tolerance { - BaudrateTolerance::Exact if actual_baud != config.baudrate => { - return Err(ConfigError::UnachievableBaudrate) + BaudrateTolerance::Exact => { + let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs() + * 100) + / actual_baud as u64; + // We tolerate deviation of 1% from the desired baud value, as it never will be + // exactly the same + if deviation > 1 as u64 { + return Err(ConfigError::UnachievableBaudrate); + } } BaudrateTolerance::ErrorPercent(percent) => { let deviation = ((config.baudrate as i64 - actual_baud as i64).unsigned_abs()