Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: drivers: can: timing: rework the CAN controller driver timing tests #70224

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 25 additions & 21 deletions drivers/can/can_fake.c
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/drivers/can.h>
#include <zephyr/drivers/can/can_fake.h>
#include <zephyr/fff.h>
#include <zephyr/sys/util.h>

#ifdef CONFIG_ZTEST
#include <zephyr/ztest.h>
Expand Down Expand Up @@ -60,7 +61,8 @@ static int fake_can_get_core_clock_delegate(const struct device *dev, uint32_t *
{
ARG_UNUSED(dev);

*rate = 16000000;
/* Recommended CAN clock from from CiA 601-3 */
*rate = MHZ(80);

return 0;
}
Expand Down Expand Up @@ -109,35 +111,37 @@ static const struct can_driver_api fake_can_driver_api = {
.set_state_change_callback = fake_can_set_state_change_callback,
.get_core_clock = fake_can_get_core_clock,
.get_max_filters = fake_can_get_max_filters,
/* Recommended configuration ranges from CiA 601-2 */
.timing_min = {
.sjw = 0x01,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
.sjw = 1,
.prop_seg = 0,
.phase_seg1 = 2,
.phase_seg2 = 2,
.prescaler = 1
},
.timing_max = {
.sjw = 0x0f,
.prop_seg = 0x0f,
.phase_seg1 = 0x0f,
.phase_seg2 = 0x0f,
.prescaler = 0xffff
.sjw = 128,
.prop_seg = 0,
.phase_seg1 = 256,
.phase_seg2 = 128,
.prescaler = 32
},
#ifdef CONFIG_CAN_FD_MODE
.set_timing_data = fake_can_set_timing_data,
/* Recommended configuration ranges from CiA 601-2 */
.timing_data_min = {
.sjw = 0x01,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
.sjw = 1,
.prop_seg = 0,
.phase_seg1 = 1,
.phase_seg2 = 1,
.prescaler = 1
},
.timing_data_max = {
.sjw = 0x0f,
.prop_seg = 0x0f,
.phase_seg1 = 0x0f,
.phase_seg2 = 0x0f,
.prescaler = 0xffff
.sjw = 16,
.prop_seg = 0,
.phase_seg1 = 32,
.phase_seg2 = 16,
.prescaler = 32
},
#endif /* CONFIG_CAN_FD_MODE */
};
Expand Down
50 changes: 28 additions & 22 deletions drivers/can/can_loopback.c
Expand Up @@ -13,6 +13,7 @@
#include <zephyr/drivers/can.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>

LOG_MODULE_REGISTER(can_loopback, CONFIG_CAN_LOG_LEVEL);

Expand Down Expand Up @@ -351,8 +352,11 @@ static void can_loopback_set_state_change_callback(const struct device *dev,

static int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate)
{
/* Return 16MHz as an realistic value for the testcases */
*rate = 16000000;
ARG_UNUSED(dev);

/* Recommended CAN clock from from CiA 601-3 */
*rate = MHZ(80);

return 0;
}

Expand All @@ -376,35 +380,37 @@ static const struct can_driver_api can_loopback_driver_api = {
.set_state_change_callback = can_loopback_set_state_change_callback,
.get_core_clock = can_loopback_get_core_clock,
.get_max_filters = can_loopback_get_max_filters,
/* Recommended configuration ranges from CiA 601-2 */
.timing_min = {
.sjw = 0x1,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
.sjw = 1,
.prop_seg = 0,
.phase_seg1 = 2,
.phase_seg2 = 2,
.prescaler = 1
},
.timing_max = {
.sjw = 0x0F,
.prop_seg = 0x0F,
.phase_seg1 = 0x0F,
.phase_seg2 = 0x0F,
.prescaler = 0xFFFF
.sjw = 128,
.prop_seg = 0,
.phase_seg1 = 256,
.phase_seg2 = 128,
.prescaler = 32
},
#ifdef CONFIG_CAN_FD_MODE
.set_timing_data = can_loopback_set_timing_data,
/* Recommended configuration ranges from CiA 601-2 */
.timing_data_min = {
.sjw = 0x1,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
.sjw = 1,
.prop_seg = 0,
.phase_seg1 = 1,
.phase_seg2 = 1,
.prescaler = 1
},
.timing_data_max = {
.sjw = 0x0F,
.prop_seg = 0x0F,
.phase_seg1 = 0x0F,
.phase_seg2 = 0x0F,
.prescaler = 0xFFFF
.sjw = 16,
.prop_seg = 0,
.phase_seg1 = 32,
.phase_seg2 = 16,
.prescaler = 32
},
#endif /* CONFIG_CAN_FD_MODE */
};
Expand Down
72 changes: 72 additions & 0 deletions tests/drivers/can/api/src/canfd.c
Expand Up @@ -375,6 +375,78 @@ ZTEST_USER(canfd, test_filters_preserved_through_fd_to_classic_mode_change)
check_filters_preserved_between_modes(CAN_MODE_FD, CAN_MODE_NORMAL);
}

/**
* @brief Test that the minimum timing values for the data phase can be set.
*/
ZTEST_USER(canfd, test_set_timing_data_min)
{
int err;

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_timing_data(can_dev, can_get_timing_data_min(can_dev));
zassert_equal(err, 0, "failed to set minimum timing data parameters (err %d)", err);

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test setting a too high data phase bitrate.
*/
ZTEST_USER(canfd, test_set_bitrate_too_high)
{
uint32_t max = 8000000U;
int expected = -EINVAL;
int err;

err = can_get_max_bitrate(can_dev, &max);
if (err != -ENOSYS) {
zassert_equal(err, 0, "failed to get max bitrate (err %d)", err);
zassert_not_equal(max, 0, "max bitrate is 0");
expected = -ENOTSUP;
}

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_bitrate_data(can_dev, max + 1);
zassert_equal(err, expected, "too high data phase bitrate accepted");

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test using an invalid sample point.
*/
ZTEST_USER(canfd, test_invalid_sample_point)
{
struct can_timing timing;
int err;

err = can_calc_timing_data(can_dev, &timing, TEST_BITRATE_3, 1000);
zassert_equal(err, -EINVAL, "invalid sample point of 100.0% accepted (err %d)", err);
}

/**
* @brief Test that the maximum timing values for the data phase can be set.
*/
ZTEST_USER(canfd, test_set_timing_data_max)
{
int err;

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_timing_data(can_dev, can_get_timing_data_max(can_dev));
zassert_equal(err, 0, "failed to set maximum timing data parameters (err %d)", err);

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test setting data phase bitrate is not allowed while started.
*/
Expand Down
60 changes: 53 additions & 7 deletions tests/drivers/can/api/src/classic.c
Expand Up @@ -502,27 +502,39 @@ ZTEST_USER(can_classic, test_bitrate_limits)
*/
ZTEST_USER(can_classic, test_set_bitrate_too_high)
{
uint32_t max = 0U;
uint32_t max = 1000000U;
int expected = -EINVAL;
int err;

err = can_get_max_bitrate(can_dev, &max);
if (err == -ENOSYS) {
ztest_test_skip();
if (err != -ENOSYS) {
zassert_equal(err, 0, "failed to get max bitrate (err %d)", err);
zassert_not_equal(max, 0, "max bitrate is 0");
expected = -ENOTSUP;
}

zassert_equal(err, 0, "failed to get max bitrate (err %d)", err);
zassert_not_equal(max, 0, "max bitrate is 0");

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_bitrate(can_dev, max + 1);
zassert_equal(err, -ENOTSUP, "too high bitrate accepted");
zassert_equal(err, expected, "too high bitrate accepted");

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test using an invalid sample point.
*/
ZTEST_USER(can_classic, test_invalid_sample_point)
{
struct can_timing timing;
int err;

err = can_calc_timing(can_dev, &timing, TEST_BITRATE_1, 1000);
zassert_equal(err, -EINVAL, "invalid sample point of 100.0% accepted (err %d)", err);
}

/**
* @brief Test setting bitrate.
*/
Expand All @@ -540,6 +552,40 @@ ZTEST_USER(can_classic, test_set_bitrate)
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test that the minimum timing values can be set.
*/
ZTEST_USER(can_classic, test_set_timing_min)
{
int err;

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_timing(can_dev, can_get_timing_min(can_dev));
zassert_equal(err, 0, "failed to set minimum timing parameters (err %d)", err);

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test that the maximum timing values can be set.
*/
ZTEST_USER(can_classic, test_set_timing_max)
{
int err;

err = can_stop(can_dev);
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);

err = can_set_timing(can_dev, can_get_timing_max(can_dev));
zassert_equal(err, 0, "failed to set maximum timing parameters (err %d)", err);

err = can_start(can_dev);
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
}

/**
* @brief Test sending a message with no filters installed.
*
Expand Down
24 changes: 12 additions & 12 deletions tests/drivers/can/shell/src/main.c
Expand Up @@ -212,17 +212,17 @@ ZTEST(can_shell, test_can_timing)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
struct can_timing expected = {
.sjw = 1U,
.prop_seg = 2U,
.phase_seg1 = 3U,
.phase_seg2 = 4U,
.prescaler = 5U,
.sjw = 16U,
.prop_seg = 0U,
.phase_seg1 = 217U,
.phase_seg2 = 32U,
.prescaler = 32U,
};
int err;

fake_can_set_timing_fake.custom_fake = can_shell_test_capture_timing;

err = shell_execute_cmd(sh, "can timing " FAKE_CAN_NAME " 1 2 3 4 5");
err = shell_execute_cmd(sh, "can timing " FAKE_CAN_NAME " 16 0 217 32 32");
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_set_timing_fake.call_count, 1, "set_timing function not called");
zassert_equal(fake_can_set_timing_fake.arg0_val, fake_can_dev, "wrong device pointer");
Expand All @@ -244,19 +244,19 @@ ZTEST(can_shell, test_can_dtiming)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
struct can_timing expected = {
.sjw = 1U,
.prop_seg = 2U,
.phase_seg1 = 3U,
.phase_seg2 = 4U,
.prescaler = 5U,
.sjw = 5U,
.prop_seg = 0U,
.phase_seg1 = 29U,
.phase_seg2 = 10U,
.prescaler = 2U,
};
int err;

Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE);

fake_can_set_timing_data_fake.custom_fake = can_shell_test_capture_timing;

err = shell_execute_cmd(sh, "can dtiming " FAKE_CAN_NAME " 1 2 3 4 5");
err = shell_execute_cmd(sh, "can dtiming " FAKE_CAN_NAME " 5 0 29 10 2");
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_set_timing_data_fake.call_count, 1,
"set_timing_data function not called");
Expand Down