The can_calc_timing_internal() function currently requires
core_clock % (prescaler * bitrate) == 0, i.e. an exact integer
number of time quanta. This silently skips every candidate
prescaler when the CAN module clock is not an exact integer
multiple of the requested bitrate, causing can_calc_timing() and
can_set_bitrate() to return -ENOTSUP even for standard CAN bitrates
(125k, 250k, 500k, 1M bps) on hardware with PLL- or FLL-derived
clocks.
Observed on: NXP MKV58F (Kinetis KV58, 120 MHz CAN clock from PLL),
and reproducible on other SoC families where the CAN peripheral
clock is indirectly derived from the system PLL.
Changes:
- Replace the exact-divisibility test with nearest-integer rounding
for total_tq, using 64-bit intermediate arithmetic to avoid
overflow.
- Compute the actual achievable bitrate for every (prescaler,
total_tq) candidate and accept it only when the deviation from the
requested rate is within 5000 ppm (0.5%, well inside the CiA 601
1.58% nominal tolerance).
- Add explicit tq_min/tq_max bounds derived from the hardware segment
limits so that prescalers yielding an unrealisable total_tq are
still skipped efficiently.
- Tighten the early-exit condition: break only when both the sample
point error is zero AND the achievable bitrate equals the requested
bitrate exactly (previously, a zero sample-point error alone
stopped the search even when the bitrate had rounding error).
- Minor: add 'U' suffix on the /2 in the SJW default calculation and
parenthesise the ternary in the return statement.
Signed-off-by: Tristen Pierson <tpierson@bitconcepts.tech>
Summary
can_calc_timing_internal()requirescore_clock % (prescaler * bitrate) == 0— an exact integer number of time quanta — before it will evaluate a prescaler candidate. On SoCs whose CAN peripheral clock is derived from a PLL or FLL (rather than a clean integer divisor of the system clock), this condition is never satisfied for any prescaler and the function returns-ENOTSUP, makingcan_calc_timing()andcan_set_bitrate()fail for all standard bitrates.Root Cause
When
core_clockis, e.g., 120 000 000 Hz (NXP MKV58F / Kinetis KV58 CAN clock from a 180 MHz PLL):core_clock % (p*br)Those examples happen to divide cleanly. A board where the CAN clock is not a nice multiple (e.g. 100 031 232 Hz from a multiply/divide PLL chain) will fail for every prescaler.
Fix
Replace the exact-divisibility test with nearest-integer rounding for
total_tq, then verify the resulting bitrate deviation against a 5000 ppm (0.5%) tolerance — well within the CiA 601 nominal limit of 1.58%:Additional changes in the same commit:
tq_min/tq_maxbounds (derived from segment limits) so that prescalers yielding an unrealisabletotal_tqare still efficiently skipped.real_bitrate == bitrateexactly (the previous code broke on zero SP error even if the bitrate had a rounding remainder).prescaler * bitrate.Usuffix on/2in SJW calculation; parenthesise ternary inreturn.Testing
Verified on:
Before:
can_set_bitrate(500k)→-ENOTSUP.After: timing selected (prescaler=12, seg1S1=6, seg2=2, sample-point err=9‰).
core_clockis an exact multiple of the bitrate is preserved; nearest-integer rounding on a value that is already an integer is identical to integer division.Related
can_calc_timing_internal()specifically.