]> rtime.felk.cvut.cz Git - can-utils.git/blobdiff - can-calc-bit-timing.c
slcan: added listen-only flag
[can-utils.git] / can-calc-bit-timing.c
index 9db79e8cae29a43eec03225b427736eac4208d5f..9031a78f36180735195ad521a24f0f30c5a435f7 100644 (file)
@@ -9,7 +9,10 @@
  *   Copyright 2005      Stanislav Marek
  *   email:pisa@cmp.felk.cvut.cz
  *
- *   This software is released under the GPL-License.
+ * 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>
@@ -26,7 +29,7 @@
 #define ENOTSUPP       524     /* Operation is not supported */
 #endif
 
-/* usefull defines */
+/* useful defines */
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
 #define do_div(a,b) a = (a) / (b)
@@ -98,6 +101,7 @@ struct can_bittiming_const {
        __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);
 };
 
@@ -138,7 +142,7 @@ static void print_usage(char* cmd)
               "\t-c <clock>   : real CAN system clock in Hz\n",
               cmd);
 
-       exit(1);
+       exit(EXIT_FAILURE);
 }
 
 static void printf_btr_sja1000(struct can_bittiming *bt, int hdr)
@@ -158,7 +162,7 @@ static void printf_btr_sja1000(struct can_bittiming *bt, int hdr)
 static void printf_btr_at91(struct can_bittiming *bt, int hdr)
 {
        if (hdr) {
-               printf("CAN_BR");
+               printf("%10s", "CAN_BR");
        } else {
                uint32_t br = ((bt->phase_seg2 - 1) |
                               ((bt->phase_seg1 - 1) << 4) |
@@ -169,6 +173,21 @@ static void printf_btr_at91(struct can_bittiming *bt, int hdr)
        }
 }
 
+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;
@@ -176,25 +195,27 @@ static void printf_btr_mcp251x(struct can_bittiming *bt, int hdr)
        if (hdr) {
                printf("CNF1 CNF2 CNF3");
        } else {
-               cnf1 = ((bt->sjw - 1) << 6) | bt->brp;
+               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_rtcantl1(struct can_bittiming *bt, int hdr)
+static void printf_btr_ti_hecc(struct can_bittiming *bt, int hdr)
 {
-       uint16_t bcr0, bcr1;
-
        if (hdr) {
-               printf("__BCR0 __BCR1");
+               printf("%10s", "CANBTC");
        } else {
-               bcr1 = ((((bt->prop_seg + bt->phase_seg1 - 1) & 0x0F) << 12) |
-                       (((bt->phase_seg2 - 1) & 0x07) << 8) |
-                       (((bt->sjw - 1) & 0x03) << 4));
-               bcr0 =  ((bt->brp - 1) & 0xFF);
-               printf("0x%04x 0x%04x", bcr0, bcr1);
+               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);
        }
 }
 
@@ -210,6 +231,35 @@ static struct can_bittiming_const can_calc_consts[] = {
                .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,
        },
        {
@@ -223,6 +273,49 @@ static struct can_bittiming_const can_calc_consts[] = {
                .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,
        },
        {
@@ -236,8 +329,108 @@ static struct can_bittiming_const can_calc_consts[] = {
                .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,
@@ -249,21 +442,37 @@ static struct can_bittiming_const can_calc_consts[] = {
                .brp_max = 64,
                .brp_inc = 1,
 
+               .ref_clk = 8000000,
                .printf_btr = printf_btr_mcp251x,
        },
        {
-               .name = "rtcantl1",
-               .tseg1_min = 4,
+               .name = "mcp251x",
+               .tseg1_min = 3,
                .tseg1_max = 16,
                .tseg2_min = 2,
                .tseg2_max = 8,
                .sjw_max = 4,
                .brp_min = 1,
-               .brp_max = 256,
+               .brp_max = 64,
                .brp_inc = 1,
 
-               .printf_btr = printf_btr_rtcantl1,
+               .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[] = {
@@ -300,7 +509,7 @@ 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, best_rate = 0;
+       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;
@@ -352,7 +561,6 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
                }
                best_tseg = tseg / 2;
                best_brp = brp;
-               best_rate = rate;
                if (error == 0)
                        break;
        }
@@ -390,6 +598,20 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
        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)
@@ -402,12 +624,15 @@ static void print_bit_timing(const struct can_bittiming_const *btc,
                .bitrate = bitrate,
                .sample_point = sample_point,
        };
-       long rate_error;
+       long rate_error, spt_error;
 
        if (!quiet) {
-               printf("Bit timing parameters for %s using %dHz\n",
-                      btc->name, ref_clk);
-               printf("Bitrate TQ[ns] PrS PhS1 PhS2 SJW BRP SampP Error ");
+               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");
        }
@@ -417,26 +642,51 @@ static void print_bit_timing(const struct can_bittiming_const *btc,
                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);
 
-       printf("%7d %6d %3d %4d %4d %3d %3d %2d.%d%% %4.1f%% ",
-              bitrate, bt.tq, bt.prop_seg, bt.phase_seg1,
-              bt.phase_seg2, bt.sjw, bt.brp,
-              bt.sample_point / 10, bt.sample_point % 10,
-              100.0 * rate_error / bitrate);
        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[])
 {
-       long bitrate = 0;
-       long ref_clk = 8000000;
+       __u32 bitrate = 0;
+       __u32 opt_ref_clk = 0, ref_clk;
        int sampl_pt = 0;
        int quiet = 0;
        int list = 0;
        char *name = NULL;
-       int i, opt;
+       unsigned int i, j;
+       int opt, found = 0;
 
        const struct can_bittiming_const *btc = NULL;
 
@@ -447,7 +697,7 @@ int main(int argc, char *argv[])
                        break;
 
                case 'c':
-                       ref_clk = atoi(optarg);
+                       opt_ref_clk = atoi(optarg);
                        break;
 
                case 'l':
@@ -475,37 +725,40 @@ int main(int argc, char *argv[])
                name = argv[optind];
 
        if (list) {
-               for (i = 0; i < sizeof(can_calc_consts) /
-                            sizeof(struct can_bittiming_const); i++)
-                       printf("%s\n", can_calc_consts[i].name);
-               return 0;
+               do_list();
+               exit(EXIT_SUCCESS);
        }
 
        if (sampl_pt && (sampl_pt >= 1000 || sampl_pt < 100))
                print_usage(argv[0]);
 
-       if (name) {
-               for (i = 0; i < sizeof(can_calc_consts) /
-                            sizeof(struct can_bittiming_const); i++) {
-                       if (!strcmp(can_calc_consts[i].name, name)) {
-                               btc = &can_calc_consts[i];
-                               break;
-                       }
-               }
-               if (!btc)
-                       print_usage(argv[0]);
+       for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) {
+               if (name && strcmp(can_calc_consts[i].name, name))
+                       continue;
 
-       } else {
-               btc = &can_calc_consts[0];
+               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 (bitrate) {
-               print_bit_timing(btc, bitrate, sampl_pt, ref_clk, quiet);
-       } else {
-               for (i = 0; i < sizeof(common_bitrates) / sizeof(long); i++)
-                       print_bit_timing(btc, common_bitrates[i], sampl_pt,
-                                        ref_clk, i);
+       if (!found) {
+               printf("error: unknown CAN controller '%s', try one of these:\n\n", name);
+               do_list();
+               exit(EXIT_FAILURE);
        }
 
-       return 0;
+       exit(EXIT_SUCCESS);
 }