2 * Copyright (C) 2012-2013 Czech Technical University in Prague
4 * Created on: 28.2.2013
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.
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.
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/>.
25 * This file contains commands for CAN test
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;
52 static void canPrintStatus(int can_num, uint32_t es)
54 uint32_t errorLevel = es & 0xE0U;
58 case canLEVEL_BUS_OFF:
61 case canLEVEL_PASSIVE:
62 levText = "Error Passive";
64 case canLEVEL_WARNING:
74 rpp_sci_printf("CAN%d status: %s, ES: %#x\n", can_num, levText, es);
77 uint32_t canCheckForError(int can_num, uint32_t es)
79 uint32_t errorLevel = es & 0xE0U;
81 if (errorLevel != 0) {
82 canPrintStatus(can_num, es);
89 * @brief Command for external CAN loopback testing.
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
96 int cmd_do_test_can_loopback(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
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;
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 };
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);
124 if (sscanf(p, "%d %d %1s", &can_src, &can_dst, &spareParams) != 2) {
125 return -CMDERR_BADPAR;
128 if (can_src == can_dst) {
129 rpp_sci_printf("ERROR: Destination equals source!\n");
132 if (can_src < 1 | can_dst > 3) {
133 rpp_sci_printf("Parameter out of range <1;3>!\n");
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);
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);
147 canDst->CTL |= 1<<15; // Reset
148 while (canDst->CTL & (1<<15)) ; // Wait for reset
150 canSrc->CTL |= 1<<15;
151 while (canSrc->CTL & (1<<15)) ;
155 vTaskDelay(50/portTICK_RATE_MS);
157 i = canSrc->ES; // Reset error flag
158 i = canDst->ES; // Reset error flag
159 canEnableErrorNotification(canDst);
160 canEnableErrorNotification(canSrc);
162 for (i = 0; i < 100; i++) { // Send 100 times the message
163 if (canCheckForError(can_src, canSendError) != canLEVEL_ACTIVE) {
166 canTransmit(canSrc, canMsgBox, tx_data);
167 if (xSemaphoreTake(canMsgSent, 100/portTICK_RATE_MS) == pdFALSE) {
171 if (canCheckForError(can_src, canSendError) & canLEVEL_BUS_OFF) {
175 messagesTransmitted++;
176 if (xSemaphoreTake(canMsgReceived, 100/portTICK_RATE_MS) == pdFALSE) {
180 if (canGetData(canDst, canMsgBox, rx_data))
183 if (canCheckForError(can_dst, canRecError) & canLEVEL_BUS_OFF) {
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);
201 canDisableErrorNotification(canDst);
202 canDisableErrorNotification(canSrc);
203 vSemaphoreDelete(canMsgReceived);
204 vSemaphoreDelete(canMsgSent);
211 static int can_inited = 0;
213 /* Default CAN timing set to 500kb */
214 static struct rpp_can_timing_cfg can_timing[] = {
248 static struct rpp_can_ctrl_config ctrl_config[] = {
252 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
253 .timing_config = NULL
258 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
259 .timing_config = NULL
264 .timing_calc_method = RPP_CAN_TIMING_CALC_AUTO,
265 .timing_config = NULL
269 static struct rpp_can_tx_config tx_config[] = {
271 .type = RPP_CAN_EXTENDED,
276 .type = RPP_CAN_EXTENDED,
281 .type = RPP_CAN_EXTENDED,
287 static struct rpp_can_rx_config rx_config[] = {
289 .type = RPP_CAN_MIXED,
296 .type = RPP_CAN_MIXED,
303 .type = RPP_CAN_MIXED,
311 static struct rpp_can_config can_config = {
314 .tx_config = tx_config,
315 .rx_config = rx_config,
320 int cmd_do_can_init(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
322 dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
323 dmmREG->PC5 = (1<<(15)); // clr CAN_EN
324 dmmREG->PC5 = (1<<(13)); // clr CAN_NSTB
325 dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
326 dmmREG->PC4 = (1<<(15)); // set CAN_EN
330 can_inited = (rpp_can_init(&can_config) == SUCCESS ? 1 : 0);
331 return (can_inited ? 0 : 1);
335 int cmd_do_can_send(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
337 uint32_t controller_id;
340 struct rpp_can_pdu pdu;
345 rpp_sci_printf("CAN is not initialized\n");
346 return -CMDERR_NODEV;
350 ret = sscanf(p, "%i %i%n", &controller_id, &pdu.id, &l);
353 rpp_sci_printf("Cannot parse parameter %d\n", ret+1);
354 return -CMDERR_BADPAR;
361 ret = sscanf(p, "%2hx%n", &data, &l);
363 pdu.data[i] = data & 0xff;
371 if (rpp_can_write(controller_id-1, &pdu) == SUCCESS)
373 rpp_sci_printf("Sent: can%u\t%X\t[%u]\t", controller_id, pdu.id, pdu.dlc);
374 for (i=0; i<pdu.dlc; i++)
376 rpp_sci_printf("%X ", pdu.data[i]);
381 rpp_sci_printf("Error: rpp_can_write");
383 rpp_sci_printf("\n");
390 int cmd_do_can_dump(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
392 uint32_t controller_id = 0;
394 struct rpp_can_pdu pdu;
400 rpp_sci_printf("CAN is not initialized\n");
401 return -CMDERR_NODEV;
404 if (!(sscanf(param[1], "%u", &controller_id) == 1))
406 rpp_sci_printf("Unable to parse controller ID\n");
410 rpp_can_init(&can_config);
412 while(cmd_io->getc(cmd_io) < 0)
414 rpp_can_check_rx_ind(controller_id-1, &rx_ind);
417 if (rpp_can_read(controller_id-1, &pdu) == SUCCESS)
419 if (pdu.id & CAN_EFF_FLAG)
421 rpp_sci_printf("can%u %08X [%u] ", controller_id & (~CAN_EFF_FLAG), pdu.id, pdu.dlc);
425 rpp_sci_printf("can%u %03X [%u] ", controller_id, pdu.id, pdu.dlc);
428 for (i=0; i<pdu.dlc; i++)
430 rpp_sci_printf("%X ", pdu.data[i]);
432 rpp_sci_printf("\n");
436 rpp_sci_printf("Error rpp_can_read\n");
445 int cmd_do_can_change_baudrate(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
448 uint32_t controller_id, baudrate;
450 if ((opchar = cmd_opchar_check(cmd_io, des, param)) < 0)
455 if (!(sscanf(param[1], "%u:%u", &controller_id, &baudrate) == 2))
457 rpp_sci_printf("Unable to parse arguments\n");
461 if (controller_id < 1 || controller_id > 3)
462 return -CMDERR_BADPAR;
464 can_config.ctrl[controller_id-1].baudrate = baudrate;
465 can_config.ctrl[controller_id-1].timing_config = NULL;
466 can_config.ctrl[controller_id-1].timing_calc_method = RPP_CAN_TIMING_CALC_AUTO;
470 if (!(sscanf(param[1], "%u", &controller_id) == 1))
472 if (controller_id < 1 || controller_id > 3)
473 return -CMDERR_BADPAR;
475 cmd_opchar_replong(cmd_io, param, can_config.ctrl[controller_id-1].baudrate, 0, 10);
481 int cmd_do_can_change_timing(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
484 uint32_t controller_id, brp, prop_seg, phase_seg1, phase_seg2, sjw;
486 if ((opchar = cmd_opchar_check(cmd_io, des, param)) < 0)
491 if (!(sscanf(param[1], "%u:%u %u %u %u %u", &controller_id, &brp, &prop_seg, &phase_seg1, &phase_seg2, &sjw) == 6))
493 rpp_sci_printf("Unable to parse arguments\n");
497 if (controller_id < 1 || controller_id > 3)
498 return -CMDERR_BADPAR;
500 can_config.ctrl[controller_id-1].baudrate = 0;
501 can_config.ctrl[controller_id-1].timing_config = &can_timing[controller_id-1];
502 can_config.ctrl[controller_id-1].timing_config->brp = brp;
503 can_config.ctrl[controller_id-1].timing_config->phase_seg1 = phase_seg1;
504 can_config.ctrl[controller_id-1].timing_config->phase_seg2 = phase_seg2;
505 can_config.ctrl[controller_id-1].timing_config->prop_seg = prop_seg;
506 can_config.ctrl[controller_id-1].timing_config->sjw = sjw;
507 can_config.ctrl[controller_id-1].timing_calc_method = RPP_CAN_TIMING_CALC_MANUAL;
511 if (!(sscanf(param[1], "%u", &controller_id) == 1))
513 if (controller_id < 1 || controller_id > 3)
514 return -CMDERR_BADPAR;
516 if (can_config.ctrl[controller_id-1].timing_config != NULL) {
517 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\nsample_pt: %u ns\r\nerror: %u\r\n tQ: %u ns\r\n",
518 can_config.ctrl[controller_id-1].timing_config->brp,
519 can_config.ctrl[controller_id-1].timing_config->prop_seg,
520 can_config.ctrl[controller_id-1].timing_config->phase_seg1,
521 can_config.ctrl[controller_id-1].timing_config->phase_seg2,
522 can_config.ctrl[controller_id-1].timing_config->sjw,
523 can_config.ctrl[controller_id-1].timing_config->sampl_pt,
524 can_config.ctrl[controller_id-1].timing_config->error,
525 can_config.ctrl[controller_id-1].timing_config->tq
530 rpp_sci_printf("CAN timing has not yet been manualy specified.\r\n");
542 /** @brief command descriptor for test CAN loopback command */
543 cmd_des_t const cmd_des_test_can_loopback={
545 "cantest*", "Test CAN loopback between two CAN interfaces",
546 "### Command syntax ###\n"
548 " cantest<SRC> <DST>\n"
550 "where `<SRC>` and `<DST>` are different numbers in range 1-3.\n"
552 "### Description ###\n"
554 "This command tests CAN communication by sending and receiving messages\n"
555 "through external loopback. At the beginning, the involved CAN\n"
556 "controller are initialized to the Bus-On state.\n"
558 "The command sends 100 messages and measures the numbers of TX errors,\n"
559 "RX errors and detected timeouts. At the end, these statistics are\n"
560 "printed as well as the status of the involved CAN controllers.\n"
562 "When an error is detected during the test, the status of faulty CAN\n"
563 "controller is printed immediately.\n"
568 " Testing CAN loopback\n"
569 " Messages transmitted: 100/100\n"
570 " Messages received: 100/100\n"
573 " Src TX error counter: 0\n"
574 " Src RX error counter: 0\n"
575 " Dst TX error counter: 0\n"
576 " Dst RX error counter: 0\n"
577 " CAN1 status: Bus-On, ES: 0x8\n"
578 " CAN2 status: Bus-On, ES: 0x10\n",
579 CMD_HANDLER(cmd_do_test_can_loopback), (void *)&cmd_list_can
583 cmd_des_t const cmd_des_can_init={
585 "caninit", "Initialize CAN controllers",
586 "### Command syntax ###\n"
590 "### Description ###\n"
592 "This command (re-)initializes all CAN controllers using current\n"
593 "CAN configuration. This configuration can be changed using\n"
594 "canbaudrate command.\n"
596 "In the default configuration the baudrate of all CAN controllers i set\n"
601 CMD_HANDLER(cmd_do_can_init), (void *)&cmd_list_can
604 cmd_des_t const cmd_des_can_baudrate={
605 0, CDESM_OPCHR|CDESM_RW,
606 "canbaudrate#", "Change baudrate of CAN controller",
607 "### Command syntax ###\n"
609 " canbaudrate<CONTROLLER>?\n"
610 " canbaudrate<CONTROLLER>:<BAUDRATE>\n"
612 "where `<CONTROLLER>` is number in range 1-3 and BAUDRATE is number in\n"
613 "range 1000-10000000 specifying the baudrate in bits per second.\n"
615 "### Description ###\n"
617 "This command is used to set or show the baudrate of a CAN controller.\n"
618 "The baudrate shown is the one which will be used by next invocation of\n"
619 "the caninit command.\n"
620 "The baudrate specified by the command is used to automatic calculation of\n"
621 "the CAN controller timing. If you want to specify the timing manually,\n"
622 "please use the command cantiming.\n"
623 "The automatic calculation might not work properly for some baudrates. In\n"
624 "this case you should calculate the timing manually and specify it by the\n"
629 " --> canbaudrate2?\n"
630 " canbaudrate2=500000\n"
632 " --> canbaudrate2:100000\n",
633 CMD_HANDLER(cmd_do_can_change_baudrate), (void *)&cmd_list_can
636 cmd_des_t const cmd_des_can_timing={
637 0, CDESM_OPCHR|CDESM_RW,
638 "cantiming#", "Change timing of CAN controller manually",
639 "### Command syntax ###\n"
641 " cantiming<CONTROLLER>?\n"
642 " cantiming<CONTROLLER>:<BRP> <PROP_SEG> <PHASE_SEG1> <PHASE_SEG2> <SJW>\n"
645 " - `<CONTROLLER>` is number in range 1-3\n"
646 " - `<BRP>` (baudrate prescaler) is number in range 1-65\n"
647 " - `<PROP_SEG>` (length of propagation segment in tQ) is a number in range 1-8\n"
648 " - `<PHASE_SEG1>` (phase buffer segment 1 in tQ) is a number in range 1-8\n"
649 " - `<PHASE_SEG2>` (phase buffer segment 2 in tQ) is a number in range 1-8\n"
650 " - `<SJW>` (synchronization jump width in tQ) is a number in range 1-4\n"
652 "### Description ###\n"
654 "This command is used to set or show the timing of a CAN controller.\n"
655 "The timing shown is the one which will be used by next invocation of\n"
656 "the caninit command.\n"
657 "The timing configured by this command defines manually the baudrate of\n"
658 "the CAN controller. If you want to calculate the timing automaticaly from\n"
659 "a baudrate, please use the command canbaudrate.\n"
666 " phase_seg1: 5 tQ\n"
667 " phase_seg2: 5 tQ\n"
669 " sample_pt: 875 ns\n"
673 " --> cantiming2:5 8 7 4 1\n",
674 CMD_HANDLER(cmd_do_can_change_timing), (void *)&cmd_list_can
678 cmd_des_t const cmd_des_can_send={
680 "cansend", "Test sending message over CAN",
681 "### Command syntax ###\n"
683 " cansend <CONTROLLER> <ID> <DATA>\n"
685 "where `<CONTROLLER>` is number in range 1-3, `<ID>` is a valid CAN ID\n"
686 "and `<DATA>` is 0-8 bytes of data in hexadecimal representation.\n"
687 "There may be any number of spaces between the data bytes.\n"
688 "`<ID>` may be given in octal, decimal or hexadecimal base.\n"
690 "### Description ###\n"
692 "This command sends a CAN frame using specified CAN controller.\n"
694 "The caninit command must be called before using this command.\n"
697 " --> cansend 2 0x123 DEAD BEEF\n"
698 " Sent: can2 123 [4] DE AD BE EF\n",
699 CMD_HANDLER(cmd_do_can_send), (void *)&cmd_list_can
703 cmd_des_t const cmd_des_can_dump={
705 "candump", "Dump all messages received over CAN",
706 "### Command syntax ###\n"
708 " candump <CONTROLLER>\n"
710 "where `<CONTROLLER>` is a number in range 1-3.\n"
712 "### Description ###\n"
714 "This command prints out all CAN messages received via the specified\n"
717 "IDs are zero-filled to length 3 if a message in the standard frame\n"
718 "format is received and to 8 for extended frame format messages.\n"
720 "caninit must be called before using this command.\n"
725 "can2 0000FADE [2] 12 34\n",
726 CMD_HANDLER(cmd_do_can_dump), (void *)&cmd_list_can
731 cmd_des_t const *cmd_list_can[]={
732 &cmd_des_test_can_loopback,
734 &cmd_des_can_baudrate,