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.

[参考译文] RTOS/MSP432P401R:SimpleLink 计时器驱动程序的奇怪行为

Guru**** 2581345 points
Other Parts Discussed in Thread: SYSBIOS

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/612033/rtos-msp432p401r-strange-behaviour-of-simplelink-timer-driver

器件型号:MSP432P401R
Thread 中讨论的其他器件:SYSBIOS

工具/软件:TI-RTOS

G'Day All、

这个问题与所附项目有关。

这是一个相对简单的项目。  它的设计指南是一个运行时钟为1MHz 的 RTOS/Simplelink 计时器、每1.6666mSec 切换引脚3.2。

如果您将此代码加载到 MSP432 Launchpad 中、请将示波器连接到引脚3.2、观察您将看到奇怪的情况。  

在大多数情况下、引脚每1.666mSec 切换一次、或按预期足够接近、但在大约20秒(以及此后的每5秒)后、引脚3.2会变得疯狂、并像 MAD 一样切换大约1.6mSec。

如果在一切正常工作时我在 testTimer_HWI 中的断点、TAR 和 TACCR0寄存器会按我的预期递增。  例如:

tar TACCR0
13109. 14760
14776 16426
16441. 18092
18107. 19758.

这是有道理的。  我们将继续进行1666次计数(1MHz 计时器上为1.666mSec)。  但是、如果我在引脚3.2快速切换时断点、我会得到更像这样的结果

tar TACCR0
36. 3322.
98 6654.
159. 9986
220 13318
282. 16650
343 19982.
404. 23314

这种模式一直持续到 TACCR0角色返回到0、然后恢复正常运行。  这毫无意义!  TACCR0正以其应有的速度递增两倍(3332而不是1666)、TAR 似乎正以大约61的步进而不是1666的步进前进。

在此期间、我还注意到、在 ROV -> Timer (ti.sysbios.family.arm.msp432)-> Device -> Timer_A1中、"currCount"为负...

您是否有建议、这里可能会发生什么情况??  非常感谢您在这方面的帮助!

谢谢

Julian

//编辑-用仍然显示相同问题的简化项目替换原始项目

e2e.ti.com/.../TestRTOSTimer.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Julian:

    让我们看一下您的代码、我们会给您回复。

    谢谢、

    David
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    G'day David、

    非常感谢您花时间来看看。
    我已将上述项目更新为更简单(并支持更低的 SMCLK 速率)。

    我在这种情况的边缘稍作介绍、并观察到随着 MCLK/SMCLK 的降低(更具体地说、电源配置中的初始值 PerfLevel 更低)、这个问题会变得更糟。 在某些计时器周期中、这种快速切换似乎也不会发生。 我发现的所有"好时期"都是400的倍数。

    initPerfLevel = 0 (MCLK = 12MHz、SMCLK = 3MHz)、1600周期内不能进行快速切换
    initPerfLevel = 1 (MCLK = 24MHz、SMCLK = 6MHz)、800、1600、2400周期内不能进行快速切换
    initPerfLevel = 2 (MCLK = 48MHz、SMCLK = 12MHz)、在400、800、1200、1600、2400周期内不能进行快速切换、 2800
    initPerfLevel = 3 (MCLK = 48MHz、SMCLK = 24MHz)、在400、800、1200、1600、2400周期内不能进行快速切换、 2800

    谢谢
    Julian
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Julian:

    我能够再现这种行为。

    我邀请 TI-RTOS 专家对此发表评论。 我猜这与如何 使用"Timer_create"和 Hwi 创建计时器有关。

    同时、您是否可以运行以下示例代码: 包含 以下修改的 timerled 示例:

    1.在 timerled.c 中

    void * mainThread (void * arg0)
    {
    /*以微秒为单位的周期和占空比*/
    Timer_handle timer0;
    Timer_Params 参数;
    
    /*调用驱动程序初始化函数*/
    GPIO_init();
    timer_init();
    
    /*关闭用户 LED */
    GPIO_WRITE (Board_GPIO_LED0、Board_GPIO_LED_OFF);
    
    /*将计时器设置为连续回调模式,以调用回调
    *每1、000、000微秒或1秒运行一次。
    *
    Timer_Params_init (&params);
    // params.period = 1000000;
    Params.Period = 166;
    Params.periodUnits = Timer_Period_US;
    params.timerMode = Timer_Continuous_callback;
    params.timerCallback = timerCallback;
    
    timer0 = Timer_open (/* Board_TIMER0*/Board_TIMER2、&params);
    
    if (timer0 == NULL){
    /*初始化计时器失败*/
    while (1);
    }
    
    如果(Timer_start (timer0)= Timer_STATUS_ERROR){
    /*无法启动计时器*/
    while (1);
    }
    
    while (1)
    {
    睡眠(2);
    }
    } 

    2.在 MSP_EXP432P401R.c 中

    const TimerMSP432_HWAttrs timerMSP432HWAttrs[MSP_EXP432P401R_TIMERCOUNT]={
    /* Timer32_0 */
    {
    .timerBaseAddress = TIMER32_0_BASE、
    时钟源= TIMER_A_CLOCKSOURCE_SMCLK、
    .intNum = INT_T32_INT1、
    .intPriority =~0
    }、
    {
    .timerBaseAddress = TIMER32_1_base、
    时钟源= TIMER_A_CLOCKSOURCE_SMCLK、
    .intNum = INT_T32_INT2、
    .intPriority =~0
    }、
    /* Timer_A1 */
    {
    .timerBaseAddress = TIMER_A1_base、
    时钟源=/*TIMER_A_CLOCKSOURCE_ACLK*/TIMER_A_CLOCKSOURCE_SMCLK,
    .intNum = INT_TA1_0、
    .intPriority =~0
    }、
    /* Timer_A2 */
    {
    .timerBaseAddress = TIMER_A2_base、
    时钟源= TIMER_A_CLOCKSOURCE_ACLK、
    .intNum = INT_TA2_0、
    .intPriority =~0
    }、
    /* Timer_A3 */
    {
    .timerBaseAddress = TIMER_A3_base、
    时钟源= TIMER_A_CLOCKSOURCE_ACLK、
    .intNum = INT_TA3_0、
    .intPriority =~0
    }
    }; 

    使用该代码、我无法重现此行为、但 您可能会获得 不同的结果。

     此致、

     David  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    G'day David、

    我已经尝试过您的示例、它对我也是正确的-没有快速切换。

    您的示例似乎是使用 SimpleLink 驱动程序、而我的方法似乎是直接深入研究 TI-RTOS 计时器驱动程序。
    (我注意到这两个驱动程序都有一个名为 Timer_Params_init()的函数,但它们使用不同的结构)

    您的示例确实为我提供了一个前进的道路、但如果您不介意、我想等待并听听 TI-RTOS 专家是否有任何建议来修复我已经拥有的代码。

    谢谢
    Julian
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    G'day David、

    我认为我发现了这个问题。

    请参阅[SIMPLELINK1.4]\kernel\tirtos\packages/ti\SysBIOS\family\arm\msp432\Timer.c 函数 Timer_setNextTick ()。

    "下一个"的计算中存在逆时针问题(第182行)。 下一步被声明为 UINT (32位)、但是它处理来自 Timer_A1的16位寄存器值。

    "下一个"的计算方式为之前的 CCR0值+定时器周期。 这对于写回 CCR 寄存器(第185行)来说很好、因为向16位寄存器写入32位值将在高16位上停止、从而在"下一个"超过65535时提供所需的模数运算。

    但是、使用"下一步"来确定哪个"区域"(请参阅从第188行开始的注释)是断开的、因为"下一步"不会像"现在"变量(直接从 TAR 寄存器读取)那样翻转。 因此当我们开始翻转时,区域被错误地确定,Timer_setNextTick()开始触发计时器中断,认为它在设置下一个节拍的时间方面很晚。 它一直像这样触发中断、直到问题消失。

    下面是一个示例、其中时间设置为具有400个周期(= 400uSec、因为计时器设置为1MHz)
    (prevoius、now 和 next 是 Timer_setNextTick()中的变量。

    上一页 下一步
    65120 65143. 65520.
    这很好! 65520 - 65120 = 400。 "现在"位于"A"区域、一切正常。

    上一页 下一步
    65520. 7. 65920
    65920 - 65520 = 400、但65920超过16位!
    此函数中的逻辑现在错误地假定"现在"位于区域 C 中、这会导致一个定时器中断被强制执行。
    但是、如果"NEXT (下一个)"已正确地滚动到384、它将是不会强制中断的区域"E"。

    上一页 下一步
    384 57. 784)
    "上一页"已正确回滚。 由于前一步中的强制中断、"现在"只移动了50、而不是400。 "下一页"-"上一页"是预期的400。 再说一次、"Now"位于区域 C 中、并强制执行计时器中断。

    我认为这里的修复方法是使该函数中的所有 UINT 变量 uint16_t 我将尝试使用此更改重新编译 RTOS、并查看问题是否已解决。


    谢谢
    Julian
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    G'day David、

    我已经测试了一个适合我的解决方案。

    1.将 Timer_setNextTick()中的变量声明更改为

    uint16_t newPeriod =(uint16_t)(obj->period)*(uint16_t) ticks;
    uint16_t NEXT;
    uint16_t Previous;
    uint16_t 现在;

    2.从[SIMPLELINK1.4] kernel\tirtos 重新编译 TI-RTOS


    谢谢
    Julian