Hi,
The device is a Cortex M3 (1768, specifically).
When I send a CAN message to both port 1 and port 2 from a third node on the network, I see a double receipt of the CAN message.
A bit of characterizing showed me the following: - if both ports are plugged into the network I get the double message - can port 2 is being read twice (which was the target port for the message) - I am seeing two interrupts being called, one for each port (which is understandable).
The only cure for this seems to be to clear the CMR bits on both CANs after reading in just one message.
It looks like this in the code snippet below: LPC_CAN2->CMR = BIT_TWO; /* Release receive buffer */ LPC_CAN1->CMR = BIT_TWO; /* Release receive buffer */
I would have thought that the correct algorithm would be: - to disable interrupts at the start, - handle what I need to, - clear the interrupt bit, - and re-enable interrupts
Using the IER register seems to be incorrect (LPC_CAN1->IER &= ~0x0001) as it also clears the interrupt so I never read the received contents.
Can anyone suggest an alternative?
Thanks,
--Erik
PS -
My CAN ISR /****************************************************************************** * CAN interrupt handler * * Message received if ICR bit 0 (receive Interrupt) is set * Bit 0 is only set if CANxIER is also 1 * * Recvs: * Return: ******************************************************************************/ void CAN_IRQHandler (void) {
/* Check CAN controller 2 -- "DOWNSTREAM" */ if (LPC_CAN2->ICR & 0x01) { /* CAN Controller #2 message is received */ // disable interrupts LPC_CAN1->IER &= ~0x0001; LPC_CAN2->IER &= ~0x0001;
canMetrics.rx2IsrCalled++; CAN_rdMsg (I_AM_A_DOWNSTREAM_CAN_PORT); /* Read the message */ LPC_CAN2->CMR = BIT_TWO; /* Release receive buffer */ LPC_CAN1->CMR = BIT_TWO; /* Release receive buffer */ }
/* Check CAN controller 1 -- "UPSTREAM" */ if (LPC_CAN1->ICR & 0x01) { /* CAN Controller #1 message is received */ // disable interrupts LPC_CAN1->IER &= ~0x0001; LPC_CAN2->IER &= ~0x0001;
canMetrics.rx1IsrCalled++; CAN_rdMsg (I_AM_AN_UPSTREAM_CAN_PORT); /* Read the message */ LPC_CAN1->CMR = BIT_TWO; /* Release receive buffer */ LPC_CAN2->CMR = BIT_TWO; /* Release receive buffer */ }
canMetrics.IRQHandlerCalled++;
// re-enable interrupts LPC_CAN1->IER |= 0x0001; LPC_CAN2->IER |= 0x0001;
}
Example CAN ISR from Keil /*---------------------------------------------------------------------------- CAN interrupt handler *----------------------------------------------------------------------------*/ void CAN_IRQHandler (void) { volatile uint32_t icr;
/* check CAN controller 1 */ icr = LPC_CAN1->ICR; /* clear interrupts */
if (icr & (1 << 0)) { /* CAN Controller #1 meassage is received */ CAN_rdMsg (1, &CAN_RxMsg[0]); /* read the message */ LPC_CAN1->CMR = (1 << 2); /* Release receive buffer */
CAN_RxRdy[0] = 1; /* set receive flag */ }
if (icr & (1 << 1)) { /* CAN Controller #1 meassage is transmitted */ CAN_TxRdy[0] = 1; }
/* check CAN controller 2 */ icr = LPC_CAN2->ICR; /* clear interrupts */
if (icr & (1 << 0)) { /* CAN Controller #2 meassage is received */ CAN_rdMsg (2, &CAN_RxMsg[1]); /* read the message */ LPC_CAN2->CMR = (1 << 2); /* Release receive buffer */
CAN_RxRdy[1] = 1; /* set receive flag */ }
if (icr & (1 << 1)) { /* CAN Controller #2 meassage is transmitted */ CAN_TxRdy[1] = 1; }
Sorry, I was unclear.
I have my development board set up in such a way that both ports are connected to a third node on the network. Port 1 simulates the Master, Port 2 is the slave.
I think I have the solution. It is not within the IRQ() but within the filtering. This ostensibly crazy configuration is for testing but not deployment.
Thanks for your response, however.
Well of course you need to filter the received data. Your messages are not sent with any address telling them to ignore port 1. So port 1 must know to drop the packets. And that is done by filtering.
I don't really see how you could have thought the message should know that it should ignore one of the ports connected to the cable. Or how port1 should know that port2 is concurrently receiving the same message.