Skip to content

drivers: can: various RTR fixes #47903

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

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions drivers/can/can_loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

#include "can_utils.h"

LOG_MODULE_REGISTER(can_loopback, CONFIG_CAN_LOG_LEVEL);

struct can_loopback_frame {
Expand Down Expand Up @@ -56,13 +58,6 @@ static void dispatch_frame(const struct device *dev,
filter->rx_cb(dev, &frame_tmp, filter->cb_arg);
}

static inline int check_filter_match(const struct zcan_frame *frame,
const struct zcan_filter *filter)
{
return ((filter->id & filter->id_mask) ==
(frame->id & filter->id_mask));
}

static void tx_thread(void *arg1, void *arg2, void *arg3)
{
const struct device *dev = arg1;
Expand All @@ -80,7 +75,7 @@ static void tx_thread(void *arg1, void *arg2, void *arg3)
for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
filter = &data->filters[i];
if (filter->rx_cb &&
check_filter_match(&frame.frame, &filter->filter)) {
can_utils_filter_match(&frame.frame, &filter->filter) != 0) {
dispatch_frame(dev, &frame.frame, filter);
}
}
Expand Down
18 changes: 13 additions & 5 deletions drivers/can/can_mcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,8 @@ static void can_mcan_get_message(const struct device *dev,
int data_length;
void *cb_arg;
struct can_mcan_rx_fifo_hdr hdr;
bool rtr_filter_mask;
bool rtr_filter;

while ((*fifo_status_reg & CAN_MCAN_RXF0S_F0FL)) {
get_idx = (*fifo_status_reg & CAN_MCAN_RXF0S_F0GI) >>
Expand Down Expand Up @@ -653,11 +655,17 @@ static void can_mcan_get_message(const struct device *dev,

filt_idx = hdr.fidx;

/* Check if RTR must match */
if ((hdr.xtd && data->ext_filt_rtr_mask & (1U << filt_idx) &&
((data->ext_filt_rtr >> filt_idx) & 1U) != frame.rtr) ||
(data->std_filt_rtr_mask & (1U << filt_idx) &&
((data->std_filt_rtr >> filt_idx) & 1U) != frame.rtr)) {
if (hdr.xtd != 0) {
rtr_filter_mask = (data->ext_filt_rtr_mask & BIT(filt_idx)) != 0;
rtr_filter = (data->ext_filt_rtr & BIT(filt_idx)) != 0;
} else {
rtr_filter_mask = (data->std_filt_rtr_mask & BIT(filt_idx)) != 0;
rtr_filter = (data->std_filt_rtr & BIT(filt_idx)) != 0;
}

if (rtr_filter_mask && (rtr_filter != frame.rtr)) {
/* RTR bit does not match filter RTR mask and bit, drop frame */
*fifo_ack_reg = get_idx;
continue;
}

Expand Down
8 changes: 4 additions & 4 deletions drivers/can/can_mcux_flexcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,11 @@ static void mcux_flexcan_copy_zfilter_to_mbconfig(const struct zcan_filter *src,
if (src->id_type == CAN_STANDARD_IDENTIFIER) {
dest->format = kFLEXCAN_FrameFormatStandard;
dest->id = FLEXCAN_ID_STD(src->id);
*mask = FLEXCAN_RX_MB_STD_MASK(src->id_mask,
src->rtr & src->rtr_mask, 1);
*mask = FLEXCAN_RX_MB_STD_MASK(src->id_mask, src->rtr_mask, 1);
} else {
dest->format = kFLEXCAN_FrameFormatExtend;
dest->id = FLEXCAN_ID_EXT(src->id);
*mask = FLEXCAN_RX_MB_EXT_MASK(src->id_mask,
src->rtr & src->rtr_mask, 1);
*mask = FLEXCAN_RX_MB_EXT_MASK(src->id_mask, src->rtr_mask, 1);
}

if ((src->rtr & src->rtr_mask) == CAN_DATAFRAME) {
Expand Down Expand Up @@ -661,6 +659,7 @@ static inline void mcux_flexcan_transfer_rx_idle(const struct device *dev,
static FLEXCAN_CALLBACK(mcux_flexcan_transfer_callback)
{
struct mcux_flexcan_data *data = (struct mcux_flexcan_data *)userData;
const struct mcux_flexcan_config *config = data->dev->config;
/*
* The result field can either be a MB index (which is limited to 32 bit
* value) or a status flags value, which is 32 bit on some platforms but
Expand All @@ -680,6 +679,7 @@ static FLEXCAN_CALLBACK(mcux_flexcan_transfer_callback)
mcux_flexcan_transfer_error_status(data->dev, status_flags);
break;
case kStatus_FLEXCAN_TxSwitchToRx:
FLEXCAN_TransferAbortReceive(config->base, &data->handle, mb);
__fallthrough;
case kStatus_FLEXCAN_TxIdle:
mcux_flexcan_transfer_tx_idle(data->dev, mb);
Expand Down
115 changes: 115 additions & 0 deletions tests/drivers/can/api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ const struct zcan_frame test_ext_frame_2 = {
.data = {1, 2, 3, 4, 5, 6, 7, 8}
};

/**
* @brief Standard (11-bit) CAN ID RTR frame 1.
*/
const struct zcan_frame test_std_rtr_frame_1 = {
.id_type = CAN_STANDARD_IDENTIFIER,
.rtr = CAN_REMOTEREQUEST,
.id = TEST_CAN_STD_ID_1,
.dlc = 0,
.data = {0}
};

/**
* @brief Extended (29-bit) CAN ID RTR frame 1.
*/
const struct zcan_frame test_ext_rtr_frame_1 = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.rtr = CAN_REMOTEREQUEST,
.id = TEST_CAN_EXT_ID_1,
.dlc = 0,
.data = {0}
};

/**
* @brief Standard (11-bit) CAN ID filter 1. This filter matches
* ``test_std_frame_1``.
Expand Down Expand Up @@ -196,6 +218,30 @@ const struct zcan_filter test_ext_masked_filter_2 = {
.id_mask = TEST_CAN_EXT_MASK
};

/**
* @brief Standard (11-bit) CAN ID RTR filter 1. This filter matches
* ``test_std_rtr_frame_1``.
*/
const struct zcan_filter test_std_rtr_filter_1 = {
.id_type = CAN_STANDARD_IDENTIFIER,
.rtr = CAN_REMOTEREQUEST,
.id = TEST_CAN_STD_ID_1,
.rtr_mask = 1,
.id_mask = CAN_STD_ID_MASK
};

/**
* @brief Extended (29-bit) CAN ID RTR filter 1. This filter matches
* ``test_ext_rtr_frame_1``.
*/
const struct zcan_filter test_ext_rtr_filter_1 = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.rtr = CAN_REMOTEREQUEST,
.id = TEST_CAN_EXT_ID_1,
.rtr_mask = 1,
.id_mask = CAN_EXT_ID_MASK
};

/**
* @brief Standard (11-bit) CAN ID filter. This filter matches
* ``TEST_CAN_SOME_STD_ID``.
Expand Down Expand Up @@ -585,6 +631,55 @@ static void send_receive(const struct zcan_filter *filter1,
can_remove_rx_filter(can_dev, filter_id_2);
}

/**
* @brief Perform a send/receive test with a set of CAN ID filters and CAN frames, RTR and data
* frames.
*
* @param data_filter CAN data filter
* @param rtr_filter CAN RTR filter
* @param data_frame CAN data frame
* @param rtr_frame CAN RTR frame
*/
void send_receive_rtr(const struct zcan_filter *data_filter,
const struct zcan_filter *rtr_filter,
const struct zcan_frame *data_frame,
const struct zcan_frame *rtr_frame)
{
struct zcan_frame frame;
int filter_id;
int err;

filter_id = add_rx_msgq(can_dev, rtr_filter);

/* Verify that RTR filter does not match data frame */
send_test_frame(can_dev, data_frame);
err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT);
zassert_equal(err, -EAGAIN, "Data frame passed RTR filter");

/* Verify that RTR filter matches RTR frame */
send_test_frame(can_dev, rtr_frame);
err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT);
zassert_equal(err, 0, "receive timeout");
assert_frame_equal(&frame, rtr_frame, 0);

can_remove_rx_filter(can_dev, filter_id);

filter_id = add_rx_msgq(can_dev, data_filter);

/* Verify that data filter does not match RTR frame */
send_test_frame(can_dev, rtr_frame);
err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT);
zassert_equal(err, -EAGAIN, "RTR frame passed data filter");

/* Verify that data filter matches data frame */
send_test_frame(can_dev, data_frame);
err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT);
zassert_equal(err, 0, "receive timeout");
assert_frame_equal(&frame, data_frame, 0);

can_remove_rx_filter(can_dev, filter_id);
}

/**
* @brief Test getting the CAN core clock rate.
*/
Expand Down Expand Up @@ -888,6 +983,24 @@ void test_send_receive_msgq(void)
can_remove_rx_filter(can_dev, filter_id);
}

/**
* @brief Test send/receive with standard (11-bit) CAN IDs and remote transmission request (RTR).
*/
void test_send_receive_std_id_rtr(void)
{
send_receive_rtr(&test_std_filter_1, &test_std_rtr_filter_1,
&test_std_frame_1, &test_std_rtr_frame_1);
}

/**
* @brief Test send/receive with extended (29-bit) CAN IDs and remote transmission request (RTR).
*/
void test_send_receive_ext_id_rtr(void)
{
send_receive_rtr(&test_ext_filter_1, &test_ext_rtr_filter_1,
&test_ext_frame_1, &test_ext_rtr_frame_1);
}

/**
* @brief Test that non-matching CAN frames do not pass a filter.
*/
Expand Down Expand Up @@ -1038,6 +1151,8 @@ void test_main(void)
ztest_unit_test(test_send_receive_std_id_masked),
ztest_unit_test(test_send_receive_ext_id_masked),
ztest_user_unit_test(test_send_receive_msgq),
ztest_user_unit_test(test_send_receive_std_id_rtr),
ztest_user_unit_test(test_send_receive_ext_id_rtr),
ztest_user_unit_test(test_send_invalid_dlc),
ztest_unit_test(test_send_receive_wrong_id),
ztest_user_unit_test(test_recover),
Expand Down