Skip to content

Commit bc4b49c

Browse files
henrikbrixandersennashif
authored andcommitted
modules: canopennode: process rx buffers in priority order
The CANopenNode stack expects registered RX buffers to be processed and matched in priority order. The priority corresponds to the index of each each registered RX buffer with lower indexes having higher priority. Depending on the CANopen COB-ID network configuration used, it may result in overlapping CAN RX filters. In the case of overlaps, the priorities of the registered RX buffers matter. When receiving a CAN frame, process the RX buffers in priority order and only dispatch the callback for the matching object with the highest priority. Fixes: #54364 Signed-off-by: Henrik Brix Andersen <[email protected]>
1 parent 693be8a commit bc4b49c

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

modules/canopennode/CO_driver.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,31 @@ static void canopen_detach_all_rx_filters(CO_CANmodule_t *CANmodule)
7878
}
7979
}
8080

81-
static void canopen_rx_callback(const struct device *dev, struct can_frame *frame, void *arg)
81+
static void canopen_rx_callback(const struct device *dev, struct can_frame *frame, void *user_data)
8282
{
83-
CO_CANrx_t *buffer = (CO_CANrx_t *)arg;
83+
CO_CANmodule_t *CANmodule = (CO_CANmodule_t *)user_data;
8484
CO_CANrxMsg_t rxMsg;
85+
CO_CANrx_t *buffer;
86+
int i;
8587

8688
ARG_UNUSED(dev);
8789

88-
if (!buffer || !buffer->pFunct) {
89-
LOG_ERR("failed to process CAN rx callback");
90-
return;
91-
}
90+
/* Loop through registered rx buffers in priority order */
91+
for (i = 0; i < CANmodule->rx_size; i++) {
92+
buffer = &CANmodule->rx_array[i];
93+
94+
if (buffer->filter_id == -ENOSPC || buffer->pFunct == NULL) {
95+
continue;
96+
}
9297

93-
rxMsg.ident = frame->id;
94-
rxMsg.DLC = frame->dlc;
95-
memcpy(rxMsg.data, frame->data, frame->dlc);
96-
buffer->pFunct(buffer->object, &rxMsg);
98+
if (((frame->id ^ buffer->ident) & buffer->mask) == 0U) {
99+
rxMsg.ident = frame->id;
100+
rxMsg.DLC = frame->dlc;
101+
memcpy(rxMsg.data, frame->data, frame->dlc);
102+
buffer->pFunct(buffer->object, &rxMsg);
103+
break;
104+
}
105+
}
97106
}
98107

99108
static void canopen_tx_callback(const struct device *dev, int error, void *arg)
@@ -298,6 +307,8 @@ CO_ReturnError_t CO_CANrxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
298307
buffer = &CANmodule->rx_array[index];
299308
buffer->object = object;
300309
buffer->pFunct = pFunct;
310+
buffer->ident = ident;
311+
buffer->mask = mask;
301312

302313
filter.flags = (rtr ? CAN_FILTER_RTR : CAN_FILTER_DATA);
303314
filter.id = ident;
@@ -309,7 +320,7 @@ CO_ReturnError_t CO_CANrxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
309320

310321
buffer->filter_id = can_add_rx_filter(CANmodule->dev,
311322
canopen_rx_callback,
312-
buffer, &filter);
323+
CANmodule, &filter);
313324
if (buffer->filter_id == -ENOSPC) {
314325
LOG_ERR("failed to add CAN rx callback, no free filter");
315326
CO_errorReport(CANmodule->em, CO_EM_MEMORY_ALLOCATION_ERROR,

modules/canopennode/CO_driver_target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ typedef struct canopen_rx {
6666
void *object;
6767
CO_CANrxBufferCallback_t pFunct;
6868
uint16_t ident;
69+
uint16_t mask;
6970
} CO_CANrx_t;
7071

7172
typedef struct canopen_tx {

0 commit comments

Comments
 (0)