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.

TDA4VM: TDA4VM Can Bus off recovery issue

Part Number: TDA4VM

I meet similar but a little different problem referred here (e2e.ti.com/.../tda4vm-one-busoff-operation-triggers-two-interrupts)
, the SDK version is 0805. The DAR is disable(which means Auto-Retransmission is enabled), BusOffProcessing Type is Interrupt.

I generated busoff by shorting CAN_H and CAN_L, can driver successfully entered Can Interrupt, then notify upper layer. The upper layer start the recovery process. During this process, I keep shorting CAN_H and CAN_L.

I use recovery strategy of AUTOSAR CanSM, it will stop upper layer from calling Can_Write to transmit once received busoff event, then start can controller.
After start can controller successfully, it will delay L1(a time set before), then restore upper layer's transmit, so that upper layer can call Can_Write to transmit.

following is the stae machine of recover process

I meet a problem that the second busoff event generated during L1, and it interrupt the recovery process.

1. I wonder how the second event generated, cause there is no new transmit request from upper layer during L1.
2. Does Can diver re-transmit as soon as started, whether upper layer call can_write or not?
3. If it is, should I start can driver after L1 timeout, instead of start it before L1?

For the first time, the BO, EP, EW and PED bit of MCAN_IR register are set to 1.
The second time, the PED and BO bit of MCAN_IR register is set to 1.

I also checked MCAN_CCCR[0] INIT bit when received busoff event by MCAN_getOpMode(baseAddr).

For the first time, INIT bit is 1. The second time, INIT bit is 0(normal operarion).
I find below explaination in TRM, does "or by going Bus_Off state" mean that this bit will be set to 1 when enter busoff?

If it is, why the INIT bit is 0 when second busoff event occured?

  • Hello,

    Can you please share MCAN_PSR register values as well in both cases ?

    In MCAN_PSR register BO,EW,EP status gives the absolute statuses.

    MCAN_IR register values are relative statuses.

    For example :

    Initailly BO = 0, bus off status changed from "no bus off state" to "bus off state" then BO sets to 1 , if the state continues the BO sets to 0 . But if the state again changes from "Bus off state " to "No bus off state" the BO sets to 1

    After bus off state, the recovery process will be started immediately(not after delay time) and then after delay time the data transmission starts again.

    From my initial understanding bus off recovery has started and recovered but not second bus off event .

    Regards

    Tarun Mukesh

  • Hello

    I checked PSR in the same case.
    For the first time, the BO, EP, EW bit of PSR are set to 1. The second time, there are set to 0.
    I also check following explaination of ISR and PSR in TRM.


    From my understanding, the BO bit of PSR indicates the real bus off state of MCAN, the BO bit of just indicates the change of busoff state.
    So I should notify upper layer there's a busoff event only if the the BO bit of PSR is 1, am I right?

    But the code in SDK 0805 notify upper layer when BO bit of IR is 1(not PSP), as follows

    if((uint32)MCAN_INTR_SRC_BUS_OFF_STATUS ==
    (intrStatus & (uint32)MCAN_INTR_SRC_BUS_OFF_STATUS))
    {
        /* Cancel all pending messages */
        Can_mcanCancelAllPendingMessages(baseAddr);
        /* In BUS OFF state call the notification function */
        CanIf_ControllerBusOff(controllerId);// here will notify upper layer, and start new recovery process
        canController->canState = CAN_CS_STOPPED;
    }

    I try to change this part to following, which means I notify upper layer only if the BO bit of PSR is 1.
    And It works, the recovery process wasn't interrupted


    if((uint32)MCAN_INTR_SRC_BUS_OFF_STATUS ==
    (intrStatus & (uint32)MCAN_INTR_SRC_BUS_OFF_STATUS))
    {
        MCAN_getProtocolStatus(baseAddr, &errStatus);// Get PSR status
        if(errStatus.busOffStatus == 1U) // if busOffStatus is 1, notify upper layer
        {
            /* Cancel all pending messages */
            Can_mcanCancelAllPendingMessages(baseAddr);
            /* In BUS OFF state call the notification function */
            CanIf_ControllerBusOff(controllerId);
            canController->canState = CAN_CS_STOPPED;
        }
    }

    If the recovery process isn't interrupted, the upper layer will request data transmission again.
    But it failed due to canTxStatus, which is cleared at the TxConfirm function. TxConfirm didn't be executed during Bus off. The code as follows

    /*- Check for pending message:
    * - pending message, return CAN_BUSY
    * - no pending message, start new transmission
    */
    if(bitIndex == (MCAN_getTxBufReqPend(baseAddr) & bitIndex))
    {
        retVal = (Std_ReturnType)CAN_BUSY; 
    }
    else if (canTxStatus == 1U)
    {
        retVal = (Std_ReturnType)CAN_BUSY;//failed here
    }
    

    During the time when data transmission consistantly failed, the BO bit of PSR is 0(not in busoff state).So the recovery process will block.

    Will auto-retransmission of MCAN stop due to Can_mcanCancelAllPendingMessages?
    From my understanding, the auto-retransmission will try to send the failed message, if it consistantly fail, will generate new busoff event.
    But as metioned above, the BO bit of PSR is 0.

  • Hello,

    From my understanding, the BO bit of PSR indicates the real bus off state of MCAN, the BO bit of just indicates the change of busoff state.

    Yes .

    I use recovery strategy of AUTOSAR CanSM, it will stop upper layer from calling Can_Write to transmit once received busoff event, then start can controller.
    After start can controller successfully, it will delay L1(a time set before), then restore upper layer's transmit, so that upper layer can call Can_Write to transmit.

    SDK just reports the Bus_Off state.It is left to software to decide how/what to recover.

    Initially bus off event happened then recovery process has to start immediately .Now it is upto AUTOSAR CanSM recovery strategy how it does recovery.

    The bus off recovery procedure involves sending a sequence of error frames to bus to clear any pending errors .After the error frames have been sent ,CANsm will wait for a specified time before attempting to re establish communication on the bus.

    Will auto-retransmission of MCAN stop due to Can_mcanCancelAllPendingMessages?

    yes.

    From my understanding, the auto-retransmission will try to send the failed message, if it consistantly fail, will generate new busoff event.

    No.

    When a CAN Node enters the bus off state , it will stop transmitting messages and auto transmission will be disabled.Other nodes on the bus can still transmit messages but the affected node will not be able to recieve any messages until it has completed bus off recovery.

    Regards

    Tarun Mukesh

  • Hello

    Thanks for your answer. No I know how to check the BusOff state.

    Can you help me to confirm that my modification below about check of busoff OK?

    If it's not right, how do I check busoff state?

    And for canTxStatus issue, Can I clear canTxStatus (canTxStatus = 0) when busoff occured?  so when can controller start and the upper layer request data transmission, it won't block in following process.

    And the busoff recovery process will keep going. If the new data transmission fail, it will trigger next recovery process, and repeat util recovery success.

    Also need you help me to confirm that the modification(clear canTxStatus when busoff occured)OK? If it's not, how can I do to avoid new data transmission block here.

    Thanks !

  • Hello,

    Can you help me to confirm that my modification below about check of busoff OK?

    If it's not right, how do I check busoff state?

    I think this is OK. Checking PSR register BO bit will give the absolute status.

    And for canTxStatus issue, Can I clear canTxStatus (canTxStatus = 0) when busoff occured?  so when can controller start and the upper layer request data transmission, it won't block in following process

    Rather than making only CanTxStatus =0 after cancelling pending messages, it is better to make all the cancelled pending messages CanController->CanTxStatus to 0.

    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
    txBufPendStatus = MCAN_getTxBufReqPend(baseAddr);
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    for (bitIndex = 0U; bitIndex < 32U; bitIndex++)
    {
    /* For each bit set call cancel request */
    uint32 bitPos = (uint32)1U << bitIndex;
    if (bitPos == (txBufPendStatus & bitPos))
    {
    /* Clear pending Tx request */
    /* Return Value is ignored as buffNum is always less than 32 */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
    (void)MCAN_txBufCancellationReq(baseAddr, bitIndex);
    timeOutStatus = GetCounterValue(CAN_OS_COUNTER_ID, &startCount);
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
     
    Isn't the same happening in Can_mcanCancelAllPendingMessages API ?

    Regards

    Tarun Mukesh

  • I will try it according to your suggestion, thanks for you help.