]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/commitdiff
Implement a test command for rpp_can functions
authorMichal Horn <hornmich@fel.cvut.cz>
Wed, 29 Oct 2014 09:40:19 +0000 (10:40 +0100)
committerMichal Horn <hornmich@fel.cvut.cz>
Wed, 29 Oct 2014 09:40:19 +0000 (10:40 +0100)
Fixes #1027

rpp-lib
rpp-test-sw/commands/cmd_can.c

diff --git a/rpp-lib b/rpp-lib
index edb9b611b9a39c4e62b254ad3bcfbe1b2be5ecc2..48c4d73964cd66c0b442e8ccada71dbcfca22646 160000 (submodule)
--- a/rpp-lib
+++ b/rpp-lib
@@ -1 +1 @@
-Subproject commit edb9b611b9a39c4e62b254ad3bcfbe1b2be5ecc2
+Subproject commit 48c4d73964cd66c0b442e8ccada71dbcfca22646
index 5d1572e60fd7ca4f6f01ca360c17a33efc4eca1c..92c25c3ad4b79823a5cb25e8232e4f6872c6e714 100644 (file)
 #include "sys/sys.h"
 #include <stdio.h>
 
+/*
+ * Error codes definitions for RPP CAN functions tests.
+ */
+#define ERR_CCT_HW_OBJ                  0x0001 /**< Wrong HW object passed to the RPP CAN function. */
+#define ERR_CCT_MSG_MISMATCH            0x0010 /**< Received message does not match to the sent message. */
+#define ERR_CCT_RX_IND_NOT_CLEARED      0x0020 /**< Message received indicator was not cleared by the rpp_can_read function.  */
+#define ERR_CCT_RX_IND_SET_NO_MSG_REC   0x0040 /**< Message received indicator is set, but no message could be retrieved by the rpp_can_read function. */
+#define ERR_CCT_RECV_TIMEOUT            0x0100 /**< Message receive timeout reached. */
+#define ERR_CCT_CLEAR_TX_PEND_TO        0x0200 /**< Timeout reached for waiting for the clearance of the transmission request flag. */
+#define ERR_CCT_SET_TX_PEND_TO          0x0400 /**< Timeout reached for waiting until the transmission request flag is set after the request is posted. */
+#define ERR_CCT_INIT                    0x1000 /**< Error while initializing the CAN bus. */
+#define ERR_CCT_SEND                    0x2000 /**< Error while sending a CAN message. */
+#define ERR_CCT_RCV                     0x4000 /**< Error while receiving a CAN message */
+#define ERR_CCT_UNEXPECTED_RETVAL       0x0008 /**< Unexpected return value has been returned from some RPP CAN function. */
+
+#define CCT_TIMEOUT                    100000  /**< Timeout for RPP CAN test steps. */
+
 /** Semaphore used for blocking task until message is received */
 extern xSemaphoreHandle canMsgReceived;
 /** Semaphore used for blocking task until message is sent */
@@ -281,25 +298,25 @@ static struct rpp_can_rx_config rx_config[] = {
                .controller = 1,
                .msg_obj = 1,
                .id = 1,
-               .mask = 0,
+               .mask = 0x7fffff,
        },
        {
                .type = RPP_CAN_MIXED,
                .controller = 2,
                .msg_obj = 1,
                .id = 1,
-               .mask = 0,
+               .mask = 0x7fffff,
        },
        {
                .type = RPP_CAN_MIXED,
                .controller = 3,
                .msg_obj = 1,
                .id = 1,
-               .mask = 0,
+               .mask = 0x7fffff,
        }
 };
 
-static struct rpp_can_config can_config = {
+struct rpp_can_config can_config = {
        .num_tx_obj = 3,
        .num_rx_obj = 3,
        .tx_config = tx_config,
@@ -307,17 +324,569 @@ static struct rpp_can_config can_config = {
        .ctrl = ctrl_config,
 };
 
+/*
+ * Structures for RPP CAN functions tests.
+ */
 
-int cmd_do_can_init(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+/**
+ * CAN test bit timings configurations.
+ */
+struct rpp_can_timing_cfg can_test_timing[] = {
+               {
+                       .brp = 10,
+                       .prop_seg = 8,
+                       .phase_seg1 = 5,
+                       .phase_seg2 = 2,
+                       .sjw = 1
+               },
+               {
+                       .brp = 10,
+                       .prop_seg = 8,
+                       .phase_seg1 = 5,
+                       .phase_seg2 = 2,
+                       .sjw = 1
+               },
+               {
+                       .brp = 10,
+                       .prop_seg = 8,
+                       .phase_seg1 = 5,
+                       .phase_seg2 = 2,
+                       .sjw = 1
+               },
+};
+
+/**
+ * CAN test controllers configurations.
+ */
+struct rpp_can_ctrl_config can_test_ctrl_cfg[] = {
+               {
+                       .baudrate = 500000,
+                       .clk = 80000000,
+                       .timing_calc_method = RPP_CAN_TIMING_CALC_MANUAL,
+                       .timing_config = &can_test_timing[0]
+               },
+               {
+                       .baudrate = 500000,
+                       .clk = 80000000,
+                       .timing_calc_method = RPP_CAN_TIMING_CALC_MANUAL,
+                       .timing_config = &can_test_timing[1]
+               },
+               {
+                       .baudrate = 500000,
+                       .clk = 80000000,
+                       .timing_calc_method = RPP_CAN_TIMING_CALC_MANUAL,
+                       .timing_config = &can_test_timing[2]
+               },
+};
+
+/**
+ * CAN test TX configuration.
+ */
+struct rpp_can_tx_config can_test_tx_cfg[] = {
+               {
+                               .type = RPP_CAN_STANDARD,
+                               .controller = 1,
+                               .msg_obj = 1
+               }
+};
+
+/**
+ * CAN test RX configuration.
+ */
+struct rpp_can_rx_config can_test_rx_cfg[] = {
+               {
+                               .type = RPP_CAN_STANDARD,
+                               .controller = 2,
+                               .id = 0x1,
+                               .mask = 1,
+                               .msg_obj = 1
+               }
+};
+
+/**
+ * Root CAN test configuration structure
+ */
+struct rpp_can_config can_test_cfg = {
+               .num_tx_obj = 1,
+               .num_rx_obj = 1,
+               .tx_config = can_test_tx_cfg,
+               .rx_config = can_test_rx_cfg,
+               .ctrl = can_test_ctrl_cfg
+};
+
+/**
+ * Compare two CAN messages.
+ *
+ * @param[in] pdu1 CAN message 1
+ * @param[in] pdu2 CAN message 2
+ * @return TRUE, if the two CAN messages are equal.
+ */
+boolean_t cmd_can_messages_equal(const struct rpp_can_pdu *pdu1, const struct rpp_can_pdu *pdu2)
+{
+       boolean_t pdus_equal = TRUE;
+       if (pdu1->id != pdu2->id ||
+               pdu1->dlc != pdu2->dlc) {
+               pdus_equal = FALSE;
+       }
+       else {
+               uint8_t i = 0;
+               for (i = 0; i < pdu1->dlc; i++) {
+                       if (pdu1->data[i] != pdu1->data[i]) {
+                               pdus_equal = FALSE;
+                               break;
+                       }
+               }
+       }
+       return pdus_equal;
+}
+
+/**
+ * Initialize the CAN bus driver for tests.
+ *
+ * @param[in] timing_calc Select RPP_CAN_TIMING_CALC_AUTO for automatic CAN bit timing calculation
+ * for a baudrate specified by desired_baudrate. Select RPP_CAN_TIMING_CALC_MANUAL for configuring the
+ * CAN bus to 500kbits/sec with verified bit timing parameters generated by HALCoGen.
+ *
+ * @return SUCCESS if the test passed, FAILURE otherwise.
+ */
+int cmd_can_test_init(enum rpp_can_timing_calculation timing_calc, uint32_t desired_baudrate)
+{
+       can_test_cfg.ctrl[0].baudrate = desired_baudrate;
+       can_test_cfg.ctrl[0].timing_calc_method = timing_calc;
+       can_test_cfg.ctrl[1].baudrate = desired_baudrate;
+       can_test_cfg.ctrl[1].timing_calc_method = timing_calc;
+       can_test_cfg.ctrl[2].baudrate = desired_baudrate;
+       can_test_cfg.ctrl[2].timing_calc_method = timing_calc;
+
+       if (rpp_can_init(&can_test_cfg) == SUCCESS) {
+               return SUCCESS;
+       }
+       else {
+               return FAILURE;
+       }
+}
+
+/**
+ * General test for receiving of message.
+ *
+ * This function verifies that the rpp_can_read() function is working
+ * properly and that the CAN driver behaves as expected.
+ *
+ * This is a blocking function that tries to receive a CAN message. The reception
+ * has to finish until specified timeout is reached.
+ * The received message is compared with the transmitted one.
+ *
+ * @param[in] can_tx_pdu A message pattern, which should be received. Used for RX
+ * and TX equality verification.
+ * @param[in] timeout How long should the test wait for the message.
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_recv(const struct rpp_can_pdu* can_tx_pdu, uint32_t timeout)
+{
+       boolean_t msg_received = FALSE;
+       volatile uint32_t rec_time = 0;
+       struct rpp_can_pdu can_rx_pdu;
+
+       while (!msg_received) {
+               int ret = rpp_can_read(0, &can_rx_pdu);
+               switch (ret) {
+               case -RPP_EINVAL:
+                       return ERR_CCT_HW_OBJ;
+               case -RPP_ENODATA:
+                       if (++rec_time >= CCT_TIMEOUT) {
+                               return ERR_CCT_RECV_TIMEOUT;
+                       }
+                       break;
+               case SUCCESS:
+                       if (!cmd_can_messages_equal(&can_rx_pdu, can_tx_pdu)) {
+                               return ERR_CCT_MSG_MISMATCH;
+                       }
+                       else {
+                               msg_received = TRUE;
+                       }
+                       break;
+               default:
+                       return ERR_CCT_UNEXPECTED_RETVAL;
+               }
+       }
+       return SUCCESS;
+}
+
+/**
+ * General test of sending a message.
+ *
+ * This function verifies that the rpp_can_write() function is working
+ * properly and that the CAN driver behaves as expected.
+ *
+ * @param[in] can_tx_msg A message for transmission.
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_send(const struct rpp_can_pdu* can_tx_msg)
+{
+       if (rpp_can_write(0, can_tx_msg) != SUCCESS) {
+               return ERR_CCT_HW_OBJ;
+       }
+       return SUCCESS;
+}
+
+/**
+ * General test of sending and receiving mechanism.
+ *
+ * This function verifies that the rpp_can_write() and rpp_can_read() functions
+ * are working properly and that the CAN driver behaves as expected.
+ *
+ * The message specified as a parameter is sent on the CAN bus and received to
+ * another mailbox. The received message is compared with the sent one.
+ *
+ * @param[in] can_tx_msg A message used to testing
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_simple_send_recv(const struct rpp_can_pdu* can_tx_msg)
+{
+       int ret_val = 0;
+       if ((ret_val = cmd_can_test_send(can_tx_msg)) != SUCCESS) {
+               return ERR_CCT_SEND|ret_val;
+       }
+       else {
+               if ((ret_val = cmd_can_test_recv(can_tx_msg, CCT_TIMEOUT)) != SUCCESS) {
+                       return ERR_CCT_RCV|ret_val;
+               }
+       }
+       return SUCCESS;
+}
+
+/**
+ * Test automatic CAN bit timing calculation for the specified baudrate.
+ *
+ * @param[in] tested_baudrate Desired baudrate.
+ * @param[in] can_tx_msg A message used to testing.
+ * @return SUCCESS if the test passed, error code otherwise.
+ *
+ */
+int cmd_can_test_baudrate_calc(uint32_t tested_baudrate,const struct rpp_can_pdu* can_tx_msg)
+{
+       int ret_val = 0;
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_AUTO, 125000)) != SUCCESS) {
+               return ERR_CCT_INIT|ret_val;
+       }
+       else {
+               if ((ret_val = cmd_can_test_simple_send_recv(can_tx_msg)) != SUCCESS) {
+                       return ret_val;
+               }
+       }
+       return SUCCESS;
+}
+
+/**
+ * Test behavioral of two consecutive TX requests posting.
+ *
+ * This function verifies that the rpp_can_write() function is working properly and
+ * that the CAN driver behaves as expected.
+ *
+ * According to the behavioral defined by tha Autosar, the rpp_can_write() should not fail when
+ * new transmission request comes before the previous one has been processed. The function should
+ * overwrite the old request and only the new one should be transmitted.
+ *
+ * @param[in] can_tx_msg1 A message which transmission is requested foremost.
+ * @param[in] can_tx_msg2 A message, which transmission is requested right after the can_tx_msg1
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_tx_request_replace(const struct rpp_can_pdu* can_tx_msg1, const struct rpp_can_pdu* can_tx_msg2)
+{
+       int ret_val = 0;
+       if ((ret_val = cmd_can_test_send(can_tx_msg1)) != SUCCESS) {
+               return ret_val;
+       }
+       else {
+               if ((ret_val = cmd_can_test_simple_send_recv(can_tx_msg2)) != SUCCESS) {
+                       return ret_val;
+               }
+       }
+       return SUCCESS;
+}
+
+/**
+ * Test the TX request flag.
+ *
+ * This function verifies that the rpp_can_check_tx_pend() function is working properly and
+ * that the CAN driver behaves as expected.
+ *
+ * The TX request flag should be clear if no transmission request is pending. Once a rpp_can_write()
+ * is called a new transmission requst is posted and the TX request flag should be set, until the CAN
+ * bus driver sends the message. After the transmission is finished, the flag should be cleared.
+ *
+ * @param[in] rpp_can_pdu A message which used to testing.
+ * @param[out] time Measured time between posting the transmission request and setting the TX request flag.
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_tx_request_flag(const struct rpp_can_pdu* can_tx_msg, uint32_t* time)
+{
+       *time = 0;
+       uint32_t timeout = 0;
+       boolean_t tx_pend = FALSE;
+       int ret_val = 0;
+       if ((ret_val = cmd_can_test_send(can_tx_msg)) != SUCCESS) {
+               return ret_val;
+       }
+       else {
+               /* Wait for the flag to be set */
+               while (!tx_pend) {
+                       if (++timeout > CCT_TIMEOUT) {
+                               return ERR_CCT_SET_TX_PEND_TO;
+                       }
+                       if (rpp_can_check_tx_pend(0, &tx_pend) == FAILURE) {
+                               return ERR_CCT_HW_OBJ;
+                       }
+               }
+               timeout = 0;
+               while (tx_pend) {
+                       if (rpp_can_check_tx_pend(0, &tx_pend) == FAILURE) {
+                               return ERR_CCT_HW_OBJ;
+                       }
+                       (*time)++;
+                       if (++timeout > CCT_TIMEOUT) {
+                               return ERR_CCT_CLEAR_TX_PEND_TO;
+                       }
+               }
+               if ((ret_val = cmd_can_test_recv(can_tx_msg, CCT_TIMEOUT)) != SUCCESS) {
+                       return ERR_CCT_RCV|ret_val;
+               }
+       }
+
+       return SUCCESS;
+}
+
+/**
+ * Test the RX indicator.
+ *
+ * This function verifies that the rpp_can_check_rx_ind() function is working properly and
+ * that the CAN driver behaves as expected.
+ *
+ * The RX indicator should be set whenever new CAN message is received and remains set, until
+ * rpp_can_read() is called in order to retrieve the message.
+ *
+ * @param[in] rpp_can_pdu A message which used to testing.
+ * @param[out] time Measured time between posting the transmission request and setting the RX flag.
+ * @return SUCCESS if the test passed, error code otherwise.
+ */
+int cmd_can_test_rx_indicator(const struct rpp_can_pdu* can_tx_msg, uint32_t* time)
 {
-    dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
-    dmmREG->PC5 = (1<<(15)); // clr CAN_EN
-    dmmREG->PC5 = (1<<(13)); // clr CAN_NSTB
-    dmmREG->PC4 = (1<<(13)); // set CAN_NSTB
-    dmmREG->PC4 = (1<<(15)); // set CAN_EN
+       *time = 0;
+       volatile uint32_t timeout = 0;
+       boolean_t rx_ind = FALSE;
+       int ret_val = 0;
+       struct rpp_can_pdu can_rx_pdu;
+
+       if ((ret_val = cmd_can_test_send(can_tx_msg)) != SUCCESS) {
+               return ret_val;
+       }
+       else {
+               /* Wait for the flag to be set */
+               while (!rx_ind) {
+                       if (rpp_can_check_rx_ind(0, &rx_ind) == FAILURE) {
+                               return ERR_CCT_HW_OBJ;
+                       }
+                       (*time)++;
+                       if (++timeout > CCT_TIMEOUT) {
+                               return ERR_CCT_SET_TX_PEND_TO;
+                       }
+               }
+
+               if ((ret_val = rpp_can_read(0, &can_rx_pdu)) != SUCCESS) {
+                       switch(ret_val) {
+                       case -RPP_ENODATA:
+                               return ERR_CCT_RX_IND_SET_NO_MSG_REC;
+                       case -RPP_EINVAL:
+                               return ERR_CCT_HW_OBJ;
+                       default:
+                               return ERR_CCT_UNEXPECTED_RETVAL;
+                       }
+               }
+               else {
+                       if (!cmd_can_messages_equal(&can_rx_pdu, can_tx_msg)) {
+                               return ERR_CCT_MSG_MISMATCH;
+                       }
+                       else {
+                               if (rpp_can_check_rx_ind(0, &rx_ind) == FAILURE) {
+                                       return ERR_CCT_HW_OBJ;
+                               }
+                               if (rx_ind == TRUE) {
+                                       return ERR_CCT_RX_IND_NOT_CLEARED;
+                               }
+                       }
+               }
+       }
 
+       return SUCCESS;
+}
 
+/**
+ * Test CAN functions from RPP library.
+ *
+ * This is a complex test command for verification of automatic CAN bit timing
+ * calculation for baudrates 125k, 250k and 500kbits/sec and for checking RPP
+ * CAN functions:
+ * - rpp_can_init()
+ * - rpp_can_write()
+ * - rpp_can_read()
+ * - rpp_can_check_rx_ind()
+ * - rpp_can_check_tx_pend()
+ *
+ * @return always SUCCESS
+ */
+int cmd_do_can_test_functions(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       struct rpp_can_pdu can_tx_msg1 = {
+                       .id = 0x1,
+                       .dlc = 8,
+                       .data = {'H', 'E', 'L', 'L', 'O', '0', '0', '1'}
+       };
+
+       struct rpp_can_pdu can_tx_msg2 = {
+                       .id = 0x1,
+                       .dlc = 8,
+                       .data = {'H', 'E', 'L', 'L', 'O', '0', '0', '2'}
+       };
+
+       rpp_sci_printf("This is a test for RPP CAN library functions:\n");
+       /*
+        * Simple send and receive a message with CAN bit time parameters for 500 kb/sec, picked
+        * from HALCoGen, which are proven to be functional.
+        */
+       rpp_sci_printf("Test of simple message transmission and reception.\n");
+       int ret_val = 0;
+       rpp_sci_printf("\tCAN bus Initialization: ");
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_MANUAL, 500000)) != SUCCESS) {
+               rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+       }
+       else {
+               rpp_sci_printf("OK\n");
+               rpp_sci_printf("\tTransmission and reception...");
+               if ((ret_val = cmd_can_test_simple_send_recv(&can_tx_msg1)) != SUCCESS) {
+                       rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+               }
+               else {
+                       rpp_sci_printf("OK\n");
+               }
+       }
+       rpp_sci_printf("---\n");
+       /* Baudrate calculation testing
+        *
+        * Based on EATON requirements for baudrates: 125k, 250k, 500k
+        *  - calculate bit timing parameters,
+        *  - initialize the CAN bus,
+        *  - send a message
+        *  - receive a message
+        *  - test if the received message is OK.
+        */
+       uint32_t baudrates[] = {125000, 250000, 500000};
+       uint8_t num_baudrates = 3;
+       uint8_t i;
+       rpp_sci_printf("Test of automatic CAN bit timing calculation.\n");
+
+       for (i = 0; i < num_baudrates; i++) {
+               rpp_sci_printf("\tBaudrate: %d: ", baudrates[i]);
+               if ((ret_val = cmd_can_test_baudrate_calc(baudrates[i], &can_tx_msg1)) != SUCCESS) {
+                       rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+               }
+               else {
+                       rpp_sci_printf("OK\n");
+               }
+       }
+       rpp_sci_printf("---\n");
+
+       /*
+        * Test the behavioral when a new message replaces the actually pending message.
+        *
+        *  - Send a request for message A transmission,
+        *  - right after that, send a request for another message B transmission,
+        *  - receive a message, which should be the message B.
+        */
+       rpp_sci_printf("Test of transmission request rewritting.\n");
+       rpp_sci_printf("\tCAN bus Initialization: ");
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_MANUAL, 500000)) != SUCCESS) {
+               rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+       }
+       else {
+               rpp_sci_printf("OK\n");
+               rpp_sci_printf("\tTX request rewritting...");
+               if ((ret_val = cmd_can_test_tx_request_replace(&can_tx_msg1, &can_tx_msg2)) != SUCCESS) {
+                       rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+               }
+               else {
+                       rpp_sci_printf("OK\n");
+               }
+       }
+       rpp_sci_printf("---\n");
+
+       /*
+        * Test the tx_pending flag detection
+        *  - Send a request for a message transmission request,
+        *  - Wait while the flag is reset, which means that the message has been received
+        *    by another node, while measuring the time between the sending the request and
+        *    resetting the flag.
+        *  - Read the message to check that it has been already received.
+        *
+        */
+       rpp_sci_printf("Test of TX request pending flag detection.\n");
+       rpp_sci_printf("\tCAN bus Initialization: ");
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_MANUAL, 500000)) != SUCCESS) {
+               rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+       }
+       else {
+               rpp_sci_printf("OK\n");
+               uint32_t time = 0;
+               rpp_sci_printf("\tTX request pending flag behavioral: ");
+               if ((ret_val = cmd_can_test_tx_request_flag(&can_tx_msg1, &time)) != SUCCESS) {
+                       rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+               }
+               else {
+                       rpp_sci_printf("OK, time: %d cycles.\n", time);
+               }
+       }
+       rpp_sci_printf("---\n");
+
+       /*
+        * Test the rx_ind flag
+        *  - Send a message
+        *  - Wait for setting the rx_ind flag
+        *  - Try to read the message.
+        */
+       rpp_sci_printf("Test of RX indicator.\n");
+       rpp_sci_printf("\tCAN bus Initialization: ");
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_MANUAL, 500000)) != SUCCESS) {
+               rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+       }
+       else {
+               rpp_sci_printf("OK\n");
+               uint32_t time = 0;
+               rpp_sci_printf("\tRX indicator behavioral: ");
+               if ((ret_val = cmd_can_test_rx_indicator(&can_tx_msg1, &time)) != SUCCESS) {
+                       rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+               }
+               else {
+                       rpp_sci_printf("OK, time: %d cycles.\n", time);
+               }
+       }
+       rpp_sci_printf("---\n");
+
+       /*
+        * Reset the CAN bus to a determined state
+        * Baudrate: 500kb
+        */
+       rpp_sci_printf("Reset the CAN bus.\n");
+       rpp_sci_printf("\tCAN bus Initialization: ");
+       if ((ret_val = cmd_can_test_init(RPP_CAN_TIMING_CALC_MANUAL, 500000)) != SUCCESS) {
+               rpp_sci_printf("failed: error: 0x%X.\n", ret_val);
+       }
+       else {
+               rpp_sci_printf("OK\n");
+       }
+       return SUCCESS;
+}
 
+int cmd_do_can_init(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
     can_inited = (rpp_can_init(&can_config) == SUCCESS ? 1 : 0);
     return (can_inited ? 0 : 1);
 }
@@ -714,6 +1283,101 @@ cmd_des_t const cmd_des_can_dump={
     CMD_HANDLER(cmd_do_can_dump), (void *)&cmd_list_can
 };
 
+cmd_des_t const cmd_des_can_test={
+    0, 0,
+    "canrpptest", "Test the CAN functions from the RPP library",
+    "### Command syntax ###\n"
+    "\n"
+    "    canrpptest\n"
+    "\n"
+    "### Description ###\n"
+    "\n"
+    "This command tests all CAN functions in the RPP library. It does those\n"
+    "particular tests:\n"
+    "\n"
+    "1) Test of the rpp_can_init(), rpp_can_write() and rpp_can_read() functions.\n"
+    "   At the beginning, the CAN bus is initialized with manually specified and\n"
+    "   verified CAN bit timing parameters. Then a message is sent on the CAN1 and is\n"
+    "   received on the CAN2. Finally the received message is compared with the sent one.\n"
+    "   If the transmissions fails, reception exceeds a timeout or the sent and\n"
+    "   received messages do not match, the command prints the appropriate error\n"
+    "   code."
+    "2) Test of the CAN bit timing parameters calculation.\n"
+    "   This test subsequently initializes the CAN bus to a baudrates 125k, 250k\n"
+    "   and 500k. For each one of them a message is sent on CAN1 and received on CAN2.\n"
+    "   Finally the received message is compared with the sent one like in a test (1).\n"
+    "   If the initialization, transmission, reception or comparison fails or\n"
+    "   if the reception timeout is reached, an appropriate error code is printed.\n"
+    "3) Test of the behavior of transmission request overwriting.\n"
+    "   The CAN bus is initialized like in the test (1). A message A transmission\n"
+    "   request is posted on CAN1 by calling rpp_can_write() and right after that\n"
+    "   another message B transmission request is posted on CAN1 by another call of\n"
+    "   the rpp_can_write(). A message B is received on CAN2, because the second request\n"
+    "   came so quickly, that it overwrote the first one. The sent and received messages\n"
+    "   are compared to verify that the transmission was correct.\n"
+    "   If the initialization, transmission, reception or comparison fails or\n"
+    "   if the reception timeout is reached, an appropriate error code is printed.\n"
+    "4) Test of the TX request pending flag detection.\n"
+    "   The CAN bus is initialized like in the test (1). A message is transmitted\n"
+    "   on the CAN1 and the test waits for the TX pending flag to be set, which\n"
+    "   signalizes that there is a message transmission request pending. After the\n"
+    "   flag has been set, the test waits for its clearance, which means that the\n"
+    "   message has been sent. The test measures, how many flag test cycles passed,\n"
+    "   until the flag has been cleared. This value is then presented as a time.\n"
+    "   At the end, the message is received on the CAN2 and is compared with the\n"
+    "   sent message for verification.\n"
+    "   If the initialization, transmission, reception or comparison fails or if\n"
+    "   timeout is reached while waiting for the flag set/clear or receive timeout\n"
+    "   is reached, an appropriate error code is printed.\n"
+    "5) Test of the message received (RX) indicator.\n"
+    "   The CAN bus is initialized like in the test (1). A message is transmitted\n"
+    "   on the CAN1. The test then waits for the RX indicator to be set, which\n"
+    "   indicates that a message has been received. The message is picked up by\n"
+    "   the rpp_can_read(). This should clear the indicator, which is tested. Finally\n"
+    "   the received messages is compared with the sent one.\n"
+    "   If the initialization, transmission, reception, message comparison or indicator\n"
+    "   test fails or if timeout is reached while waiting for the flag set, the\n"
+    "   appropriate error code is printed.\n"
+    "\n"
+    "At the end the CAN bus is reset and left with the configuration from test (1).\n"
+    "Those tests assumes the CAN1 and CAN2 to be connected in HW loopback.\n"
+    "Any previous configuration is canceled, but is not deleted, so any following\n"
+    "call of caninit command will restore the CAN bus to previous configuration.\n"
+    "\n"
+    "For error codes description refer please the API documentation for the rpp-test-sw.\n"
+    "\n"
+    "### Example ###\n"
+    "\n"
+    "    --> canrpptest\n"
+    "This is a test for RPP CAN library functions:"
+    "Test of simple message transmission and reception."
+    "  CAN bus Initialization...OK"
+    "  Transmission and reception...OK"
+    "---"
+    "Test od automatic CAN bit timing calculation."
+    "  Baudrate: 125000: OK"
+    "  Baudrate: 250000: OK"
+    "  Baudrate: 500000: OK"
+    "---"
+    "Test of transmission request rewritting."
+    "  CAN bus Initialization...OK"
+    "  TX request rewritting...OK"
+    "---"
+    "Test of TX request pending flag detection."
+    "  CAN bus Initialization...OK"
+    "  TX request pending flag behavioral: OK, time: 256 cycles."
+    "---"
+    "Test of RX indicator."
+    "  CAN bus Initialization...OK"
+    "  RX indicator behavioral:"
+    "OK, time: 0 cycles."
+    "---"
+    "Reset the CAN bus."
+    "  CAN bus Initialization...OK",
+    CMD_HANDLER(cmd_do_can_test_functions), (void *)&cmd_list_can
+};
+
+
 
 
 cmd_des_t const *cmd_list_can[]={
@@ -723,5 +1387,6 @@ cmd_des_t const *cmd_list_can[]={
   &cmd_des_can_timing,
   &cmd_des_can_send,
   &cmd_des_can_dump,
+  &cmd_des_can_test,
   NULL
 };