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.

SK-TDA4VM: CAN bus cannot be recovered after bus off happened.

Part Number: SK-TDA4VM
Other Parts Discussed in Thread: TDA4VM

CAN bus cannot be recovered after bus off happened.

After recovered by Cansm, Can_wirte can not executed due to the function "Can_writeGetFreeMsgObj" always returns CAN_BUSY, as  the condition  canTxStatus == 1,

In normal case, the canTxStatus is cleared at the TxConfirm function, but this didn't  be executed during Bus off.

we fix the issue by modify the  Can_mcanProcessISR,like below

is that a bug?please check it and reply, thanks.

  • Hi,

    The driver code need note be changed to handle this, the additional piece of code you have added needs to be in the CanIf_ControllerBusOff() function from the CAN IF layer.

    You can refer to a sample implementation in the gateway-demos/mcuss_demos/Bsw_Stubs/CanIf/src/CanIf_Cbk.c.

    Regards

    Karan

  • HI,

    i did't find the gateway-demos/mcuss_demos/Bsw_Stubs/CanIf/src/CanIf_Cbk.c file in my pc.  please provide me this file

    Best Regards

  • Hi,

    Posting the code from that here:

    void CanIf_ControllerBusOff(uint8 ControllerId)
    {
        Std_ReturnType status;
        /* To get out of error, set controller Mode to Start */
        status = Can_SetControllerMode(ControllerId, CAN_CS_STARTED);
        if (status != E_OK)
        {
            busOff_error_cnt += 1;
        }
    }

    file: 

    /*
    *
    * Copyright (c) 2019 Texas Instruments Incorporated
    *
    * All rights reserved not granted herein.
    *
    * Limited License.
    *
    * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
    * license under copyrights and patents it now or hereafter owns or controls to make,
    * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
    * terms herein.  With respect to the foregoing patent license, such license is granted
    * solely to the extent that any such patent is necessary to Utilize the software alone.
    * The patent license shall not apply to any combinations which include this software,
    * other than combinations with devices manufactured by or for TI ("TI Devices").
    * No hardware patent is licensed hereunder.
    *
    * Redistributions must preserve existing copyright notices and reproduce this license
    * (including the above copyright notice and the disclaimer and (if applicable) source
    * code license limitations below) in the documentation and/or other materials provided
    * with the distribution
    *
    * Redistribution and use in binary form, without modification, are permitted provided
    * that the following conditions are met:
    *
    * *       No reverse engineering, decompilation, or disassembly of this software is
    * permitted with respect to any software provided in binary form.
    *
    * *       any redistribution and use are licensed by TI for use only with TI Devices.
    *
    * *       Nothing shall obligate TI to provide you with source code for the software
    * licensed and provided to you in object code.
    *
    * If software source code is provided to you, modification and redistribution of the
    * source code are permitted provided that the following conditions are met:
    *
    * *       any redistribution and use of the source code, including any resulting derivative
    * works, are licensed by TI for use only with TI Devices.
    *
    * *       any redistribution and use of any object code compiled from the source code
    * and any resulting derivative works, are licensed by TI for use only with TI Devices.
    *
    * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
    *
    * may be used to endorse or promote products derived from this software without
    * specific prior written permission.
    *
    * DISCLAIMER.
    *
    * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS
    * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    * IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
    * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    * OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    
    
    
    #ifdef __cplusplus
    extern "C"{
    #endif
    
    /* ========================================================================== */
    /*                           Include Files                                    */
    /* ========================================================================== */
    #include "CanIf_Cbk.h"
    #include "Can.h"
    #include "Can_GeneralTypes.h"
    
    #include <ti/osal/osal.h>
    #include <ti/osal/SemaphoreP.h>
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    #define CANIF_START_SEC_VAR_CLEARED_UNSPECIFIED
    #include "CanIf_MemMap.h"
    
    /* Global variables used in callback functions */
    volatile VAR(uint8, CANIF_VAR_CLEARED) CanIf_ControllerId;
    #if defined (AUTOSAR_421)
    volatile VAR(CanIf_ControllerModeType, CANIF_VAR_CLEARED) CanIf_ControllerMode;
    #else
    volatile VAR(Can_ControllerStateType, CANIF_VAR_CLEARED) CanIf_ControllerMode;
    #endif
    volatile P2VAR(Can_HwType, CANIF_VAR_CLEARED, CANIF_APPL_DATA) CanIf_Mailbox;
    volatile VAR(Can_HwType, CANIF_VAR_CLEARED) CanIf_MailBuf;
    volatile VAR(PduInfoType, CANIF_VAR_CLEARED) CanIf_PduInfo;
    int32_t (*push_frame_to_app_queue)(const PduInfoType*);
    
    volatile VAR(uint32, CANIF_VAR_CLEARED) CanIf_RxConfirmationCount;
    volatile VAR(uint32, CANIF_VAR_CLEARED) CanIf_TxConfirmationCount;
    volatile P2CONST(PduInfoType, CANIF_VAR_CLEARED, CANIF_APPL_DATA) 
             CanIf_PduInfoPtr;
    volatile VAR(uint8, CANIF_VAR_CLEARED) CanIf_TxCounter;
    volatile VAR(PduIdType, CANIF_VAR_CLEARED) CanIf_GblTxPduIdStore[32];
    volatile VAR(PduIdType, CANIF_VAR_CLEARED) CanIf_CanTxPduId;
    uint32  busOff_error_cnt = 0;
    /**< Counter which increments during Bus off error */
    /* ========================================================================== */
    /*                          Externals                                         */
    /* ========================================================================== */
    extern SemaphoreP_Handle CanIf_TxConfirmationSemaphore;
    /**< TX Confirmation semaphore */
    extern SemaphoreP_Handle CanIf_RxConfirmationSemaphore;
    /**< Rx Confirmation semaphore */
    
    #define CANIF_STOP_SEC_VAR_CLEARED_UNSPECIFIED
    #include "CanIf_MemMap.h"
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    #define CANIF_START_SEC_CODE
    #include "CanIf_MemMap.h"
    
    void CanIf_TxConfirmation(PduIdType CanTxPduId)
    {
    #if (CAN_TX_POLLING == STD_OFF)
        SemaphoreP_postFromISR(CanIf_TxConfirmationSemaphore);
    #endif //CAN_TX_POLLING
        CanIf_TxConfirmationCount++;
    }
    
    void CanIf_RxIndication(const Can_HwType* Mailbox, 
        const PduInfoType* PduInfoPtr)
    {
        CanIf_Mailbox = &CanIf_MailBuf;
        CanIf_Mailbox->CanId = Mailbox->CanId;
        CanIf_Mailbox->Hoh = Mailbox->Hoh;
        CanIf_Mailbox->ControllerId = Mailbox->ControllerId;
    
        /*Put data in application CAN queues*/
        (*push_frame_to_app_queue)(PduInfoPtr);
    
    #if (CAN_RX_POLLING == STD_OFF)
        SemaphoreP_postFromISR(CanIf_RxConfirmationSemaphore);
    #endif //CAN_RX_POLLING
        CanIf_RxConfirmationCount++;
    }
    
    void CanIf_ControllerBusOff(uint8 ControllerId)
    {
        Std_ReturnType      status;
        /* To get out of error, set controller Mode to Start */
        status = Can_SetControllerMode(ControllerId, CAN_CS_STARTED);
        if (status != E_OK)
        {
            busOff_error_cnt += 1;
        }
    }
    #if defined (AUTOSAR_421)
    void CanIf_ControllerModeIndication(uint8 ControllerId,
                                        CanIf_ControllerModeType ControllerMode)
    #else
    void CanIf_ControllerModeIndication(uint8 ControllerId,
                                        Can_ControllerStateType ControllerMode)
    #endif
    {
        CanIf_ControllerId = ControllerId;
        CanIf_ControllerMode = ControllerMode;
    }
    #define CANIF_STOP_SEC_CODE
    #include "CanIf_MemMap.h"
    
    #ifdef __cplusplus
    }
    #endif
    
    

    Regards

    Karan

  • Hi,

    Follow the steps below and have a similar problem.
    The operation steps are as follows:
    1. Connect CANoe and Device, and start CANoe and Device;
    2. Send NM Frame through CANoe, Device will periodically send messages to CAN bus;
    3. Without stopping sending NM Frame, click the Stop button directly to disconnected CANoe;
    4. Click the Start button again, CANoe Start, and continue to send NM Frame to the CAN bus;
    5. The problem occurs: At this time, the Device no longer sends messages to the CAN bus;

    After debugging, it is the same as the cause of this problem: the function Can_writeGetFreeMsgObj() always returns CAN_BUSY.

    Question:
    If the Device does not generate a BusOff event, the status 'canTxStatus' cannot be cleared;
    If the state 'canTxStatus' is not cleared, after CANoe Restart, the Device is in the CAN_BUSY state and cannot send messages.

    When should I go to clear the 'canTxStatus' state?

    How to deal with the above problems, please give guidance.

    Best Regards.

  • Hi,

    1. Connect CANoe and Device, and start CANoe and Device;
    2. Send NM Frame through CANoe, Device will periodically send messages to CAN bus;
    3. Without stopping sending NM Frame, click the Stop button directly to disconnected CANoe;
    4. Click the Start button again, CANoe Start, and continue to send NM Frame to the CAN bus;
    5. The problem occurs: At this time, the Device no longer sends messages to the CAN bus;

    1. I'm trying to understand the system. In the below diagram, the periodic Tx from TDA4VM (device) - who receives this message i.e. which node has filters setup to accept this message?

    Assuming that your CAN messages from TDA4VM were intended for CANoe, what I understand is that when you disconnect the CANoe - you start getting an AckError (PSR register LEC and DLEC) as message is transmitted but not received correctly on the intended CANoe node.

    In this system is Auto re-transmission enabled in your system (DAR bit unset)?

    2. When the MCAN controller on the TDA4VM is not generating a BusOff event, are you checking this in the ISR if that flag is set or not?

    What is the configuration of your Tx buffers? Also, are you using buffers or FIFO and what is the length?

    Regards

    Karan

  • Hi, Karan

    1. I'm trying to understand the system. In the below diagram, the periodic Tx from TDA4VM (device) - who receives this message i.e. which node has filters setup to accept this message?

    As shown in the figure below, only CANoe and TDA4VM are connected to the CAN BUS (if there is a third device on the CAN BUS, the above problems will not occur)

    Assuming that your CAN messages from TDA4VM were intended for CANoe, what I understand is that when you disconnect the CANoe - you start getting an AckError (PSR register LEC and DLEC) as message is transmitted but not received correctly on the intended CANoe node.

    When CANoe is disconnected, an AckError should be received, but referring to the following code, no control logic processing for the registers (PSR register LEC and DLEC) is found.
    \ti-processor-sdk-rtos-j721e-evm-08_00_00_12\mcusw\mcal_drv\mcal\Can\src\Can_Mcan.c
    The processing of reading errStatus.lastErrCode and errStatus.dlec is not found in the above code.

    In this system is Auto re-transmission enabled in your system (DAR bit unset)?

    The current setting is the same as the sdk8.0, DAR bit unset.
    \ti-processor-sdk-rtos-j721e-evm-08_00_00_12\mcusw\mcal_drv\mcal\Can\src\Can_Mcan.c
    Line1607: initParams->darEnable = (uint32)MCAN_CCCR_DAR_DISABLE;

    2. When the MCAN controller on the TDA4VM is not generating a BusOff event, are you checking this in the ISR if that flag is set or not?

    I'm not sure if the above Case should generate a BusOff event, I'll check later if the ISR flag is set. contact later.

    What is the configuration of your Tx buffers? Also, are you using buffers or FIFO and what is the length?

    Whether it refers to the setting of CanHwObjectCount, the settings for TX are as follows:

    Best Regards.

  • Hi, Karan:

    add some information:

    Assuming that your CAN messages from TDA4VM were intended for CANoe, what I understand is that when you disconnect the CANoe - you start getting an AckError (PSR register LEC and DLEC) as message is transmitted but not received correctly on the intended CANoe node.

    When CANoe is disconnected, an AckError should be received, but referring to the following code, no control logic processing for the registers (PSR register LEC and DLEC) is found.
    \ti-processor-sdk-rtos-j721e-evm-08_00_00_12\mcusw\mcal_drv\mcal\Can\src\Can_Mcan.c

    When CANoe is disconnected, the program will stop at the following breakpoint(Can_Mcan.c line721).

    At this time, the PSR register is as follows (LEC=0h, DLEC=3h)

    \ti-processor-sdk-rtos-j721e-evm-08_00_00_12\mcusw\mcal_drv\mcal\Can\src\Can_Mcan.c

    2. When the MCAN controller on the TDA4VM is not generating a BusOff event, are you checking this in the ISR if that flag is set or not?

    I'm not sure if the above Case should generate a BusOff event, I'll check later if the ISR flag is set. contact later.

    In the above case does not generate a BusOff event, and I don't think it should generate a BusOff.

    After the above Error occurs, the interrupt service routine Can_mcanProcessISR() is not executed again.

    What is the configuration of your Tx buffers? Also, are you using buffers or FIFO and what is the length?

    Can you tell me how to confirm the above information? Which configuration parameters need to be checked?

    Can you give me some guidance, thanks.

    Best Regards.

  • Hi, Karan:

    excuse me,

    can you give me some guidance about this issue(about the messages replied by Mr. Zhao Yongmin). thank you very much. :)

    Best Regards.

  • HI, Karan

    I was also confused by the above question.

    when Tx errores occured, the canTxStatus were set as 1.  But in somecases, the tx error was not enough to genereate a busoff error, then where should we clear it? 

    I solved it via following midifications, please check if it is suitable, thanks.

    1. enable the corresponding error interruption,

    2. check the interrupt resigster in the ISR, and clear the status if confirmed.

  • HI, Karan

    As the above modifications, i enabled the error interruption of PROTOCOL_ERR_ARB to solve the issue that commnication cannot be recovered due to   canTxStatus = 1.

    But this modification introduced some other issues, 

    When the terminal resistance is not connected, the error interruption isr was reached frequently (200 times per 20ms), and that caused the cpu running with a heavy load.

    So i wonder if my above modification was suitable, please check and reply, thanks.

  • Hi,

    Sorry for the late response here.

    1. Clearing the status for all Tx buffers for every protocol error is not advisable. This would involve running multiple instructions for all errors, most of the time the issue would be resolved by a simple re-transmission.

    2. You are using CAN Tx buffer (not FIFO) and for this the API Can_writeGetFreeMsgObj() will return CAN_BUSY if:

    a. The MCAN_TXBRP's bit corresponding to the intended messageBox (the buffer which is being used for transmission) is set or,

    b. The Tx ISR is not yet completed. The canTxStatus is reset there.

    if(bitIndex == (MCAN_getTxBufReqPend(baseAddr) & bitIndex))
    {
        retVal = (Std_ReturnType)CAN_BUSY;
    }
    else if (canTxStatus == 1U)
    {
        retVal = (Std_ReturnType)CAN_BUSY;
    }
    else
    {
        *msgObj = messageBox;
        retVal = E_OK;
    }

    3. Any persistent Tx error, which is not resolving by re-transmission would lead to a BUS OFF state (when Transmit Error Counter of a CAN controller exceeds 255). The BUS OFF recovery sequence should be take from my above post here.

    I would assume that this should solve your issue. If you are trying to resend the message (due to auto-retransmission) and every time it is failing, this would increment MCAN_ECR's TEC field > 255 and lead to a BUS OFF. The recovery sequence should set things right again.

    If in case there is no BUS OFF this means that somehow successful transmissions are happening.

    void CanIf_ControllerBusOff(uint8 ControllerId)
    {
        Std_ReturnType      status;
        /* To get out of error, set controller Mode to Start */
        status = Can_SetControllerMode(ControllerId, CAN_CS_STARTED);
        if (status != E_OK)
        {
            busOff_error_cnt += 1;
        }
    }

    Regards

    Karan

  • hi, Karan

    Thanks for your reply.  The failed message was resent sucessfully by the auto-retransmission.

  • Hi,

    Thanks for the feedback, so is there anything open on this thread now? Can you please confirm.

    Regards

    Karan