]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp/lib/cmdproc/src/commands/cmd_can.c
Exclude docgen.c from CCS build
[pes-rpp/rpp-test-sw.git] / rpp / lib / cmdproc / src / 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 "commands/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 xSemaphoreHandle canMsgReceived;
39 /** Semaphore used for blocking task until message is sent */
40 xSemaphoreHandle canMsgSent;
41 /** Pointer to Destination CAN registers */
42 canBASE_t* canDst;
43 /** Pointer to Source CAN registers */
44 canBASE_t* canSrc;
45 /** Can message box for received messages */
46 uint32_t canMsgBox;
47 /** Error counter for errors in sending */
48 uint32_t canSendError;
49 /** Error counter for errors in receiving */
50 uint32_t canRecError;
51
52 /**
53  *      @brief  Function for printing CAN error status
54  *
55  *      Function prints CAN status as a human readable string and status code.
56  *
57  *      @note The function canInit has to be called before this function can be used.
58  *
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
64  */
65 uint32_t canCheckForError(canBASE_t *node, const char* str, uint32_t *errorStatus, uint8_t isFinal)
66 {
67     //uint32_t errorStatus = node->ES;
68     uint32_t errorLevel = *errorStatus & 0xE0U;
69     uint32_t errStat = *errorStatus;
70     char* levText = "Unknown level. ES: 0x";
71
72
73         if (*errorStatus != 0) {
74         if (errorLevel & canLEVEL_BUS_OFF) {
75                 levText = "CAN bus is off. ES: 0x";
76         }
77         else if (errorLevel & canLEVEL_PASSIVE) {
78                 levText = "CAN bus in passive mode. ES: 0x";
79         }
80         else if (errorLevel & canLEVEL_WARNING) {
81                 levText = "CAN bus in passive mode. ES: 0x";
82         }
83         else if (errorLevel == canLEVEL_ACTIVE) {
84                 if (isFinal) {
85                         levText = "CAN is active. ES: 0x";
86                         *errorStatus = 0;
87                 }
88                 else levText = NULL;
89         }
90     }
91         else {
92                 if (isFinal) {
93                         levText = "CAN no error. ES: 0x";
94                 }
95                 else levText = NULL;
96         }
97
98         if (levText == NULL) return errorLevel;
99
100         rpp_sci_printf(str);
101         rpp_sci_printf(levText);
102         rpp_sci_printf("%h\r\n", errStat);
103
104     return errorLevel;
105 }
106
107 /**
108  *      @brief  Command for external CAN loopback testing.
109  *
110  *      Command syntax: testcan src dest, where src and dest are numbers of CAN in range 1 - 3 and can not be equal.
111  *
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.
114  *
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
119  */
120 int cmd_do_test_can_loopback(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
121 {
122         uint32_t can[2];
123         canBASE_t *canBases[3] = {canREG1, canREG2, canREG3};
124         uint32_t canMailBoxes[3] = {canMESSAGE_BOX1, canMESSAGE_BOX2, canMESSAGE_BOX3};
125         char* token = NULL;
126         uint32_t txTimeOutCnt = 0;
127         uint32_t rxTimeOutCnt = 0;
128         uint32_t messagesTransmitted = 0;
129         uint32_t messagesReceived = 0;
130         uint32_t i;
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 };
133
134
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);
145
146         // Get can ID 1
147         if ((token = strtok(param[1], " ")) == NULL) {
148
149                 rpp_sci_printf("ERROR: Parameter 1 expected.");
150                 return 1;
151         }
152         if (EOF == sscanf(token, "%d", &can[0])){
153                 rpp_sci_printf("ERROR: unsigned number expected as param 1!");
154                 return 1;
155         }
156         // Get can ID 2
157         if ((token = strtok(NULL, " ")) == NULL) {
158                 rpp_sci_printf("ERROR: Parameter 2 expected.");
159                 return 1;
160         }
161         if (EOF == sscanf(token, "%d", &can[1])){
162                 rpp_sci_printf("ERROR: unsigned number expected as param 2!");
163                 return 1;
164         }
165         if ((token = strtok(NULL, " ")) != NULL) {
166                 rpp_sci_printf("ERROR: More than 2 parameters detected!");
167                 return 1;
168         }
169         if (can[0] == can[1]) {
170                 rpp_sci_printf("ERROR: Destination equals source!);");
171                 return 1;
172         }
173         if (can[0] < 1 | can[1] > 3) {
174                 rpp_sci_printf("Parameter out of range <1;3>!");
175                 return 1;
176         }
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);
182
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);
187         canRecError = 0;
188         canDst->CTL |= 1<<15;           // Reset
189         while (canDst->CTL & (1<<15)) ; // Wait for reset
190         canSendError = 0;
191         canSrc->CTL |= 1<<15;
192         while (canSrc->CTL & (1<<15)) ;
193         canInit();
194         canDst->CTL |= 1<<9;
195         canSrc->CTL |= 1<<9;
196         vTaskDelay(50/portTICK_RATE_MS);
197
198         i = canSrc->ES; // Reset error flag
199         i = canDst->ES; // Reset error flag
200         canEnableErrorNotification(canDst);
201         canEnableErrorNotification(canSrc);
202
203         for (i = 0; i < 100; i++) {             // Send 100 times the message
204                 if (canCheckForError(canSrc, "TX", &canSendError, 0) != canLEVEL_ACTIVE) {
205                         break;
206                 }
207                 canTransmit(canSrc, canMsgBox, tx_data);
208                 if (xSemaphoreTake(canMsgSent, 100/portTICK_RATE_MS) == pdFALSE) {
209                         txTimeOutCnt++;
210                 }
211                 else {
212                         if (canCheckForError(canSrc, "TX", &canSendError, 0) & canLEVEL_BUS_OFF) {
213                                 break;
214                         }
215                         else {
216                                 messagesTransmitted++;
217                                 if (xSemaphoreTake(canMsgReceived, 100/portTICK_RATE_MS) == pdFALSE) {
218                                         rxTimeOutCnt++;
219                                 }
220                                 else {
221                                         if (canGetData(canDst, canMsgBox, rx_data))
222                                                 messagesReceived++;
223
224                                         if (canCheckForError(canDst, "RX", &canRecError, 0) & canLEVEL_BUS_OFF) {
225                                                 break;
226                                         }
227                                 }
228                         }
229                 }
230         }
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);
242
243         canDisableErrorNotification(canDst);
244         canDisableErrorNotification(canSrc);
245         vSemaphoreDelete(canMsgReceived);
246         vSemaphoreDelete(canMsgSent);
247         return 0;
248 }
249
250 #endif  /* DOCGEN */
251
252 /** @brief command descriptor for test CAN loopback command */
253 cmd_des_t const cmd_des_test_can_loopback={
254     0, 0,
255     "testcan","testcan src<1;3> dest<1;3> Test CAN loopback between src and dest.",
256     "=== Description ===\n"
257     "\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"
261     "\n"
262     "Command expects two parameters. First parameter specifies source CAN\n"
263     "and the second one specifies destination CAN.\n"
264     "\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"
268     "\n"
269     "=== Command syntax ===\n"
270     "\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"
274     "\n"
275     "=== Example ===\n"
276     "\n"
277     "   --> testcan 1 2\n"
278     "\n"
279     "Sends 100 times message from CAN1 to CAN2\n",
280     CMD_HANDLER(cmd_do_test_can_loopback), (void *)&cmd_list_can
281 };
282
283 cmd_des_t const *cmd_list_can[]={
284   &cmd_des_test_can_loopback,
285   NULL
286 };