Skip to content

Commit

Permalink
HAL_ChibiOS: fixed CANFD timings
Browse files Browse the repository at this point in the history
our CANFD timings were resulting in a lot of busoff errors. Here is an
example of master at 1Mbit/5MBit:

Getting @SYS/can0_stats.txt as -
------- Clock Config -------
CAN_CLK_FREQ:   80MHz
Std Timings: bitrate=1000000 presc=7
sjw=0 bs1=7 bs2=0 sample_point=90.00000%
FD Timings:  bitrate=5000000 presc=1
sjw=0 bs1=5 bs2=0 sample_point=90.00000%
------- CAN Interface Stats -------
tx_requests:    2689
tx_rejected:    0
tx_overflow:    443
tx_success:     7
tx_timedout:    2232
tx_abort:       0
rx_received:    18470
rx_overflow:    0
rx_errors:      0
num_busoff_err: 34439
num_events:     18477
ECR:            F8
fdf_rx:         18467
fdf_tx_req:     2182
fdf_tx:         0

here is an example with the new timings:

------- Clock Config -------
CAN_CLK_FREQ:   80MHz
Std Timings: bitrate=1000000 presc=8
sjw=1 bs1=8 bs2=1 sample_point=90.00000%
FD Timings:  bitrate=8000000 presc=2
sjw=3 bs1=8 bs2=3 sample_point=80.00000%
------- CAN Interface Stats -------
tx_requests:    3023
tx_rejected:    0
tx_overflow:    0
tx_success:     3023
tx_timedout:    0
tx_abort:       0
rx_received:    27865
rx_overflow:    0
rx_errors:      0
num_busoff_err: 0
num_events:     30888
ECR:            0
fdf_rx:         27862
fdf_tx_req:     3016
fdf_tx:         3016

I am testing between a CubeOrange and a Pixhawk6X. I tested 1, 2, 4, 5
and 8 MBit (which are the only valid FD bitrates in our parameters)

Many thanks to Kai from Salient Motion for finding this issue and
providing the corrected timing table
  • Loading branch information
tridge committed Jan 22, 2024
1 parent 0c943ca commit fc0a3fb
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 15 deletions.
62 changes: 48 additions & 14 deletions libraries/AP_HAL_ChibiOS/CANFDIface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void CANIface::handleBusOffInterrupt()
_detected_bus_off = true;
}

bool CANIface::computeTimings(const uint32_t target_bitrate, Timings& out_timings)
bool CANIface::computeTimings(const uint32_t target_bitrate, Timings& out_timings) const
{
if (target_bitrate < 1) {
return false;
Expand Down Expand Up @@ -316,13 +316,46 @@ bool CANIface::computeTimings(const uint32_t target_bitrate, Timings& out_timing
}

out_timings.sample_point_permill = solution.sample_point_permill;
out_timings.prescaler = uint16_t(prescaler - 1U);
out_timings.sjw = 0; // Which means one
out_timings.bs1 = uint8_t(solution.bs1 - 1);
out_timings.bs2 = uint8_t(solution.bs2 - 1);
out_timings.prescaler = uint16_t(prescaler);
out_timings.sjw = 1;
out_timings.bs1 = uint8_t(solution.bs1);
out_timings.bs2 = uint8_t(solution.bs2);
return true;
}

/*
table driven timings for CANFD
*/
bool CANIface::computeFDTimings(const uint32_t target_bitrate, Timings& out_timings) const
{
static const struct {
uint8_t bitrate_mbaud;
uint8_t prescaler;
uint8_t bs1;
uint8_t bs2;
uint8_t sjw;
uint8_t sample_point_pct;
} CANFD_timings[] {
{ 1, 5, 15, 6, 6, 75},
{ 2, 3, 15, 6, 6, 75},
{ 4, 2, 15, 6, 6, 75},
{ 5, 2, 12, 5, 5, 75},
{ 8, 2, 8, 3, 3, 80},
};
for (const auto &t : CANFD_timings) {
if (t.bitrate_mbaud*1000U*1000U == target_bitrate) {
// out_timings has the register bits, which are the actual value minus 1
out_timings.prescaler = t.prescaler;
out_timings.bs1 = t.bs1;
out_timings.bs2 = t.bs2;
out_timings.sjw = t.sjw;
out_timings.sample_point_permill = t.sample_point_pct*10;
return true;
}
}
return false;
}

int16_t CANIface::send(const AP_HAL::CANFrame& frame, uint64_t tx_deadline,
CanIOFlags flags)
{
Expand Down Expand Up @@ -666,13 +699,13 @@ bool CANIface::init(const uint32_t bitrate, const uint32_t fdbitrate, const Oper
unsigned(timings.prescaler), unsigned(timings.sjw), unsigned(timings.bs1), unsigned(timings.bs2));

//setup timing register
can_->NBTP = ((timings.sjw << FDCAN_NBTP_NSJW_Pos) |
(timings.bs1 << FDCAN_NBTP_NTSEG1_Pos) |
(timings.bs2 << FDCAN_NBTP_NTSEG2_Pos) |
(timings.prescaler << FDCAN_NBTP_NBRP_Pos));
can_->NBTP = (((timings.sjw-1) << FDCAN_NBTP_NSJW_Pos) |
((timings.bs1-1) << FDCAN_NBTP_NTSEG1_Pos) |
((timings.bs2-1) << FDCAN_NBTP_NTSEG2_Pos) |
((timings.prescaler-1) << FDCAN_NBTP_NBRP_Pos));

if (fdbitrate) {
if (!computeTimings(fdbitrate, fdtimings)) {
if (!computeFDTimings(fdbitrate, fdtimings)) {
can_->CCCR &= ~FDCAN_CCCR_INIT;
uint32_t while_start_ms = AP_HAL::millis();
while ((can_->CCCR & FDCAN_CCCR_INIT) == 1) {
Expand All @@ -685,9 +718,10 @@ bool CANIface::init(const uint32_t bitrate, const uint32_t fdbitrate, const Oper
_fdbitrate = fdbitrate;
Debug("CANFD Timings: presc=%u bs1=%u bs2=%u\n",
unsigned(fdtimings.prescaler), unsigned(fdtimings.bs1), unsigned(fdtimings.bs2));
can_->DBTP = ((fdtimings.bs1 << FDCAN_DBTP_DTSEG1_Pos) |
(fdtimings.bs2 << FDCAN_DBTP_DTSEG2_Pos) |
(fdtimings.prescaler << FDCAN_DBTP_DBRP_Pos));
can_->DBTP = (((fdtimings.bs1-1) << FDCAN_DBTP_DTSEG1_Pos) |
((fdtimings.bs2-1) << FDCAN_DBTP_DTSEG2_Pos) |
((fdtimings.prescaler-1) << FDCAN_DBTP_DBRP_Pos) |
((fdtimings.sjw-1) << FDCAN_DBTP_DSJW_Pos));
}

//RX Config
Expand Down Expand Up @@ -1111,7 +1145,7 @@ void CANIface::get_stats(ExpandingString &str)
unsigned(timings.bs2), timings.sample_point_permill/10.0f,
_fdbitrate, unsigned(fdtimings.prescaler),
unsigned(fdtimings.sjw), unsigned(fdtimings.bs1),
unsigned(fdtimings.bs2), timings.sample_point_permill/10.0f,
unsigned(fdtimings.bs2), fdtimings.sample_point_permill/10.0f,
stats.tx_requests,
stats.tx_rejected,
stats.tx_overflow,
Expand Down
3 changes: 2 additions & 1 deletion libraries/AP_HAL_ChibiOS/CANFDIface.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class ChibiOS::CANIface : public AP_HAL::CANIface

const uint8_t self_index_;

bool computeTimings(uint32_t target_bitrate, Timings& out_timings);
bool computeTimings(uint32_t target_bitrate, Timings& out_timings) const;
bool computeFDTimings(uint32_t target_bitrate, Timings& out_timings) const;

void setupMessageRam(void);

Expand Down

0 comments on commit fc0a3fb

Please sign in to comment.