FlexCan Transmit MB issue

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

FlexCan Transmit MB issue

Jump to solution
1,652 Views
davidzhou
Contributor V

Hi,

I have two MBs setup for transmit CAN IDs. MB[8] and MB[10].

I copied TX task here:

while (1) {

//1. Check MB is Active or not, if so abort process

if (iBuffer==0) {//Use MB[8] for ID=0x0C20FF00

   iBuffer=1;   

   if ((g_pCanReg1->MB[8].CS & CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE))== CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE)) { // check if mailbox is set for transmit           

      //2. write ID and Data

      g_pCanReg1->MB[8].CS; // |= CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE); // Locking mailbox

      g_pCanReg1->MB[8].CS = CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE);   

      g_pCanReg1->MB[8].CS |= (DEFAULT_DLC_8 << CAN_CS_DLC_SHIFT); 

      g_pCanReg1->MB[8].CS &= ~CAN_CS_SRR_MASK;            

      g_pCanReg1->MB[8].CS |= CAN_CS_IDE_MASK;        

      g_pCanReg1->MB[8].ID &= ~(0x1FFFFFFF);

      g_pCanReg1->MB[8].ID |= (0x0C20FF00L & 0x1FFFFFFF);

      g_pCanReg1->MB[8].WORD0++;

      g_pCanReg1->MB[8].WORD1++;

      g_pCanReg1->MB[8].CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_ONCE) | TX_DLC); //transmit data

   }

   else {  //NOT ready

      iTxError0++;

   }

}

else {  //Use MB[8] for ID=0x0C21FF00

   iBuffer=0;

   if ((g_pCanReg1->MB[10].CS & CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE))==  

             CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE)) { // check if mailbox is set for transmit           

      g_pCanReg1->MB[10].CS;  // |= CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE); // Locking mailbox

      g_pCanReg1->MB[10].CS = CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE);        //Initialize CODE Status

      g_pCanReg1->MB[10].CS |= (DEFAULT_DLC_8 << CAN_CS_DLC_SHIFT); 

      g_pCanReg1->MB[10].CS &= ~CAN_CS_SRR_MASK;                    

      g_pCanReg1->MB[10].CS |= CAN_CS_IDE_MASK;                    

      g_pCanReg1->MB[10].ID &= ~(0x1FFFFFFF);

      g_pCanReg1->MB[10].ID |= (0x0C21FF00L & 0x1FFFFFFF);

      g_pCanReg1->MB[10].WORD0 ++;

      g_pCanReg1->MB[10].WORD1 ++;

      g_pCanReg1->MB[10].CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_ONCE) | TX_DLC); // transmit data

   }

   else {//NOT ready

      iTxError1++;

   }

}

if ((iTxError0!=0 || iTxError1 !=0)) {

}

} //end while

_time_delay(1);

// end of the task

The code runs ok without error.  But if the last line _time_delay(1) is commented out, it causes a problem.

The transmit doesn't use interrupt. interrupt mask is not enable and interrupt ISR is not installed.

The logic is simple:

    check the MB for TX is not active, then setup data, status, and transmit once.

     if is active, skip it. ErrorCount++;

    two MBs alternatively to transmit each ID.

Run results:

    no error counter is logged.

    Both IDs are transmitted.

    But from CAN capture problem, it also transmitted another Standard ID=0x308 periodically. I don't know where this ID come from. If I transmit just one MB, either of the both, it will receive the above 0x308 ID.

  it seems that transmit has error. I though the transmit arbitration process shall take care of the MBs transmit. What's the best way to resolve it?

It runs on K60 tower.

Thank you,

David

0 Kudos
Reply
1 Solution
1,097 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi David zhou,

  Actually, the function of _time_delay(1); in your code it is just wait the transmit is finished.

  If the first FlexCAN transfer is not finished, then you do anther transfer, it will have problem, because you are not use the interrupt, just use the polling, then after you transfer the CAN data, you need to wait the transmit is finished, but in your code, I didn't find the according code, please add the wait the transfer finished code, you can check register CANx_ESR1[TX] bit, or use the delay.

    About the different ID your are sending, you should check your code and combine with the debug, check which code send the other ID which you don't want to have.

Wish it helps you!

If you still have question, please contact with me!

  


Have a great day,
Jingjing

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

View solution in original post

0 Kudos
Reply
4 Replies
1,098 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi David zhou,

  Actually, the function of _time_delay(1); in your code it is just wait the transmit is finished.

  If the first FlexCAN transfer is not finished, then you do anther transfer, it will have problem, because you are not use the interrupt, just use the polling, then after you transfer the CAN data, you need to wait the transmit is finished, but in your code, I didn't find the according code, please add the wait the transfer finished code, you can check register CANx_ESR1[TX] bit, or use the delay.

    About the different ID your are sending, you should check your code and combine with the debug, check which code send the other ID which you don't want to have.

Wish it helps you!

If you still have question, please contact with me!

  


Have a great day,
Jingjing

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

0 Kudos
Reply
1,097 Views
davidzhou
Contributor V

It works. Thank you, JingJing!

David Zhou

0 Kudos
Reply
1,097 Views
davidzhou
Contributor V

Hi JingJing,

Although it works, by checking ESR1 register, I still have two questions. And you can help me to clarify them:

According to document K60P144M150SF3RM (page 1672):

When the MB is activated, it will participate into the arbitration process and eventually

be transmitted according to its priority. At the end of the successful transmission, the

value of the Free Running Timer is written into the Time Stamp field, the CODE field in

the Control and Status word is updated, the CRC Register is updated, a status flag is set

in the Interrupt Flag Register and an interrupt is generated if allowed by the

corresponding Interrupt Mask Register bit. The new CODE field after transmission

depends on the code that was used to activate the MB (see Table 52-103 and Table

52-104 in Message buffer structure).

0b1100: DATA — MB is a Tx Data Frame (MB RTR must be 0)

   DATA 0 INACTIVE Transmit data frame unconditionally once.

   After transmission, the MB automatically returns to the

   INACTIVE state.

1. In my code, it checks the CS Code field to be INACTIVE state, then it sets up another transmit. Logically, if frame has been transmitted, why it causes the problem?

2. I enabled Interrupt, after TX interrupt is received, then it starts another TX. It has the some problem. It transmits an extra frame with a wrong ID 0x0308. But according to the document, the transmit is done after interrupt is generated. Why it can not be setup immediately to another TX?

3. The only way to transmit as fast as it can is to check ESR1. After ESR1 indicates transmit is done, it can be setup for another TX immediately.

Thank you,

David Zhou

0 Kudos
Reply
1,097 Views
davidzhou
Contributor V

Hi JingJing,

Interrupt is working. I think there is a bug in my original code. Please ignore my previous post.

Thank you,

David

0 Kudos
Reply