This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC2378 CAN semaphore bug

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.

Parents
  • Another CAN bug:
    The receive mailboxes are filled from the CAN interrupt. They are emptied from whatever part of main code reads the CAN bus. If the mailboxes fill up, then the receive buffer is never released and the CAN interrupt fires constantly, so that the main code never gets a chance to empty the mailboxes.

Reply
  • Another CAN bug:
    The receive mailboxes are filled from the CAN interrupt. They are emptied from whatever part of main code reads the CAN bus. If the mailboxes fill up, then the receive buffer is never released and the CAN interrupt fires constantly, so that the main code never gets a chance to empty the mailboxes.

Children