Skip to content
Open
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
32 changes: 20 additions & 12 deletions sys/can/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#ifdef MODULE_FDCAN
/**
* The loop delay in CAN, especially in CAN FD with bitrate switching, affects synchronization due to increased data rates.

Check warning on line 40 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* The unit is nanoseconds.
*/
#ifndef CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY
#error "CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY must be defined. This property can be found in the datasheet of the CAN transceiver in use. The unit is nanoseconds."

Check warning on line 44 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
#endif /* CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY */
#endif /* MODULE_FDCAN */

Expand Down Expand Up @@ -187,7 +187,7 @@
}

if (candev_dev->last_pm_update == 0 ||
value > (candev_dev->last_pm_value - (ztimer_now(ZTIMER_USEC) - candev_dev->last_pm_update))) {

Check warning on line 190 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
candev_dev->last_pm_value = value;
candev_dev->last_pm_update = ztimer_now(ZTIMER_USEC);
ztimer_set(ZTIMER_USEC, &candev_dev->pm_timer, value);
Expand Down Expand Up @@ -424,7 +424,7 @@
* @return the computed sample point from @p tseg1 and @p tseg2
*/
static uint32_t update_sample_point(const struct can_bittiming_const *btc, uint32_t spt_nominal,
uint32_t tseg, uint32_t *p_tseg1, uint32_t *p_tseg2, uint32_t *p_spt_error)

Check warning on line 427 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
{
uint32_t best_spt = 0;
uint32_t min_spt_error = UINT32_MAX;
Expand Down Expand Up @@ -537,7 +537,7 @@
uint32_t rate = clock / (brp * nbt);
rate_error = max(timing->bitrate, rate) - min(timing->bitrate, rate);
if (rate_error > min_rate_error) {
DEBUG("timing->rate=%" PRIu32 ", rate=%" PRIu32 ", rate_error=%" PRIu32 " > min_rate_error=%" PRIu32 ", continuing\n",

Check warning on line 540 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
timing->bitrate, rate, rate_error, min_rate_error);
continue;
}
Expand Down Expand Up @@ -565,7 +565,7 @@
}
}

DEBUG("computed values: min_rate_error=%" PRIu32 ", min_spt_error=%" PRIu32 "\n", min_rate_error, min_spt_error);

Check warning on line 568 in sys/can/device.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

if (min_rate_error) {
rate_error = min_rate_error * 1000 / timing->bitrate;
Expand All @@ -581,25 +581,33 @@
timing->phase_seg1 = tseg1 - timing->prop_seg;
timing->phase_seg2 = tseg2;

if (!timing->sjw || !timing_const->sjw_max) {
timing->sjw = SJW;
}
else {
if (timing->sjw > timing_const->sjw_max) {
timing->sjw = timing_const->sjw_max;
/* this paper http://www.oertel-halle.de/files/cia99paper.pdf might help to understand SJW */
if (!timing->sjw) {
if (!timing_const->sjw_max) {
/* fallback if no device max value is known */
timing->sjw = SJW;
}
if (timing->sjw > tseg2) {
timing->sjw = tseg2;
else {
/* try to find the max_value start at max */
timing->sjw = timing_const->sjw_max;
}
}

if (timing->sjw > timing->phase_seg2) {
/* SJW shall not be bigger than phase segment 1 */
timing->sjw = timing->phase_seg2;
}
if (timing->sjw > timing->phase_seg1) {
/* SJW shall not be bigger than phase segment 1 */
timing->sjw = timing->phase_seg1;
}
timing->brp = best_brp;

timing->bitrate = clock / (timing->brp * (CAN_SYNC_SEG + tseg1 + tseg2));

DEBUG("bitrate=%" PRIu32 ", sample_point=%" PRIu32 ", brp=%" PRIu32 ", prop_seg=%" PRIu32
", phase_seg1=%" PRIu32 ", phase_seg2=%" PRIu32 "\n", timing->bitrate, timing->sample_point,
timing->brp, timing->prop_seg, timing->phase_seg1, timing->phase_seg2);
DEBUG("clock=%" PRIu32 ", bitrate=%" PRIu32 ", sample_point=%" PRIu32 ", brp=%" PRIu32
", prop_seg=%" PRIu32", phase_seg1=%" PRIu32 ", phase_seg2=%" PRIu32", sjw=%" PRIu32 "\n",
clock, timing->bitrate, timing->sample_point, timing->brp,
timing->prop_seg, timing->phase_seg1, timing->phase_seg2, timing->sjw);

return 0;
}