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.

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 < 0) ? -__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[ 16 ]; /* 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 - 1 ) & 0x3f ) | ( ( ( bt->sjw - 1 ) & 0x3 ) << 6 );
    btr1 = ( ( bt->prop_seg + bt->phase_seg1 - 1 ) & 0xf )
      | ( ( ( bt->phase_seg2 - 1 ) & 0x7 ) << 4 );
    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 - 1 ) | ( ( bt->phase_seg1 - 1 ) << 4 )
      | ( ( bt->prop_seg - 1 ) << 8 ) | ( ( bt->sjw - 1 ) << 12 )
      | ( ( bt->brp - 1 ) << 16 ) );
    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 - 1 ) << 24 ) | ( ( bt->sjw - 1 ) << 22 )
      | ( ( bt->phase_seg1 - 1 ) << 19 ) | ( ( bt->phase_seg2 - 1 ) << 16 )
      | ( ( bt->prop_seg - 1 ) << 0 ) );
    
    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 - 1 ) << 6 ) | ( bt->brp - 1 );
    cnf2 = 0x80 | ( ( bt->phase_seg1 - 1 ) << 3 ) | ( bt->prop_seg - 1 );
    cnf3 = bt->phase_seg2 - 1;
    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 - 1 ) & 0x7;
    can_btc |= ( ( bt->phase_seg1 + bt->prop_seg - 1 ) & 0xF ) << 3;
    can_btc |= ( ( bt->sjw - 1 ) & 0x3 ) << 8;
    can_btc |= ( ( bt->brp - 1 ) & 0xFF ) << 16;
    
    printf( "0x%08x", can_btc );
  }
}

static struct can_bittiming_const can_calc_consts[ ] =
{
{ .name = "sja1000", .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

  .ref_clk = 8000000, .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 32000000, .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 33000000, .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 33300000, .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 33333333, .printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 66660000, /* mpc5121 */
.printf_btr = printf_btr_sja1000, },
{ .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

.ref_clk = 66666666, /* mpc5121 */
.printf_btr = printf_btr_sja1000, },
{ .name = "at91", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 2, .brp_max = 128, .brp_inc = 1,

.ref_clk = 100000000, .printf_btr = printf_btr_at91, },
{ .name = "at91", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2, .tseg2_max =
  8, .sjw_max = 4, .brp_min = 2, .brp_max = 128, .brp_inc = 1,

/* real world clock as found on the ronetix PM9263 */
.ref_clk = 99532800, .printf_btr = printf_btr_at91, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 24000000, /* mx28 */
  .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 49875000, .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 66000000, .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 66500000, .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 66666666, .printf_btr = printf_btr_flexcan, },
{ .name = "flexcan", .tseg1_min = 4, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 83368421, .printf_btr = printf_btr_flexcan, /* vybrid */
},
{ .name = "mcp251x", .tseg1_min = 3, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

  .ref_clk = 8000000, .printf_btr = printf_btr_mcp251x, },
{ .name = "mcp251x", .tseg1_min = 3, .tseg1_max = 16, .tseg2_min = 2,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1,

  .ref_clk = 16000000, .printf_btr = printf_btr_mcp251x, },
{ .name = "ti_hecc", .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1,
  .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 256, .brp_inc = 1,

  .ref_clk = 13000000, .printf_btr = printf_btr_ti_hecc, } };

static long common_bitrates[ ] =
{ 1000000, 800000, 500000, 250000, 125000, 100000, 50000, 20000, 10000, };

#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 + 1 - ( sampl_pt * ( tseg + 1 ) ) / 1000;
  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 1000 * ( tseg + 1 - *tseg2 ) / ( tseg + 1 );
}

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 = 0;
  long best_error = 1000000000, error = 0;
  int best_tseg = 0, best_brp = 0, brp = 0;
  int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
  int spt_error = 1000, spt = 0, 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 > 800000 )
      sampl_pt = 750;
    else if ( bt->bitrate > 500000 )
      sampl_pt = 800;
    else
      sampl_pt = 875;
  }
  
  /* tseg even = round down, odd = round up */
  for ( tseg = ( btc->tseg1_max + btc->tseg2_max ) * 2 + 1;
      tseg >= ( btc->tseg1_min + btc->tseg2_min ) * 2; tseg-- )
  {
    tsegall = 1 + tseg / 2;
    /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
    brp = priv->clock.freq / ( tsegall * bt->bitrate ) + tseg % 2;
    /* 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 < 0 )
      error = -error;
    if ( error > best_error )
      continue;
    best_error = error;
    if ( error == 0 )
    {
      spt = can_update_spt( btc, sampl_pt, tseg / 2, &tseg1, &tseg2 );
      error = sampl_pt - spt;
      if ( error < 0 )
        error = -error;
      if ( error > spt_error )
        continue;
      spt_error = error;
    }
    best_tseg = tseg / 2;
    best_brp = brp;
    if ( error == 0 )
      break;
  }
  
  if ( best_error )
  {
    /* Error in one-tenth of a percent */
    error = ( best_error * 1000 ) / bt->bitrate;
    if ( error > CAN_CALC_MAX_ERROR )
    {
      dev_err( dev->dev.parent, "bitrate error %ld.%ld%% too high\n",
        error / 10, error % 10 );
      return -EDOM;
    }
    else
    {
      dev_warn( dev->dev.parent, "bitrate error %ld.%ld%%\n", error / 10,
        error % 10 );
    }
  }
  
  /* 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 / 2;
  bt->phase_seg1 = tseg1 - bt->prop_seg;
  bt->phase_seg2 = tseg2;
  bt->sjw = 1;
  bt->brp = best_brp;
  
  /* real bit-rate */
  bt->bitrate = priv->clock.freq / ( bt->brp * ( tseg1 + tseg2 + 1 ) );
  
  return 0;
}

static __u32 get_cia_sample_point( __u32 bitrate )
{
  __u32 sampl_pt;
  
  if ( bitrate > 800000 )
    sampl_pt = 750;
  else if ( bitrate > 500000 )
    sampl_pt = 800;
  else
    sampl_pt = 875;
  
  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, 1 );
    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, 0 );
  printf( "\n" );
}

static void do_list( void )
{
  unsigned int i;
  
  for ( i = 0; i < ARRAY_SIZE( can_calc_consts ); i++ )
    printf( "%s\n", can_calc_consts[ i ].name );
}

int main( int argc, char *argv[ ] )
{
  __u32 bitrate = 0;
  __u32 opt_ref_clk = 0, ref_clk;
  int sampl_pt = 0;
  int quiet = 0;
  int list = 0;
  char *name = NULL;
  unsigned int i, j;
  int opt, found = 0;
  
  const struct can_bittiming_const *btc = NULL;
  
  while ( ( opt = getopt( argc, argv, "b:c:lps:" ) ) != -1 )
  {
    switch ( opt )
    {
      case 'b':
        bitrate = atoi( optarg );
        break;
        
      case 'c':
        opt_ref_clk = atoi( optarg );
        break;
        
      case 'l':
        list = 1;
        break;
        
      case 'q':
        quiet = 1;
        break;
        
      case 's':
        sampl_pt = atoi( optarg );
        break;
        
      default:
        print_usage( argv[ 0 ] );
        break;
    }
  }
  
  if ( argc > optind + 1 )
    print_usage( argv[ 0 ] );
  
  if ( argc == optind + 1 )
    name = argv[ optind ];
  
  if ( list )
  {
    do_list( );
    exit( EXIT_SUCCESS );
  }
  
  if ( sampl_pt && ( sampl_pt >= 1000 || sampl_pt < 100 ) )
    print_usage( argv[ 0 ] );
  
  for ( i = 0; i < ARRAY_SIZE( can_calc_consts ); i++ )
  {
    if ( name && strcmp( can_calc_consts[ i ].name, name ) )
      continue;
    
    found = 1;
    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 = 0; 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 );
}

 

posted @ 2015-08-10 00:22  IAmAProgrammer  阅读(12547)  评论(0编辑  收藏  举报