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.
您好、TI 专家
我们在 AM263x SDK V8.2中遇到了多 CAN 消息的 MCAN RX ISR 延迟问题
(1)当我们仅为 用 1ms 时间触发任务的 CAN0启用 MCAN_ProcessCanIntraISR (0)时
当接收到200ms 周期消息时、MCAN_ProcessCanIntrISR (0)触发器有延迟问题(200~1000ms)
(2) CAN 总线负载(~4%)如下 :
CAN0发送的 CAN ID:0x228和0x504 (CAN 工具中显示 RX)
CAN0接收的其它 CAN ID (TX 显示在 CAN 工具中)、
是否有任何关于 MCAN_ProcessCanIntraISR 用于多 CAN 消息的建议?
BR
Jay
您好、Jay、
我们将对此进行研究、并很快与您联系。
此致、
弗兰克
您好、 TI 专家
请按以下方式检查 MCAN 功能
/*******************************************************************************/ /* 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
您好、Jay
对迟交的答复表示歉意。
您能否告诉我这个问题是仅在 SBL 还是在应用程序中发生?
此致
Sri Vidya
你(们)好,Sri Vidya
在 SBL 中或在应用中、当 MCAN RX ISR 同时发送多个 CAN 消息时、这个问题是相同的
BR
Jay
您好、Jay
我将介绍您共享的代码。 看起来 MCAN_ProcessCanIntraISR 是客户创建的 API。
在此 API 中、使用 ApiCan_ReceiveFIFOMessage 接收消息。 这是导致您指定的延迟的原因吗?
如果是、您是否还可以共享 在 ApiCan_ReceiveFIFOMessage 中执行的操作?
此致
Sri Vidya
你(们)好,Sri Vidya
ApiCan_ReceiveFIFOMessag 和 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
您好、Jay
我需要更多时间来查看此代码。 将与内部团队联系、并尽快回复您
此致
Sri Vidya
您好、Jay
在 MCAN_ProcessCanIntrISR -> ApiCAN_ReceiveFIFOMessage 中、此 API 能否调用 ApiCAN_SendMessage。
因为 ApiCan_SendMessage 有一个 SemaphoreP_pend (TxDoneSem、0)被调用。
我怀疑 ISR 中的 Pend 操作可能会导致等待时间。 可以确认吗? 同时、我将探讨其他可能性。
此致
Sri Vidya。
你(们)好,Sri Vidya
对于 mcan 示例、mCAN_loopback _interrupt_main 有一个 SemaphoreP_pend (&gMcanRxDoneSem、SystemP_WAIT_FOREVER)正在被调用。
(1)该过程将在 SemaphoreP_pend (&gMcanRxDoneSem、SystemP_WAIT_FOREVY)上挂起、而不具有 CAN 节点 ACK 响应(am263x mcan 仅作为发送器、而其他 CAN 节点作为接收器)。
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; }
因此、我们修改了一个 SemaphoreP_pend (TxDoneSem、0)=>每当没有 CAN 应答的 CAN TX 消息时、该过程就会继续
实际上、我们将 MCAN_ProcessCanIntraISR (0)修改 为 MCAN_IntraISR 中断函数、如下所示。
/*******************************************************************************/ /* 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; }
修改后、 收到200ms 周期消息时、可以_ProcessCanIntISR(0)触发器有延迟问题(200~400ms)
是否有任何关于 MCAN_ProcessCanIntraISR 用于多 CAN 消息的建议?
BR
Jay
您好、Jay
此项目是否处于内置发布模式以启用优化? 如果不是、您可以更改为"发布"模式并检查其是否解决了您的问题?
您能否共享您的项目、以便我可以在我的结尾复制并检查它。
此致
Sri Vidya
你(们)好,Sri Vidya
项目是在“发布”模式下构建的, 并且未启用优化。
我们发现根本原因是具有错误帧的 CAN 总线。
我们将尝试通过检查 BUSOFF 标志来解决此问题。
BR
Jay
好的、将等待您的结果。
此致
Sri Vidya