Skip to content

Commit

Permalink
rework Exact setting
Browse files Browse the repository at this point in the history
  • Loading branch information
playfulFence committed Feb 4, 2025
1 parent 8fb6c69 commit 46bd259
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 12 deletions.
12 changes: 8 additions & 4 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down Expand Up @@ -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)
}
Expand Down
55 changes: 47 additions & 8 deletions esp-hal/src/uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 46bd259

Please sign in to comment.