Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mcan/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Tagging in git follows a pattern: `mcan/<version>`.

## [Unreleased]
- Added support for fractional baudrates (#59)

## [0.7.0] - 2025-04-23

Expand Down
35 changes: 25 additions & 10 deletions mcan/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,30 @@ pub struct BitTiming {
/// MCAN peripheral is divisible into time quanta such that the bit time
/// determined by `phase_seg_1` and `phase_seg_2` is a whole number of time
/// quanta.
///
/// When [`Self::allow_fractional`] is selected, the real bitrate
/// is allowed to be up to 0.05% off (Which is within tolerance)
pub bitrate: HertzU32,
/// Allows for fractional bitrates where there may be no perfect
/// combination of bit-timing parameters. This is useful for bitrates
/// like 83.3kbps where some tolerance is allowed (Up to 0.05%).
pub allow_fractional: bool,
}

impl BitTiming {
/// Create an instance
///
/// Nominal bitrate value must be provided, all other settings come
/// pre-populated with default values.
/// pre-populated with default values. No fractional bitrates
/// are allowed.
pub fn new(bitrate: HertzU32) -> Self {
Self {
// Note: SWJ and {N,D}TSEG{1,2} defaults come from reset values
sjw: 0x4,
phase_seg_1: 0xB,
phase_seg_2: 0x4,
bitrate,
allow_fractional: false,
}
}
}
Expand Down Expand Up @@ -199,19 +208,25 @@ impl BitTiming {
let f_out = self.bitrate;
let bit_time_quanta = self.time_quanta_per_bit();
let f_q = f_out * bit_time_quanta;
if let Some(0) = f_can.to_Hz().checked_rem(f_q.to_Hz()) {
let prescaler = f_can / f_q;
if !valid.prescaler.contains(&prescaler) {
Err(BitTimingError::PrescalerOutOfRange(valid.prescaler.clone()))
} else {
Ok(prescaler as u16)
}
let max_tolerance = if self.allow_fractional {
self.bitrate.to_Hz() / 2000 // 0.05% tolerance
} else {
Err(BitTimingError::NoValidPrescaler {
0
};
match f_can.to_Hz().checked_rem(f_q.to_Hz()) {
Some(x) if x <= max_tolerance => {
let prescaler = f_can / f_q;
if !valid.prescaler.contains(&prescaler) {
Err(BitTimingError::PrescalerOutOfRange(valid.prescaler.clone()))
} else {
Ok(prescaler as u16)
}
}
_ => Err(BitTimingError::NoValidPrescaler {
can_clock: f_can,
bitrate: f_out,
bit_time_quanta,
})
}),
}
}
}
Expand Down
Loading