AnsweredAssumed Answered

MSCAN CAN0TAAK register not being set

Question asked by gator on Mar 17, 2015
Latest reply on Apr 27, 2015 by gator

 

I have the following code in my application and every so often, the code gets stuck in the while loop. There seems to be no discernible pattern - sometimes the code just gets stuck there.


if (CAN0TFLG != 0x07) 

{

 

   CAN0TARQ = 0x07; // abort the transmission

 

   while (!CAN0TAAK)

   {

      ; // Wait for the message transmission to be aborted

   }

}


The above code is actually a smaller piece to a bigger picture. My device requests OBD II data from a vehicle via the CAN bus. It sends messages to the vehicle and then listens for the response(s) from the vehicle. Since there are several addresses that I need to query to get the information I'm looking for, I have to change the CAN filters in order to be able to receive the responses from the different addresses. Normally, the CAN filters are configured such that no CAN filter hits are generated. They are effectively closed. I only open them up when I need to request a certain parameter and at that point, they are configured based on the address of the parameter I'm requesting.


Changing the CAN filters on the fly requires entering initialization mode. According to the data sheet, the best practice is to enter sleep mode before entering initialization mode to avoid CAN bus violations. My code currently does that. Before attempting to enter sleep mode, I check for and abort any ongoing transmissions. This must be done in order to enter sleep mode. I first found the need for aborting an ongoing transmission when my device attempted to connect to the vehicle's CAN bus. My device attempts to connect to the vehicle at CAN speeds of 250k and 500k using 11 and 29 bit identifiers. When my device attempted to connect to a 11 bit CAN 500k vehicle via 11bit CAN at 250k, it determined the CAN speed was wrong, but when it attempted to enter sleep mode, it got stuck in the busy wait loop waiting for sleep mode to be entered. I believe this was caused by error frames being generated on the bus since my device was transmitting at the wrong baud rate.


Once I added code to abort any ongoing transmissions before entering sleep mode, things seemed to work great for a while. Then I ran into the issue where the code gets stuck in the while(!CAN0TAAK) loop sometimes. I think what is happening is that at the moment I enter the if(CAN0TFLG != 0x07) statement, there is a transmission in progress and by the time the code attempts to abort the transmission, the transmission has completed so there is nothing to abort. Since there is now nothing to abort, the code gets stuck in the loop waiting for CAN0TAAK to get set.


Now the question is why would there be a transmission in progress at this point that would cause the code to enter the if(CAN0TFLG != 0x07) statement. By the time the code execution gets to the if(CAN0TFLG != 0x07) check, my device has already sent it's request and received a response so nothing else should be being sent and I would expect all of the transmit buffers to be empty, but there is obviously a situation where this is not true since the code is entering the if(CAN0TFLG != 0x07) statement.


Does anyone have any ideas as to what might be causing this behavior?


My code has the following flow:


.

. code elided

.

CAN message sent to vehicle

Wait for response from vehicle

CAN message received from vehicle

.

. code elided

.

EnterCAN0InitMode() is called that contains the following code:


if (CAN0TFLG != 0x07)

{

   CAN0TARQ = 0x07;


   while( !CAN0TAAK)

   {

      ; // wait for the message transmission to be aborted

   }

}


CAN0CTL0 |= SLPRQ; // Put the CAN controller to sleep before entering initialization mode to avoid CAN bus violations


while (!(CAN0CTL1 & SLPAK))

{

   ; // Wait for the CAN controller to go to sleep

}


CAN0CTL0 |= INITRQ // Set the INITRQ bit to request entrance into initialization mode


while (!(CAN0CTL1 & INITAK))

{

   ; // Wait for the CAN module to enter initialization mode

}


Here is my potential fix:


Replace this:


if (CAN0TFLG != 0x07)

{

   CAN0TARQ = 0x07;


   while( !CAN0TAAK)

   {

      ; // wait for the message transmission to be aborted

   }

}


with this:


while( !CAN0TAAK && (CAN0TFLG != 0x07)) // if we haven't aborted and CAN0TFLG is not 0x07, then that means a message is in the transmit buffer

{

   CAN0TARQ = 0x07; // abort any ongoing transmission

}



 

 





Outcomes