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.

MCU-PLUS-SDK-AM263X: MCAN RX ISR delay issue with multi CAN message

Part Number: MCU-PLUS-SDK-AM263X

Hi TI expert

We face MCAN RX ISR delay issue  with multi  CAN message in AM263x SDK V8.2

(1)When we only enable Mcan_ProcessCanIntrISR(0)  for CAN0  which  trigger by 1ms task

Mcan_ProcessCanIntrISR(0) trigger have delay issue(200~1000ms) when received 200ms period message

(2)CAN bus loading(~4%) as following :

CAN ID:0x228 and 0x504 for CAN0 transmit (RX shows in CAN tools) 

others CAN ID for CAN0 receive (TX shows in CAN tools) ,

Have any suggestion for Mcan_ProcessCanIntrISR usage for multi CAN message?

BR

Jay

  • Hi Jay,

    We're looking into this and will get back with you shortly.

    Regards,
    Frank

  • Hi TI expert

    Please check MCAN function as following

    /*******************************************************************************/
    /* Function name: HHCAN_Init()*/
    /* Description  : Initialize HH CAN Module Data*/
    /* Parameters   : N.A  */
    /* Returns      : N.A*/
    /* Remark       : N.A*/
    /*******************************************************************************/
    void HHCAN_Init(void)
    {
        for(int i=0;i < APP_MCAN_CHANNEL_CNT; i++)
        {
            Mcan_Init(i);
        }
    
        HHCANPar_Init();
    }
    
    void HHCAN_CheckCanISRStatus(void)
    {
      Mcan_ProcessCanIntrISR(0);
    /*    for(int i = 0;i < 4; i++)
        {
            if(CanRxISR.CanRXFlag[i] == 1)
            {
                CanRxISR.CanRXFlag[i] = 0;
                Mcan_ProcessCanIntrISR(i);
            }
        }*/
    }
    void HHCAN_ResetCANNode(TICan_Channel canChannel)
    {
        Mcan_Config(canChannel);
    }
    
    void HHCAN_ReInit(TICan_Channel canChannel)
    {
        Mcan_Init(canChannel);
    }
    
    /*******************************************************************************/
    /* Static Function Definition*/
    /*******************************************************************************/
    static void Mcan_Init(TICan_Channel canChannel)
    {
        //DebugP_log("[MCAN] TICAN %d _ Init:, Init started ...\r\n", canChannel);
        int32_t                 status = SystemP_SUCCESS;
        TS_TICAN_DATA*       canInitdata = &ticandata[canChannel];
        
        status = SemaphoreP_constructBinary(&canInitdata->gMcanTxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        status = SemaphoreP_constructBinary(&canInitdata->gMcanRxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
    
        /* Register interrupt */
        HwiP_Params_init(&canInitdata->hwiPrms);
        canInitdata->hwiPrms.intNum      = gCANISRData[canChannel].IntrNum;
        canInitdata->hwiPrms.callback    = &Mcan_IntrISR;
        canInitdata->hwiPrms.args    =  &gCANISRData[canChannel].ChannelIndex;
        status = HwiP_construct(&canInitdata->gMcanHwiObject, &canInitdata->hwiPrms);
        DebugP_assert(status == SystemP_SUCCESS);
        /* Assign MCAN instance address */
        canInitdata->gMcanBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(gCANISRData[canChannel].IntrAddr);
    
        /* Select buffer and fifo number, Buffer is used in this app */
        canInitdata->bufNum = 0U;
        canInitdata->fifoNum = MCAN_RX_FIFO_NUM_0;
        canInitdata->bitPos = (1U << canInitdata->bufNum);
    
        /* Configure MCAN module, Disable LoopBack Mode */
        Mcan_Config(canChannel);
        /* Enable Interrupts */
        Mcan_EnableIntr(canChannel);
        //DebugP_log("[MCAN] TICAN %d _ Init, Init end ...\r\n", canChannel);
    }
    
    static void Mcan_Config(TICan_Channel canChannel)
    {
    
        TS_TICAN_DATA*       canInitdata = &ticandata[canChannel];;
    
        /* Initialize MCAN module initParams */
        MCAN_initOperModeParams(&canInitdata->initParams);
        /* CAN FD Mode and Bit Rate Switch Enabled */
    #if (EN_ZCU==LZCU)
        canInitdata->initParams.fdMode          = FALSE;
        canInitdata->initParams.brsEnable       = FALSE;
    #elif (EN_ZCU==RZCU)
        canInitdata->initParams.fdMode          = FALSE;
        canInitdata->initParams.brsEnable       = FALSE;
    #elif (EN_ZCU==FRZCU)
        canInitdata->initParams.fdMode          = TRUE;
        canInitdata->initParams.brsEnable       = TRUE;
    #elif (EN_ZCU==DRZCU)
        if(canChannel==MCAN2)//CAN
        {
            canInitdata->initParams.fdMode          = FALSE;
            canInitdata->initParams.brsEnable       = FALSE;
        }
        else //CAN FD
        {
            canInitdata->initParams.fdMode          = TRUE;
            canInitdata->initParams.brsEnable       = TRUE;
        }
    #endif
        /* Initialize MCAN module Global Filter Params */
        MCAN_initGlobalFilterConfigParams(&canInitdata->configParams);
    
        /* Initialize MCAN module Bit Time Params */
        /* Configuring default 1Mbps and 5Mbps as nominal and data bit-rate resp */
        //MCAN_initSetBitTimeParams(&tican0data.bitTimes);
    
        Mcan_InitSetBitTimeParams(&canInitdata->bitTimes); //20220324
    
        /* Initialize MCAN module Message Ram Params */
        Mcan_InitMsgRamConfigParams(&canInitdata->msgRAMConfigParams);
    
        /* Initialize Filter element to receive msg, should be same as tx msg id */
    
        /* Initialize Filter element to receive msg, should be same as tx msg id */
    
        canInitdata->stdFiltElem[0].sfid1 = 0x0;
        canInitdata->stdFiltElem[0].sfid2 = 0x7FF;
        canInitdata->stdFiltElem[0].sfec =  0x1U;
        canInitdata->stdFiltElem[0].sft = 0x0;
    
        canInitdata->stdFiltElem[1].sfid1 = 0xA0;
        canInitdata->stdFiltElem[1].sfid2 = 0xB0;
        canInitdata->stdFiltElem[1].sfec = 0x1U;
        canInitdata->stdFiltElem[1].sft = 0x1;
    
        canInitdata->extFiltElem[0].efid1 = 0x800;
        canInitdata->extFiltElem[0].efid2 = 0x8FF;
        canInitdata->extFiltElem[0].efec =  0x1U;
        canInitdata->extFiltElem[0].eft = 0x0;
    
        /* wait for memory initialization to happen */
        while (FALSE == MCAN_isMemInitDone(canInitdata->gMcanBaseAddr))
        {}
    
        /* Put MCAN in SW initialization mode */
        MCAN_setOpMode(canInitdata->gMcanBaseAddr, MCAN_OPERATION_MODE_SW_INIT);
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(canInitdata->gMcanBaseAddr))
        {}
    
        /* Initialize MCAN module */
        MCAN_init(canInitdata->gMcanBaseAddr, &canInitdata->initParams);
        /* Configure MCAN module Gloabal Filter */
        MCAN_config(canInitdata->gMcanBaseAddr, &canInitdata->configParams);
        /* Configure Bit timings */
        MCAN_setBitTime(canInitdata->gMcanBaseAddr, &canInitdata->bitTimes);
        /* Configure Message RAM Sections */
        MCAN_msgRAMConfig(canInitdata->gMcanBaseAddr, &canInitdata->msgRAMConfigParams);
        /* Set Extended ID Mask */
        MCAN_setExtIDAndMask(canInitdata->gMcanBaseAddr, APP_MCAN_EXT_ID_MASK);
    
        /* Configure Standard ID filter element */
        for (int i = 0U; i < APP_MCAN_STD_ID_FILTER_CNT; i++)
        {
            MCAN_addStdMsgIDFilter(canInitdata->gMcanBaseAddr, i, &canInitdata->stdFiltElem[i]);
        }
    
        /* Configure Extend ID filter element */
        for (int i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            MCAN_addExtMsgIDFilter(canInitdata->gMcanBaseAddr, i, &canInitdata->extFiltElem[i]);
        }
    /*
        if (TRUE == enableInternalLpbk)
        {
            MCAN_lpbkModeEnable(tican1data.gMcanBaseAddr, MCAN_LPBK_MODE_INTERNAL, TRUE);
        }
    */
        /* Take MCAN out of the SW initialization mode */
        MCAN_setOpMode(canInitdata->gMcanBaseAddr, MCAN_OPERATION_MODE_NORMAL);
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(canInitdata->gMcanBaseAddr))
        {}
    
        return;
    }
    
    
    static void Mcan_InitSetBitTimeParams(MCAN_BitTimingParams *bitTimes) //20220324
    {
        //80M/((15+1)*(1+6+3))=500K
        //80M/((9+1)*(1+4+3))=1M
        //80M/{(3+1)*[1+(1+5)+(1+2)]}=2M
        bitTimes->nomRatePrescalar   = 0xFU;
        bitTimes->nomTimeSeg1        = 0x5U;
        bitTimes->nomTimeSeg2        = 0x2U;
        bitTimes->nomSynchJumpWidth  = 0x0U;
        bitTimes->dataRatePrescalar  = 0x3U;
        bitTimes->dataTimeSeg1       = 0x5U;
        bitTimes->dataTimeSeg2       = 0x2U;
        bitTimes->dataSynchJumpWidth = 0x0U;
        return;
    }
    
    static void Mcan_InitMsgRamConfigParams(MCAN_MsgRAMConfigParams
                                               *msgRAMConfigParams)
    {
        int32_t status;
    
        MCAN_initMsgRamConfigParams(msgRAMConfigParams);
    
    
        /* Configure the user required msg ram params */
        msgRAMConfigParams->lss                 = APP_MCAN_STD_ID_FILTER_CNT;
        msgRAMConfigParams->lse                 = APP_MCAN_EXT_ID_FILTER_CNT;
    
        msgRAMConfigParams->txBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
        msgRAMConfigParams->txEventFIFOWaterMark = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txBufCnt             = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txFIFOCnt            = APP_MCAN_TX_FIFO_CNT;
        /* Buffer/FIFO mode is selected */
        msgRAMConfigParams->txBufMode           = MCAN_TX_MEM_TYPE_BUF;
        msgRAMConfigParams->txEventFIFOCnt      = APP_MCAN_TX_EVENT_FIFO_CNT;
    
        msgRAMConfigParams->rxFIFO0Cnt           = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO0WaterMark     = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO0OpMode        = 0U;//0
        msgRAMConfigParams->rxFIFO1Cnt           = APP_MCAN_FIFO_1_CNT;
        msgRAMConfigParams->rxFIFO1WaterMark     = APP_MCAN_FIFO_1_CNT;
        msgRAMConfigParams->rxFIFO1OpMode        = 0U;//0
    
        
        /* FIFO blocking mode is selected */
        msgRAMConfigParams->rxFIFO0OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
        msgRAMConfigParams->rxFIFO1OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
    
        status = MCAN_calcMsgRamParamsStartAddr(msgRAMConfigParams);
        DebugP_assert(status == CSL_PASS);
    
        return;
    }
    static void Mcan_EnableIntr(TICan_Channel canChannel)
    {
        uint32_t McanBaseAddr;
        McanBaseAddr = getCanBaseAddr(canChannel);
    
        MCAN_enableIntr(McanBaseAddr, MCAN_INTR_MASK_ALL, (uint32_t)TRUE);
        MCAN_enableIntr(McanBaseAddr,
                        MCAN_INTR_SRC_RES_ADDR_ACCESS, (uint32_t)FALSE);
        /* Select Interrupt Line 0 */
        MCAN_selectIntrLine(McanBaseAddr, MCAN_INTR_MASK_ALL, MCAN_INTR_LINE_NUM_0);
        /* Enable Interrupt Line */
        MCAN_enableIntrLine(McanBaseAddr, MCAN_INTR_LINE_NUM_0, (uint32_t)TRUE);
    
        return;
    }
    /*******************************************************************************/
    /* Interrupt Routine Definition*/
    /*******************************************************************************/
    
    static void Mcan_ProcessCanIntrISR(uint8 iCanIndex)
    {
        uint32_t intrStatus;
        MCAN_RxBufElement   rxCanMsg ={0};
    
        intrStatus = CanRxISR.IntrStatus[iCanIndex];
    
        /* If FIFO0/FIFO1 is used, then MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG macro
        * needs to be replaced by MCAN_INTR_SRC_RX_FIFO0_NEW_MSG/
        * MCAN_INTR_SRC_RX_FIFO1_NEW_MSG respectively */
        if (MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG ==
         (intrStatus & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG))
        {
            //SemaphoreP_post(&tican0data.gMcanRxDoneSem);
        }
    
        if (MCAN_INTR_SRC_RX_FIFO0_NEW_MSG ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG))//0x1U
        {
            //DebugP_log("-------RX Fifo0 receive ok------------------\r\n");
         
            ApiCan_ReceiveFIFOMessage(iCanIndex, 0, &rxCanMsg );
    
    #if EN_UDS_TASK
             if(iCanIndex == 0)
             {
                 ApiCan_UdsReceiveMessage(iCanIndex , &rxCanMsg);
             }
    #endif
        }
         
        if (MCAN_INTR_SRC_RX_FIFO1_NEW_MSG ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG))//0x10
        {
            //DebugP_log("-------RX Fifo1 new MSG receive ok------------------\n");
            ApiCan_ReceiveFIFOMessage(iCanIndex ,1 , &rxCanMsg );
        }
         
        if (MCAN_INTR_SRC_RX_FIFO0_MSG_LOST ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO0_MSG_LOST))//0x08
        {
            //DebugP_log("-------RX new MSG Lost------------------\n");
            ApiCan_ReceiveFIFOMessage(iCanIndex , 0, &rxCanMsg );
        }
    
         if (MCAN_INTR_SRC_ERR_PASSIVE ==
             (intrStatus & MCAN_INTR_SRC_ERR_PASSIVE))//0x800000U
         {
             //DebugP_log("-------TX Err Passive------\n");
             error_flag = passive;
         }
         if (MCAN_INTR_SRC_BUS_OFF_STATUS ==
             (intrStatus & MCAN_INTR_SRC_BUS_OFF_STATUS))//0x2000000U    //Bus Off process
         {
             //DebugP_log("-------TX Bus off--------\n");
             error_flag = bus_off;
    #if EN_UDS_TASK
             if(iCanIndex == 0)
             {
                 CanNM_BusOffStart();
             }
    #endif
         }
    
         return;
    }
    
    //= &ticandata[canChannel];
    static void Mcan_IntrISR(void* args)
    {
        uint32_t intrStatus;
        TICan_Channel canChannel;
        TICan_Channel* C1 = args;
        canChannel = *C1;
    
        intrStatus = MCAN_getIntrStatus(ticandata[canChannel].gMcanBaseAddr);
        MCAN_clearIntrStatus(ticandata[canChannel].gMcanBaseAddr, intrStatus);
    
        if (MCAN_INTR_SRC_TRANS_COMPLETE ==
         (intrStatus & MCAN_INTR_SRC_TRANS_COMPLETE))
        {
            SemaphoreP_post(&ticandata[canChannel].gMcanTxDoneSem);
            ApiCan_ProcessTxFIFOEvent(canChannel);
    #if EN_UDS_TASK
            if(0 == canChannel)
            {
                CAN_TXCONF_CBK();
            }
    #endif
        }else
        {
            CanRxISR.CanRXFlag[canChannel] = 1;
            CanRxISR.IntrStatus[canChannel] = intrStatus;
        }
        return;
    }

    BR

    Jay

  • Hi Jay

    Apologies for the late reply.

    Could you tell me if this issue is happening only in SBL or in APP as well?

    Regards

    Sri Vidya

  • Hi Sri Vidya

    This  issue are same in SBL or in APP when MCAN RX ISR  with multi CAN message at the same time 

    BR

    Jay

  • Hi Jay

    I am going through the code you have shared. Looks like Mcan_ProcessCanIntrISR is a customer created API.

    Inside this API you have, ApiCan_ReceiveFIFOMessage is being used to receive the message. Is this what is causing your delay that you specified?

    If yes, could you also share what is being done in ApiCan_ReceiveFIFOMessage?

    Regards

    Sri Vidya

  • Hi Sri Vidya

    ApiCan_ReceiveFIFOMessag and ApiCan_ProcessRxFIFOEvent

    int8_t ApiCan_ReceiveFIFOMessage(TICan_Channel canChannel,uint8_t fifo_num, MCAN_RxBufElement*  rxBuff)
    {
        int8_t  testStatus  = 0;
        MCAN_ErrCntStatus    errCounter;
        uint32_t Rx_id;
        uint32_t           baseAddr;
    
        baseAddr = getCanBaseAddr(canChannel);
    
        /* Checking for Errors */
        MCAN_getErrCounters(baseAddr, &errCounter);
        if ((0U == errCounter.recErrCnt) &&
            (0U == errCounter.canErrLogCnt))
        {
            
            MCAN_readMsgRam(baseAddr,
                            MCAN_MEM_TYPE_FIFO,//MCAN_MEM_TYPE_BUF,
                            0U,//not use
                            fifo_num,
                            rxBuff);
    
            if(0 ==rxBuff->xtd)
            {
            Rx_id = rxBuff->id >> 18;
            }
            else
            {
                Rx_id = rxBuff->id;
            }
    
            if(canChannel == MCAN1)
            {
            for(int i =0; i < m_CAN_1_MsgCnt; i++)
            {
                if((CAN_1MsgCfgGrp[i].dir  == m_can_dirRx) && (CAN_1MsgCfgGrp[i].id == Rx_id))
                {
                    for(int j =0; j < CAN_1MsgCfgGrp[i].dlc; j++)
                    {
                        CAN_1MsgCfgGrp[i].buf[j]= rxBuff->data[j] ;
                    }
                    /*if((OS_GetCurrentTimeInMsecs() - g_RxCan1_Timeout_count[i] )> (CAN_1MsgCfgGrp[i].period * 100))
                    {
                        CAN_1MsgCfgGrp[i].rxTimeout[0] = TRUE;
                    }
                    g_RxCan1_Timeout_count[i] = getTimeMS;*/
                }
    #if (EN_ZCU==DRZCU)
                //gateway 0x7D0
                if(   (Rx_id == CAN1_TP_DR_DIAG_FUNC_REQ_FT_FRAME_ID)     &&
                      (CAN_1MsgCfgGrp[i].id == CAN1_TP_DR_DIAG_FUNC_REQ_FT_FRAME_ID) )
                {
                    ApiCan_SendMessage(MCAN2, CAN1_TP_DR_DIAG_FUNC_REQ_FT_FRAME_ID, CAN_1MsgCfgGrp[i].extFrame, CAN_1MsgCfgGrp[i].dlc, CAN_1MsgCfgGrp[i].buf);
                }
    #endif
            }     
            }
    
    #if EN_DBC_DR
            if(canChannel == MCAN2)
            {
            for(int i =0; i < m_CAN_2_MsgCnt; i++)
            {
                if((CAN_2MsgCfgGrp[i].dir  == m_can_dirRx) && (CAN_2MsgCfgGrp[i].id == Rx_id))
                {
                    for(int j =0; j < CAN_2MsgCfgGrp[i].dlc; j++)
                    {
                        CAN_2MsgCfgGrp[i].buf[j]= rxBuff->data[j] ;
                    }
                    /*if((OS_GetCurrentTimeInMsecs() - g_RxCan1_Timeout_count[i] )> (CAN_1MsgCfgGrp[i].period * 100))
                    {
                        CAN_1MsgCfgGrp[i].rxTimeout[0] = TRUE;
                    }
                    g_RxCan1_Timeout_count[i] = getTimeMS;*/
                }
            }
            }
    
    #endif
            ApiCan_ProcessRxFIFOEvent(canChannel, fifo_num);
        }
        else
        {
            ///DebugP_log("\nError in reception with payload Bytes:0x%x\n", rxBuff->dlc);
            testStatus = -1;
        }
    
        return testStatus;
    
    }
    
    int8_t ApiCan_ProcessRxFIFOEvent(TICan_Channel canChannel, uint8_t fifo_num)
    {
        MCAN_RxFIFOStatus   fifo0Status, fifo1Status;
        uint32_t           baseAddr;
    
        baseAddr = getCanBaseAddr(canChannel);
    
        if(fifo_num == 0)
        {
            fifo0Status.num = 0;
            MCAN_getRxFIFOStatus(baseAddr, &fifo0Status);
            //DebugP_log("RX FIFO0 num:%d, Put IDX: %d, full: %d, fillLv: %d\n", fifo0Status.getIdx, fifo0Status.putIdx, fifo0Status.fifoFull, fifo0Status.fillLvl);
            MCAN_writeRxFIFOAck(baseAddr, 0, fifo0Status.getIdx );//write the index to get right RX data
        }else
        {
            fifo1Status.num = 1;
            MCAN_getRxFIFOStatus(baseAddr, &fifo1Status);
            //DebugP_log("RX FIFO1 num:%d, Put IDX: %d, full: %d, fillLv: %d\n", fifo1Status.getIdx, fifo1Status.putIdx, fifo1Status.fifoFull, fifo1Status.fillLvl);
            MCAN_writeRxFIFOAck(baseAddr, 1, fifo1Status.getIdx );//write the index to get right RX data
        }
        return 0;
    }

    ApiCan_SendMessage

    int8_t ApiCan_SendMessage(TICan_Channel canChannel, uint32_t id, uint8_t extFrame, uint8_t datalength, uint8_t* data)
    {
        int8_t   configStatus = 0, i;
        MCAN_ProtocolStatus protStatus;
        MCAN_TxBufElement  txCanMsg;
        SemaphoreP_Object  *TxDoneSem;
        uint32_t           baseAddr;
    
        baseAddr = getCanBaseAddr(canChannel);
        TxDoneSem = getCanTxDoneSem(canChannel);
    
        /* Initialize message to transmit */
        if (1 == extFrame)
        {
            txCanMsg.id  = (uint32_t)(id);
            txCanMsg.xtd = 1U;
        }
        else
        {
        txCanMsg.id  = (uint32_t)((uint32_t)(id) << 18U);
        txCanMsg.xtd = 0U;
        }
        txCanMsg.rtr = 0U;
        txCanMsg.esi = 0U;
        txCanMsg.dlc = datalength;
        txCanMsg.brs = 0U;
        txCanMsg.fdf = 1U;
        txCanMsg.efc = 1U;
        txCanMsg.mm  = 0xAAU;
    
        for(i = 0; i < datalength; i++ )
        {
            txCanMsg.data[i]  = *(data+i);
        }
    
        //DebugP_log("Can id: %x send data: %x, %x, %x, %x,",id, txCanMsg.data[0], txCanMsg.data[1],txCanMsg.data[2],txCanMsg.data[3]);   
        //DebugP_log(" %x, %x, %x, %x:\n", txCanMsg.data[4], txCanMsg.data[5],txCanMsg.data[6],txCanMsg.data[7]);   
        if(g_TxBufferCount >= APP_MCAN_TX_BUFF_CNT)
        {
            g_TxBufferCount = 0;
        }
    
        /* Enable Transmission interrupt for the selected buf num,
         * If FIFO is used, then need to send FIFO start index until FIFO count */
        MCAN_txBufTransIntrEnable(baseAddr, g_TxBufferCount, (uint32_t)TRUE);
    
        /* Write message to Msg RAM */
        MCAN_writeMsgRam(baseAddr,
                         MCAN_MEM_TYPE_BUF,
                         g_TxBufferCount,
                         &txCanMsg);
    
        /* Add request for transmission */
        configStatus += MCAN_txBufAddReq(baseAddr, g_TxBufferCount);
        if (configStatus != 0)
        {
            DebugP_log("Error in Adding Transmission Request...\n");
            return -1;
        }
        g_TxBufferCount++;
        
        SemaphoreP_pend(TxDoneSem, 0);
    
    
        MCAN_getProtocolStatus(baseAddr, &protStatus);
    
    
        /* Checking for Errors */
        if (((MCAN_ERR_CODE_NO_ERROR == protStatus.lastErrCode) ||
             (MCAN_ERR_CODE_NO_CHANGE == protStatus.lastErrCode)) &&
            ((MCAN_ERR_CODE_NO_ERROR == protStatus.dlec) ||
             (MCAN_ERR_CODE_NO_CHANGE == protStatus.dlec)) &&
            (0U == protStatus.pxe))
        {
            //DebugP_log("Message successfully transferred with payload Bytes:0x%x, id: 0x%x\n",txCanMsg.dlc, id);
        }
        else
        {
    #if _DEBUG_
            DebugP_log("CAN Error in transmission with payload Bytes:0x%x\n", txCanMsg.dlc);
    #endif
            configStatus = -1;
        }
    
        return configStatus;
    
    }

    BR

    JAY

  • Hi Jay

    I need some more time to review this code. Will check with internal team and get back to you soon

    Regards

    Sri Vidya

  • Hi Jay

    In  Mcan_ProcessCanIntrISR -> ApiCan_ReceiveFIFOMessage, Can this API invoke ApiCan_SendMessage.

    Because ApiCan_SendMessage has a SemaphoreP_pend(TxDoneSem, 0) being called.

    I suspect the Pend Operation in an ISR might be causing wait time. Could you confirm? Meanwhile I will look into other possibilities.

    Regards

    Sri Vidya.

  • Hi Sri Vidya

    For mcan example mcan_loopback_interrupt_main has a SemaphoreP_pend(&gMcanRxDoneSem, SystemP_WAIT_FOREVER) being called.

    (1)The process will hang on SemaphoreP_pend(&gMcanRxDoneSem, SystemP_WAIT_FOREVER) without CAN node ACK response.( am263x mcan as sender only, without other CAN node as receiver).

    void mcan_loopback_interrupt_main(void *args)
    {
        int32_t                 status = SystemP_SUCCESS;
        HwiP_Params             hwiPrms;
        MCAN_TxBufElement       txMsg;
        MCAN_ProtocolStatus     protStatus;
        MCAN_RxBufElement       rxMsg;
        MCAN_RxNewDataStatus    newDataStatus;
        MCAN_ErrCntStatus       errCounter;
        uint32_t                i, bufNum, fifoNum, bitPos = 0U;
    
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[MCAN] Loopback Interrupt mode, application started ...\r\n");
    
        /* Construct Tx/Rx Semaphore objects */
        status = SemaphoreP_constructBinary(&gMcanTxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        status = SemaphoreP_constructBinary(&gMcanRxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
    
        /* Register interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum      = APP_MCAN_INTR_NUM;
        hwiPrms.callback    = &App_mcanIntrISR;
        status              = HwiP_construct(&gMcanHwiObject, &hwiPrms);
        DebugP_assert(status == SystemP_SUCCESS);
    
        /* Assign MCAN instance address */
        gMcanBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(APP_MCAN_BASE_ADDR);
    
        /* Configure MCAN module, Enable LoopBack Mode */
        App_mcanConfig(TRUE);
    
        /* Enable Interrupts */
        App_mcanEnableIntr();
    
        /* Transmit And Receive Message */
        for (i = 0U; i < APP_MCAN_MSG_LOOP_COUNT; i++)
        {
            /* Configure Tx Msg to transmit */
            App_mcanConfigTxMsg(&txMsg);
    
            /* Select buffer number, 32 buffers available */
            bufNum = 0U;
            /* Enable Transmission interrupt for the selected buf num,
             * If FIFO is used, then need to send FIFO start index until FIFO count */
            status = MCAN_txBufTransIntrEnable(gMcanBaseAddr, bufNum, (uint32_t)TRUE);
            DebugP_assert(status == CSL_PASS);
    
            /* Write message to Msg RAM */
            MCAN_writeMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, &txMsg);
    
            /* Add request for transmission, This function will trigger transmission */
            status = MCAN_txBufAddReq(gMcanBaseAddr, bufNum);
            DebugP_assert(status == CSL_PASS);
    
            /* Wait for Tx completion */
            SemaphoreP_pend(&gMcanTxDoneSem, SystemP_WAIT_FOREVER);
    
            MCAN_getProtocolStatus(gMcanBaseAddr, &protStatus);
            /* Checking for Tx Errors */
            if (((MCAN_ERR_CODE_NO_ERROR != protStatus.lastErrCode) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.lastErrCode)) &&
                ((MCAN_ERR_CODE_NO_ERROR != protStatus.dlec) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.dlec)) &&
                (0U != protStatus.pxe))
            {
                 DebugP_assert(FALSE);
            }
    
            /* Wait for Rx completion */
            SemaphoreP_pend(&gMcanRxDoneSem, SystemP_WAIT_FOREVER);
    
            /* Checking for Rx Errors */
            MCAN_getErrCounters(gMcanBaseAddr, &errCounter);
            DebugP_assert((0U == errCounter.recErrCnt) &&
                          (0U == errCounter.canErrLogCnt));
    
            /* Get the new data staus, indicates buffer num which received message */
            MCAN_getNewDataStatus(gMcanBaseAddr, &newDataStatus);
            MCAN_clearNewDataStatus(gMcanBaseAddr, &newDataStatus);
    
            /* Select buffer and fifo number, Buffer is used in this app */
            bufNum = 0U;
            fifoNum = MCAN_RX_FIFO_NUM_0;
    
            bitPos = (1U << bufNum);
            if (bitPos == (newDataStatus.statusLow & bitPos))
            {
                MCAN_readMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, fifoNum, &rxMsg);
            }
            else
            {
                DebugP_assert(FALSE);
            }
    
            /* Compare Tx/Rx data */
            App_mcanCompareMsg(&txMsg, &rxMsg);
        }
        /* De-Construct Tx/Rx Semaphore objects */
        HwiP_destruct(&gMcanHwiObject);
        SemaphoreP_destruct(&gMcanTxDoneSem);
        SemaphoreP_destruct(&gMcanRxDoneSem);
    
        DebugP_log("All tests have passed!!\r\n");
    
        Board_driversClose();
        Drivers_close();
    
        return;
    }
    

    so we modifty ApiCan_SendMessage has a SemaphoreP_pend(TxDoneSem, 0) => the process will go next whenever CAN TX message without CAN ack

    Actually, we modify Mcan_ProcessCanIntrISR(0)  to Mcan_IntrISR interrupt function as following.

    /*******************************************************************************/
    /* Function name: HHCAN_Init()*/
    /* Description  : Initialize HH CAN Module Data*/
    /* Parameters   : N.A  */
    /* Returns      : N.A*/
    /* Remark       : N.A*/
    /*******************************************************************************/
    void HHCAN_Init(void)
    {
        for(int i=0;i < APP_MCAN_CHANNEL_CNT; i++)
        {
            Mcan_Init(i);
        }
    
        HHCANPar_Init();
    }
    
    void HHCAN_CheckCanISRStatus(void)
    {
        for(int i = 0;i < 4; i++)
        {
            if(CanRxISR.CanRXFlag[i] == 1)
            {
                CanRxISR.CanRXFlag[i] = 0;
                Mcan_ProcessCanIntrISR(i);
            }
        }
    }
    void HHCAN_ResetCANNode(TICan_Channel canChannel)
    {
        Mcan_Config(canChannel);
    }
    
    void HHCAN_ReInit(TICan_Channel canChannel)
    {
        Mcan_Init(canChannel);
    }
    /*******************************************************************************/
    /* Static Function Definition*/
    /*******************************************************************************/
    static void Mcan_Init(TICan_Channel canChannel)
    {
        //DebugP_log("[MCAN] TICAN %d _ Init:, Init started ...\r\n", canChannel);
        int32_t                 status = SystemP_SUCCESS;
        TS_TICAN_DATA*       canInitdata = &ticandata[canChannel];
        
        status = SemaphoreP_constructBinary(&canInitdata->gMcanTxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        status = SemaphoreP_constructBinary(&canInitdata->gMcanRxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
    
        /* Register interrupt */
        HwiP_Params_init(&canInitdata->hwiPrms);
        canInitdata->hwiPrms.intNum      = gCANISRData[canChannel].IntrNum;
        canInitdata->hwiPrms.callback    = &Mcan_IntrISR;
        canInitdata->hwiPrms.args    =  &gCANISRData[canChannel].ChannelIndex;
        status = HwiP_construct(&canInitdata->gMcanHwiObject, &canInitdata->hwiPrms);
        DebugP_assert(status == SystemP_SUCCESS);
        /* Assign MCAN instance address */
        canInitdata->gMcanBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(gCANISRData[canChannel].IntrAddr);
    
        /* Select buffer and fifo number, Buffer is used in this app */
        canInitdata->bufNum = 0U;
        canInitdata->fifoNum = MCAN_RX_FIFO_NUM_0;
        canInitdata->bitPos = (1U << canInitdata->bufNum);
    
        /* Configure MCAN module, Disable LoopBack Mode */
        Mcan_Config(canChannel);
        /* Enable Interrupts */
        Mcan_EnableIntr(canChannel);
        //DebugP_log("[MCAN] TICAN %d _ Init, Init end ...\r\n", canChannel);
    }
    
    static void Mcan_Config(TICan_Channel canChannel)
    {
    
        TS_TICAN_DATA*       canInitdata = &ticandata[canChannel];;
    
        /* Initialize MCAN module initParams */
        MCAN_initOperModeParams(&canInitdata->initParams);
        /* CAN FD Mode and Bit Rate Switch Enabled */
            canInitdata->initParams.fdMode          = TRUE;
            canInitdata->initParams.brsEnable       = TRUE;
    
        /* Initialize MCAN module Global Filter Params */
        MCAN_initGlobalFilterConfigParams(&canInitdata->configParams);
    
        /* Initialize MCAN module Bit Time Params */
        /* Configuring default 1Mbps and 5Mbps as nominal and data bit-rate resp */
        //MCAN_initSetBitTimeParams(&tican0data.bitTimes);
    
        Mcan_InitSetBitTimeParams(&canInitdata->bitTimes); //20220324
    
        /* Initialize MCAN module Message Ram Params */
        Mcan_InitMsgRamConfigParams(&canInitdata->msgRAMConfigParams);
    
        /* Initialize Filter element to receive msg, should be same as tx msg id */
    
        /* Initialize Filter element to receive msg, should be same as tx msg id */
    
        canInitdata->stdFiltElem[0].sfid1 = 0x0;
        canInitdata->stdFiltElem[0].sfid2 = 0x7FF;
        canInitdata->stdFiltElem[0].sfec =  0x1U;
        canInitdata->stdFiltElem[0].sft = 0x0;
    
        canInitdata->stdFiltElem[1].sfid1 = 0xA0;
        canInitdata->stdFiltElem[1].sfid2 = 0xB0;
        canInitdata->stdFiltElem[1].sfec = 0x1U;
        canInitdata->stdFiltElem[1].sft = 0x1;
    
        canInitdata->extFiltElem[0].efid1 = 0x800;
        canInitdata->extFiltElem[0].efid2 = 0x8FF;
        canInitdata->extFiltElem[0].efec =  0x1U;
        canInitdata->extFiltElem[0].eft = 0x0;
    
        /* wait for memory initialization to happen */
        while (FALSE == MCAN_isMemInitDone(canInitdata->gMcanBaseAddr))
        {}
    
        /* Put MCAN in SW initialization mode */
        MCAN_setOpMode(canInitdata->gMcanBaseAddr, MCAN_OPERATION_MODE_SW_INIT);
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(canInitdata->gMcanBaseAddr))
        {}
    
        /* Initialize MCAN module */
        MCAN_init(canInitdata->gMcanBaseAddr, &canInitdata->initParams);
        /* Configure MCAN module Gloabal Filter */
        MCAN_config(canInitdata->gMcanBaseAddr, &canInitdata->configParams);
        /* Configure Bit timings */
        MCAN_setBitTime(canInitdata->gMcanBaseAddr, &canInitdata->bitTimes);
        /* Configure Message RAM Sections */
        MCAN_msgRAMConfig(canInitdata->gMcanBaseAddr, &canInitdata->msgRAMConfigParams);
        /* Set Extended ID Mask */
        MCAN_setExtIDAndMask(canInitdata->gMcanBaseAddr, APP_MCAN_EXT_ID_MASK);
    
        /* Configure Standard ID filter element */
        for (int i = 0U; i < APP_MCAN_STD_ID_FILTER_CNT; i++)
        {
            MCAN_addStdMsgIDFilter(canInitdata->gMcanBaseAddr, i, &canInitdata->stdFiltElem[i]);
        }
    
        /* Configure Extend ID filter element */
        for (int i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            MCAN_addExtMsgIDFilter(canInitdata->gMcanBaseAddr, i, &canInitdata->extFiltElem[i]);
        }
    /*
        if (TRUE == enableInternalLpbk)
        {
            MCAN_lpbkModeEnable(tican1data.gMcanBaseAddr, MCAN_LPBK_MODE_INTERNAL, TRUE);
        }
    */
        /* Take MCAN out of the SW initialization mode */
        MCAN_setOpMode(canInitdata->gMcanBaseAddr, MCAN_OPERATION_MODE_NORMAL);
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(canInitdata->gMcanBaseAddr))
        {}
    
        return;
    }
    
    
    static void Mcan_InitSetBitTimeParams(MCAN_BitTimingParams *bitTimes) //20220324
    {
        //80M/((15+1)*(1+6+3))=500K
        //80M/((9+1)*(1+4+3))=1M
        //80M/{(3+1)*[1+(1+5)+(1+2)]}=2M
        bitTimes->nomRatePrescalar   = 0xFU;
        bitTimes->nomTimeSeg1        = 0x5U;
        bitTimes->nomTimeSeg2        = 0x2U;
        bitTimes->nomSynchJumpWidth  = 0x0U;
        bitTimes->dataRatePrescalar  = 0x3U;
        bitTimes->dataTimeSeg1       = 0x5U;
        bitTimes->dataTimeSeg2       = 0x2U;
        bitTimes->dataSynchJumpWidth = 0x0U;
        return;
    }
    
    static void Mcan_InitMsgRamConfigParams(MCAN_MsgRAMConfigParams
                                               *msgRAMConfigParams)
    {
        int32_t status;
    
        MCAN_initMsgRamConfigParams(msgRAMConfigParams);
    
    
        /* Configure the user required msg ram params */
        msgRAMConfigParams->lss                 = APP_MCAN_STD_ID_FILTER_CNT;
        msgRAMConfigParams->lse                 = APP_MCAN_EXT_ID_FILTER_CNT;
    
        msgRAMConfigParams->txBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
        msgRAMConfigParams->txEventFIFOWaterMark = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txBufCnt             = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txFIFOCnt            = APP_MCAN_TX_FIFO_CNT;
        /* Buffer/FIFO mode is selected */
        msgRAMConfigParams->txBufMode           = MCAN_TX_MEM_TYPE_BUF;
        msgRAMConfigParams->txEventFIFOCnt      = APP_MCAN_TX_EVENT_FIFO_CNT;
    
        msgRAMConfigParams->rxFIFO0Cnt           = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO0WaterMark     = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO0OpMode        = 0U;//0
        msgRAMConfigParams->rxFIFO1Cnt           = APP_MCAN_FIFO_1_CNT;
        msgRAMConfigParams->rxFIFO1WaterMark     = APP_MCAN_FIFO_1_CNT;
        msgRAMConfigParams->rxFIFO1OpMode        = 0U;//0
    
        
        /* FIFO blocking mode is selected */
        msgRAMConfigParams->rxFIFO0OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
        msgRAMConfigParams->rxFIFO1OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
    
        status = MCAN_calcMsgRamParamsStartAddr(msgRAMConfigParams);
        DebugP_assert(status == CSL_PASS);
    
        return;
    }
    static void Mcan_EnableIntr(TICan_Channel canChannel)
    {
        uint32_t McanBaseAddr;
        McanBaseAddr = getCanBaseAddr(canChannel);
    
        MCAN_enableIntr(McanBaseAddr, MCAN_INTR_MASK_ALL, (uint32_t)TRUE);
        MCAN_enableIntr(McanBaseAddr,
                        MCAN_INTR_SRC_RES_ADDR_ACCESS, (uint32_t)FALSE);
        /* Select Interrupt Line 0 */
        MCAN_selectIntrLine(McanBaseAddr, MCAN_INTR_MASK_ALL, MCAN_INTR_LINE_NUM_0);
        /* Enable Interrupt Line */
        MCAN_enableIntrLine(McanBaseAddr, MCAN_INTR_LINE_NUM_0, (uint32_t)TRUE);
    
        return;
    }
    /*******************************************************************************/
    /* Interrupt Routine Definition*/
    /*******************************************************************************/
    
    static void Mcan_ProcessCanIntrISR(uint8 iCanIndex)
    {
        uint32_t intrStatus;
        MCAN_RxBufElement   rxCanMsg ={0};
    
        intrStatus = CanRxISR.IntrStatus[iCanIndex];
    
        /* If FIFO0/FIFO1 is used, then MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG macro
        * needs to be replaced by MCAN_INTR_SRC_RX_FIFO0_NEW_MSG/
        * MCAN_INTR_SRC_RX_FIFO1_NEW_MSG respectively */
        if (MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG ==
         (intrStatus & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG))
        {
            //SemaphoreP_post(&tican0data.gMcanRxDoneSem);
        }
    
        if (MCAN_INTR_SRC_RX_FIFO0_NEW_MSG ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG))//0x1U
        {
            //DebugP_log("-------RX Fifo0 receive ok------------------\r\n");
         
            ApiCan_ReceiveFIFOMessage(iCanIndex, 0, &rxCanMsg );
    
    #if EN_UDS_TASK
             if(iCanIndex == 0)
             {
                 ApiCan_UdsReceiveMessage(iCanIndex , &rxCanMsg);
             }
    #endif
        }
         
        if (MCAN_INTR_SRC_RX_FIFO1_NEW_MSG ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG))//0x10
        {
            //DebugP_log("-------RX Fifo1 new MSG receive ok------------------\n");
            ApiCan_ReceiveFIFOMessage(iCanIndex ,1 , &rxCanMsg );
        }
         
        if (MCAN_INTR_SRC_RX_FIFO0_MSG_LOST ==
         (intrStatus & MCAN_INTR_SRC_RX_FIFO0_MSG_LOST))//0x08
        {
            //DebugP_log("-------RX new MSG Lost------------------\n");
            ApiCan_ReceiveFIFOMessage(iCanIndex , 0, &rxCanMsg );
        }
    
         if (MCAN_INTR_SRC_ERR_PASSIVE ==
             (intrStatus & MCAN_INTR_SRC_ERR_PASSIVE))//0x800000U
         {
             //DebugP_log("-------TX Err Passive------\n");
             error_flag = passive;
         }
         if (MCAN_INTR_SRC_BUS_OFF_STATUS ==
             (intrStatus & MCAN_INTR_SRC_BUS_OFF_STATUS))//0x2000000U    //Bus Off process
         {
             //DebugP_log("-------TX Bus off--------\n");
             error_flag = bus_off;
    #if EN_UDS_TASK
             if(iCanIndex == 0)
             {
                 CanNM_BusOffStart();
             }
    #endif
         }
    
         return;
    }
    
    //= &ticandata[canChannel];
    static void Mcan_IntrISR(void* args)
    {
        uint32_t intrStatus;
        TICan_Channel canChannel;
        TICan_Channel* C1 = args;
        canChannel = *C1;
    
        intrStatus = MCAN_getIntrStatus(ticandata[canChannel].gMcanBaseAddr);
        MCAN_clearIntrStatus(ticandata[canChannel].gMcanBaseAddr, intrStatus);
    
        if (MCAN_INTR_SRC_TRANS_COMPLETE ==
         (intrStatus & MCAN_INTR_SRC_TRANS_COMPLETE))
        {
            SemaphoreP_post(&ticandata[canChannel].gMcanTxDoneSem);
            ApiCan_ProcessTxFIFOEvent(canChannel);
        }else
        {
            CanRxISR.CanRXFlag[canChannel] = 1;
            CanRxISR.IntrStatus[canChannel] = intrStatus;
            HHCAN_CheckCanISRStatus();         /* CAN      Module ISR process */
        }
        return;
    }

    After this modify, Mcan_ProcessCanIntrISR(0) trigger have delay issue(200~400ms) when received 200ms period message

    Have any suggestion for Mcan_ProcessCanIntrISR usage for multi CAN message?

    BR

    Jay

  • Hi Jay

    Is this project in built in Release mode for enabling optimizations? If not could you change to Release mode and check if its resolving your issue?

    Also could you share your project so that I can reproduce at my end and check it.

    Regards

    Sri Vidya

  • Hi Sri Vidya

    Project is built in Release mode , and  did not enable optimizations.

    We find root cause is CAN bus with error frame.  

    We will try to fix this issue by checking busoff flag.

    BR

    Jay

  • Okay, will wait for your results.

    Regards

    Sri Vidya