diff --git a/tests/drivers/can/api/src/main.c b/tests/drivers/can/api/src/main.c index acaf634184c..5db384b9106 100644 --- a/tests/drivers/can/api/src/main.c +++ b/tests/drivers/can/api/src/main.c @@ -1,55 +1,58 @@ /* + * Copyright (c) 2022 Vestas Wind Systems A/S * Copyright (c) 2019 Alexander Wachter * * SPDX-License-Identifier: Apache-2.0 */ + #include #include -#include -/* +/** * @addtogroup t_can_driver * @{ - * @defgroup t_can_basic test_basic_can - * @brief TestPurpose: verify can driver works - * @details - * - Test Steps - * -# Set driver to loopback mode - * -# Try to send a message. - * -# Add a filter from every kind - * -# Test if message reception is really blocking - * -# Send and receive a message with standard id without masking - * -# Send and receive a message with extended id without masking - * -# Send and receive a message with standard id with masking - * -# Send and receive a message with extended id with masking - * -# Send and message with different id that should not be received. - * - Expected Results - * -# All tests MUST pass + * @defgroup t_can_api test_can_api * @} */ +/** + * @brief Test timeouts. + */ #define TEST_SEND_TIMEOUT K_MSEC(100) #define TEST_RECEIVE_TIMEOUT K_MSEC(100) +/** + * @brief Standard (11-bit) CAN IDs and masks used for testing. + */ #define TEST_CAN_STD_ID_1 0x555 #define TEST_CAN_STD_ID_2 0x556 #define TEST_CAN_STD_MASK_ID_1 0x55A #define TEST_CAN_STD_MASK_ID_2 0x56A -#define TEST_CAN_STD_MASK 0x7F0 -#define TEST_CAN_SOME_STD_ID 0x123 +#define TEST_CAN_STD_MASK 0x7F0 +#define TEST_CAN_SOME_STD_ID 0x123 +/** + * @brief Extended (29-bit) CAN IDs and masks used for testing. + */ #define TEST_CAN_EXT_ID_1 0x15555555 #define TEST_CAN_EXT_ID_2 0x15555556 #define TEST_CAN_EXT_MASK_ID_1 0x1555555A #define TEST_CAN_EXT_MASK_ID_2 0x1555556A #define TEST_CAN_EXT_MASK 0x1FFFFFF0 -CAN_MSGQ_DEFINE(can_msgq, 5); -struct k_sem rx_isr_sem; -struct k_sem tx_cb_sem; +/** + * @brief Global variables. + */ const struct device *can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); +struct k_sem rx_callback_sem; +struct k_sem tx_callback_sem; -const struct zcan_frame test_std_msg_1 = { +CAN_MSGQ_DEFINE(can_msgq, 5); + +/** + * @brief Standard (11-bit) CAN ID frame 1. + */ +const struct zcan_frame test_std_frame_1 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, .id = TEST_CAN_STD_ID_1, @@ -57,7 +60,10 @@ const struct zcan_frame test_std_msg_1 = { .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -const struct zcan_frame test_std_msg_2 = { +/** + * @brief Standard (11-bit) CAN ID frame 2. + */ +const struct zcan_frame test_std_frame_2 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, .id = TEST_CAN_STD_ID_2, @@ -65,7 +71,10 @@ const struct zcan_frame test_std_msg_2 = { .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -const struct zcan_frame test_ext_msg_1 = { +/** + * @brief Extended (29-bit) CAN ID frame 1. + */ +const struct zcan_frame test_ext_frame_1 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, .id = TEST_CAN_EXT_ID_1, @@ -73,7 +82,10 @@ const struct zcan_frame test_ext_msg_1 = { .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -const struct zcan_frame test_ext_msg_2 = { +/** + * @brief Extended (29-bit) CAN ID frame 1. + */ +const struct zcan_frame test_ext_frame_2 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, .id = TEST_CAN_EXT_ID_2, @@ -81,6 +93,10 @@ const struct zcan_frame test_ext_msg_2 = { .data = {1, 2, 3, 4, 5, 6, 7, 8} }; +/** + * @brief Standard (11-bit) CAN ID filter 1. This filter matches + * ``test_std_frame_1``. + */ const struct zcan_filter test_std_filter_1 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -89,6 +105,10 @@ const struct zcan_filter test_std_filter_1 = { .id_mask = CAN_STD_ID_MASK }; +/** + * @brief Standard (11-bit) CAN ID filter 2. This filter matches + * ``test_std_frame_2``. + */ const struct zcan_filter test_std_filter_2 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -97,6 +117,10 @@ const struct zcan_filter test_std_filter_2 = { .id_mask = CAN_STD_ID_MASK }; +/** + * @brief Standard (11-bit) CAN ID masked filter 1. This filter matches + * ``test_std_frame_1``. + */ const struct zcan_filter test_std_masked_filter_1 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -105,6 +129,10 @@ const struct zcan_filter test_std_masked_filter_1 = { .id_mask = TEST_CAN_STD_MASK }; +/** + * @brief Standard (11-bit) CAN ID masked filter 2. This filter matches + * ``test_std_frame_2``. + */ const struct zcan_filter test_std_masked_filter_2 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -113,7 +141,10 @@ const struct zcan_filter test_std_masked_filter_2 = { .id_mask = TEST_CAN_STD_MASK }; - +/** + * @brief Extended (29-bit) CAN ID filter 1. This filter matches + * ``test_ext_frame_1``. + */ const struct zcan_filter test_ext_filter_1 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -122,6 +153,10 @@ const struct zcan_filter test_ext_filter_1 = { .id_mask = CAN_EXT_ID_MASK }; +/** + * @brief Extended (29-bit) CAN ID filter 2. This filter matches + * ``test_ext_frame_2``. + */ const struct zcan_filter test_ext_filter_2 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -130,6 +165,10 @@ const struct zcan_filter test_ext_filter_2 = { .id_mask = CAN_EXT_ID_MASK }; +/** + * @brief Extended (29-bit) CAN ID masked filter 1. This filter matches + * ``test_ext_frame_1``. + */ const struct zcan_filter test_ext_masked_filter_1 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -138,6 +177,10 @@ const struct zcan_filter test_ext_masked_filter_1 = { .id_mask = TEST_CAN_EXT_MASK }; +/** + * @brief Extended (29-bit) CAN ID masked filter 2. This filter matches + * ``test_ext_frame_2``. + */ const struct zcan_filter test_ext_masked_filter_2 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -146,6 +189,10 @@ const struct zcan_filter test_ext_masked_filter_2 = { .id_mask = TEST_CAN_EXT_MASK }; +/** + * @brief Standard (11-bit) CAN ID filter. This filter matches + * ``TEST_CAN_SOME_STD_ID``. + */ const struct zcan_filter test_std_some_filter = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, @@ -154,197 +201,325 @@ const struct zcan_filter test_std_some_filter = { .id_mask = CAN_STD_ID_MASK }; -static inline void check_msg(const struct zcan_frame *msg1, - const struct zcan_frame *msg2, - uint32_t mask) +/** + * @brief Assert that two CAN frames are equal given a CAN ID mask. + * + * @param frame1 First CAN frame. + * @param frame2 Second CAN frame. + * @param id_mask CAN ID mask. + */ +static inline void assert_frame_equal(const struct zcan_frame *frame1, + const struct zcan_frame *frame2, + uint32_t id_mask) { - int cmp_res; - zassert_equal(msg1->id_type, msg2->id_type, - "ID type does not match"); - - zassert_equal(msg1->rtr, msg2->rtr, - "RTR bit does not match"); - - zassert_equal(msg1->id | mask, msg2->id | mask, - "ID does not match"); - - zassert_equal(msg1->dlc, msg2->dlc, - "DLC does not match"); - cmp_res = memcmp(msg1->data, msg2->data, msg1->dlc); - zassert_equal(cmp_res, 0, "Received data differ"); + zassert_equal(frame1->id_type, frame2->id_type, "ID type does not match"); + zassert_equal(frame1->rtr, frame2->rtr, "RTR bit does not match"); + zassert_equal(frame1->id | id_mask, frame2->id | id_mask, "ID does not match"); + zassert_equal(frame1->dlc, frame2->dlc, "DLC does not match"); + zassert_mem_equal(frame1->data, frame2->data, frame1->dlc, "Received data differ"); } -static void tx_std_isr_1(const struct device *dev, int error, void *arg) +/** + * @brief Standard (11-bit) CAN ID transmit callback 1. + * + * See @a can_tx_callback_t() for argument description. + */ +static void tx_std_callback_1(const struct device *dev, int error, void *user_data) { - const struct zcan_frame *msg = (const struct zcan_frame *)arg; + const struct zcan_frame *frame = user_data; - k_sem_give(&tx_cb_sem); + k_sem_give(&tx_callback_sem); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal(msg->id, TEST_CAN_STD_ID_1, "Arg does not match"); + zassert_equal(frame->id, TEST_CAN_STD_ID_1, "ID does not match"); } -static void tx_std_isr_2(const struct device *dev, int error, void *arg) +/** + * @brief Standard (11-bit) CAN ID transmit callback 2. + * + * See @a can_tx_callback_t() for argument description. + */ +static void tx_std_callback_2(const struct device *dev, int error, void *user_data) { - const struct zcan_frame *msg = (const struct zcan_frame *)arg; + const struct zcan_frame *frame = user_data; - k_sem_give(&tx_cb_sem); + k_sem_give(&tx_callback_sem); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal(msg->id, TEST_CAN_STD_ID_2, "Arg does not match"); + zassert_equal(frame->id, TEST_CAN_STD_ID_2, "ID does not match"); } -static void tx_ext_isr_1(const struct device *dev, int error, void *arg) +/** + * @brief Extended (29-bit) CAN ID transmit callback 1. + * + * See @a can_tx_callback_t() for argument description. + */ +static void tx_ext_callback_1(const struct device *dev, int error, void *user_data) { - const struct zcan_frame *msg = (const struct zcan_frame *)arg; + const struct zcan_frame *frame = user_data; - k_sem_give(&tx_cb_sem); + k_sem_give(&tx_callback_sem); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal(msg->id, TEST_CAN_EXT_ID_1, "Arg does not match"); + zassert_equal(frame->id, TEST_CAN_EXT_ID_1, "ID does not match"); } -static void tx_ext_isr_2(const struct device *dev, int error, void *arg) +/** + * @brief Extended (29-bit) CAN ID transmit callback 2. + * + * See @a can_tx_callback_t() for argument description. + */ +static void tx_ext_callback_2(const struct device *dev, int error, void *user_data) { - const struct zcan_frame *msg = (const struct zcan_frame *)arg; + const struct zcan_frame *frame = user_data; - k_sem_give(&tx_cb_sem); + k_sem_give(&tx_callback_sem); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal(msg->id, TEST_CAN_EXT_ID_2, "Arg does not match"); + zassert_equal(frame->id, TEST_CAN_EXT_ID_2, "ID does not match"); } -static void rx_std_isr_1(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Standard (11-bit) CAN ID receive callback 1. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_std_callback_1(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_std_msg_1, 0); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_std_frame_1, 0); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_std_filter_1, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_std_isr_2(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Standard (11-bit) CAN ID receive callback 2. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_std_callback_2(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_std_msg_2, 0); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_std_frame_2, 0); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_std_filter_2, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_std_mask_isr_1(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Standard (11-bit) masked CAN ID receive callback 1. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_std_mask_callback_1(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_std_msg_1, 0x0F); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_std_frame_1, 0x0F); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_std_masked_filter_1, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_std_masked_filter_1, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_std_mask_isr_2(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Standard (11-bit) masked CAN ID receive callback 2. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_std_mask_callback_2(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_std_msg_2, 0x0F); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_std_frame_2, 0x0F); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_std_masked_filter_2, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_std_masked_filter_2, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_ext_isr_1(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Extended (29-bit) CAN ID receive callback 1. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_ext_callback_1(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_ext_msg_1, 0); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_ext_frame_1, 0); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_ext_filter_1, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_ext_filter_1, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_ext_isr_2(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Extended (29-bit) CAN ID receive callback 2. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_ext_callback_2(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_ext_msg_2, 0); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_ext_frame_2, 0); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_ext_filter_2, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_ext_filter_2, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_ext_mask_isr_1(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Extended (29-bit) masked CAN ID receive callback 1. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_ext_mask_callback_1(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_ext_msg_1, 0x0F); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_ext_frame_1, 0x0F); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_ext_masked_filter_1, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_ext_masked_filter_1, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void rx_ext_mask_isr_2(const struct device *dev, struct zcan_frame *msg, void *arg) +/** + * @brief Extended (29-bit) masked CAN ID receive callback 2. + * + * See @a can_rx_callback_t() for argument description. + */ +static void rx_ext_mask_callback_2(const struct device *dev, struct zcan_frame *frame, + void *user_data) { - check_msg(msg, &test_ext_msg_2, 0x0F); + struct zcan_filter *filter = user_data; + + assert_frame_equal(frame, &test_ext_frame_2, 0x0F); zassert_equal(dev, can_dev, "CAN device does not match"); - zassert_equal_ptr(arg, &test_ext_masked_filter_2, "arg does not match"); - k_sem_give(&rx_isr_sem); + zassert_equal_ptr(filter, &test_ext_masked_filter_2, "filter does not match"); + + k_sem_give(&rx_callback_sem); } -static void send_test_msg(const struct device *can_dev, - const struct zcan_frame *msg) +/** + * @brief Send a CAN test frame with asserts. + * + * This function will block until the frame is transmitted or a test timeout + * occurs. + * + * @param dev Pointer to the device structure for the driver instance. + * @param frame Pointer to the CAN frame to send. + */ +static void send_test_frame(const struct device *dev, const struct zcan_frame *frame) { - int ret; + int err; - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, NULL, NULL); - zassert_not_equal(ret, -EBUSY, - "Arbitration though in loopback mode"); - zassert_equal(ret, 0, "Can't send a message. Err: %d", ret); + err = can_send(dev, frame, TEST_SEND_TIMEOUT, NULL, NULL); + zassert_not_equal(err, -EBUSY, "arbitration lost in loopback mode"); + zassert_equal(err, 0, "failed to send frame (err %d)", err); } -static void send_test_msg_nowait(const struct device *can_dev, - const struct zcan_frame *msg, - can_tx_callback_t cb) +/** + * @brief Send a CAN test frame with asserts. + * + * This function will block until the frame is queued or a test timeout + * occurs. + * + * @param dev Pointer to the device structure for the driver instance. + * @param frame Pointer to the CAN frame to send. + * @param callback Transmit callback function. + */ +static void send_test_frame_nowait(const struct device *dev, const struct zcan_frame *frame, + can_tx_callback_t callback) { - int ret; - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, cb, - (struct zcan_frame *)msg); - zassert_not_equal(ret, -EBUSY, - "Arbitration though in loopback mode"); - zassert_equal(ret, 0, "Can't send a message. Err: %d", ret); + int err; + + err = can_send(dev, frame, TEST_SEND_TIMEOUT, callback, (void *)frame); + zassert_not_equal(err, -EBUSY, "arbitration lost in loopback mode"); + zassert_equal(err, 0, "failed to send frame (err %d)", err); } -static inline int add_rx_msgq(const struct device *can_dev, - const struct zcan_filter *filter) +/** + * @brief Add a CAN message queue with asserts. + * + * @param dev Pointer to the device structure for the driver instance. + * @param filter CAN filter for the CAN message queue. + * + * @return CAN filter ID. + */ +static inline int add_rx_msgq(const struct device *dev, const struct zcan_filter *filter) { int filter_id; - filter_id = can_add_rx_filter_msgq(can_dev, &can_msgq, filter); - zassert_not_equal(filter_id, -ENOSPC, - "Filter full even for a single one"); - zassert_true((filter_id >= 0), "Negative filter number"); + filter_id = can_add_rx_filter_msgq(dev, &can_msgq, filter); + zassert_not_equal(filter_id, -ENOSPC, "no filters available"); + zassert_true(filter_id >= 0, "negative filter number"); return filter_id; } -static inline int add_rx_filter(const struct device *can_dev, +/** + * @brief Add a CAN filter with asserts. + * + * @param dev Pointer to the device structure for the driver instance. + * @param filter CAN filter. + * @param callback Receive callback function. + * + * @return CAN filter ID. + */ +static inline int add_rx_filter(const struct device *dev, const struct zcan_filter *filter, can_rx_callback_t callback) { int filter_id; - k_sem_reset(&rx_isr_sem); + k_sem_reset(&rx_callback_sem); - filter_id = can_add_rx_filter(can_dev, callback, (void *)filter, filter); - zassert_not_equal(filter_id, -ENOSPC, - "Filter full even for a single one"); - zassert_true((filter_id >= 0), "Negative filter number"); + filter_id = can_add_rx_filter(dev, callback, (void *)filter, filter); + zassert_not_equal(filter_id, -ENOSPC, "no filters available"); + zassert_true(filter_id >= 0, "negative filter number"); return filter_id; } +/** + * @brief Perform a send/receive test with a set of CAN ID filters and CAN frames. + * + * @param filter1 CAN filter 1 + * @param filter2 CAN filter 2 + * @param frame1 CAN frame 1 + * @param frame2 CAN frame 2 + */ static void send_receive(const struct zcan_filter *filter1, const struct zcan_filter *filter2, - const struct zcan_frame *msg1, - const struct zcan_frame *msg2) + const struct zcan_frame *frame1, + const struct zcan_frame *frame2) { - int ret, filter_id_1, filter_id_2; - struct zcan_frame msg_buffer; + struct zcan_frame frame_buffer; uint32_t mask = 0U; - - zassert_not_null(can_dev, "Device not not found"); + int filter_id_1; + int filter_id_2; + int err; filter_id_1 = add_rx_msgq(can_dev, filter1); - send_test_msg(can_dev, msg1); - ret = k_msgq_get(&can_msgq, &msg_buffer, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, 0, "Receiving timeout"); + send_test_frame(can_dev, frame1); + + err = k_msgq_get(&can_msgq, &frame_buffer, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); if (filter1->id_type == CAN_STANDARD_IDENTIFIER) { if (filter1->id_mask != CAN_STD_ID_MASK) { @@ -356,92 +531,91 @@ static void send_receive(const struct zcan_filter *filter1, } } - check_msg(&msg_buffer, msg1, mask); + assert_frame_equal(&frame_buffer, frame1, mask); can_remove_rx_filter(can_dev, filter_id_1); - k_sem_reset(&tx_cb_sem); - if (msg1->id_type == CAN_STANDARD_IDENTIFIER) { + k_sem_reset(&tx_callback_sem); + + if (frame1->id_type == CAN_STANDARD_IDENTIFIER) { if (filter1->id_mask == CAN_STD_ID_MASK) { - filter_id_1 = add_rx_filter(can_dev, filter1, - rx_std_isr_1); - filter_id_2 = add_rx_filter(can_dev, filter2, - rx_std_isr_2); - send_test_msg_nowait(can_dev, msg1, tx_std_isr_1); - send_test_msg_nowait(can_dev, msg2, tx_std_isr_2); + filter_id_1 = add_rx_filter(can_dev, filter1, rx_std_callback_1); + filter_id_2 = add_rx_filter(can_dev, filter2, rx_std_callback_2); + send_test_frame_nowait(can_dev, frame1, tx_std_callback_1); + send_test_frame_nowait(can_dev, frame2, tx_std_callback_2); } else { - filter_id_1 = add_rx_filter(can_dev, filter1, - rx_std_mask_isr_1); - filter_id_2 = add_rx_filter(can_dev, filter2, - rx_std_mask_isr_2); - send_test_msg_nowait(can_dev, msg1, tx_std_isr_1); - send_test_msg_nowait(can_dev, msg2, tx_std_isr_2); + filter_id_1 = add_rx_filter(can_dev, filter1, rx_std_mask_callback_1); + filter_id_2 = add_rx_filter(can_dev, filter2, rx_std_mask_callback_2); + send_test_frame_nowait(can_dev, frame1, tx_std_callback_1); + send_test_frame_nowait(can_dev, frame2, tx_std_callback_2); } } else { if (filter1->id_mask == CAN_EXT_ID_MASK) { - filter_id_1 = add_rx_filter(can_dev, filter1, - rx_ext_isr_1); - filter_id_2 = add_rx_filter(can_dev, filter2, - rx_ext_isr_2); - send_test_msg_nowait(can_dev, msg1, tx_ext_isr_1); - send_test_msg_nowait(can_dev, msg2, tx_ext_isr_2); + filter_id_1 = add_rx_filter(can_dev, filter1, rx_ext_callback_1); + filter_id_2 = add_rx_filter(can_dev, filter2, rx_ext_callback_2); + send_test_frame_nowait(can_dev, frame1, tx_ext_callback_1); + send_test_frame_nowait(can_dev, frame2, tx_ext_callback_2); } else { - filter_id_1 = add_rx_filter(can_dev, filter1, - rx_ext_mask_isr_1); - filter_id_2 = add_rx_filter(can_dev, filter2, - rx_ext_mask_isr_2); - send_test_msg_nowait(can_dev, msg1, tx_ext_isr_1); - send_test_msg_nowait(can_dev, msg2, tx_ext_isr_2); + filter_id_1 = add_rx_filter(can_dev, filter1, rx_ext_mask_callback_1); + filter_id_2 = add_rx_filter(can_dev, filter2, rx_ext_mask_callback_2); + send_test_frame_nowait(can_dev, frame1, tx_ext_callback_1); + send_test_frame_nowait(can_dev, frame2, tx_ext_callback_2); } } - ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, 0, "Receiving timeout"); - ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, 0, "Receiving timeout"); - ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); - zassert_equal(ret, 0, "Missing TX callback"); - ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); - zassert_equal(ret, 0, "Missing TX callback"); + err = k_sem_take(&rx_callback_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); + + err = k_sem_take(&rx_callback_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); + + err = k_sem_take(&tx_callback_sem, TEST_SEND_TIMEOUT); + zassert_equal(err, 0, "missing TX callback"); + + err = k_sem_take(&tx_callback_sem, TEST_SEND_TIMEOUT); + zassert_equal(err, 0, "missing TX callback"); + can_remove_rx_filter(can_dev, filter_id_1); can_remove_rx_filter(can_dev, filter_id_2); } -/* - * Set driver to loopback mode - * The driver stays in loopback mode after that. - * The controller can now be tested against itself +/** + * @brief Test configuring the CAN controller for loopback mode. + * + * This must be the first test case as it allows the other test cases to + * send/receive their own frames. */ static void test_set_loopback(void) { - int ret; + int err; - ret = can_set_mode(can_dev, CAN_LOOPBACK_MODE); - zassert_equal(ret, 0, "Can't set loopback-mode. Err: %d", ret); + err = can_set_mode(can_dev, CAN_LOOPBACK_MODE); + zassert_equal(err, 0, "failed to set loopback-mode (err %d)", err); } -/* - * Sending a message to the wild should work because we are in loopback mode - * and therefore ACK the frame ourselves +/** + * @brief Test sending a message with no filters installed. + * + * This basic test work since the CAN controller is in loopback mode and + * therefore ACKs its own frame. */ static void test_send_and_forget(void) { - zassert_not_null(can_dev, "Device not not found"); - - send_test_msg(can_dev, &test_std_msg_1); + send_test_frame(can_dev, &test_std_frame_1); } -/* - * Test adding a very basic filter - * Test each type but only one filter at a time +/** + * @brief Test adding basic filters. + * + * Test each filter type but only one filter at a time. */ static void test_add_filter(void) { int filter_id; - filter_id = add_rx_filter(can_dev, &test_std_filter_1, rx_std_isr_1); + filter_id = add_rx_filter(can_dev, &test_std_filter_1, rx_std_callback_1); can_remove_rx_filter(can_dev, filter_id); - filter_id = add_rx_filter(can_dev, &test_ext_filter_1, rx_ext_isr_1); + filter_id = add_rx_filter(can_dev, &test_ext_filter_1, rx_ext_callback_1); can_remove_rx_filter(can_dev, filter_id); filter_id = add_rx_msgq(can_dev, &test_std_filter_1); @@ -450,104 +624,92 @@ static void test_add_filter(void) filter_id = add_rx_msgq(can_dev, &test_ext_filter_1); can_remove_rx_filter(can_dev, filter_id); - filter_id = add_rx_filter(can_dev, &test_std_masked_filter_1, - rx_std_mask_isr_1); + filter_id = add_rx_filter(can_dev, &test_std_masked_filter_1, rx_std_mask_callback_1); can_remove_rx_filter(can_dev, filter_id); - filter_id = add_rx_filter(can_dev, &test_ext_masked_filter_1, - rx_ext_mask_isr_1); + filter_id = add_rx_filter(can_dev, &test_ext_masked_filter_1, rx_ext_mask_callback_1); can_remove_rx_filter(can_dev, filter_id); } -/* - * Test if a message is received wile nothing was sent. +/** + * @brief Test that no message is received when nothing was sent. */ static void test_receive_timeout(void) { - int ret, filter_id; - struct zcan_frame msg; + struct zcan_frame frame; + int filter_id; + int err; filter_id = add_rx_msgq(can_dev, &test_std_filter_1); - ret = k_msgq_get(&can_msgq, &msg, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, -EAGAIN, "Got a message without sending it"); + err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, -EAGAIN, "received a frame without sending one"); can_remove_rx_filter(can_dev, filter_id); } -/* - * Test if the callback function is called +/** + * @brief Test that transmit callback function is called. */ static void test_send_callback(void) { - int ret; + int err; - k_sem_reset(&tx_cb_sem); + k_sem_reset(&tx_callback_sem); - send_test_msg_nowait(can_dev, &test_std_msg_1, tx_std_isr_1); + send_test_frame_nowait(can_dev, &test_std_frame_1, tx_std_callback_1); - ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); - zassert_equal(ret, 0, "Missing TX callback"); + err = k_sem_take(&tx_callback_sem, TEST_SEND_TIMEOUT); + zassert_equal(err, 0, "missing TX callback"); } -/* - * Add a filter that should pass the message and send the message. - * The massage should be received within a small timeout. - * Standard identifier +/** + * @brief Test send/receive with standard (11-bit) CAN IDs. */ -void test_send_receive_std(void) +void test_send_receive_std_id(void) { send_receive(&test_std_filter_1, &test_std_filter_2, - &test_std_msg_1, &test_std_msg_2); + &test_std_frame_1, &test_std_frame_2); } -/* - * Add a filter that should pass the message and send the message. - * The massage should be received within a small timeout - * Extended identifier +/** + * @brief Test send/receive with extended (29-bit) CAN IDs. */ -void test_send_receive_ext(void) +void test_send_receive_ext_id(void) { send_receive(&test_ext_filter_1, &test_ext_filter_2, - &test_ext_msg_1, &test_ext_msg_2); + &test_ext_frame_1, &test_ext_frame_2); } -/* - * Add a filter that should pass the message and send the message. - * The massage should be received within a small timeout. - * The message ID is slightly different to the filter but should still - * because of the mask settind in the filter. - * Standard identifier +/** + * @brief Test send/receive with standard (11-bit) masked CAN IDs. */ -void test_send_receive_std_masked(void) +void test_send_receive_std_id_masked(void) { send_receive(&test_std_masked_filter_1, &test_std_masked_filter_2, - &test_std_msg_1, &test_std_msg_2); + &test_std_frame_1, &test_std_frame_2); } -/* - * Add a filter that should pass the message and send the message. - * The massage should be received within a small timeout. - * The message ID is slightly different to the filter but should still - * because of the mask settind in the filter. - * Extended identifier +/** + * @brief Test send/receive with extended (29-bit) masked CAN IDs. */ -void test_send_receive_ext_masked(void) +void test_send_receive_ext_id_masked(void) { send_receive(&test_ext_masked_filter_1, &test_ext_masked_filter_2, - &test_ext_msg_1, &test_ext_msg_2); + &test_ext_frame_1, &test_ext_frame_2); } -/* - * Add a filter that should pass the message and send multiple messages. - * The massage should be received and buffered within a small timeout. - * Extended identifier +/** + * @brief Test send/receive with messages buffered in a CAN message queue. */ -void test_send_receive_buffer(void) +void test_send_receive_msgq(void) { - int filter_id, i, ret, nframes; struct k_msgq_attrs attrs; struct zcan_frame frame; + int filter_id; + int nframes; + int err; + int i; filter_id = add_rx_msgq(can_dev, &test_std_filter_1); @@ -555,80 +717,78 @@ void test_send_receive_buffer(void) nframes = attrs.max_msgs; for (i = 0; i < nframes; i++) { - send_test_msg(can_dev, &test_std_msg_1); + send_test_frame(can_dev, &test_std_frame_1); } for (i = 0; i < nframes; i++) { - ret = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, 0, "Receiving timeout"); + err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); } for (i = 0; i < nframes; i++) { - send_test_msg(can_dev, &test_std_msg_1); + send_test_frame(can_dev, &test_std_frame_1); } for (i = 0; i < nframes; i++) { - ret = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, 0, "Receiving timeout"); + err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); } can_remove_rx_filter(can_dev, filter_id); } -/* - * Add a filter that should not pass the message and send a message - * with a different id. - * The massage should not be received. +/** + * @brief Test that non-matching CAN frames do not pass a filter. */ static void test_send_receive_wrong_id(void) { - int ret, filter_id; - struct zcan_frame msg_buffer; + struct zcan_frame frame_buffer; + int filter_id; + int err; filter_id = add_rx_msgq(can_dev, &test_std_filter_1); - send_test_msg(can_dev, &test_std_msg_2); + send_test_frame(can_dev, &test_std_frame_2); - ret = k_msgq_get(&can_msgq, &msg_buffer, TEST_RECEIVE_TIMEOUT); - zassert_equal(ret, -EAGAIN, - "Got a message that should not pass the filter"); + err = k_msgq_get(&can_msgq, &frame_buffer, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, -EAGAIN, "recevied a frame that should not pass the filter"); can_remove_rx_filter(can_dev, filter_id); } -/* - * Check if a call with dlc > CAN_MAX_DLC returns -EINVAL +/** + * @brief Test that frames with invalid Data Length Code (DLC) are rejected. */ static void test_send_invalid_dlc(void) { struct zcan_frame frame; - int ret; + int err; frame.dlc = CAN_MAX_DLC + 1; - ret = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, tx_std_isr_1, NULL); - zassert_equal(ret, -EINVAL, - "ret [%d] not equal to %d", ret, -EINVAL); + err = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, tx_std_callback_1, NULL); + zassert_equal(err, -EINVAL, "sent a frame with an invalid DLC"); } void test_main(void) { - k_sem_init(&rx_isr_sem, 0, 2); - k_sem_init(&tx_cb_sem, 0, 2); + k_sem_init(&rx_callback_sem, 0, 2); + k_sem_init(&tx_callback_sem, 0, 2); + zassert_true(device_is_ready(can_dev), "CAN device not ready"); - ztest_test_suite(can_driver, + ztest_test_suite(can_api_tests, ztest_unit_test(test_set_loopback), ztest_unit_test(test_send_and_forget), ztest_unit_test(test_add_filter), ztest_unit_test(test_receive_timeout), ztest_unit_test(test_send_callback), - ztest_unit_test(test_send_receive_std), + ztest_unit_test(test_send_receive_std_id), + ztest_unit_test(test_send_receive_ext_id), + ztest_unit_test(test_send_receive_std_id_masked), + ztest_unit_test(test_send_receive_ext_id_masked), + ztest_unit_test(test_send_receive_msgq), ztest_unit_test(test_send_invalid_dlc), - ztest_unit_test(test_send_receive_ext), - ztest_unit_test(test_send_receive_std_masked), - ztest_unit_test(test_send_receive_ext_masked), - ztest_unit_test(test_send_receive_buffer), ztest_unit_test(test_send_receive_wrong_id)); - ztest_run_test_suite(can_driver); + ztest_run_test_suite(can_api_tests); }