|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
CAN (Controller Area Network) bit timing: a wanted bit rate turned into segment counts. More...
#include <stdbool.h>#include <stdint.h>Go to the source code of this file.
Data Structures | |
| struct | can_timing_limits_t |
| struct | can_timing_t |
Macros | |
| #define | CAN_SAMPLE_POINT_DEFAULT 875 |
| The sample point CiA (CAN in Automation) recommends for rates above 800kbit/s, in permille. Later is better for propagation delay and worse for oscillator tolerance; 87.5% is the usual compromise. | |
| #define | CAN_SAMPLE_POINT_LINK 750 |
| The sample point this link uses, at both ends. | |
| #define | MCP2515_CNF1 0x2A |
| #define | MCP2515_CNF2 0x29 |
| #define | MCP2515_CNF3 0x28 |
Functions | |
| bool | can_timing_solve (const can_timing_limits_t *lim, uint32_t bitrate, uint16_t target_permille, can_timing_t *out) |
| uint32_t | can_timing_max_bitrate (const can_timing_limits_t *lim) |
| void | can_timing_limits_mcp2515 (can_timing_limits_t *out, uint32_t crystal_hz) |
| void | can_timing_limits_twai (can_timing_limits_t *out) |
| The panel's TWAI on the ESP32-P4, off the 40MHz crystal: even prescalers from 2 to 32768. | |
| bool | mcp2515_encode_timing (const can_timing_t *t, uint8_t cnf[3]) |
CAN (Controller Area Network) bit timing: a wanted bit rate turned into segment counts.
A CAN controller divides its source clock into time quanta and splits each bit into one sync quantum plus two programmable segments. A bit rate that is a fraction of a percent off, or a sample point in the wrong place, works on a short cable with one other node and logs errors when the bus is longer, colder or busier.
The arithmetic is here, in pure C with tests, rather than in a table of register values. Two controllers use it: the panel's TWAI (Two-Wire Automotive Interface, the ESP32-P4's CAN controller) and the IOmcu's XL2515. They have different clocks and segment limits and the same arithmetic.
The rule this module enforces: the bit rate comes out exact. CAN has no framing to resynchronise against beyond its own bit stuffing, and two nodes that disagree by 1% agree on short frames and fail on long ones. A rate that cannot be hit exactly is reported as impossible; an 8MHz crystal cannot make 1Mbit/s.
SPDX-License-Identifier: MIT
| #define CAN_SAMPLE_POINT_LINK 750 |
The sample point this link uses, at both ends.
The IOmcu's XL2515 has one way to make 1Mbit/s from a 16MHz crystal: the smallest divisor and 8 quanta per bit, the fewest a bit may have, which puts the sample point at 75%. The panel has slack and matches the IOmcu, so both ends sample the bit in the same place.
| void can_timing_limits_mcp2515 | ( | can_timing_limits_t * | out, |
| uint32_t | crystal_hz ) |
The IOmcu's XL2515 (MCP2515-compatible), given its crystal.
| void can_timing_limits_twai | ( | can_timing_limits_t * | out | ) |
The panel's TWAI on the ESP32-P4, off the 40MHz crystal: even prescalers from 2 to 32768.
| out | Filled with the limits; NULL is ignored. |
| uint32_t can_timing_max_bitrate | ( | const can_timing_limits_t * | lim | ) |
The highest rate this controller can reach exactly, or 0 if none.
| bool can_timing_solve | ( | const can_timing_limits_t * | lim, |
| uint32_t | bitrate, | ||
| uint16_t | target_permille, | ||
| can_timing_t * | out ) |
Solve for the segmentation closest to target_permille that hits bitrate exactly.
False when no combination does, which means the source clock cannot make the rate.
| bool mcp2515_encode_timing | ( | const can_timing_t * | t, |
| uint8_t | cnf[3] ) |
Encode a solution into CNF1..CNF3.
cnf receives three bytes in register order CNF1, CNF2, CNF3.
tseg1 is split into propagation and phase-1 segments here, because that split is the MCP2515's business: both are 1..8 quanta, and the bus does not care where the boundary falls. Returns false if the solution cannot be expressed; a tseg1 of 17 or more has no legal split.