LPC1768 has no output on CAN TX while sending

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1768 has no output on CAN TX while sending

870 Views
hans-georgkujaw
Contributor I

Hello there!

I have designed software for a device, consisting of 8 CAN nodes (Master, Display, 6 Motor Controller) using KEIL µVision 5, RTX and newest Middleware for LPC1768. Everything works fine, but sometimes - once or twice a day - one of the Motor-Controllers stops to communicate via CAN. The CAN-API-Driver gives no error code back and the CAN hardware seems to be blocked, no output on TX pin, no data received. Because of missing any error messages from API driver I cannot react within the code, so the node (board) must be reseted manually.  

I tried the "old" CMSIS CAN driver, but there is the same behaviour. So I may assume, this is not a software problem, may I?

I tried to calculate the proper timing factors for the current CAN architecture, so I have got this:

status = DriverCAN->SetBitrate(ARM_CAN_BITRATE_NOMINAL,            /* Set nominal bitrate */
           LocalCANRate,                         /* Set bitrate to 500 kbit/s */
           ARM_CAN_BIT_PROP_SEG(4U)   |          /* Set propagation segment to 4 time quanta */
           ARM_CAN_BIT_PHASE_SEG1(2U) |          /* Set phase segment 2 to 2 time quantum (sample point at 87.5% of bit time) */
           ARM_CAN_BIT_PHASE_SEG2(3U) |          /* Set phase segment 2 to 3 time quantum (total bit is 8 time quanta long) */
           ARM_CAN_BIT_SJW(2U));         /* Resynchronization jump width 2 is same as phase segment 2 */

For the sending I use the code

while (tries)
  {   
  FeedExtWD();   
  CANSendingDone = 0;    
  osKernelLock();  
  Result = DriverCAN->MessageSend(tx_obj_idx, &tx_msg_info, data, len);
  osKernelUnlock();  
  if (Result == len)
   { 
   while (!(CANSendingDone || CANSendError)) WDT_Feed();   
   if (CANSendingDone)
    {
    break;
    }
   else if (CANSendError)
    {
    if (tries) tries--; 
    dbgprintf("CAN Driver Sending Error %d, %d tries left\r\n", CANSendError, tries);
    DriverCAN->Control(ARM_CAN_ABORT_MESSAGE_SEND, tx_obj_idx);
    dbgprintf("Sending aborted...\r\n");  
    }
   else
    {
    dbgprintf("Sending status unknown!\r\n"); 
    }
   }  
  else
   {
   if (tries) tries--;
   switch (Result)
    {
    case ARM_DRIVER_ERROR:
     uprintf("CAN Driver not sending, Unspecified error!\r\n");
     break;
 
    case ARM_DRIVER_ERROR_BUSY:
     uprintf("CAN Driver not sending, Driver is busy!\r\n");
     break;
 
    case ARM_DRIVER_ERROR_TIMEOUT:
     uprintf("CAN Driver not sending, Timeout occurred\r\n");
     break;
 
    case ARM_DRIVER_ERROR_UNSUPPORTED:
     uprintf("CAN Driver not sending, Operation not supported!\r\n");
     break;
 
    case ARM_DRIVER_ERROR_PARAMETER:
     uprintf("CAN Driver not sending, Parameter error!\r\n");
     break;
 
    case  ARM_DRIVER_ERROR_SPECIFIC:
    default:  
     uprintf("CAN Driver not sending, Result=%d\r\n", Result);
     break;
    } 
   DriverCAN->Control(ARM_CAN_ABORT_MESSAGE_SEND, tx_obj_idx);
   dbgprintf("Sending aborted...\r\n");  
   }   
  }

I try to lock the RTX Kernel during the sending for eliminate the influence of other threads.

My callback functions look this way:

void CANSignalObjectEvent (uint32_t obj_idx, uint32_t event) 
{
uint8_t ix, rLen;
 
if (obj_idx == rx_obj_idx)         /* If receive object event */ 
 {                  
   if (event == ARM_CAN_EVENT_RECEIVE)         /* If message was received successfully */
  {
   
  rLen = DriverCAN->MessageRead(rx_obj_idx, &rx_msg_info, rx_data, 8U);  
  if ( rLen > 0U) 
   {
         for (ix = 0; ix < rLen; ix++)
    {
    CANData.RxBuffer[CANData.RxInIndex].data[ix] = rx_data[ix];
    }
   CANData.RxBuffer[CANData.RxInIndex].len = rx_msg_info.dlc;
   CANData.RxBuffer[CANData.RxInIndex].id = rx_msg_info.id; 
   CANData.RxInIndex = (CANData.RxInIndex+1) % CAN_MAX_BUFFERS;         /* Point to the next free position */
   osThreadFlagsSet(idThreadCAN, THREAD_FLAG_CAN_RECEIVED); 
   }
  }
 }
 
if (obj_idx == tx_obj_idx)         /* If transmit object event */
 {                  
 if (event == ARM_CAN_EVENT_SEND_COMPLETE)   /* If message was sent successfully */
  { 
  osThreadFlagsSet(idThreadCANLiveMessage, THREAD_FLAG_CAN_SENT); 
  CANSendingDone = 1;
  CANSendError = 0; 
  // KU dbgprintf("!"); 
  }
 }
}

and

void CANSignalUnitEvent (uint32_t event) 
{
switch (event)
 {
 case ARM_CAN_EVENT_UNIT_INACTIVE:
  dbgprintf("\r\nCAN unit changes to inactive state\r\n");
  break;

 case ARM_CAN_EVENT_UNIT_ACTIVE:
  dbgprintf("\r\nCAN unit changes to active state\r\n");
  CANSendError = 0;
  break;

 case ARM_CAN_EVENT_UNIT_WARNING:
  dbgprintf("\r\nCAN unit error or warning\r\nCAN will be resetted...\r\n");
  CANSendError = 1;
  break;

 case ARM_CAN_EVENT_UNIT_PASSIVE:
  dbgprintf("\r\nCAN unit changest to passive state\r\n");
  CANSendError = 2;
  break;

 case ARM_CAN_EVENT_UNIT_BUS_OFF:
  dbgprintf("\r\nCAN unit bus is off\r\n");
  break; 
 }  
}

As I said, it works fine all the day, but sometimes it stucks somehow, mostly the first or the last device on bus. And no case of error is reported by the CAN driver...

Did somebody make a similar experience? Is there something, I should try out? 

My colleague, who designed the hardware (boards and wiring), says there is no problem with it. Who is right?   

Labels (1)
0 Kudos
1 Reply

771 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Hans-Georg Kujawa ,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
According to your description, in my opinion, it's hard to say what the reason causes the issue.
Above all, you should find out the condition which can replicate the issue definitely.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos