LPC2368 using RTX
I've spent several days tracking down a problem where the CAN would stop transmitting after a time period - usually after exactly 31845 packets - which is 0x5555.
I found that CAN_hw_tx_empty was returning CAN_TX_BUSY_ERROR, but then the CAN interrupt was never transmitting the message waiting in the mailbox.
Next I looked at the wr_sem semaphore, and found that the token count was increasing with every successful transmission. Eventually the token count was rolling from 0xFFFF to 0x0000, which would cause CAN_hw_tx_empty to fail. Now I see 0x5555 x 3 = 0xFFFF.
Next I found that the wr_sem semaphore was being sent 2 - 3 times from the interrupt runtine.
Looking at the CAN_ISR function it seems that the semaphore is sent every interrupt if the CAN TX hardware is free. This is a bug, because the interrupt is called for receive, as well as TX for the other controller.
if (CAN1GSR & (1 << 3)) { if (isr_mbx_receive (MBX_tx_ctrl[0], (void **)&ptrmsg) != OS_R_OK) { CAN_hw_wr (1, ptrmsg); _free_box(CAN_mpool, ptrmsg); } else { isr_sem_send(wr_sem[0]); /* Return a token back to semaphore */ } }
Adding an additional test for the type of interrupt fixed the problem:
// If the CAN has transmitted if(CAN1ICR & (1<<1)) { // If the CAN hardware is ready to transmit if(CAN1GSR & (1 << 3)) { // See if there are any messages to send if(isr_mbx_receive(MBX_tx_ctrl[0], (void **)&ptrmsg) != OS_R_OK) { CAN_hw_wr(1, ptrmsg); _free_box(CAN_mpool, ptrmsg); } else { // Release semaphore token isr_sem_send(wr_sem[0]); } } }
Hope that this saves someone else 3 days of their life.
Yes this happens on controllers which do not have separate interrupt handlers for transmit and receive.
Thank you for pointing this out.