drivers: can: remove run-time RTR filtering, add build-time RTR filter

A growing number of CAN controllers do not have support for individual RX
hardware filters based on the Remote Transmission Request (RTR) bit. This
leads to various work-arounds on the driver level mixing hardware and
software filtering.

As the use of RTR frames is discouraged by CAN in Automation (CiA) - and
not even supported by newer standards, e.g. CAN FD - this often leads to
unnecessary overhead, added complexity, and worst-case to non-portable
behavior between various CAN controller drivers.

Instead, move to a simpler approach where the ability to accept/reject RTR
frames is globally configured via Kconfig. By default, all incoming RTR
frames are rejected at the driver level, a setting which can be supported
in hardware by most in-tree CAN controllers drivers.

Legacy applications or protocol implementations, where RTR reception is
required, can now select CONFIG_CAN_ACCEPT_RTR to accept incoming RTR
frames matching added CAN filters. These applications or protocols will
need to distinguish between RTR and data frames in their respective CAN RX
frame handling routines.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2023-12-15 13:36:18 +01:00 committed by Henrik Brix Andersen
commit 3436c93387
29 changed files with 243 additions and 235 deletions

View file

@ -96,6 +96,11 @@ static void canopen_rx_callback(const struct device *dev, struct can_frame *fram
}
if (((frame->id ^ buffer->ident) & buffer->mask) == 0U) {
#ifdef CONFIG_CAN_ACCEPT_RTR
if (buffer->rtr && ((frame->flags & CAN_FRAME_RTR) == 0U)) {
continue;
}
#endif /* CONFIG_CAN_ACCEPT_RTR */
rxMsg.ident = frame->id;
rxMsg.DLC = frame->dlc;
memcpy(rxMsg.data, frame->data, frame->dlc);
@ -310,7 +315,18 @@ CO_ReturnError_t CO_CANrxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
buffer->ident = ident;
buffer->mask = mask;
filter.flags = (rtr ? CAN_FILTER_RTR : CAN_FILTER_DATA);
#ifndef CONFIG_CAN_ACCEPT_RTR
if (rtr) {
LOG_ERR("request for RTR frames, but RTR frames are rejected");
CO_errorReport(CANmodule->em, CO_EM_GENERIC_SOFTWARE_ERROR,
CO_EMC_SOFTWARE_INTERNAL, 0);
return CO_ERROR_ILLEGAL_ARGUMENT;
}
#else /* !CONFIG_CAN_ACCEPT_RTR */
buffer->rtr = rtr;
#endif /* CONFIG_CAN_ACCEPT_RTR */
filter.flags = 0U;
filter.id = ident;
filter.mask = mask;

View file

@ -69,6 +69,9 @@ typedef struct canopen_rx {
CO_CANrxBufferCallback_t pFunct;
uint16_t ident;
uint16_t mask;
#ifdef CONFIG_CAN_ACCEPT_RTR
bool rtr;
#endif /* CONFIG_CAN_ACCEPT_RTR */
} CO_CANrx_t;
typedef struct canopen_tx {