I'm trying to implement a simple CAN RX thread for a STM32F767ZIT6 witch ChibiOS 20.3.2 using both RX FIFOs provided by the chip. The used transceiver is a MCP2551SN. As of now, I am able to receive messages just fine, if no filters are applied to them. Problem is, if the filters (shown below) get applied to the mailboxes, all messages get received in mailbox 2 (FIFO1). However, messages with ID 0x00000100 and 0x07000000 should be stored in mailbox 1 (FIFO0), while all other relevant messages should be stored in mailbox 2 (FIFO1).
Code: Select all
CANFilter cfp[3] = {
{
.filter = 0,
.mode = 0,
.scale = 1,
.assignment = 0,
.register1 = 0x07000000,
.register2 = 0xFFFFFFFF
},
{
.filter = 1,
.mode = 0,
.scale = 1,
.assignment = 0,
.register1 = 0x00000100,
.register2 = 0xFFFFFFFF
},
{
.filter = 2,
.mode = 0,
.scale = 1,
.assignment = 1,
.register1 = 0x00000000,
.register2 = 0xFFFF0000
}
};
Since I did not use identifier mode for any of the filters and all are scaled to be 32 bit, I expected filter 0 to be applied first, followed by filter 1 and then 2, leading all messages to their correct mailboxes. I looked at all registers for filters (CAN_FMR, CAN_FM1R, CAN_FS1R, CAN_FFA1R, CAN_FFA1R, CAN_FA1R, as well as all correspondig CAN_FiRx) and they seem to be set up correctly. Did I mess up something in the event system? The whole thread function is shown below.
Code: Select all
THD_FUNCTION(CAN_RX_THD, p) {
(void)p;
chRegSetThreadName("CAN_RX");
event_listener_t receiveListener;
event_listener_t errorListener;
CANRxFrame rxFrame;
CANConfig canConfig;
/* Initialize filters */
CANFilter cfp[3] = {
{
.filter = 0,
.mode = 0,
.scale = 1,
.assignment = 0,
.register1 = 0x07000000,
.register2 = 0xFFFFFFFF
},
{
.filter = 1,
.mode = 0,
.scale = 1,
.assignment = 0,
.register1 = 0x00000100,
.register2 = 0xFFFFFFFF
},
{
.filter = 2,
.mode = 0,
.scale = 1,
.assignment = 1,
.register1 = 0x00000000,
.register2 = 0xFFFF0000
}
};
/* Activate filters */
canSTM32SetFilters(&CAND1, 3, 3, cfp);
/* 75% Sample point, AHP = 54MHz = ABP1. */
canConfig.btr = CAN_BTR_TS2(3) | CAN_BTR_TS1(12) | CAN_BTR_BRP(2);
canConfig.mcr = CAN_MCR_AWUM | CAN_MCR_ABOM;
canStart(&CAND1, &canConfig);
/* Listen to RX MB0 and MB1 */
chEvtRegisterMask(&CAND1.rxfull_event, &receiveListener, EVENT_MASK(0));
chEvtRegisterMask(&CAND1.error_event, &errorListener, EVENT_MASK(1));
while (!chThdShouldTerminateX()) {
eventmask_t mask = chEvtWaitAny(EVENT_MASK(0));
/* Serve RX */
if (mask & EVENT_MASK(0)) {
eventflags_t flags = chEvtGetAndClearFlags(&receiveListener);
/* Check if MB0 received */
if (flags & CAN_MAILBOX_TO_MASK(1U)) {
/* Service all messages in this queue */
while (canReceiveTimeout(&CAND1, 1, &rxFrame, TIME_IMMEDIATE) == MSG_OK) {
...
}
}
/* Check if MB1 received */
if (flags & CAN_MAILBOX_TO_MASK(2U)) {
/* Service all messages in this queue */
while (canReceiveTimeout(&CAND1, 2, &rxFrame, TIME_IMMEDIATE) == MSG_OK) {
...
}
}
}
/* Serve errors */
if (mask & EVENT_MASK(1)) {
...
}
}
chEvtUnregister(&CAND1.rxfull_event, &receiveListener);
chEvtUnregister(&CAND1.error_event, &errorListener);
}
Thanks,
mormod