This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28075: Clearing sequence of MsgLst bit in CAN mailbox

Part Number: TMS320F28075


Hi,
in Technical Reference Manual I didn't find a description of the right sequence to clear MsgLst bit of a CAN receive mailbox.
In section 21.12.9 TRM reports that "MsgLst will not be automatically reset", however there is no bit in IF register to clear it.
On the opposite, NewDat and IndPnd bit can be cleared by writing 1 to TXRQST and ClrIntPnd bit respectively.

I found the following sequence, that is based on a read-modify-write operation.

----------------- MY CODE ----------------

// local variable
uint32_t msgCtrl = 0;

//
// --- READ STEP ---
// Read Data A, Data B, Control informations and clear NewDat e IntPnd bits
//
HWREG_BP(CANB_BASE + CAN_O_IF2CMD) = (CAN_IF2CMD_DATA_A | CAN_IF2CMD_DATA_B |
                                                                                          CAN_IF2CMD_CONTROL | CAN_IF2CMD_TXRQST | CAN_IF2CMD_CLRINTPND | (objID & CAN_IF2CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while((HWREG_BP(CANB_BASE + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) != 0)
{
    ;
}
//
// Read out the IF control Register (saving in a local variable).
//
msgCtrl = HWREG_BP(CANB_BASE + CAN_O_IF2MCTL);



//
// --- MODIFY STEP ---
// Reset of MsgLst, NewDat and IntPnd bits in the local variable (NewDat and IntPnd are already cleared in the mailbox by the writing on IF2CMD in READ STEP).
//
msgCtrl &= ~(CAN_IF2MCTL_MSGLST | CAN_IF2MCTL_NEWDAT | CAN_IF2MCTL_INTPND);



//
// --- WRITE STEP ---
// Write Control image on the register
//
HWREG_BP(CANB_BASE + CAN_O_IF2MCTL) = msgCtrl;
//
// Transfer of CAN_IF2MCTL to the mailbox
//
HWREG_BP(CANB_BASE + CAN_O_IF2CMD) = (CAN_IF2CMD_DIR | CAN_IF2CMD_CONTROL | (objID & CAN_IF2CMD_MSG_NUM_M));

//
// Wait for busy bit to clear
//
while((HWREG_BP(CANB_BASE + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) != 0)
{
    ;
}

----------------- END OF MY CODE ----------------


The sequence is effective in the sense that after WRITE STEP MsgLst bit is equal to 0.

However I'm not sure this is a good way to clear MsgLst bit because of the following scenario.
Suppose a new message is stored in receive mailbox after READ STEP and before WRITE STEP: NewDat and IntPnd bit are set to 1 in the mailbox. However in the WRITE STEP I force both them to 0.
Then if I read NewDat again from mailbox I will find it equal to 0 so I don't know that a new message has arrived and it is lost!

Which is the correct way to clear MsgLst bit without message loss or other unwanted side effects?

Thank you.

Best regards,

Demis

  • Demis,

    I am looking into this post right now.

  • Demis,

               

    Could you please confirm if you have tried this:

     

    Before the MODIFY step (but after the READ step), transmit a frame to the same mailbox and ensure NewDat & IntPnd bits are 1. Now, execute the WRITE step and verify if those bits are indeed cleared to 0.

     

    On a different note, I am curious why you are running into a MsgLst situation. Has your application used up all the mailboxes? Or unable to read them fast enough?

  • Demis,

                In the method you have outlined in your post, there does appear to be a risk of clearing NewDat inadvertently. The spec does not indicate any other method to clear the MsgLst bit.

     

    I presume you check the value of MsgLst bit in your receive ISR and clear it only when it is set. So, you are talking about a scenario where both NewDat and MsgLst bits are set, meaning the previously received message has been overwritten (lost) before the CPU has had a chance to transfer the data. Now, it is indeed conceivable that a new message could arrive in the window between you clearing NewDat & IntPnd bits and the instruction that clears the MsgLst bit. Have you verified if the interrupt is still asserted and if so does the INTxID field point to the mailbox tha asserted the interrupt? I understand the IntPnd bit is cleared along with the MsgLst bit. Nevertheless, there exists a window when IntPnd is active and the interrupt should be taken

  • Hi Hareesh,
    thank you for your analysis.

    Hareesh J said:

    I am curious why you are running into a MsgLst situation. Has your application used up all the mailboxes? Or unable to read them fast enough?


    I'm not running into a MsgLst situation by chance but specially to check if MsgLst bit goes high and to understand how to clear it without affecting other bits.

    Hareesh J said:

    Before the MODIFY step (but after the READ step), transmit a frame to the same mailbox and ensure NewDat & IntPnd bits are 1. Now, execute the WRITE step and verify if those bits are indeed cleared to 0.


    I've made the test and I've seen that after the frame reception between READ and MODIFY steps NewDat & IntPnd bits are 1. Then after WRITE step NewDat & IntPnd bits are cleared to 0.

    Hareesh J said:

    I presume you check the value of MsgLst bit in your receive ISR and clear it only when it is set.


    You're right.

    Hareesh J said:

    So, you are talking about a scenario where both NewDat and MsgLst bits are set, meaning the previously received message has been overwritten (lost) before the CPU has had a chance to transfer the data.


    Right again.

    Hareesh J said:

    Now, it is indeed conceivable that a new message could arrive in the window between you clearing NewDat & IntPnd bits and the instruction that clears the MsgLst bit. Have you verified if the interrupt is still asserted and if so does the INTxID field point to the mailbox tha asserted the interrupt?


    I've verified that if a new message is received between READ and MODIFY steps the INT0ID field points to the correct mailbox (I use INT0 interrupt line in my tests). However after WRITE step INT0ID is cleared to 0, like NewDat & IntPnd bits.

    Hareesh J said:

    I understand the IntPnd bit is cleared along with the MsgLst bit. Nevertheless, there exists a window when IntPnd is active and the interrupt should be taken


    I clear INT0_FLG in CAN_GLB_INT_FLG register after the WRITE step so interrupt won't be taken any more.

    Anyway I've made further test: I've changed my code to clear INT0_FLG right after NewDat & IntPnd clearing but before READ step. If a new message is received between READ and MODIFY steps the INT0ID field points to the correct mailbox and INT0_FLG is set to 1 again. However after WRITE step INT0ID field is cleared to 0 while INT0_FLG is still 1. So another interrupt is asserted but INT0ID is equal to 0 so I cannot identify the cause of the interrupt!

    Indeed I think it is correct to clear INT0_FLG just before the end of the interrupt routine as showed in TI driver example.

    Hareesh J said:

    In the method you have outlined in your post, there does appear to be a risk of clearing NewDat inadvertently. The spec does not indicate any other method to clear the MsgLst bit.

    After our considerations and tests it seems to me there is no way to avoid that risk, right?

    Thank you for your precious support.

    Best regards,

    Demis