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.

[参考译文] AM2634:SBL CAN 问题

Guru**** 1640390 points
Other Parts Discussed in Thread: AM2632, UNIFLASH
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1110095/am2634-sbl-can-issue

器件型号:AM2634
主题中讨论的其他器件:AM2632UNIFLASH

你(们)好。

我想通过 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 要求我帮助解决这个问题。

    我通读了该主题、我的理解如下:

    • 您正在尝试用 CAN 替换 SBL UART Uniflash 中的 UART
    • MCAN Tx 以您期望的频率的两倍发生(10毫秒内2次与1次)
    • 您有几个测试程序来证明问题。

    第一个测试程序将计时器配置为10个周期、并在无限循环中轮询计时器周期完成情况。 在定时器周期完成时、程序:

    • 执行计时器处理程序
    • 切换调试 GPIO
    • 执行 MCAN Tx 函数

    第二个测试程序获取一个 MCAN Tx 中断。 在 MCAN Tx ISR 中、程序:

    • 切换调试 GPIO
    • 执行 MCAN Tx 函数

    示波器捕获显示:

    • GPIO 在每个计时器周期(10毫秒)内切换
    • MCAN Tx 背靠背发生两次

    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、

    好的、非常感谢。 我现在要关闭这个线程。

    此致、
    弗兰克