Re: sjw in can_calc_bittiming

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

Am 02.11.21 um 16:36 schrieb Oliver Hartkopp:
> Hi Matthias,
> 
> On 02.11.21 16:03, Matthias Weißer wrote:
> 
>> we recently had a case here where one member of a CAN bus couldn't
>> receive
>> frames with data content of only zeros:
>>
>> $ cansend can0 123#0000000000000000
>>
>> After some investigation we found the root cause to be a slight
>> difference
>> (about 1%) in actual bitrates of the two members. The one with showed the
>> RX errors had a sjw value of 1 and a lot of time quanta (40) due to
>> the 40MHz
>> CAN clock.
>>
>> This leads to a build up of phase error (as sjw is not able to
>> compensate for
>> enough of the bitrate difference) which at some point leads to a framing
>> error due to missing a stuff bit. Playing around with the sample point
>> can
>> improve or worsen the behavior.
>>
>> We can fix this quite easily by specifying a higher sjw value.
> 
> You can specify the sjw value with the ip command (for CAN FD there is
> also a dsjw). And IIRC you can set it to the max. value for your CAN
> controller if you define sjw to be 4.
> 
> Best regards,
> Oliver
> 
> $ ip link help can
> Usage: ip link set DEVICE type can
>     [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
>     [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
>        phase-seg2 PHASE-SEG2 [ sjw SJW ] ]

This usage description is not totally correct! It is also possible, to
increase "sjw" together with the bitrate, e.g.:

  # ip link set can0 type can bitrate 250000 sjw 2
  # ip -d link show can0 | grep sjw
      tq 250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 2
  
Here is the code for it:

  # cat dev.c
  ...
        /* check for sjw user settings */
        if (!bt->sjw || !btc->sjw_max) {
                bt->sjw = 1;
        } else {
                /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
                if (bt->sjw > btc->sjw_max)
                        bt->sjw = btc->sjw_max;
                /* bt->sjw must not be higher than tseg2 */
                if (tseg2 < bt->sjw)
                        bt->sjw = tseg2;
        }

Wolfgang



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux