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
29 #include "commands/cmd_can.h"
37 /** Semaphore used for blocking task until message is received */
38 xSemaphoreHandle canMsgReceived;
39 /** Semaphore used for blocking task until message is sent */
40 xSemaphoreHandle canMsgSent;
41 /** Pointer to Destination CAN registers */
43 /** Pointer to Source CAN registers */
45 /** Can message box for received messages */
47 /** Error counter for errors in sending */
48 uint32_t canSendError;
49 /** Error counter for errors in receiving */
53 * @brief Function for printing CAN error status
55 * Function prints CAN status as a human readable string and status code.
57 * @note The function canInit has to be called before this function can be used.
59 * @param[in] node Pointer to CAN registers
60 * @param[in] str String to be printed befor status and code
61 * @param[in] errorStatus Code of the CAN status
62 * @param[in] isFinal 0 when error testing during sending and receiving
63 * 1 when final printout was requested
65 uint32_t canCheckForError(canBASE_t *node, const char* str, uint32_t *errorStatus, uint8_t isFinal)
67 //uint32_t errorStatus = node->ES;
68 uint32_t errorLevel = *errorStatus & 0xE0U;
69 uint32_t errStat = *errorStatus;
70 char* levText = "Unknown level. ES: 0x";
73 if (*errorStatus != 0) {
74 if (errorLevel & canLEVEL_BUS_OFF) {
75 levText = "CAN bus is off. ES: 0x";
77 else if (errorLevel & canLEVEL_PASSIVE) {
78 levText = "CAN bus in passive mode. ES: 0x";
80 else if (errorLevel & canLEVEL_WARNING) {
81 levText = "CAN bus in passive mode. ES: 0x";
83 else if (errorLevel == canLEVEL_ACTIVE) {
85 levText = "CAN is active. ES: 0x";
93 levText = "CAN no error. ES: 0x";
98 if (levText == NULL) return errorLevel;
101 rpp_sci_printf(levText);
102 rpp_sci_printf("%h\r\n", errStat);
108 * @brief Command for external CAN loopback testing.
110 * Command syntax: testcan src dest, where src and dest are numbers of CAN in range 1 - 3 and can not be equal.
112 * Command resets CAN bus and than sends 100 times message from source and destination.
113 * During the sending process number of tx errors, rx errors, tx timeouts and rx timeouts is being tracked.
115 * @param[in] cmd_io Pointer to IO stack
116 * @param[in] des Pointer to command descriptor
117 * @param[in] param Parameters of command
118 * @return 0 when OK or error code
120 int cmd_do_test_can_loopback(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
123 canBASE_t *canBases[3] = {canREG1, canREG2, canREG3};
124 uint32_t canMailBoxes[3] = {canMESSAGE_BOX1, canMESSAGE_BOX2, canMESSAGE_BOX3};
126 uint32_t txTimeOutCnt = 0;
127 uint32_t rxTimeOutCnt = 0;
128 uint32_t messagesTransmitted = 0;
129 uint32_t messagesReceived = 0;
131 uint8_t tx_data[8] = {'T', 'E', 'S', 'T', ' ', 'C', 'A', 'N'};
132 uint8_t rx_data[8] = {0, 0, 0, 0, 0, 0, 0, 0 };
135 dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
136 vTaskDelay(50/portTICK_RATE_MS);
137 dmmREG->PC5 = (1<<(15)); // clr CAN_EN
138 vTaskDelay(50/portTICK_RATE_MS);
139 dmmREG->PC5 = (1<<(13)); // clr CAN_NSTB
140 vTaskDelay(50/portTICK_RATE_MS);
141 dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
142 vTaskDelay(50/portTICK_RATE_MS);
143 dmmREG->PC4 = (1<<(15)); // set CAN_EN
144 vTaskDelay(50/portTICK_RATE_MS);
147 if ((token = strtok(param[1], " ")) == NULL) {
149 rpp_sci_printf("ERROR: Parameter 1 expected.");
152 if (EOF == sscanf(token, "%d", &can[0])){
153 rpp_sci_printf("ERROR: unsigned number expected as param 1!");
157 if ((token = strtok(NULL, " ")) == NULL) {
158 rpp_sci_printf("ERROR: Parameter 2 expected.");
161 if (EOF == sscanf(token, "%d", &can[1])){
162 rpp_sci_printf("ERROR: unsigned number expected as param 2!");
165 if ((token = strtok(NULL, " ")) != NULL) {
166 rpp_sci_printf("ERROR: More than 2 parameters detected!");
169 if (can[0] == can[1]) {
170 rpp_sci_printf("ERROR: Destination equals source!);");
173 if (can[0] < 1 | can[1] > 3) {
174 rpp_sci_printf("Parameter out of range <1;3>!");
177 canSrc = canBases[can[0]-1];
178 canDst = canBases[can[1]-1];
179 canMsgBox = canMailBoxes[can[0]-1];
180 canMsgReceived = xSemaphoreCreateCounting(1, 0);
181 canMsgSent = xSemaphoreCreateCounting(1, 0);
183 rpp_sci_printf("Testing CAN loopback\r\n");
184 canREG1->CTL |= 1|(1<<9);
185 canREG2->CTL |= 1|(1<<9);
186 canREG3->CTL |= 1|(1<<9);
188 canDst->CTL |= 1<<15; // Reset
189 while (canDst->CTL & (1<<15)) ; // Wait for reset
191 canSrc->CTL |= 1<<15;
192 while (canSrc->CTL & (1<<15)) ;
196 vTaskDelay(50/portTICK_RATE_MS);
198 i = canSrc->ES; // Reset error flag
199 i = canDst->ES; // Reset error flag
200 canEnableErrorNotification(canDst);
201 canEnableErrorNotification(canSrc);
203 for (i = 0; i < 100; i++) { // Send 100 times the message
204 if (canCheckForError(canSrc, "TX", &canSendError, 0) != canLEVEL_ACTIVE) {
207 canTransmit(canSrc, canMsgBox, tx_data);
208 if (xSemaphoreTake(canMsgSent, 100/portTICK_RATE_MS) == pdFALSE) {
212 if (canCheckForError(canSrc, "TX", &canSendError, 0) & canLEVEL_BUS_OFF) {
216 messagesTransmitted++;
217 if (xSemaphoreTake(canMsgReceived, 100/portTICK_RATE_MS) == pdFALSE) {
221 if (canGetData(canDst, canMsgBox, rx_data))
224 if (canCheckForError(canDst, "RX", &canRecError, 0) & canLEVEL_BUS_OFF) {
231 rpp_sci_printf("CAN final error state:\r\n");
232 canCheckForError(canSrc, "TX", &canSendError, 1);
233 canCheckForError(canDst, "RX", &canRecError, 1);
234 rpp_sci_printf("Messages transmitted: %d/100\r\n", messagesTransmitted);
235 rpp_sci_printf("Messages received: %d/100\r\n", messagesReceived);
236 rpp_sci_printf("TX timeouts: %d\r\n", txTimeOutCnt);
237 rpp_sci_printf("RX timeouts: %d\r\n", rxTimeOutCnt);
238 rpp_sci_printf("Src TX error counter: %d\r\n", canSrc->EERC & 0xFFU);
239 rpp_sci_printf("Src RX error counter: %d\r\n", (canSrc->EERC & 0xFF00U) >> 8);
240 rpp_sci_printf("Dst TX error counter: %d\r\n", canDst->EERC & 0xFFU);
241 rpp_sci_printf("Dst RX error counter: %d\r\n", (canDst->EERC & 0xFF00U) >> 8);
243 canDisableErrorNotification(canDst);
244 canDisableErrorNotification(canSrc);
245 vSemaphoreDelete(canMsgReceived);
246 vSemaphoreDelete(canMsgSent);
252 /** @brief command descriptor for test CAN loopback command */
253 cmd_des_t const cmd_des_test_can_loopback={
255 "testcan","testcan src<1;3> dest<1;3> Test CAN loopback between src and dest.",
256 "=== Description ===\n"
258 "This command tests CAN bus by sending and receiving messages through\n"
259 "external loopback. When bus is in fault state, this command resets it\n"
260 "into functional state.\n"
262 "Command expects two parameters. First parameter specifies source CAN\n"
263 "and the second one specifies destination CAN.\n"
265 "Command sends a massage 100 times and measures number of TX errors, RX\n"
266 "errors and eventual timeouts. In the end the state of bus and number\n"
267 "of errors is printed.\n"
269 "=== Command syntax ===\n"
271 " testcan SOURCE DESTINATION\n"
272 "where SOURCE and DESTINATION is a number in the range 1-3 and SOURCE\n"
273 "is not equal DESTINATION.\n"
279 "Sends 100 times message from CAN1 to CAN2\n",
280 CMD_HANDLER(cmd_do_test_can_loopback), (void *)&cmd_list_can
283 cmd_des_t const *cmd_list_can[]={
284 &cmd_des_test_can_loopback,