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.
你(们)好。
我想通过 AM2632上的 CAN 使用 SBL 单闪存启动功能,我们参考了 TI 支持的“SBL_QSPI”示例以添加 CAN 功能。 但我现在混淆了一个问题。 我们发现、该 API 将在一个任务周期中触发两次。 在本例中、我们创建一个10ms 任务来测试 CAN Tx 函数。 但是、当我们使用 CAN 工具检查行为时、该 MCAN-writeMsgRam 函数的操作错误。
如下所示、它预计每10ms 发送一次。 因此、它会变得有点奇怪。 这两个发送时间为10ms。 换句话说、它必须在一个周期时间内被触发两次。 但这是错误的。
另一方面、我们尝试使用 XDS200进行实验、将.out 文件下载到 AM2632。 我们在 MCAN-writeMsgRam 函数上设置了一个断点、以便我们可以检查它在一个周期中是否确实执行了两次。 因此、在这种情况下、此函数被触发两次。 我们将胶片附在 YouTube 上。 www.youtube.com/watch
大家可以看看这个问题吗?
非常感谢
您好、Jay、
看起来 MCAN-writeMsgRam()在两个不同的位置被调用:在 ApiCAN_SendMessage 和 HHCan0TxTest 中。 这是问题吗?
此致、
Ming
你好、配合。 你的观点是毫无疑问的。 我们检查了这些位置、只有一个位置使用 MCAN-writeMsgRam 函数、因此我们设置了一个断点来查看发生了什么。 它在第400行显示了一个双触发器。 如前所述、调试步骤显示在视频中、从0:31到0:36。
谢谢您和 BR、
Jay
您好、Jay、
这意味着 HHHCAN_Handler()在10ms 内被调用两次,对吧? 谁正在调用 HHCAN_Handler()。 我假设它在计时器中断中被调用。 是否也可以在 CAN TX 中断中调用它?
此致、
Ming
你(们)好。
我已经简化了我们的代码来检查问题。 “HHHHCAN-Handler”每10ms 执行一次。 CAN 模块设置几乎与 SDK 相同、在 我们使用的其他项目中也是可以的。 这里的区别在于此项目是“SBL”。 因此、我在这里附上了我的主代码、请帮助我找出问题所在。
您好、Jay、
我不明白为什么要将以下代码段放在 main 的 while 循环中:
bootloader_profileAddProfilePoint ("System_init");
drivers_open();
bootloader_profileAddProfilePoint ("Drivers_open");
DebugP_log ("\r\n");
DebugP_log ("正在启动 QSPI 引导加载程序... \r\n");
状态= Board_driversOpen();
DebugP_assert (status =SystemP_Success);
bootloader_profileAddProfilePoint ("Board_driversOpen");
此致、
Ming
您好、Ming Wei、
很抱歉提供了错误的版本。
如下图所示、图片与 图片相同。
有关引导加载程序系列的这一段落基于 示例代码。
我们已通过这些步骤检查了这个问题、但仍然存在。
谢谢您和 BR、
Jay
您好、Jay、
根据您提供的源代码,唯一有问题的两个函数是: TBM_PollData()和 TBM_Handler()。 您能否为这两个函数提供代码? 一种可能是 TBM_PollData 每秒的真实值可能超过100次。 另一种可能是 TBM_Handler()也以某种方式调用 MCAN_writeMsgRam。
此致、
Ming
您好、Ming Wei、
TBM 的配置在 systemconfig 中设置。
此外、相对函数如下。 (时基)
/*******************************************************************************/ /* NEC Interrupt Vector Define */ /*******************************************************************************/ //#pragma interrupt INTTM50 Timebase_Routine //#pragma interrupt INTTMH1 CycleWakeUp_Routine /*******************************************************************************/ /* Header File Includes*/ /*******************************************************************************/ //#include "TI_Define.h" //#include "DF_Value.h" #include <stdio.h> #include <kernel/dpl/ClockP.h> #include <kernel/dpl/DebugP.h> #include <kernel/dpl/SystemP.h> #include <drivers/soc.h> #include <kernel/dpl/AddrTranslateP.h> #include "ti_dpl_config.h" #include "ti_drivers_config.h" #include "HHtimebase.h" #include "DF_Value.h" //#define CONFIG_TIMER0_INT_NUM (CONFIG_TIMER0_INT_NUM) #define APP_MCAN_INTR_NUM (CONFIG_MCAN0_INTR) #define APP_MCAN_MSG_LOOP_COUNT (10U) void myClockCallback(void *args); /*******************************************************************************/ /* Private Typedef Structure*/ /*******************************************************************************/ typedef struct { DF_U08 T1msFlag ; /* Flag for 1ms */ DF_U08 T10msFlag ; /* Flag for 10ms */ DF_U08 T50msFlag ; /* Flag for 50ms */ DF_U08 T100msFlag ; /* Flag for 100ms */ DF_U32 T10msTimer ; DF_U32 T50msTimer ; DF_U32 T100msTimer ; DF_U32 DelayCount ; }TS_TIMEBASE_DATA; /*******************************************************************************/ /* Private Variable Definition*/ /*******************************************************************************/ static TS_TIMEBASE_DATA tbmData = {0}; uint32_t gOneShotCount = 0; uint32_t gPeriodicCount = 0; /*******************************************************************************/ /* Public Function Definition*/ /*******************************************************************************/ /*******************************************************************************/ /* Function name: TBM_Init()*/ /* Description : Initialize TimeBase Module Data*/ /* Parameters : N.A */ /* Returns : N.A*/ /* Remark : N.A*/ /*******************************************************************************/ void TBM_Init(void) { tbmData.T1msFlag = DF_CLEAR; tbmData.T10msFlag = DF_CLEAR; tbmData.T50msFlag = DF_CLEAR; tbmData.T100msFlag = DF_CLEAR; tbmData.T10msTimer = 10; tbmData.T50msTimer = 5; tbmData.T100msTimer = 2; } /*******************************************************************************/ /* Function name: TBM_Handler()*/ /* Description : Handler TimeBase Module Data*/ /* Parameters : N.A*/ /* Returns : N.A*/ /* Remark : N.A*/ /*******************************************************************************/ void TBM_Handler(void) { //DebugP_log("TBM_Handler ...\r\n"); /* Clear All Timer Base Flags */ tbmData.T1msFlag = DF_CLEAR; tbmData.T10msFlag = DF_CLEAR; tbmData.T50msFlag = DF_CLEAR; tbmData.T100msFlag = DF_CLEAR; /* Clear WatchDog Timer*/ //WDOG_Refresh(WDOG); /* Handle 50 ms */ tbmData.T50msTimer--; if (tbmData.T50msTimer == DF_CLEAR) { tbmData.T50msFlag = DF_ON; /* Reset 50ms Timer*/ tbmData.T50msTimer = 5; /* Handle 100 ms */ tbmData.T100msTimer--; if (tbmData.T100msTimer == DF_CLEAR) { tbmData.T100msFlag = DF_ON; /* Reset 100ms Timer*/ tbmData.T100msTimer = 2; } } } DF_BOOL TBM_PollData(TE_TIMEBASE_TYPE inType) { switch (inType) { case TBM_10ms: return (tbmData.T10msFlag); case TBM_50ms: return (tbmData.T50msFlag); case TBM_100ms: return (tbmData.T100msFlag); default: return DF_OFF; } return DF_OFF; } /*******************************************************************************/ /* Function name: TBM_Delay(LS_U16 value)*/ /* Description : Delay function.*/ /* Parameters : LS_U16 value, timebase = 1 ms*/ /* Returns : N.A*/ /* Remark : N.A*/ /*******************************************************************************/ void TBM_Delay(DF_U16 value)/*timebase 10ms*/ { tbmData.DelayCount = DF_CLEAR; while (tbmData.DelayCount < value) { if ((tbmData.DelayCount%20) == 0) { // WDOG_Refresh(WDOG); } } } /*******************************************************************************/ /* Interrupt Routine Definition*/ /*******************************************************************************/ volatile unsigned int SwTimer=0; unsigned char PollingTask10ms=0; unsigned char PollingTask100ms=0; unsigned char PollingTask1000ms=0; uint32_t gTimerCount = 0; uint32_t gpioFlag_timer = 0; void HHClockCallback(void *args) { uint32_t *value = (uint32_t*)args; (*value)++; /* increment number of time's this callback is called */ DebugP_log("value %d ...\r\n", (*value)); SwTimer++; if(SwTimer>10000) {SwTimer=1;} if((SwTimer%10)==0) {PollingTask10ms=1;} if((SwTimer%100)==0) {PollingTask100ms=1;} if((SwTimer%1000)==0) {PollingTask1000ms=1;} //PRINTF("Timebase_Routine: %d\r\n", tbmData.T1msFlag); /* Handle 10 ms */ tbmData.T10msTimer-- ; if (tbmData.T10msTimer == DF_CLEAR) { tbmData.T10msFlag = DF_ON; /* Reset 10ms Timer */ tbmData.T10msTimer = 10; } }
顺便说一下、我们也在10ms 内将 CAN 函数更改为 GPIO 函数。 相反、它在10ms 内正确执行一次。
您好、Jay、
它可实现以下功能:
空 HHCan0TxTest (空)
{
tican0data.status = MCAN_txBufAddReq (tican0data.gMcanBaseAddr、tican0data.bufNum);
/*将 Tx 消息配置为发送*/
app_mcan1ConfigTxMsg (_tican0msgdata.txMsg);
tican0data.bufNum = 0U;
/*为选定的 buf num 启用传输中断,
*如果使用 FIFO、则需要发送 FIFO 起始索引直到 FIFO 计数*/
tican0data.status = MCAN_txBufTransIntrEnable (tican0data.gMcanBaseAddr、tican0data.bufNum、(uint32_t) true);
//DebugP_assert (tican0data.status = CSL_Pass);
/*将消息写入 Msg RAM */
MCAN_writeMsgRam (tican0data.gMcanBaseAddr、MCAN_MEM_TYPE_BUF、tican0data.bufNum、&tican0msgdata.txMsg);
}
您能否计算 在10ms 内调用 MCAN_writeMsgRam()的次数以及 在10ms 内调用 HHCan0TxTest()的次数?
MCAN TX 中断是如何处理的(ISR 代码)?
此致、
Ming
您好、Ming Wei、
HHCan0TxTest (void)会在10ms 内调用一次。 MCAN_writeMsgRam()应该被调用一次。 然而、它在10ms 内在 HHCan0TxTest (void)中获得两次的 calds。 如视频所示,MCAN_writeMsgRam()在10ms 内在 HHCan0TxTest (void)中激活两次。
我们在 其他正常项目中使用相同的 MCAN TX 中断处理程序、它工作正常。
谢谢您和 BR、
Jay
您好、Ming Wei、
我们尝试将 GPIO 函数与 CAN Tx 函数和 MCANISR 相结合。 下面显示的图片是结果。
第一个是 CAN TX、可以在同一时间段调用 mcanISR。
第二个和第三个是 IO 和 CAN 比较。 我们检查 CAN 信号是否发送两次、IO 仅触发一次。
我们的修改如下所示。
一方面、我们检查了我们的图中预期的 ISR 和 CANTx_handler。 另一方面、MCAN_writeMsgRam 函数看起来仍然很奇怪。 您能否查看 SBL 示例、了解 它为何无法正常使用 CAN 功能、或者 我们需要在何处修改代码。
谢谢您和 BR、
Jay
您好、Ming Wei
对 CAN TX 两次时间问题有什么想法吗?
BR
Jay
您好、Jay、
Ming 要求我帮助解决这个问题。
我通读了该主题、我的理解如下:
第一个测试程序将计时器配置为10个周期、并在无限循环中轮询计时器周期完成情况。 在定时器周期完成时、程序:
第二个测试程序获取一个 MCAN Tx 中断。 在 MCAN Tx ISR 中、程序:
示波器捕获显示:
MCAN 配置类似于 SDK 示例。 此外、此配置在其他 MCAN 示例代码中工作。 它仅在您修改的 SBL 示例中以这种方式运行。
您能确认我的理解是否正确吗?
您的测试结果似乎表明 MCAN_writeMsgRam()只被调用一次是10msec,但对于单次调用 MCAN_writeMsgRam(),MCAN Tx 发生两次。
您能否共享清楚地展示在 AM263x CC 上执行的问题的示例代码(整个 CCS 项目)?
此致、
弗兰克
你(们)好、Frank
您的理解是正确的!
BR
Jay
Jay、
谢谢、我将与您一起回顾一下。
此致、
弗兰克
你(们)好、Frank
有此主题的更新吗?
BR
Jay
您好、Jay、
很抱歉、我花了这么长的时间来回答。 此问题是否已解决?
此致、
弗兰克
你(们)好、Frank
Sunil Kumar M S 已解决此问题
BR
Jay
Jay、
好的、非常感谢。 我现在要关闭这个线程。
此致、
弗兰克