Calculate CAN bit timing parameters
Calculate CAN bit timing parameters


TSYNC_SEG === 1
TSEG1 = Prop_Seg + Phase_Seg1
TSEG2 = Phase_Seg2
TBit = TSYNC_SEG + TSEG1 + TSEG2
( TBit - TSEG2 ) / TBit = Sample Point







A detailed description about setting the correct CAN bit timing is given in a paper
by Florian Hartwich and Armin Bassemir by Robert Bosch:
The Configuration of the CAN Bit Timing.
Basically the CAN bit period can be subdivided into four time segments.
Each time segment consists of a number of Time Quanta (tq). The Time Quanta is the smallest time unit for all configuration values.
- SYNC_SEG is 1 Time Quantum long. It is used to synchronize the various bus nodes.
- PROP_SEG is programmable to be 1, 2,... 8 Time Quanta long.
It is used to compensate for signal delays across the network. - PHASE_SEG1 is programmable to be 1,2, ... 8 Time Quanta long.
It is used to compensate for edge phase errors and may be lengthened during resynchronization. - PHASE_SEG2 is the maximum of PHASE_SEG1 and the Information Processing Time long.
It is also used to compensate edge phase errors and may be shortened during resynchronization.
For this the minimum value of PHASE_SEG2 is the value of SJW. - Information Processing Time is less than or equal to 2 Time Quanta long.
- The total number of Time Quanta has to be from 8 to 25.
(Newer CAN controllers might allow other ranges. Check e.g. the BOSCH M_CAN. - The SJW ist not calculated by the tool. Values are always zero, which means the Synchronization Jump Width is 1 tq.
- SAM or (SAMP) determines the number of CAN bus samples taken per bit time. and sometimes offered to be configured



Programming of the Sample Point allows optimizing the Bit Timing:
A late sampling for example allows a maximum bus length.
an early sampling allows slower rising and falling edges.





Step-by-Step Calculation of Bit Timing Parameters




The following steps provide a method for determining the optimum bit timing parameters which satisfy the requirements for proper bit sampling.
Step 1:
Determine minimum permissible time for the PROP_SEG segment.
Obtain the maximum propagation delay of the physical interface
for both the transmitter and the receiver from the manufacturers data sheet.
Calculate the propagation delay of the bus by multiplying the maximum length of the bus
by the signal propagation delay of the bus cable.
Use these values to calculate tPROP_SEG using equation (8).
Step 2:
Choose CAN System Clock Frequency As the CAN system clock is derived from the MCU system clock or oscillator,
the possible CAN system clock frequencies will be limited to whole fractions of the MCU system clock or oscillator by the prescaler.
The CAN system clock is chosen so that the desired CAN bus Nominal Bit Time (NBT)
is an integer number of time quanta (CAN system clock periods) from 8 to 25.
Step 3:
Calculate PROP_SEG duration. From equation (9), the number of time quanta required for the PROP_SEG segment are calculated.
If the result is greater than 8, go back to Step 2 and choose a lower CAN system clock frequency.
Step 4:
Determine PHASE_SEG1, PHASE_SEG2 From the number of time quanta per bit obtained in Step 2,
subtract the PROP_SEG value calculated in Step 3 and subtract 1 tQ for SYNC_SEG.
If the remaining number is less than 3 then go back to Step 2 and select a higher CAN system clock frequency.
If the remaining number is an odd number greater than 3 then add one to the PROP_SEG value and recalculate.
If the remaining number is equal to 3 then PHASE_SEG1 = 1 and PHASE_SEG2 = 2
and only one sample per bit may be chosen.
Otherwise divide the remaining number by two and assign the result to PHASE_SEG1 and PHASE_SEG2.
Step 5:
Determine RJW RJW is chosen as the smaller of 4 and PHASE_SEG1
Step 6:
Calculate required oscillator tolerance from equations (10) and (11).
In the case of PHASE_SEG1 > 4 tQ, it is recommended to repeat steps 2 to 6 with a larger value for the prescaler,
i.e. smaller TQ period, as this may result in a reduced oscillator tolerance requirement.
Conversely, if PHASE_SEG1 < 4 tQ, it is recommended to repeat steps 2 to 6 with a smaller value for the prescaler,
as long as PROP_SEG ð 8, as this may result in a reduced oscillator tolerance requirement.
If the prescaler is already equal to 1 and a reduced oscillator tolerance is still required,
the only option is to consider using a higher frequency for the prescaler clock source.






ST Microelectronics bxCAN
The bXCAN module is used in the very popular Cortex M3 family STM32.
All relevant parameters are concentrated in one CAN bit timing register (CAN_BTR).
The bit timing pre-scaler is 10 bit wide and can divide by 1 to 1024.
Use the table calculated value of BTR and add all additional bits according your requirements to get the final value for CAN_BTR.

Clock Rate : 8 MHz, Sample Point : 87.5%, SJW : 1
Type: bxCAN, Clock: 8, max brp: 1024, SP: 87.5, min tq: 8, max tq: 25, FD factor: undefined, SJW: 1
Yellow background rows are settings with an bittime consisting of 16 time quanta tq.
At the time this tool was first developed, this seems to be the best value.
In these days where we talk about CAN FD, as much as possible tq should be used to construct an bit time.
| Bit Rate | accuracy | Pre-scaler | Number of time quanta | Seg 1 (Prop_Seg+Phase_Seg1) | Seg 2 | Sample Point at | Register CAN_BTR |
| 1000 | 0.00 | 1 | 8 | 6 | 1 | 87.5 | 0x00050000 |
| 800 | 0.00 | 1 | 10 | 8 | 1 | 90.0 | 0x00070000 |
| 500 | 0.00 | 1 | 16 | 13 | 2 | 87.5 | 0x001c0000 |
| 500 | 0.00 | 2 | 8 | 6 | 1 | 87.5 | 0x00050001 |
| 250 | 0.00 | 2 | 16 | 13 | 2 | 87.5 | 0x001c0001 |
| 250 | 0.00 | 4 | 8 | 6 | 1 | 87.5 | 0x00050003 |
| 125 | 0.00 | 4 | 16 | 13 | 2 | 87.5 | 0x001c0003 |
| 125 | 0.00 | 8 | 8 | 6 | 1 | 87.5 | 0x00050007 |
| 100 | 0.00 | 4 | 20 | 17 | 2 | 90.0 | 0x00100003 |
| 100 | 0.00 | 5 | 16 | 13 | 2 | 87.5 | 0x001c0004 |
| 100 | 0.00 | 8 | 10 | 8 | 1 | 90.0 | 0x00070007 |
| 100 | 0.00 | 10 | 8 | 6 | 1 | 87.5 | 0x00050009 |
| 83.333 | 0.00 | 4 | 24 | 20 | 3 | 87.5 | 0x00330003 |
| 83.333 | 0.00 | 6 | 16 | 13 | 2 | 87.5 | 0x001c0005 |
| 83.333 | 0.00 | 8 | 12 | 10 | 1 | 91.7 | 0x00090007 |
| 83.333 | 0.00 | 12 | 8 | 6 | 1 | 87.5 | 0x0005000b |
| 50 | 0.00 | 8 | 20 | 17 | 2 | 90.0 | 0x00100007 |
| 50 | 0.00 | 10 | 16 | 13 | 2 | 87.5 | 0x001c0009 |
| 50 | 0.00 | 16 | 10 | 8 | 1 | 90.0 | 0x0007000f |
| 50 | 0.00 | 20 | 8 | 6 | 1 | 87.5 | 0x00050013 |
| 20 | 0.00 | 16 | 25 | 21 | 3 | 88.0 | 0x0034000f |
| 20 | 0.00 | 20 | 20 | 17 | 2 | 90.0 | 0x00100013 |
| 20 | 0.00 | 25 | 16 | 13 | 2 | 87.5 | 0x001c0018 |
| 20 | 0.00 | 40 | 10 | 8 | 1 | 90.0 | 0x00070027 |
| 20 | 0.00 | 50 | 8 | 6 | 1 | 87.5 | 0x00050031 |
| 10 | 0.00 | 32 | 25 | 21 | 3 | 88.0 | 0x0034001f |
| 10 | 0.00 | 40 | 20 | 17 | 2 | 90.0 | 0x00100027 |
| 10 | 0.00 | 50 | 16 | 13 | 2 | 87.5 | 0x001c0031 |
| 10 | 0.00 | 80 | 10 | 8 | 1 | 90.0 | 0x0007004f |
| 10 | 0.00 | 100 | 8 | 6 | 1 | 87.5 | 0x00050063 |
CAN Bus Bit Timing Calculator
The following bus parameters are allowed, assuming
- your CAN controller is clocked with 16 MHz,
- you want a CAN bus bit rate of 250 kbps,
- settings leading to speed deviations of more than 0% are discarded.
- SJA1000/82C200 CAN Controller
| T1 | T2 | BTQ | SP% | SJW | Bit Rate | Err% | BTR0 | BTR1 |
| 8 | 8 | 16 | 50 | 1 | 250 | 0 | 01 | 76 |
| 8 | 8 | 16 | 50 | 2 | 250 | 0 | 41 | 76 |
| 8 | 8 | 16 | 50 | 3 | 250 | 0 | 81 | 76 |
| 8 | 8 | 16 | 50 | 4 | 250 | 0 | c1 | 76 |
| 9 | 7 | 16 | 56.25 | 1 | 250 | 0 | 01 | 67 |
| 9 | 7 | 16 | 56.25 | 2 | 250 | 0 | 41 | 67 |
| 9 | 7 | 16 | 56.25 | 3 | 250 | 0 | 81 | 67 |
| 9 | 7 | 16 | 56.25 | 4 | 250 | 0 | c1 | 67 |
| 10 | 6 | 16 | 62.5 | 1 | 250 | 0 | 01 | 58 |
| 10 | 6 | 16 | 62.5 | 2 | 250 | 0 | 41 | 58 |
| 10 | 6 | 16 | 62.5 | 3 | 250 | 0 | 81 | 58 |
| 10 | 6 | 16 | 62.5 | 4 | 250 | 0 | c1 | 58 |
| 11 | 5 | 16 | 68.75 | 1 | 250 | 0 | 01 | 49 |
| 11 | 5 | 16 | 68.75 | 2 | 250 | 0 | 41 | 49 |
| 11 | 5 | 16 | 68.75 | 3 | 250 | 0 | 81 | 49 |
| 11 | 5 | 16 | 68.75 | 4 | 250 | 0 | c1 | 49 |
| 12 | 4 | 16 | 75 | 1 | 250 | 0 | 01 | 3a |
| 12 | 4 | 16 | 75 | 2 | 250 | 0 | 41 | 3a |
| 12 | 4 | 16 | 75 | 3 | 250 | 0 | 81 | 3a |
| 12 | 4 | 16 | 75 | 4 | 250 | 0 | c1 | 3a |
| 13 | 3 | 16 | 81.25 | 1 | 250 | 0 | 01 | 2b |
| 13 | 3 | 16 | 81.25 | 2 | 250 | 0 | 41 | 2b |
| 13 | 3 | 16 | 81.25 | 3 | 250 | 0 | 81 | 2b |
| 13 | 3 | 16 | 81.25 | 4 | 250 | 0 | c1 | 2b |
| 14 | 2 | 16 | 87.5 | 1 | 250 | 0 | 01 | 1c |
| 14 | 2 | 16 | 87.5 | 2 | 250 | 0 | 41 | 1c |
| 14 | 2 | 16 | 87.5 | 3 | 250 | 0 | 81 | 1c |
| 14 | 2 | 16 | 87.5 | 4 | 250 | 0 | c1 | 1c |
| 4 | 4 | 8 | 50 | 1 | 250 | 0 | 03 | 32 |
| 4 | 4 | 8 | 50 | 2 | 250 | 0 | 43 | 32 |
| 4 | 4 | 8 | 50 | 3 | 250 | 0 | 83 | 32 |
| 4 | 4 | 8 | 50 | 4 | 250 | 0 | c3 | 32 |
| 5 | 3 | 8 | 62.5 | 1 | 250 | 0 | 03 | 23 |
| 5 | 3 | 8 | 62.5 | 2 | 250 | 0 | 43 | 23 |
| 5 | 3 | 8 | 62.5 | 3 | 250 | 0 | 83 | 23 |
| 5 | 3 | 8 | 62.5 | 4 | 250 | 0 | c3 | 23 |
| 6 | 2 | 8 | 75 | 1 | 250 | 0 | 03 | 14 |
| 6 | 2 | 8 | 75 | 2 | 250 | 0 | 43 | 14 |
| 6 | 2 | 8 | 75 | 3 | 250 | 0 | 83 | 14 |
| 6 | 2 | 8 | 75 | 4 | 250 | 0 | c3 | 14 |
Explanations
- T1: the number of quanta before the sampling point.
- T2: the number of quanta after the sampling point.
- BTQ: the number of quanta per bit.
- SP%: the position of the sampling point, in percent of the whole bit.
- SJW: the Synchronization Jump Width.
- Bit Rate: the resulting bus speed, in kbps.
- Err%: the deviation, in percent, from the desired bit rate.
- BTR0: Bus Timing Register 0, in hex, for 82527/SJA1000/82C200/compatible.
- BTR1: Bus Timing Register 1, in hex, for 82527/SJA1000/82C200/compatible.
The following bus parameters are allowed, assuming
- your CAN controller is clocked with 16 MHz,
- you want a CAN bus bit rate of 250 kbps,
- settings leading to speed deviations of more than 0% are discarded.
- MCP2510 CAN Controller
| T1 | T2 | BTQ | SP% | SJW | Bit Rate | Err% | CNF1 | CNF2 | CNF3 |
| 8 | 8 | 16 | 50 | 1 | 250 | 0 | 01 | 9a | 07 |
| 8 | 8 | 16 | 50 | 2 | 250 | 0 | 41 | 9a | 07 |
| 8 | 8 | 16 | 50 | 3 | 250 | 0 | 81 | 9a | 07 |
| 8 | 8 | 16 | 50 | 4 | 250 | 0 | c1 | 9a | 07 |
| 9 | 7 | 16 | 56.25 | 1 | 250 | 0 | 01 | 9b | 06 |
| 9 | 7 | 16 | 56.25 | 2 | 250 | 0 | 41 | 9b | 06 |
| 9 | 7 | 16 | 56.25 | 3 | 250 | 0 | 81 | 9b | 06 |
| 9 | 7 | 16 | 56.25 | 4 | 250 | 0 | c1 | 9b | 06 |
| 10 | 6 | 16 | 62.5 | 1 | 250 | 0 | 01 | a3 | 05 |
| 10 | 6 | 16 | 62.5 | 2 | 250 | 0 | 41 | a3 | 05 |
| 10 | 6 | 16 | 62.5 | 3 | 250 | 0 | 81 | a3 | 05 |
| 10 | 6 | 16 | 62.5 | 4 | 250 | 0 | c1 | a3 | 05 |
| 11 | 5 | 16 | 68.75 | 1 | 250 | 0 | 01 | a4 | 04 |
| 11 | 5 | 16 | 68.75 | 2 | 250 | 0 | 41 | a4 | 04 |
| 11 | 5 | 16 | 68.75 | 3 | 250 | 0 | 81 | a4 | 04 |
| 11 | 5 | 16 | 68.75 | 4 | 250 | 0 | c1 | a4 | 04 |
| 12 | 4 | 16 | 75 | 1 | 250 | 0 | 01 | ac | 03 |
| 12 | 4 | 16 | 75 | 2 | 250 | 0 | 41 | ac | 03 |
| 12 | 4 | 16 | 75 | 3 | 250 | 0 | 81 | ac | 03 |
| 12 | 4 | 16 | 75 | 4 | 250 | 0 | c1 | ac | 03 |
| 13 | 3 | 16 | 81.25 | 1 | 250 | 0 | 01 | ad | 02 |
| 13 | 3 | 16 | 81.25 | 2 | 250 | 0 | 41 | ad | 02 |
| 13 | 3 | 16 | 81.25 | 3 | 250 | 0 | 81 | ad | 02 |
| 13 | 3 | 16 | 81.25 | 4 | 250 | 0 | c1 | ad | 02 |
| 14 | 2 | 16 | 87.5 | 1 | 250 | 0 | 01 | b5 | 01 |
| 14 | 2 | 16 | 87.5 | 2 | 250 | 0 | 41 | b5 | 01 |
| 14 | 2 | 16 | 87.5 | 3 | 250 | 0 | 81 | b5 | 01 |
| 14 | 2 | 16 | 87.5 | 4 | 250 | 0 | c1 | b5 | 01 |
| 4 | 4 | 8 | 50 | 1 | 250 | 0 | 03 | 88 | 03 |
| 4 | 4 | 8 | 50 | 2 | 250 | 0 | 43 | 88 | 03 |
| 4 | 4 | 8 | 50 | 3 | 250 | 0 | 83 | 88 | 03 |
| 4 | 4 | 8 | 50 | 4 | 250 | 0 | c3 | 88 | 03 |
| 5 | 3 | 8 | 62.5 | 1 | 250 | 0 | 03 | 89 | 02 |
| 5 | 3 | 8 | 62.5 | 2 | 250 | 0 | 43 | 89 | 02 |
| 5 | 3 | 8 | 62.5 | 3 | 250 | 0 | 83 | 89 | 02 |
| 5 | 3 | 8 | 62.5 | 4 | 250 | 0 | c3 | 89 | 02 |
| 6 | 2 | 8 | 75 | 1 | 250 | 0 | 03 | 91 | 01 |
| 6 | 2 | 8 | 75 | 2 | 250 | 0 | 43 | 91 | 01 |
| 6 | 2 | 8 | 75 | 3 | 250 | 0 | 83 | 91 | 01 |
| 6 | 2 | 8 | 75 | 4 | 250 | 0 | c3 | 91 | 01 |
Explanations
- T1: the number of quanta beforethe sampling point.
- T2: the number of quanta after the sampling point.
- BTQ: the number of quanta per bit.
- SP%: the position of the sampling point, in percent of the whole bit.
- SJW: the Synchronization Jump Width.
- Bit Rate: the resulting bus speed, in kbps.
- Err%: the deviation, in percent, from the desired bit rate.
- CNF0: Configuration Register 0, in hex
- CNF1: Configuration Register 1, in hex
- CNF2: Configuration Register 2, in hex
/* can-calc-bit-timing.c: Calculate CAN bit timing parameters
*
* Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
*
* Derived from:
* can_baud.c - CAN baudrate calculation
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email:pisa@cmp.felk.cvut.cz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*/ #include <errno.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <linux/types.h> /* seems not to be defined in errno.h */
#ifndef ENOTSUPP
#define ENOTSUPP 524 /* Operation is not supported */
#endif /* useful defines */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define do_div(a,b) a = (a) / (b) #define abs(x) ({ \
long __x = (x); \
(__x < ) ? -__x : __x; \
}) /**
* clamp - return a value clamped to a given range with strict typechecking
* @val: current value
* @min: minimum allowable value
* @max: maximum allowable value
*
* This macro does strict typechecking of min/max to make sure they are of the
* same type as val. See the unnecessary pointer comparisons.
*/
#define clamp(val, min, max) ({ \
typeof(val) __val = (val); \
typeof(min) __min = (min); \
typeof(max) __max = (max); \
(void) (&__val == &__min); \
(void) (&__val == &__max); \
__val = __val < __min ? __min: __val; \
__val > __max ? __max: __val; }) /* we don't want to see these prints */
#define dev_err(dev, format, arg...) do { } while (0)
#define dev_warn(dev, format, arg...) do { } while (0) /* define in-kernel-types */
typedef __u64 u64;
typedef __u32 u32; /*
* CAN bit-timing parameters
*
* For futher information, please read chapter "8 BIT TIMING
* REQUIREMENTS" of the "Bosch CAN Specification version 2.0"
* at http://www.semiconductors.bosch.de/pdf/can2spec.pdf.
*/
struct can_bittiming
{
__u32 bitrate; /* Bit-rate in bits/second */
__u32 sample_point; /* Sample point in one-tenth of a percent */
__u32 tq; /* Time quanta (TQ) in nanoseconds */
__u32 prop_seg; /* Propagation segment in TQs */
__u32 phase_seg1; /* Phase buffer segment 1 in TQs */
__u32 phase_seg2; /* Phase buffer segment 2 in TQs */
__u32 sjw; /* Synchronisation jump width in TQs */
__u32 brp; /* Bit-rate prescaler */
}; /*
* CAN harware-dependent bit-timing constant
*
* Used for calculating and checking bit-timing parameters
*/
struct can_bittiming_const
{
char name[ ]; /* Name of the CAN controller hardware */
__u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
__u32 tseg1_max;
__u32 tseg2_min; /* Time segement 2 = phase_seg2 */
__u32 tseg2_max;
__u32 sjw_max; /* Synchronisation jump width */
__u32 brp_min; /* Bit-rate prescaler */
__u32 brp_max;
__u32 brp_inc; /* added for can-calc-bit-timing utility */
__u32 ref_clk; /* CAN system clock frequency in Hz */
void (*printf_btr)( struct can_bittiming *bt, int hdr );
}; /*
* CAN clock parameters
*/
struct can_clock
{
__u32 freq; /* CAN system clock frequency in Hz */
}; /*
* minimal structs, just enough to be source level compatible
*/
struct can_priv
{
const struct can_bittiming_const *bittiming_const;
struct can_clock clock;
}; struct net_device
{
struct can_priv priv;
}; static inline void *netdev_priv( const struct net_device *dev )
{
return (void *) &dev->priv;
} static void print_usage( char* cmd )
{
printf( "Usage: %s [options] [<CAN-contoller-name>]\n"
"\tOptions:\n"
"\t-q : don't print header line\n"
"\t-l : list all support CAN controller names\n"
"\t-b <bitrate> : bit-rate in bits/sec\n"
"\t-s <samp_pt> : sample-point in one-tenth of a percent\n"
"\t or 0 for CIA recommended sample points\n"
"\t-c <clock> : real CAN system clock in Hz\n", cmd ); exit( EXIT_FAILURE );
} static void printf_btr_sja1000( struct can_bittiming *bt, int hdr )
{
uint8_t btr0, btr1; if ( hdr )
{
printf( "BTR0 BTR1" );
}
else
{
btr0 = ( ( bt->brp - ) & 0x3f ) | ( ( ( bt->sjw - ) & 0x3 ) << );
btr1 = ( ( bt->prop_seg + bt->phase_seg1 - ) & 0xf )
| ( ( ( bt->phase_seg2 - ) & 0x7 ) << );
printf( "0x%02x 0x%02x", btr0, btr1 );
}
} static void printf_btr_at91( struct can_bittiming *bt, int hdr )
{
if ( hdr )
{
printf( "%10s", "CAN_BR" );
}
else
{
uint32_t br = ( ( bt->phase_seg2 - ) | ( ( bt->phase_seg1 - ) << )
| ( ( bt->prop_seg - ) << ) | ( ( bt->sjw - ) << )
| ( ( bt->brp - ) << ) );
printf( "0x%08x", br );
}
} static void printf_btr_flexcan( struct can_bittiming *bt, int hdr )
{
if ( hdr )
{
printf( "%10s", "CAN_CTRL" );
}
else
{
uint32_t ctrl = ( ( ( bt->brp - ) << ) | ( ( bt->sjw - ) << )
| ( ( bt->phase_seg1 - ) << ) | ( ( bt->phase_seg2 - ) << )
| ( ( bt->prop_seg - ) << ) ); printf( "0x%08x", ctrl );
}
} static void printf_btr_mcp251x( struct can_bittiming *bt, int hdr )
{
uint8_t cnf1, cnf2, cnf3; if ( hdr )
{
printf( "CNF1 CNF2 CNF3" );
}
else
{
cnf1 = ( ( bt->sjw - ) << ) | ( bt->brp - );
cnf2 = 0x80 | ( ( bt->phase_seg1 - ) << ) | ( bt->prop_seg - );
cnf3 = bt->phase_seg2 - ;
printf( "0x%02x 0x%02x 0x%02x", cnf1, cnf2, cnf3 );
}
} static void printf_btr_ti_hecc( struct can_bittiming *bt, int hdr )
{
if ( hdr )
{
printf( "%10s", "CANBTC" );
}
else
{
uint32_t can_btc; can_btc = ( bt->phase_seg2 - ) & 0x7;
can_btc |= ( ( bt->phase_seg1 + bt->prop_seg - ) & 0xF ) << ;
can_btc |= ( ( bt->sjw - ) & 0x3 ) << ;
can_btc |= ( ( bt->brp - ) & 0xFF ) << ; printf( "0x%08x", can_btc );
}
} static struct can_bittiming_const can_calc_consts[ ] =
{
{ .name = "sja1000", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , /* mpc5121 */
.printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , /* mpc5121 */
.printf_btr = printf_btr_sja1000, },
{ .name = "at91", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_at91, },
{ .name = "at91", .tseg1_min = , .tseg1_max = , .tseg2_min = , .tseg2_max =
, .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , /* real world clock as found on the ronetix PM9263 */
.ref_clk = , .printf_btr = printf_btr_at91, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , /* mx28 */
.printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_flexcan, /* vybrid */
},
{ .name = "mcp251x", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_mcp251x, },
{ .name = "mcp251x", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_mcp251x, },
{ .name = "ti_hecc", .tseg1_min = , .tseg1_max = , .tseg2_min = ,
.tseg2_max = , .sjw_max = , .brp_min = , .brp_max = , .brp_inc = , .ref_clk = , .printf_btr = printf_btr_ti_hecc, } }; static long common_bitrates[ ] =
{ , , , , , , , , , }; #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ static int can_update_spt( const struct can_bittiming_const *btc, int sampl_pt,
int tseg, int *tseg1, int *tseg2 )
{
*tseg2 = tseg + - ( sampl_pt * ( tseg + ) ) / ;
if ( *tseg2 < btc->tseg2_min )
*tseg2 = btc->tseg2_min;
if ( *tseg2 > btc->tseg2_max )
*tseg2 = btc->tseg2_max;
*tseg1 = tseg - *tseg2;
if ( *tseg1 > btc->tseg1_max )
{
*tseg1 = btc->tseg1_max;
*tseg2 = tseg - *tseg1;
}
return * ( tseg + - *tseg2 ) / ( tseg + );
} static int can_calc_bittiming( struct net_device *dev,
struct can_bittiming *bt )
{
struct can_priv *priv = netdev_priv( dev );
const struct can_bittiming_const *btc = priv->bittiming_const;
long rate = ;
long best_error = , error = ;
int best_tseg = , best_brp = , brp = ;
int tsegall, tseg = , tseg1 = , tseg2 = ;
int spt_error = , spt = , sampl_pt;
u64 v64; if ( !priv->bittiming_const )
return -ENOTSUPP; /* Use CIA recommended sample points */
if ( bt->sample_point )
{
sampl_pt = bt->sample_point;
}
else
{
if ( bt->bitrate > )
sampl_pt = ;
else if ( bt->bitrate > )
sampl_pt = ;
else
sampl_pt = ;
} /* tseg even = round down, odd = round up */
for ( tseg = ( btc->tseg1_max + btc->tseg2_max ) * + ;
tseg >= ( btc->tseg1_min + btc->tseg2_min ) * ; tseg-- )
{
tsegall = + tseg / ;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / ( tsegall * bt->bitrate ) + tseg % ;
/* chose brp step which is possible in system */
brp = ( brp / btc->brp_inc ) * btc->brp_inc;
if ( ( brp < btc->brp_min ) || ( brp > btc->brp_max ) )
continue;
rate = priv->clock.freq / ( brp * tsegall );
error = bt->bitrate - rate;
/* tseg brp biterror */
if ( error < )
error = -error;
if ( error > best_error )
continue;
best_error = error;
if ( error == )
{
spt = can_update_spt( btc, sampl_pt, tseg / , &tseg1, &tseg2 );
error = sampl_pt - spt;
if ( error < )
error = -error;
if ( error > spt_error )
continue;
spt_error = error;
}
best_tseg = tseg / ;
best_brp = brp;
if ( error == )
break;
} if ( best_error )
{
/* Error in one-tenth of a percent */
error = ( best_error * ) / bt->bitrate;
if ( error > CAN_CALC_MAX_ERROR )
{
dev_err( dev->dev.parent, "bitrate error %ld.%ld%% too high\n",
error / , error % );
return -EDOM;
}
else
{
dev_warn( dev->dev.parent, "bitrate error %ld.%ld%%\n", error / ,
error % );
}
} /* real sample point */
bt->sample_point = can_update_spt( btc, sampl_pt, best_tseg, &tseg1, &tseg2 ); v64 = (u64) best_brp * 1000000000UL;
do_div( v64, priv->clock.freq );
bt->tq = (u32) v64;
bt->prop_seg = tseg1 / ;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
bt->sjw = ;
bt->brp = best_brp; /* real bit-rate */
bt->bitrate = priv->clock.freq / ( bt->brp * ( tseg1 + tseg2 + ) ); return ;
} static __u32 get_cia_sample_point( __u32 bitrate )
{
__u32 sampl_pt; if ( bitrate > )
sampl_pt = ;
else if ( bitrate > )
sampl_pt = ;
else
sampl_pt = ; return sampl_pt;
} static void print_bit_timing( const struct can_bittiming_const *btc,
__u32 bitrate, __u32 sample_point, __u32 ref_clk, int quiet )
{
struct net_device dev =
{ .priv.bittiming_const = btc, .priv.clock.freq = ref_clk, };
struct can_bittiming bt =
{ .bitrate = bitrate, .sample_point = sample_point, };
long rate_error, spt_error; if ( !quiet )
{
printf( "Bit timing parameters for %s with %.6f MHz ref clock\n"
"nominal real Bitrt nom real SampP\n"
"Bitrate TQ[ns] PrS PhS1 PhS2 SJW BRP Bitrate Error SampP SampP Error ",
btc->name, ref_clk / 1000000.0 ); btc->printf_btr( &bt, );
printf( "\n" );
} if ( can_calc_bittiming( &dev, &bt ) )
{
printf( "%7d ***bitrate not possible***\n", bitrate );
return;
} /* get nominal sample point */
if ( !sample_point )
sample_point = get_cia_sample_point( bitrate ); rate_error = abs( ( __s32 )( bitrate - bt.bitrate ) );
spt_error = abs( ( __s32 )( sample_point - bt.sample_point ) ); printf( "%7d "
"%6d %3d %4d %4d "
"%3d %3d "
"%7d %4.1f%% "
"%4.1f%% %4.1f%% %4.1f%% ", bitrate, bt.tq, bt.prop_seg, bt.phase_seg1,
bt.phase_seg2, bt.sjw, bt.brp, bt.bitrate, 100.0 * rate_error / bitrate, sample_point / 10.0, bt.sample_point / 10.0,
100.0 * spt_error / sample_point ); btc->printf_btr( &bt, );
printf( "\n" );
} static void do_list( void )
{
unsigned int i; for ( i = ; i < ARRAY_SIZE( can_calc_consts ); i++ )
printf( "%s\n", can_calc_consts[ i ].name );
} int main( int argc, char *argv[ ] )
{
__u32 bitrate = ;
__u32 opt_ref_clk = , ref_clk;
int sampl_pt = ;
int quiet = ;
int list = ;
char *name = NULL;
unsigned int i, j;
int opt, found = ; const struct can_bittiming_const *btc = NULL; while ( ( opt = getopt( argc, argv, "b:c:lps:" ) ) != - )
{
switch ( opt )
{
case 'b':
bitrate = atoi( optarg );
break; case 'c':
opt_ref_clk = atoi( optarg );
break; case 'l':
list = ;
break; case 'q':
quiet = ;
break; case 's':
sampl_pt = atoi( optarg );
break; default:
print_usage( argv[ ] );
break;
}
} if ( argc > optind + )
print_usage( argv[ ] ); if ( argc == optind + )
name = argv[ optind ]; if ( list )
{
do_list( );
exit( EXIT_SUCCESS );
} if ( sampl_pt && ( sampl_pt >= || sampl_pt < ) )
print_usage( argv[ ] ); for ( i = ; i < ARRAY_SIZE( can_calc_consts ); i++ )
{
if ( name && strcmp( can_calc_consts[ i ].name, name ) )
continue; found = ;
btc = &can_calc_consts[ i ]; if ( opt_ref_clk )
ref_clk = opt_ref_clk;
else
ref_clk = btc->ref_clk; if ( bitrate )
{
print_bit_timing( btc, bitrate, sampl_pt, ref_clk, quiet );
}
else
{
for ( j = ; j < ARRAY_SIZE( common_bitrates ); j++ )
print_bit_timing( btc, common_bitrates[ j ], sampl_pt, ref_clk, j );
}
printf( "\n" );
} if ( !found )
{
printf( "error: unknown CAN controller '%s', try one of these:\n\n", name );
do_list( );
exit( EXIT_FAILURE );
} exit( EXIT_SUCCESS );
}
Calculate CAN bit timing parameters的更多相关文章
- Calculate CAN bit timing parameters -- STM32
Calculate CAN bit timing parameters Calculate CAN bit timing parameters typedef struct { //char name ...
- CRT/LCD/VGA Information and Timing
彩色阴极射线管的剖面图: 1. 电子QIANG Three Electron guns (for red, green, and blue phosphor dots)2. 电子束 Electron ...
- CRT/LCD/VGA Information and Timing【转】
转自:http://www.cnblogs.com/shangdawei/p/4760933.html 彩色阴极射线管的剖面图: 1. 电子QIANG Three Electron guns (for ...
- CALayer之 customizing timing of an animation
customizing timing of an animation Timing is an important part of animations, and with Core Animatio ...
- RFID 读写器 Reader Writer Cloner
RFID读写器的工作原理 RFID的数据采集以读写器为主导,RFID读写器是一种通过无线通信,实现对标签识别和内存数据的读出和写入操作的装置. 读写器又称为阅读器或读头(Reader).查询器(Int ...
- RFID Reader 线路图收集
This 125 kHz RFID reader http://www.serasidis.gr/circuits/RFID_reader/125kHz_RFID_reader.htm http:// ...
- 0xWS2812 STM32 driver for WS2812(B) RGB LEDs
0xWS2812 STM32 driver for WS2812(B) RGB LEDs 0xWS2812 pronounced "hex-WS2812" This code ai ...
- BlackArch-Tools
BlackArch-Tools 简介 安装在ArchLinux之上添加存储库从blackarch存储库安装工具替代安装方法BlackArch Linux Complete Tools List 简介 ...
- Timequest静态时序分析(STA)基础
Setup Slack Hold Slack Recovery&Removal Recovery: The minimum time an asynchronous signal must b ...
随机推荐
- opencv附加依赖性选择,提示找不到opencv_world400d.dll
连接器>>输入>>附加依赖项,添加opencv_world400d.lib库文件名,在....\opencv\build\x64\vc14\lib有2个lib文件, 带d的是d ...
- Ubuntu接显示器问题
1.Could not apply the stored configuration for monitors 解决办法:Ubuntu在开机进入桌面的时候,会调用gnome-setting-deamo ...
- python2.7中MySQLdb的安装与使用详解
Python2.7中MySQLdb的使用 import MySQLdb #1.建立连接 connect = MySQLdb.connect( '127.0.0.1', #数据库地址 'root', # ...
- 高通Trustzone and QSEE介绍
http://blog.csdn.net/iamliuyanlei/article/details/52625968
- Oracle 数据库和监听器开机自启动两种实现方法
数据库和监听器开机自启动 编辑oratab文件: 修改:orcl:/u01/app/oracle/product/11.2.0/db_1:N orcl:/u01/app/or ...
- 使用Eclipse运行第一个Go程序
Windows 10家庭中文版,go version go1.11 windows/amd64, Eclipse IDE for C/C++ Developers Photon Release (4. ...
- Oracle JDK vs OpenJDK
OpenJDK是Sun在2006年末把Java开源而形成的项目,这里的“开源”是通常意义上的源码开放形式,即源码是可被复用的,例如IcedTea.UltraViolet都是从OpenJDK源码衍生出的 ...
- 《Redis设计与实现》学习笔记
第2章 简单动态字符串(SDS) redis的字符串不是直接用c语言的字符串,而是用了一种称为简单动态字符串(SDS)的抽象类型,并将其作为默认字符串. redis中包含字符串值的键值对在底层都是由S ...
- poj 2253 一条路径中的最大边 再找出最小的
题目大意,有两只青蛙,分别在两个石头上,青蛙A想要到青蛙B那儿去,他可以直接跳到B的石头上,也可以跳到其他石头上,再从其他石头跳到B那儿,求青蛙从A到B的所有路径中最小的Frog Distance,我 ...
- FileSystemResource在Srping FrameWork 5中的变化
之前在项目中一直使用FileSystemResource这个类作为PropertyPlaceholderConfigurer的Resource引入部署目录外的配置文件,并设置了setIgnoreRes ...
