]> rtime.felk.cvut.cz Git - can-utils.git/blob - can-calc-bit-timing.c
add can-calc-bit-timing
[can-utils.git] / can-calc-bit-timing.c
1 /* can-calc-bit-timing.c: Calculate CAN bit timing parameters
2  *
3  * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
4  *
5  * Derived from:
6  *   can_baud.c - CAN baudrate calculation
7  *   Code based on LinCAN sources and H8S2638 project
8  *   Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
9  *   Copyright 2005      Stanislav Marek
10  *   email:pisa@cmp.felk.cvut.cz
11  *
12  *   This software is released under the GPL-License.
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <string.h>
19 #include <getopt.h>
20
21 #define do_div(a,b) a = (a) / (b)
22
23 static void print_usage(char* cmd)
24 {
25         printf("Usage: %s [options] [<CAN-contoller-name>]\n"
26                "\tOptions:\n"
27                "\t-q           : don't print header line\n"
28                "\t-l           : list all support CAN controller names\n"
29                "\t-b <bitrate> : bit-rate in bits/sec\n"
30                "\t-s <samp_pt> : sample-point in one-tenth of a percent\n"
31                "\t               or 0 for CIA recommended sample points\n"
32                "\t-c <clock>   : real CAN system clock in Hz\n",
33                cmd);
34
35         exit(1);
36 }
37
38 struct can_bittime {
39         uint32_t brp;
40         uint8_t prop_seg;
41         uint8_t phase_seg1;
42         uint8_t phase_seg2;
43         uint8_t sjw;
44         uint32_t tq;
45         uint32_t error;
46         int sampl_pt;
47 };
48
49 struct can_bittiming_const {
50         char name[32];
51         int prop_seg_min;
52         int prop_seg_max;
53         int phase_seg1_min;
54         int phase_seg1_max;
55         int phase_seg2_min;
56         int phase_seg2_max;
57         int sjw_max;
58         int brp_min;
59         int brp_max;
60         int brp_inc;
61         void (*printf_btr)(struct can_bittime *bt, int hdr);
62 };
63
64 static void printf_btr_sja1000(struct can_bittime *bt, int hdr)
65 {
66         uint8_t btr0, btr1;
67
68         if (hdr) {
69                 printf("BTR0 BTR1");
70         } else {
71                 btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
72                 btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
73                         (((bt->phase_seg2 - 1) & 0x7) << 4);
74                 printf("0x%02x 0x%02x", btr0, btr1);
75         }
76 }
77
78 static void printf_btr_at91(struct can_bittime *bt, int hdr)
79 {
80         if (hdr) {
81                 printf("CAN_BR");
82         } else {
83                 uint32_t br = ((bt->phase_seg2 - 1) |
84                                ((bt->phase_seg1 - 1) << 4) |
85                                ((bt->prop_seg - 1) << 8) |
86                                ((bt->sjw - 1) << 12) |
87                                ((bt->brp - 1) << 16));
88                 printf("0x%08x", br);
89         }
90 }
91
92 static void printf_btr_mcp2510(struct can_bittime *bt, int hdr)
93 {
94         uint8_t cnf1, cnf2, cnf3;
95
96         if (hdr) {
97                 printf("CNF1 CNF2 CNF3");
98         } else {
99                 cnf1 = ((bt->sjw - 1) << 6) | bt->brp;
100                 cnf2 = 0x80 | ((bt->phase_seg1 - 1) << 3) | (bt->prop_seg - 1);
101                 cnf3 = bt->phase_seg2 - 1;
102                 printf("0x%02x 0x%02x 0x%02x", cnf1, cnf2, cnf3);
103         }
104 }
105
106 static void printf_btr_rtcantl1(struct can_bittime *bt, int hdr)
107 {
108   uint16_t bcr0, bcr1;
109
110   if (hdr) {
111           printf("__BCR0 __BCR1");
112   } else {
113           bcr1 = ((((bt->prop_seg + bt->phase_seg1 - 1) & 0x0F) << 12) |
114                   (((bt->phase_seg2 - 1) & 0x07) << 8) |
115                   (((bt->sjw - 1) & 0x03) << 4));
116           bcr0 =  ((bt->brp - 1) & 0xFF);
117           printf("0x%04x 0x%04x", bcr0, bcr1);
118   }
119 }
120
121 struct can_bittiming_const can_calc_consts[] = {
122         {
123                 "sja1000",
124                 /* Note: only prop_seg + bt->phase_seg1 matters */
125                 .phase_seg1_min = 1,
126                 .phase_seg1_max = 16,
127                 .phase_seg2_min = 1,
128                 .phase_seg2_max = 8,
129                 .sjw_max = 4,
130                 .brp_min = 1,
131                 .brp_max = 64,
132                 .brp_inc = 1,
133                 .printf_btr = printf_btr_sja1000,
134         },
135         {
136                 "mscan",
137                 /* Note: only prop_seg + bt->phase_seg1 matters */
138                 .phase_seg1_min = 4,
139                 .phase_seg1_max = 16,
140                 .phase_seg2_min = 2,
141                 .phase_seg2_max = 8,
142                 .sjw_max = 4,
143                 .brp_min = 1,
144                 .brp_max = 64,
145                 .brp_inc = 1,
146                 .printf_btr = printf_btr_sja1000,
147         },
148         {
149                 "at91",
150                 .prop_seg_min = 1,
151                 .prop_seg_max = 8,
152                 .phase_seg1_min = 1,
153                 .phase_seg1_max = 8,
154                 .phase_seg2_min = 2,
155                 .phase_seg2_max = 8,
156                 .sjw_max = 4,
157                 .brp_min = 1,
158                 .brp_max = 128,
159                 .brp_inc = 1,
160                 .printf_btr = printf_btr_at91,
161         },
162         {
163                 "mcp2510",
164                 .prop_seg_min = 1,
165                 .prop_seg_max = 8,
166                 .phase_seg1_min = 1,
167                 .phase_seg1_max = 8,
168                 .phase_seg2_min = 2,
169                 .phase_seg2_max = 8,
170                 .sjw_max = 4,
171                 .brp_min = 1,
172                 .brp_max = 64,
173                 .brp_inc = 1,
174                 .printf_btr = printf_btr_mcp2510,
175         },
176         {
177                 "rtcantl1",
178                 .prop_seg_min = 2,
179                 .prop_seg_max = 8,
180                 .phase_seg1_min = 2,
181                 .phase_seg1_max = 8,
182                 .phase_seg2_min = 2,
183                 .phase_seg2_max = 8,
184                 .sjw_max = 4,
185                 .brp_min = 1,
186                 .brp_max = 256,
187                 .brp_inc = 1,
188                 .printf_btr = printf_btr_rtcantl1,
189         },
190 };
191
192 static long common_bitrates[] = {
193         1000000,
194         800000,
195         500000,
196         250000,
197         125000,
198         100000,
199         50000,
200         20000,
201         10000
202 };
203
204 static int can_update_spt(const struct can_bittiming_const *btc,
205                           int sampl_pt, int tseg, int *tseg1, int *tseg2)
206 {
207         *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
208         if (*tseg2 < btc->phase_seg2_min)
209                 *tseg2 = btc->phase_seg2_min;
210         if (*tseg2 > btc->phase_seg2_max)
211                 *tseg2 = btc->phase_seg2_max;
212         *tseg1 = tseg - *tseg2;
213         if (*tseg1 > btc->prop_seg_max + btc->phase_seg1_max) {
214                 *tseg1 = btc->prop_seg_max + btc->phase_seg1_max;
215                 *tseg2 = tseg - *tseg1;
216         }
217         return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
218 }
219
220 int can_calc_bittiming(struct can_bittime *bt, long bitrate,
221                        int sampl_pt, long clock,
222                        const struct can_bittiming_const *btc)
223 {
224         long best_error = 1000000000, error;
225         int best_tseg = 0, best_brp = 0, brp = 0;
226         int spt_error = 1000, spt = 0;
227         long rate, best_rate = 0;
228         int tseg = 0, tseg1 = 0, tseg2 = 0;
229         uint64_t v64;
230
231         if (sampl_pt == 0) {
232                 /* Use CIA recommended sample points */
233                 if (bitrate > 800000)
234                          sampl_pt = 750;
235                 else if (bitrate > 500000)
236                         sampl_pt = 800;
237                 else
238                         sampl_pt = 875;
239         }
240
241 #ifdef DEBUG
242         printf("tseg brp bitrate biterror\n");
243 #endif
244
245         /* tseg even = round down, odd = round up */
246         for (tseg = (btc->prop_seg_max + btc->phase_seg1_max +
247                      btc->phase_seg2_max) * 2 + 1;
248              tseg >= (btc->prop_seg_min + btc->phase_seg1_min +
249                       btc->phase_seg2_min) * 2; tseg--) {
250                 /* Compute all posibilities of tseg choices (tseg=tseg1+tseg2) */
251                 brp = clock / ((1 + tseg / 2) * bitrate) + tseg % 2;
252                 /* chose brp step which is possible in system */
253                 brp = (brp / btc->brp_inc) * btc->brp_inc;
254                 if ((brp < btc->brp_min) || (brp > btc->brp_max))
255                         continue;
256                 rate = clock / (brp * (1 + tseg / 2));
257                 error = bitrate - rate;
258                 /* tseg brp biterror */
259 #if DEBUG
260                 printf("%4d %3d %7ld %8ld %03d\n", tseg, brp, rate, error,
261                        can_update_spt(btc, sampl_pt, tseg / 2,
262                                       &tseg1, &tseg2));
263 #endif
264                 if (error < 0)
265                         error = -error;
266                 if (error > best_error)
267                         continue;
268                 best_error = error;
269                 if (error == 0) {
270                         spt = can_update_spt(btc, sampl_pt, tseg / 2,
271                                              &tseg1, &tseg2);
272                         error = sampl_pt - spt;
273                         //printf("%d %d %d\n", sampl_pt, error, spt_error);
274                         if (error < 0)
275                                 error = -error;
276                         if (error > spt_error)
277                                 continue;
278                         spt_error = error;
279                         //printf("%d\n", spt_error);
280                 }
281                 //printf("error=%d\n", best_error);
282                 best_tseg = tseg / 2;
283                 best_brp = brp;
284                 best_rate = rate;
285                 if (error == 0)
286                     break;
287         }
288
289         if (best_error && (bitrate / best_error < 10))
290                 return -1;
291
292         spt = can_update_spt(btc, sampl_pt, best_tseg,
293                              &tseg1, &tseg2);
294
295         if (tseg2 > tseg1) {
296                 /* sample point < 50% */
297                 bt->phase_seg1 = tseg1 / 2;
298         } else {
299                 /* keep phase_seg{1,2} equal around the sample point */
300                 bt->phase_seg1 = tseg2;
301         }
302         bt->prop_seg = tseg1 - bt->phase_seg1;
303         /* Check prop_seg range if necessary */
304         if (btc->prop_seg_min || btc->prop_seg_max) {
305                 if (bt->prop_seg < btc->prop_seg_min)
306                         bt->prop_seg = btc->prop_seg_min;
307                 else if (bt->prop_seg > btc->prop_seg_max)
308                         bt->prop_seg = btc->prop_seg_max;
309                 bt->phase_seg1 = tseg1 - bt->prop_seg;
310         }
311         bt->phase_seg2 = tseg2;
312         bt->sjw = 1;
313         bt->brp = best_brp;
314         bt->error = best_error;
315         bt->sampl_pt = spt;
316         v64 = (uint64_t)bt->brp * 1000000000UL;
317         v64 /= clock;
318         bt->tq = (int)v64;
319
320         return 0;
321 }
322
323 void print_bit_timing(const struct can_bittiming_const *btc,
324                       long bitrate, int sampl_pt, long ref_clk, int quiet)
325 {
326         struct can_bittime bt;
327
328         memset(&bt, 0, sizeof(bt));
329
330         if (!quiet) {
331                 printf("Bit timing parameters for %s using %ldHz\n",
332                        btc->name, ref_clk);
333                 printf("Bitrate TQ[ns] PrS PhS1 PhS2 SJW BRP SampP Error ");
334                 btc->printf_btr(&bt, 1);
335                 printf("\n");
336         }
337
338         if (can_calc_bittiming(&bt, bitrate, sampl_pt, ref_clk, btc)) {
339                 printf("%7ld ***bitrate not possible***\n", bitrate);
340                 return;
341         }
342
343         printf("%7ld %6d %3d %4d %4d %3d %3d %2d.%d%% %4.1f%% ",
344                bitrate, bt.tq, bt.prop_seg, bt.phase_seg1,
345                bt.phase_seg2, bt.sjw, bt.brp,
346                bt.sampl_pt / 10, bt.sampl_pt % 10,
347                (double)100 * bt.error / bitrate);
348         btc->printf_btr(&bt, 0);
349         printf("\n");
350 }
351
352 int main(int argc, char *argv[])
353 {
354         long bitrate = 0;
355         long ref_clk = 8000000;
356         int sampl_pt = 0;
357         int quiet = 0;
358         int list = 0;
359         char *name = NULL;
360         int i, opt;
361
362         const struct can_bittiming_const *btc = NULL;
363
364         while ((opt = getopt(argc, argv, "b:c:lps:")) != -1) {
365                 switch (opt) {
366                 case 'b':
367                         bitrate = atoi(optarg);
368                         break;
369
370                 case 'c':
371                         ref_clk = atoi(optarg);
372                         break;
373
374                 case 'l':
375                         list = 1;
376                         break;
377
378                 case 'q':
379                         quiet = 1;
380                         break;
381
382                 case 's':
383                         sampl_pt = atoi(optarg);
384                         break;
385
386                 default:
387                         print_usage(argv[0]);
388                         break;
389                 }
390         }
391
392         if (argc > optind + 1)
393                 print_usage(argv[0]);
394
395         if (argc == optind + 1)
396                 name = argv[optind];
397
398         if (list) {
399                 for (i = 0; i < sizeof(can_calc_consts) /
400                              sizeof(struct can_bittiming_const); i++)
401                         printf("%s\n", can_calc_consts[i].name);
402                 return 0;
403         }
404
405         if (sampl_pt && (sampl_pt >= 1000 || sampl_pt < 100))
406                 print_usage(argv[0]);
407
408         if (name) {
409                 for (i = 0; i < sizeof(can_calc_consts) /
410                              sizeof(struct can_bittiming_const); i++) {
411                         if (!strcmp(can_calc_consts[i].name, name)) {
412                                 btc = &can_calc_consts[i];
413                                 break;
414                         }
415                 }
416                 if (!btc)
417                         print_usage(argv[0]);
418
419         } else {
420                 btc = &can_calc_consts[0];
421         }
422
423         if (bitrate) {
424                 print_bit_timing(btc, bitrate, sampl_pt, ref_clk, quiet);
425         } else {
426                 for (i = 0; i < sizeof(common_bitrates) / sizeof(long); i++)
427                         print_bit_timing(btc, common_bitrates[i], sampl_pt,
428                                          ref_clk, i);
429         }
430
431         return 0;
432 }