]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_can.c
Library update, excessive struct params remove
[pes-rpp/rpp-test-sw.git] / rpp-test-sw / commands / cmd_can.c
1 /*
2  * Copyright (C) 2012-2013 Czech Technical University in Prague
3  *
4  * Created on: 28.2.2013
5  *
6  * Authors:
7  *     - Michal Horn
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * File : cmd_can.c
23  *
24  * Abstract:
25  *      This file contains commands for CAN test
26  *
27  */
28
29 #include "cmd_can.h"
30
31 #ifndef DOCGEN
32
33 #include "rpp/rpp.h"
34 #include "sys/sys.h"
35 #include <stdio.h>
36
37 /** Semaphore used for blocking task until message is received */
38 extern xSemaphoreHandle canMsgReceived;
39 /** Semaphore used for blocking task until message is sent */
40 extern xSemaphoreHandle canMsgSent;
41 /** Pointer to Destination CAN registers */
42 extern canBASE_t* canDst;
43 /** Pointer to Source CAN registers */
44 extern canBASE_t* canSrc;
45 /** Can message box for received messages */
46 extern uint32_t canMsgBox;
47 /** Error counter for errors in sending */
48 extern uint32_t canSendError;
49 /** Error counter for errors in receiving */
50 extern uint32_t canRecError;
51
52 static void canPrintStatus(int can_num, uint32_t es)
53 {
54         uint32_t errorLevel = es & 0xE0U;
55         char* levText;
56
57         switch (errorLevel) {
58         case canLEVEL_BUS_OFF:
59                 levText = "Bus-Off";
60                 break;
61         case canLEVEL_PASSIVE:
62                 levText = "Error Passive";
63                 break;
64         case canLEVEL_WARNING:
65                 levText = "Warning";
66                 break;
67         case canLEVEL_ACTIVE:
68                 levText = "Bus-On";
69                 break;
70         default:
71                 levText = "Unknown";
72         }
73
74         rpp_sci_printf("CAN%d status: %s, ES: %#x\n", can_num, levText, es);
75 }
76
77 uint32_t canCheckForError(int can_num, uint32_t es)
78 {
79         uint32_t errorLevel = es & 0xE0U;
80
81         if (errorLevel != 0) {
82                 canPrintStatus(can_num, es);
83         }
84
85         return errorLevel;
86 }
87
88 /**
89  *      @brief  Command for external CAN loopback testing.
90  *
91  * @param[in]   cmd_io  Pointer to IO stack
92  * @param[in]   des             Pointer to command descriptor
93  * @param[in]   param   Parameters of command
94  * @return      0 when OK or error code
95  */
96 int cmd_do_test_can_loopback(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
97 {
98         uint32_t can_src, can_dst;
99         canBASE_t *canBases[3] = {canREG1, canREG2, canREG3};
100         uint32_t canMailBoxes[3] = {canMESSAGE_BOX1, canMESSAGE_BOX2, canMESSAGE_BOX3};
101         uint32_t txTimeOutCnt = 0;
102         uint32_t rxTimeOutCnt = 0;
103         uint32_t messagesTransmitted = 0;
104         uint32_t messagesReceived = 0;
105         uint32_t i;
106         uint8_t tx_data[8] = {'T', 'E', 'S', 'T', ' ', 'C', 'A', 'N'};
107         uint8_t rx_data[8] = {0, 0, 0, 0, 0, 0, 0, 0 };
108         char *p=param[1];
109         char spareParams;
110
111
112         dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
113         vTaskDelay(50/portTICK_RATE_MS);
114         dmmREG->PC5 = (1<<(15)); // clr CAN_EN
115         vTaskDelay(50/portTICK_RATE_MS);
116         dmmREG->PC5 = (1<<(13)); // clr CAN_NSTB
117         vTaskDelay(50/portTICK_RATE_MS);
118         dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
119         vTaskDelay(50/portTICK_RATE_MS);
120         dmmREG->PC4 = (1<<(15)); // set CAN_EN
121         vTaskDelay(50/portTICK_RATE_MS);
122
123
124         if (sscanf(p, "%d %d %1s", &can_src, &can_dst, &spareParams) != 2) {
125                 return -CMDERR_BADPAR;
126         }
127
128         if (can_src == can_dst) {
129                 rpp_sci_printf("ERROR: Destination equals source!\n");
130                 return 1;
131         }
132         if (can_src < 1 | can_dst > 3) {
133                 rpp_sci_printf("Parameter out of range <1;3>!\n");
134                 return 1;
135         }
136         canSrc = canBases[can_src-1];
137         canDst = canBases[can_dst-1];
138         canMsgBox = canMailBoxes[can_src-1];
139         canMsgReceived = xSemaphoreCreateCounting(1, 0);
140         canMsgSent = xSemaphoreCreateCounting(1, 0);
141
142         rpp_sci_printf("Testing CAN loopback\r\n");
143         canREG1->CTL |= 1|(1<<9);
144         canREG2->CTL |= 1|(1<<9);
145         canREG3->CTL |= 1|(1<<9);
146         canRecError = 0;
147         canDst->CTL |= 1<<15;           // Reset
148         while (canDst->CTL & (1<<15)) ; // Wait for reset
149         canSendError = 0;
150         canSrc->CTL |= 1<<15;
151         while (canSrc->CTL & (1<<15)) ;
152         canInit();
153         canDst->CTL |= 1<<9;
154         canSrc->CTL |= 1<<9;
155         vTaskDelay(50/portTICK_RATE_MS);
156
157         i = canSrc->ES; // Reset error flag
158         i = canDst->ES; // Reset error flag
159         canEnableErrorNotification(canDst);
160         canEnableErrorNotification(canSrc);
161
162         for (i = 0; i < 100; i++) {             // Send 100 times the message
163                 if (canCheckForError(can_src, canSendError) != canLEVEL_ACTIVE) {
164                         break;
165                 }
166                 canTransmit(canSrc, canMsgBox, tx_data);
167                 if (xSemaphoreTake(canMsgSent, 100/portTICK_RATE_MS) == pdFALSE) {
168                         txTimeOutCnt++;
169                 }
170                 else {
171                         if (canCheckForError(can_src, canSendError) & canLEVEL_BUS_OFF) {
172                                 break;
173                         }
174                         else {
175                                 messagesTransmitted++;
176                                 if (xSemaphoreTake(canMsgReceived, 100/portTICK_RATE_MS) == pdFALSE) {
177                                         rxTimeOutCnt++;
178                                 }
179                                 else {
180                                         if (canGetData(canDst, canMsgBox, rx_data))
181                                                 messagesReceived++;
182
183                                         if (canCheckForError(can_dst, canRecError) & canLEVEL_BUS_OFF) {
184                                                 break;
185                                         }
186                                 }
187                         }
188                 }
189
190                 rpp_sci_printf("Messages transmitted: %d/100\r\n", messagesTransmitted);
191                 rpp_sci_printf("Messages received: %d/100\r\n", messagesReceived);
192                 rpp_sci_printf("TX timeouts: %d\r\n", txTimeOutCnt);
193                 rpp_sci_printf("RX timeouts: %d\r\n", rxTimeOutCnt);
194                 rpp_sci_printf("Src TX error counter: %d\r\n", canSrc->EERC & 0xFFU);
195                 rpp_sci_printf("Src RX error counter: %d\r\n", (canSrc->EERC & 0xFF00U) >> 8);
196                 rpp_sci_printf("Dst TX error counter: %d\r\n", canDst->EERC & 0xFFU);
197                 rpp_sci_printf("Dst RX error counter: %d\r\n", (canDst->EERC & 0xFF00U) >> 8);
198                 canPrintStatus(can_src, canSendError);
199                 canPrintStatus(can_dst, canRecError);
200
201                 canDisableErrorNotification(canDst);
202                 canDisableErrorNotification(canSrc);
203                 vSemaphoreDelete(canMsgReceived);
204                 vSemaphoreDelete(canMsgSent);
205                 return 0;
206         }
207         return 0;
208 }
209
210
211 static int can_inited = 0;
212
213 /* Default CAN timing set to 500kb */
214 static struct rpp_can_timing_cfg can_timing[] = {
215         {
216                 .brp = 10,
217                 .phase_seg1 = 5,
218                 .phase_seg2 = 2,
219                 .prop_seg = 8,
220                 .sjw = 1
221         },
222         {
223                 .brp = 10,
224                 .phase_seg1 = 5,
225                 .phase_seg2 = 2,
226                 .prop_seg = 8,
227                 .sjw = 1
228         },
229         {
230                 .brp = 10,
231                 .phase_seg1 = 5,
232                 .phase_seg2 = 2,
233                 .prop_seg = 8,
234                 .sjw = 1
235         },
236 };
237
238
239 static struct rpp_can_ctrl_config ctrl_config[] = {
240         {
241                 .baudrate = 500000,
242                 .clk = 80000000,
243                 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
244                 .timing_config = NULL
245         },
246         {
247                 .baudrate = 500000,
248                 .clk = 80000000,
249                 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
250                 .timing_config = NULL
251         },
252         {
253                 .baudrate = 500000,
254                 .clk = 80000000,
255                 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
256                 .timing_config = NULL
257         }
258 };
259
260 static struct rpp_can_tx_config tx_config[] = {
261         {
262                 .type = RPP_CAN_EXTENDED,
263                 .controller = 1,
264                 .msg_obj = 2,
265         },
266         {
267                 .type = RPP_CAN_EXTENDED,
268                 .controller = 2,
269                 .msg_obj = 2,
270         },
271         {
272                 .type = RPP_CAN_EXTENDED,
273                 .controller = 3,
274                 .msg_obj = 2,
275         }
276 };
277
278 static struct rpp_can_rx_config rx_config[] = {
279         {
280                 .type = RPP_CAN_MIXED,
281                 .controller = 1,
282                 .msg_obj = 1,
283                 .id = 1,
284                 .mask = 0,
285         },
286         {
287                 .type = RPP_CAN_MIXED,
288                 .controller = 2,
289                 .msg_obj = 1,
290                 .id = 1,
291                 .mask = 0,
292         },
293         {
294                 .type = RPP_CAN_MIXED,
295                 .controller = 3,
296                 .msg_obj = 1,
297                 .id = 1,
298                 .mask = 0,
299         }
300 };
301
302 static struct rpp_can_config can_config = {
303         .num_tx_obj = 3,
304         .num_rx_obj = 3,
305         .tx_config = tx_config,
306         .rx_config = rx_config,
307         .ctrl = ctrl_config,
308 };
309
310
311 int cmd_do_can_init(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
312 {
313     dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
314     dmmREG->PC5 = (1<<(15)); // clr CAN_EN
315     dmmREG->PC5 = (1<<(13)); // clr CAN_NSTB
316     dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
317     dmmREG->PC4 = (1<<(15)); // set CAN_EN
318
319
320
321     can_inited = (rpp_can_init(&can_config) == SUCCESS ? 1 : 0);
322     return (can_inited ? 0 : 1);
323 }
324
325
326 int cmd_do_can_send(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
327 {
328         uint32_t controller_id;
329         uint32_t i, l = 0;
330         int ret;
331         struct rpp_can_pdu pdu;
332         char *p;
333
334         if (!can_inited)
335         {
336                 rpp_sci_printf("CAN is not initialized\n");
337                 return -CMDERR_NODEV;
338         }
339
340         p = param[1];
341         ret = sscanf(p, "%i %i%n", &controller_id, &pdu.id, &l);
342         if (ret < 2)
343         {
344                 rpp_sci_printf("Cannot parse parameter %d\n", ret+1);
345                 return -CMDERR_BADPAR;
346         }
347         p += l;
348
349         i = 0;
350         do {
351                 uint16_t data;
352                 ret = sscanf(p, "%2hx%n", &data, &l);
353                 if (ret < 1) break;
354                 pdu.data[i] = data & 0xff;
355                 i++;
356                 p += l;
357         } while (1);
358
359         pdu.dlc = i;
360
361
362         if (rpp_can_write(controller_id-1, &pdu) == SUCCESS)
363         {
364                 rpp_sci_printf("Sent: can%u\t%X\t[%u]\t", controller_id, pdu.id, pdu.dlc);
365                 for (i=0; i<pdu.dlc; i++)
366                 {
367                         rpp_sci_printf("%X ", pdu.data[i]);
368                 }
369         }
370         else
371         {
372                 rpp_sci_printf("Error: rpp_can_write");
373         }
374         rpp_sci_printf("\n");
375
376
377         return 0;
378 }
379
380
381 int cmd_do_can_dump(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
382 {
383         uint32_t controller_id = 0;
384         bool rx_ind;
385         struct rpp_can_pdu pdu;
386
387         uint32_t i;
388
389         if (!can_inited)
390         {
391                 rpp_sci_printf("CAN is not initialized\n");
392                 return -CMDERR_NODEV;
393         }
394
395         if (!(sscanf(param[1], "%u", &controller_id) == 1))
396         {
397                 rpp_sci_printf("Unable to parse controller ID\n");
398                 return 1;
399         }
400
401         rpp_can_init(&can_config);
402
403         while(cmd_io->getc(cmd_io) < 0)
404         {
405                 rpp_can_check_rx_ind(controller_id-1, &rx_ind);
406                 if (rx_ind)
407                 {
408                         if (rpp_can_read(controller_id-1, &pdu) == SUCCESS)
409                         {
410                                 if (pdu.id & CAN_EFF_FLAG)
411                                 {
412                                         rpp_sci_printf("can%u  %08X  [%u]  ", controller_id & (~CAN_EFF_FLAG), pdu.id, pdu.dlc);
413                                 }
414                                 else
415                                 {
416                                         rpp_sci_printf("can%u  %03X  [%u]  ", controller_id, pdu.id, pdu.dlc);
417                                 }
418
419                                 for (i=0; i<pdu.dlc; i++)
420                                 {
421                                             rpp_sci_printf("%X ", pdu.data[i]);
422                                 }
423                                 rpp_sci_printf("\n");
424                         }
425                         else
426                         {
427                                 rpp_sci_printf("Error rpp_can_read\n");
428                         }
429                 }
430         }
431
432         return 0;
433 }
434
435
436 int cmd_do_can_change_baudrate(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
437 {
438         int opchar;
439         uint32_t controller_id, baudrate;
440
441         if ((opchar = cmd_opchar_check(cmd_io, des, param)) < 0)
442                 return opchar;
443
444         if (opchar == ':')
445         {
446                 if (!(sscanf(param[1], "%u:%u", &controller_id, &baudrate) == 2))
447                 {
448                         rpp_sci_printf("Unable to parse arguments\n");
449                         return 1;
450                 }
451
452                 if (controller_id < 1 || controller_id > 3)
453                         return -CMDERR_BADPAR;
454
455                 can_config.ctrl[controller_id-1].baudrate = baudrate;
456                 can_config.ctrl[controller_id-1].timing_config = NULL;
457                 can_config.ctrl[controller_id-1].timing_calc_method = RPP_CAN_TIMING_CALC_AUTO;
458         }
459         else
460         {
461                 if (!(sscanf(param[1], "%u", &controller_id) == 1))
462
463                 if (controller_id < 1 || controller_id > 3)
464                         return -CMDERR_BADPAR;
465
466                 cmd_opchar_replong(cmd_io, param, can_config.ctrl[controller_id-1].baudrate, 0, 10);
467         }
468
469         return 0;
470 }
471
472 int cmd_do_can_change_timing(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
473 {
474         int opchar;
475         uint32_t controller_id, brp, prop_seg, phase_seg1, phase_seg2, sjw;
476
477         if ((opchar = cmd_opchar_check(cmd_io, des, param)) < 0)
478                 return opchar;
479
480         if (opchar == ':')
481         {
482                 if (!(sscanf(param[1], "%u:%u %u %u %u %u", &controller_id, &brp, &prop_seg, &phase_seg1, &phase_seg2, &sjw) == 6))
483                 {
484                         rpp_sci_printf("Unable to parse arguments\n");
485                         return 1;
486                 }
487
488                 if (controller_id < 1 || controller_id > 3)
489                         return -CMDERR_BADPAR;
490
491                 can_config.ctrl[controller_id-1].baudrate = 0;
492                 can_config.ctrl[controller_id-1].timing_config = &can_timing[controller_id-1];
493                 can_config.ctrl[controller_id-1].timing_config->brp = brp;
494                 can_config.ctrl[controller_id-1].timing_config->phase_seg1 = phase_seg1;
495                 can_config.ctrl[controller_id-1].timing_config->phase_seg2 = phase_seg2;
496                 can_config.ctrl[controller_id-1].timing_config->prop_seg = prop_seg;
497                 can_config.ctrl[controller_id-1].timing_config->sjw = sjw;
498                 can_config.ctrl[controller_id-1].timing_calc_method = RPP_CAN_TIMING_CALC_MANUAL;
499         }
500         else
501         {
502                 if (!(sscanf(param[1], "%u", &controller_id) == 1))
503
504                 if (controller_id < 1 || controller_id > 3)
505                         return -CMDERR_BADPAR;
506
507                 if (can_config.ctrl[controller_id-1].timing_config != NULL) {
508                         rpp_sci_printf("brp: %u\r\nprop_seg: %u tQ\r\nphase_seg1: %u tQ\r\nphase_seg2: %u tQ\r\nsjw: %u tQ\r\n",
509                                         can_config.ctrl[controller_id-1].timing_config->brp,
510                                         can_config.ctrl[controller_id-1].timing_config->prop_seg,
511                                         can_config.ctrl[controller_id-1].timing_config->phase_seg1,
512                                         can_config.ctrl[controller_id-1].timing_config->phase_seg2,
513                                         can_config.ctrl[controller_id-1].timing_config->sjw
514                         );
515
516                 }
517                 else {
518                         rpp_sci_printf("CAN timing has not yet been manually specified.\r\n");
519                 }
520         }
521
522         return 0;
523 }
524
525
526
527
528 #endif  /* DOCGEN */
529
530 /** @brief command descriptor for test CAN loopback command */
531 cmd_des_t const cmd_des_test_can_loopback={
532     0, 0,
533     "cantest*", "Test CAN loopback between two CAN interfaces",
534     "### Command syntax ###\n"
535     "\n"
536     "    cantest<SRC> <DST>\n"
537     "\n"
538     "where `<SRC>` and `<DST>` are different numbers in range 1-3.\n"
539     "\n"
540     "### Description ###\n"
541     "\n"
542     "This command tests CAN communication by sending and receiving messages\n"
543     "through external loopback. At the beginning, the involved CAN\n"
544     "controller are initialized to the Bus-On state.\n"
545     "\n"
546     "The command sends 100 messages and measures the numbers of TX errors,\n"
547     "RX errors and detected timeouts. At the end, these statistics are\n"
548     "printed as well as the status of the involved CAN controllers.\n"
549     "\n"
550     "When an error is detected during the test, the status of faulty CAN\n"
551     "controller is printed immediately.\n"
552     "\n"
553     "### Example ###\n"
554     "\n"
555     "    --> cantest1 2\n"
556     "    Testing CAN loopback\n"
557     "    Messages transmitted: 100/100\n"
558     "    Messages received: 100/100\n"
559     "    TX timeouts: 0\n"
560     "    RX timeouts: 0\n"
561     "    Src TX error counter: 0\n"
562     "    Src RX error counter: 0\n"
563     "    Dst TX error counter: 0\n"
564     "    Dst RX error counter: 0\n"
565     "    CAN1 status: Bus-On, ES: 0x8\n"
566     "    CAN2 status: Bus-On, ES: 0x10\n",
567     CMD_HANDLER(cmd_do_test_can_loopback), (void *)&cmd_list_can
568 };
569
570
571 cmd_des_t const cmd_des_can_init={
572     0, 0,
573     "caninit", "Initialize CAN controllers",
574     "### Command syntax ###\n"
575     "\n"
576     "    caninit\n"
577     "\n"
578     "### Description ###\n"
579     "\n"
580     "This command (re-)initializes all CAN controllers using current\n"
581     "CAN configuration. This configuration can be changed using\n"
582     "canbaudrate command.\n"
583     "\n"
584     "In the default configuration the baudrate of all CAN controllers i set\n"
585     "to 500 kbit/s.\n"
586     "\n"
587     "### Example ###\n"
588     "  --> caninit\n",
589     CMD_HANDLER(cmd_do_can_init), (void *)&cmd_list_can
590 };
591
592 cmd_des_t const cmd_des_can_baudrate={
593     0, CDESM_OPCHR|CDESM_RW,
594     "canbaudrate#", "Change baudrate of CAN controller",
595     "### Command syntax ###\n"
596     "\n"
597     "    canbaudrate<CONTROLLER>?\n"
598     "    canbaudrate<CONTROLLER>:<BAUDRATE>\n"
599     "\n"
600     "where `<CONTROLLER>` is number in range 1-3 and BAUDRATE is number in\n"
601     "range 1000-10000000 specifying the baudrate in bits per second.\n"
602     "\n"
603     "### Description ###\n"
604     "\n"
605     "This command is used to set or show the baudrate of a CAN controller.\n"
606     "The baudrate shown is the one which will be used by next invocation of\n"
607     "the caninit command.\n"
608     "The baudrate specified by the command is used to automatic calculation of\n"
609     "the CAN controller timing. If you want to specify the timing manually,\n"
610     "please use the command cantiming.\n"
611     "The automatic calculation might not work properly for some baudrates. In\n"
612     "this case you should calculate the timing manually and specify it by the\n"
613     "command cantiming."
614     "\n"
615     "### Examples ###\n"
616     "\n"
617     "    --> canbaudrate2?\n"
618     "    canbaudrate2=500000\n"
619     "\n"
620     "    --> canbaudrate2:100000\n",
621     CMD_HANDLER(cmd_do_can_change_baudrate), (void *)&cmd_list_can
622 };
623
624 cmd_des_t const cmd_des_can_timing={
625     0, CDESM_OPCHR|CDESM_RW,
626     "cantiming#", "Change timing of CAN controller manually",
627     "### Command syntax ###\n"
628     "\n"
629     "    cantiming<CONTROLLER>?\n"
630     "    cantiming<CONTROLLER>:<BRP> <PROP_SEG> <PHASE_SEG1> <PHASE_SEG2> <SJW>\n"
631     "\n"
632     "where:"
633     " - `<CONTROLLER>` is number in range 1-3\n"
634     " - `<BRP>` (baudrate prescaler) is number in range 1-65\n"
635     " - `<PROP_SEG>` (length of propagation segment in tQ) is a number in range 1-8\n"
636     " - `<PHASE_SEG1>` (phase buffer segment 1 in tQ) is a number in range 1-8\n"
637     " - `<PHASE_SEG2>` (phase buffer segment 2 in tQ) is a number in range 1-8\n"
638     " - `<SJW>` (synchronization jump width in tQ) is a number in range 1-4\n"
639     "\n"
640     "### Description ###\n"
641     "\n"
642     "This command is used to set or show the timing of a CAN controller.\n"
643     "The timing shown is the one which will be used by next invocation of\n"
644     "the caninit command.\n"
645     "The timing configured by this command defines manually the baudrate of\n"
646     "the CAN controller. If you want to calculate the timing automaticaly from\n"
647     "a baudrate, please use the command canbaudrate.\n"
648     "\n"
649     "### Examples ###\n"
650     "\n"
651     "    --> cantiming2?\n"
652     "    brp: 17\n"
653     "    prop_seg: 4 tQ\n"
654     "    phase_seg1: 5 tQ\n"
655     "    phase_seg2: 5 tQ\n"
656     "    sjw: 4 tQ\n"
657     "    sample_pt: 875 ns\n"
658     "    error: 0\n"
659     "    tQ: 125 ns\n"
660     "\n"
661     "    --> cantiming2:5 8 7 4 1\n",
662     CMD_HANDLER(cmd_do_can_change_timing), (void *)&cmd_list_can
663 };
664
665
666 cmd_des_t const cmd_des_can_send={
667     0, 0,
668     "cansend", "Test sending message over CAN",
669     "### Command syntax ###\n"
670     "\n"
671     "    cansend <CONTROLLER> <ID> <DATA>\n"
672     "\n"
673     "where `<CONTROLLER>` is number in range 1-3, `<ID>` is a valid CAN ID\n"
674     "and `<DATA>` is 0-8 bytes of data in hexadecimal representation.\n"
675     "There may be any number of spaces between the data bytes.\n"
676     "`<ID>` may be given in octal, decimal or hexadecimal base.\n"
677     "\n"
678     "### Description ###\n"
679     "\n"
680     "This command sends a CAN frame using specified CAN controller.\n"
681     "\n"
682     "The caninit command must be called before using this command.\n"
683     "\n"
684     "### Example ###\n"
685     "    --> cansend 2 0x123 DEAD BEEF\n"
686     "    Sent: can2      123     [4]     DE AD BE EF\n",
687     CMD_HANDLER(cmd_do_can_send), (void *)&cmd_list_can
688 };
689
690
691 cmd_des_t const cmd_des_can_dump={
692     0, 0,
693     "candump", "Dump all messages received over CAN",
694     "### Command syntax ###\n"
695     "\n"
696     "    candump <CONTROLLER>\n"
697     "\n"
698     "where `<CONTROLLER>` is a number in range 1-3.\n"
699     "\n"
700     "### Description ###\n"
701     "\n"
702     "This command prints out all CAN messages received via the specified\n"
703     "controller.\n"
704     "\n"
705     "IDs are zero-filled to length 3 if a message in the standard frame\n"
706     "format is received and to 8 for extended frame format messages.\n"
707     "\n"
708     "caninit must be called before using this command.\n"
709     "\n"
710     "### Example ###\n"
711     "\n"
712     "    --> candump 2\n"
713     "can2  0000FADE  [2]  12 34\n",
714     CMD_HANDLER(cmd_do_can_dump), (void *)&cmd_list_can
715 };
716
717
718
719 cmd_des_t const *cmd_list_can[]={
720   &cmd_des_test_can_loopback,
721   &cmd_des_can_init,
722   &cmd_des_can_baudrate,
723   &cmd_des_can_timing,
724   &cmd_des_can_send,
725   &cmd_des_can_dump,
726   NULL
727 };