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.

[参考译文] TMS320F2.8335万:浮点'大于'比较故障?

Guru**** 2595780 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/666666/tms320f28335-floating-point-greater-than-comparison-failure

部件号:TMS320F2.8335万

我在使用TMS320F2.8335万时遇到了一个奇怪的问题。

当我对浮点数执行简单的'大于'比较时,比较有时似乎给出了错误的结果。

为了精确定位问题,我测试了以下代码:

如果(test_variable > 100.0)
	{
		pjup++;
		asm (" MOV32 @_pregvalue, R0H");
		pjumpvalue = test_variable;
		test_variable = 100.0 ;
	}
	IF (test_variable < 0.0)
	{
		njump++;
		ASM(" MOV32 @_nregvalue, R0H");
		njumpvalue = test_variable;
		test_variable = 0.0 ;
	} 

ASM()命令将R0H寄存器的值放入pregvalue或nregvalue变量中,该寄存器是将test_variable移动到其中以在输出.asm文件中执行浮点比较的寄存器(大小写相同)。

我通过串行端口输出这些变量的值来定期监控它们的值。 该数据清楚地显示,即使test_variable的值低于100.0 ,在执行IF (test_variable > 100.0)之后,代码块有时(看似随机)仍会被阻止。 这种情况发生的频率是,例如,每隔几小时发生一次。 但是,第二次(<)比较从未发现同样的情况。  

这是一个已知问题吗? 使用 __fmin()和__fmax()函数代替if()测试似乎可以解决这个问题,但我仍然觉得有点麻烦。  

提前感谢!

Laurent Badel

有关信息,生成的装配体的相关部分如下-我看不到任何错误:

MOV32 R0H,@Ω test_variable
CMPF32 R0H,#1.7096万
MOVST0 ZF,NF
BF $C$L16,GT

...

$C$L16:
inc @_pjump
MOV32 @_pregvalue,R0H
MOVL ACC,@ test_variable
MOVL @_pjumpvalue,附件
MOVIZ R0H,#1.7096万
MOV32 @_test_variable,R0H

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

    当然,代码不应该这样做,我和您一样,在您粘贴的汇编代码中没有发现问题。 我尝试过类似的代码,但迄今为止我尝试过的任何代码都不会出现意外的行为。

    您能否谈谈周围的代码和"test_variable"被操纵的方式? 此外,代码片段是否在循环中,如果是,您是否可以发送循环代码?

    我还想物理检查代码在内存中的位置,以便您也可以粘贴拆卸窗口? 谢谢。

    此致,

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

    Richard

    非常感谢您的回复。  

    周围的代码相当复杂,因为它在RTOS内运行(我认为基于MUC/OS,但不完全相同)。 我会考虑如何简明扼要地描述周围环境,同时尽可能保持准确。 我还将了解如何进行拆卸。

    同时,请看看这两行数据,我已说服我这个问题-也许你们对此有另一种解释。

    时间 test_variable 跳转 pjumpval pregval 跳转 njumpval nregval
    2018年02月08日 15:15:00:43.386万 55.8 129. 55.8 55.8 1.2065万 0 0
    2018年02月08日 15:15:00:99.635万 55.8 130 55.8 55.8 1.2065万 0 0

    如前所述,我通过串行端口(这是一种在RTOS中作为任务运行的调试控制台)输出受监视变量的值来收集此数据。 一般来说,我可以看到更新速率为每600ms左右一次的值。 也许还值得注意的是,运行相关代码的任务是低优先级任务(10项任务中次低)。  

    在上述数据中,您可以看到在~600ms的间隔内,pjump的值从129更改为130。 129的值可以忽略,因为这是来自测试变量确实> 100.0 的早期情况,因此代码是合法执行的。 但是,在这种特殊情况下,您可以看到test_variable = 55.8 ,因此没有理由执行>比较后的代码块。  

    test_variable未被指定值100.0 的原因是我同时测试了一种机制以防止跳转(只需强制执行,如果值在一次迭代中更改了多个0.1 ,我们将恢复到以前的值), 但是我可以确认它确实具有值100.0 ,因为我将此值存储在另一个变量中,并将恢复为以前的值。   

    我们还可以看到pjumpval和pregval的值与test_variable相同,因此我们可以排除以下情形:(i)执行比较时test_variable确实> 100.0 ,但其值在执行比较后发生了某种变化;(ii)在这两个时刻之间发生了上下文变化 当test_variable的值被推入R0H寄存器时,执行CMPF32操作的时刻,并且R0H的值已从该上下文中更改。

    根据这些数据,我能想到的唯一解释是,浮点比较得出了错误的结果,但也许我漏掉了什么?

    谢谢!  

    Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不幸的是,我没有我观察到这个问题的确切代码了。 我重新编译了一个版本,在我的原始帖子中包含测试代码的部分,我正在运行测试以查看是否再次出现问题。 如果是,我将发布反汇编,但我可以看到反汇编的.obj文件与原始.asm文件没有区别。

    谢谢!

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

    感谢您提供更多信息。 我认为问题的原因不在于你发布的汇编代码。 如果是这样,我们可以在简单的测试案例中再现。 我感觉问题很可能与RTOS任务或中断有关。 这种情况需要如此长的时间,这表明了一组具体的情况,而这种情况很少发生。

    我对周围的代码很感兴趣,以查看是否有任何分支指令靠近可疑线路。 如果是这样,我们必须考虑分支的管道效应,特别是结合上下文切换。 我还对指令在内存中的实际位置感兴趣-它们位于哪个内存块中以及位于什么地址?

    请您详细介绍一下RTOS吗?

    此致,

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

    Richard

    非常感谢您的回复。

    到目前为止,我还不能重现该问题, 但我会继续尝试。

    >我对周围的代码感兴趣,以查看是否有分支指令靠近可疑行

    此代码在频率 为每100毫秒一次的计时器上执行。

    整个过程如下

    //如果
    
    (x < T &&(-1 * x)< T)
    {//
    	删除了此部分的大部分内容,因为它与
    	IF(!flag)标志= true无关
    ;}
    否则
    {
    	IF(flag)标志= false;
    	update(x);//此函数内的可疑代码
    },则此代码每隔100毫秒执行一次
    

    使用update()函数:

    void update (long x)
    {
    	float increment = dt * slope *((Float) x)/ 100.0 ;
    	if ((Increment > 1.0 )||((-increment)> 1.0 ))
    	{
    		return;//这在实践中从未发生
    	}
    
    	if (x >0)
    	{
    		estimate == increment;
    	}
    	else
    	{
    		Estimment -= increment * eff;
    	}
    
    	//调试-找出估计值有时跳至100的原因 
    IF (INCREMENT > INCREMENTMAX) INCREMENTmax = INCREMENT; IF (-INCREMENT > INCREMENTAX) INCREMENTAX = INCREMENT ;IF ( MERENT > INCREMTEAX)= Estimate;IF (Estimate > 100.0) { pjup++; ASM(" MOV32 @_pregvalue, R0H"); pjumpvalue = estimate; estimate = 100.0 ; } IF (Estimate < 0.0) { njump++; ASM(" MOV32 @_nregvalue, R0H"); njumpvalue =估计值; 估计值= 0.0 ; }

    >我还对指令在内存中的物理位置感兴趣-它们位于哪个内存块中以及位于什么地址

    我不知道如何找出说明在内存中的位置。 您能否解释一下如何操作?

    >您能否详细介绍RTOS?

    这是一个简单的RTOS,我认为它 与 µC ë/OS II相当相似,但似乎只包括核心功能。

    据我所知 ,这只能简单地描述如下。

    操作系统为每个任务维护一个TCB和一个堆栈。

    -与TINT2关联的ISR似乎(1)启用中断(EINT) ,(2) 让 任何待处理的ISR执行,(3)检查优先级高于当前任务的任务是否已就绪,如果已就绪(4)执行向高优先级任务的上下文切换, 和(5)禁用中断(DINT)。

    上下文切换 函数写入程序集,基本上将所有寄存器值和CPU堆栈指针的值推入当前堆栈,将CPU 堆栈指针更改为高优先级任务的位置,并提取以前保存的寄存器值)。

    -上下文切换通过操作系统调度功能(每个任务调用此功能以等待操作系统事件(主要是计时器事件))在中断之外发生的第二种可能性。 通过发出trap #31指令来执行某些程序集代码(实质上与上述内容相同),可以完成此上下文切换。

    我希望这能有所帮助,

    Laurent

     

     

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

    Richard

    我能够重现该问题。 如所附图表所示,'估计'变量突然跳过两次(红点),其间间隔约为9小时。 还有其他一些跳跃,但这些都是合理的-因为算法的某些部分 我在上一篇文章中没有描述(因为我认为这些部分与当前问题无关)。

    由于代码每隔100毫秒执行一次,因此第一次跳转和第二次跳转之间的浮点比较大约为300'000。 正如我在前面的文章中提到的,我从未见过"<"运算符出现过同样的问题。

    以下是围绕第一次跳跃捕获的数据:

    时间 估计数 X 标志 斜率*1e6. 跳转 pjumpvalue      pregvalue     
    2018年02月28日 20:29:28:76.029万 30.2 14.64 0 654.9 0 0 0
    2018年02月28日 20:29:29:31.606万 30.2 14.64 0 654.9 0 0 0
    2018年02月28日 20:29:30:15.962万 30.2 14.64 0 654.9 0 0 0
    2018年02月28日 20:29:30:72.451万 30.2 14.64 0 654.9 0 0 0
    2018年02月28日 20:29:31:28.42万 30.2 14.66 0 654.9 1. 30.2 30.2
    2018年02月28日 20:29:32:12.33万 99.9 14.66 0 654.9 1. 30.2 30.2
    2018年02月28日 20:29:32:68.759万 99.9 14.66 0 654.9 1. 30.2 30.2
    2018年02月28日 20:29:33:24.821万 99.9 14.64 0 654.9 1. 30.2 30.2
    2018年02月28日 20:29:33:81.168万 99.9 14.64 0 654.9 1. 30.2 30.2

    在第二次跳跃时:

    时间 估计数 X 标志 斜率*1e6. 跳转 pjumpval pregval
    2018年03月01日 05:16:28:97.44万 48. 20.94 0 612.4 119 100 100
    2018年03月01日 05:16:29:81.46万 48. 20.94 0 612.4 119 100 100
    2018年03月01日 05:16:30:37.939万 48. 20.94 0 612.4 119 100 100
    2018年03月01日 05:16:30:93.92万 48. 20.94 0 612.4 119 100 100
    2018年03月01日 05:16:31:78.266万 48. 20.94 0 612.4 119 100 100
    2018年03月01日 05:16:32:34.727万 48. 20.94 0 612.4 120 48. 48.
    2018年03月01日 05:16:32:90.346万 99.9 20.94 0 612.4 120 48. 48.
    2018年03月01日 05:16:33:47.087万 99.9 20.94 0 612.4 120 48. 48.
    2018年03月01日 05:16:34:31.093万 99.9 20.94 0 612.4 120 48. 48.

    我将很快发布.obj文件的反汇编信息。 如果您有任何需要,请告诉我。

    谢谢!

    Laurent

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

    还值得注意的是其他比较

    如果(increment > incrementmax) incrementmax = increment;
    如果(-increment > incrementmax) incrementmax =-increment;
    如果(估计>估计速率)估计速率=估计;
    如果(-estimate > estimatemax) estimatemax = estimate;
    
    

    也似乎多次给出错误的结果。 变量incumentmax用于保存变量increment的最大绝对值(即,进行两次比较以给出有效结果“incumentmax = max(incumentmax, abs(cincrement);)”),而其他变量的estimatemax也是如此。

    鉴于上述代码,原则上,这两个变量的值都不应减少。 但以下是记录的数据:

    正如您所看到的,有许多情况下值会降低,但据我所见,这应该是不可能的。
    我搜索了代码,100 % 确信这些变量在代码中的任何其他位置都不能访问,除了在调试器中读取它们,当然不能写入它们。

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

    下面是update()函数的反汇编(通过在.obj文件上运行dis2000.exe获得)

    0.0051万: _update:
    0.0051万 b2bd. MOVL *SP++,XAR100000052
    fe02 ADDB SP,200000053
    8ba9 MOVL XAR1,ACC
    0万54 761f5.4761万f MOVW dp,#0x000000055
    0000
    00000056 e2af MOV32. r0h,@0x34,UNCF
    0.0057万 0034
    00000058 bda1 MOV32. *(0:0x0f16),XAR100000059
    0f160000005
    a 7700 无操作
    0.0005万b 7700 无操作
    0.0005万c 7700 无操作
    0.0005万d 7700 无操作
    0.0005万e e689 I32 TOF32 r2h,r1h
    0.0005万f 000a
    0.006万 e2af MOV32. r1h,@0x2a,UNCF
    0万61 012A6.1012万A
    0.0062万 E700 MPYF32. R0H,R1H,R0H
    0.0063万 0008
    00000064 e802 MOVIZ r1,#0x42c800000065
    1641
    00000066 E700 MPYF32. R0H,R2H,R0H
    0.0067万 1万
    0006.8764万0 LCR 0x0亿
    0000006.9万 0000万
    6a e811 CMPF32. r0h,#0x3f800000006
    b fc000000006
    c ad14 MOVST0 NF,ZF
    0.0006万d 56c2 BF 112,GT
    0.0006万e 0070
    0000006f e6cf MOV32. r1h,r0h,UNCF
    0.007万 0001
    00000071 e6af NEGF32. R1H,R1H,UNCF
    0.0072万 0009
    00000073 e811 CMPF32. r1h,#0x3f8万
    0000.0074万 fc0.1万
    0000.0075万 ad14 MOVST0 NF,ZF
    0.0076万 56c2 BF 103,GT
    0.0077万 0067
    00000078 b2a9 MOVL ACC,XAR100000079
    56c2 BF 17,GT
    0.0007万a 0011
    0000007b 761f MOVW dp,#0x00000007
    c 0000
    0000007d e2af MOV32. r1h,@0x26,UNCF
    0.0007万e 0126
    0000007f E700 MPYF32. R1H,R0H,R1H
    0.008万 0041
    00000081 e2af MOV32. r2h,@0x2e,UNCF
    0万82 022e8.2022万e
    0.0083万 e720 SUBF32. R1H,R2H,R1H
    0.0084万 5.1万
    0008.577万0 无操作
    0.0086万 E203 MOV32. @0x2e,R1H
    0万87 012e8.7012万e
    0.0088万 56CF BF 11,UNC
    0万89 000b8.9万b
    0.0008万a: $C$L3:
    0.0008万a 761f MOVW dp,#0x00000008
    b 0000
    0000008c e2af MOV32. r1h,@0x2e,UNCF
    0.0008万d 012e
    0.0008万e e720 SUBF32. R1H,R1H,R0H
    0.0008万f 0.9万
    0000.009万 7700 无操作
    0.0091万 E203 MOV32. @0x2e,R1H
    0万92 012e9.2012万e
    0.0093万: $C$L4:
    0.0093万 e2af MOV32. r1h,@0x1a,UNCF
    0万94 011a9.4011万a
    0.0095万 e694 CMPF32. R0H,R1H
    0.0096万 0008
    00000097 ad14 MOVST0 NF,ZF
    0.0098万 56c5 BF 4,Lq
    0.0099万 0004
    0000009a E203 MOV32. @0x1a,R0H
    0.0009万b 001A
    0.0009万c: $C$L5:
    0.0009万c e6af NEGF32. R0H,R0H,UNCF
    0.0009万d 0000
    0000009e e2af MOV32. r1h,@0x1a,UNCF
    0.0009万f 011a
    0万a0 e694 CMPF32. R0H,R1H
    0万a1 000810008
    000000a2 ad14 MOVST0 NF,ZF
    0万a3 56c5 BF 4,Lq
    0万a4 000440004
    000000a5 E203 MOV32. @0x1a,R0H
    0万a6 001A6001A
    0000a7: $C$L6:
    0万a7 e2af MOV32. r0h,@0x28,UNCF
    0万a8 002880028
    000000a9 e2af MOV32. r1h,@0x2e,UNCF
    0万aa 012e
    0万ab e694 CMPF32. r1h,r0h
    0万ac 0.01亿
    ad ad14 MOVST0 NF,ZF
    0万ae 56c5 BF 4,leq
    0万af 0.04亿
    000000b0062e MOVL acc,@0x2e
    0万b1 1e28 MOVL @0x28,符合
    0000b2: $C$L7:
    0万b2 e2af MOV32. r0h,@0x2e,UNCF
    0万b3 002E3002E
    0万b4 e6af NEGF32. R0H,R0H,UNCF
    0万b5 000050000
    000000b6 e2af MOV32. r1h,@0x28,UNCF
    0万b7 012870128
    000000b8 e694 CMPF32. R0H,R1H
    0万b9 000890008
    000000ba ad14 MOVST0 nf,zf
    0万bb 56c5 BF 4,Laq
    0万bc 0.04亿
    bd E203 MOV32. @0x28,R0H
    0万be 0028
    0000bf: $C$L8:
    0万bf e2af MOV32. r0h,@0x2e,UNCF
    0万c0 002E0002E
    0万c1 e812 CMPF32. r0h,#0x42c800万
    000000c21640
    000000c3 ad14 MOVST0 NF,ZF
    0万c4 56c2 BF 16,gt
    0万c5 001050010
    000000c6 e5a0 CMPF32. r0h,#rcd0000c7 0.0
    ad14 MOVST0 NF,ZF
    0万c8 56c3 BF 21,GEQ
    0万c9 001590015
    000000ca 0a07 包括 @0x700万
    cb E203 MOV32. @0x18,R0H
    0万cc 0.18亿
    cd 062e MOVL acc,@0x2e
    0万ce 1e16 MOVL @0x16,ACC
    0万CF e590 零 r0万
    d0 E203 MOV32. @0x2e,R0H
    0万d1 002E1002E
    0万d2 56CF BF 11,UNC
    0万d3 000b3000b
    0000d4: $C$L9:
    0万d4 0a09 包括 @0x900万
    d5 E203 MOV32. @0x1c,r0H
    0万d6 001C6001C
    0万d7 062e7062e MOVL acc,@0x2e
    0万d8 1e14 MOVL @0x14,ACC
    0万d9 e802 MOVIZ r0,#0x42c800万
    da 16.4亿
    db E203 MOV32. @0x2e,R0H
    0万dc 002E
    0000dd: $C$L10:
    0万dd fe82 副B SP,#200万
    de 8bbe MOVL XAR1,*--SP
    0万df ff69 SPM #0万
    000000e00006 LRETR 
    
    

    我相信可疑的分支机构位于
    0.0098万  56c5      BF          4,Leq

    0万a3  56c5      BF          4,Leq

    0万ae  56c5      BF          4,Leq

    0万bb  56c5      BF          4,Leq

    0万c4  56c2      BF          16,GT

    指令似乎位于".text"部分(分解的.obj文件以.sect ".text"开头),该部分位于内存页0,从地址0.302万f4开始,长度为0.0011万bcb。
    obj文件本身从内存地址0.0311万de2开始,长度为0.028万。

    如果我还有什么可以提供的,请告诉我。

    谢谢!

    Laurent

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

    Laurent,

    感谢您提供附加信息。  在某些设备上,有效内存的末尾附近存在分支指令问题。  我目前正在出差,所以不能将所有信息都提供给我,但从上面的地址来看,这似乎不是问题。 感谢您的拆卸屏幕截图。  

    事实是,这些异常似乎很少与我自己几年前的操作系统错误经验相符,在这种情况下,关键注册表没有受到上下文保存的保护。 正如我在较早前的一篇文章中所说,我相信这是最可能导致问题的原因。  我对此犹豫不决,但您是否认为值得尝试TI RTOS来看看您是否可以重现该问题?

    另一件我想检查的事情是堆栈。  您是否对堆栈进行任何监控以确保没有过流?  例如,您是否可以用已知数据填充堆栈内存并稍后检查“高水位标记”?  有一个关于堆栈过流保护(我认为是spra820)的应用说明也可能有帮助。

    我将出差到下周,但我将随时监控此论坛。 感谢您的耐心等待。

    此致,

    Richard

     

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

    Richard

    非常感谢您的快速反馈。 我不确定我是否能够试用TI RTOS,因为这可能涉及到迁移到新操作系统的大量工作。 不过,我会看看这些文件,看看是否可行。

    关于操作系统错误的可能性,我想知道是否有办法更精确地测试此错误。 我保存了R0H寄存器的值,以检查指令“CMPF32   R0H,#0x42c8”是否在R0H寄存器中使用损坏的值执行-从数据来看,情况似乎不是这样。

    另一种可能是,BF指令使用的st0寄存器在ZF和NF标志移动到它之后被损坏。 这将要求在C7和C8指令之间发生准确的上下文变化:

    0万c7 ad14   MOVST0   NF,ZF

    0万c8 56c3   BF      21,GEQ

    我不确定这是否可行,但是否有办法将st0的值以及可能还有STF寄存器的值保存到变量中?

    以下是在操作系统中将寄存器推入堆栈的汇编宏的代码:

    REGSAVE 宏
    按 DP:ST1 ;保存SPA标记
    按 AR1H:AR0H
    按 XAR2
    按 XAR3.
    按 XAR4.
    按 XAR5.
    按 XAR6.
    按 XAR7
    按 xt
    按 RPC
    
    如果 TMS320C2800_FPU32
    按 经常预算
    第32款 *SP++,R0H
    第32款 *SP++,R1H
    第32款 *SP++,R2H
    第32款 *SP++,R3H
    第32款 *SP++,R4H
    第32款 *SP++,R5H
    第32款 *SP++,R6H
    第32款 *SP++,R7H
    第32款 *SP++,STF
    endif 

    st0寄存器似乎未保存。 这是否意味着在C7指令之后立即发生的上下文切换可能会在代码在 指令C8处恢复之前修改st0的内容? 如果是,根据需要添加push T:st0 / POP T:st0是否足以解决问题?

    关于堆栈,我已经对另一个问题的堆栈使用情况进行了相当广泛的监视。 因为当时我没有发现任何问题,但为了安全起见,我决定将纸叠的大小增加一倍,所以我非常怀疑纸叠溢出的可能性。

    此致,

    Laurent

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

    我从DSP文档中发现,当执行中断时,st0寄存器会自动保存:

    3.准备中断服务例程并保存寄存器值。 在中执行的主要任务
    此阶段为:
    •完成当前指令的执行,并从管道中清除具有的任何指令
    未达到解码2阶段。
    •通过将以下寄存器保存到,自动保存大多数当前程序上下文
    堆栈:ST0,T,AL,AH,PL, PH,AR0,AR1,DP,ST1, DBGSTAT,PC和IER。
    •获取中断向量并将其加载到程序计数器(PC)中。 对于带有PIE的设备
    模块中,提取的矢量将取决于PIE启用和标志寄存器的设置。

    因此,在上述"REGSAVE"例程中不保存st0似乎是正确的。

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

    我现在可以 在CCS中以调试模式运行程序。

    我测试了一个版本,在这个版本中我 没有启动RTOS ,而只是在main()函数内循环运行了错误的代码。 我 在这种情况下没有遇到任何问题,因此问题可能出在RTOS上,正如您所建议的那样。

    我现在正在运行一个带有RTOS的版本,但10个任务中只有两个正在运行-我应该能够在下星期一之前查看此问题是否也出现在这种情况下。 我设置了一个断点,在“IF (Estimeable > 100.0)”之后立即停止执行,因此如果程序在该处停止,我应该能够在该特定点看到寄存器和内存的内容。

    如果您对具体的查找内容有任何建议,我很高兴听到这些建议。

    谢谢!

    Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Laurent,
    感谢您执行此操作并进行其他测试。 我认为这是值得的。
    我必须将此主题传递给同事,但我们将跟进此主题,因此请在回复时提供任何额外的发现。 非常感谢。
    此致,
    Richard
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Richard

    非常感谢您的支持。  

    到目前为止,我还不能在调试模式下重现该问题。 该程序是多个多氯联苯系统的一部分,因此很难再现完全相同的情况。 我将继续尝试,并使用任何相关结果更新帖子。  

    此致,

    Laurent

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

    Laurent,

    欢迎你,我希望我能做得更多。  

    感谢您进行测试,我完全理解重现该问题的困难。  我的感觉是您可能不会看到TI-RTOS的问题,在这种情况下,我强烈怀疑上下文保存不完整是根本原因。

    正如我所提到的,我必须将此主题交给同事,因为我有一个个人问题需要处理,但请将您掌握的任何其他信息发回,这里的人员将会帮助您。

    此致,

    Richard

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

    您好,  

    我能够在调试器中重现该问题。  

    代码分支从311d7e到311d8e。

    在指令311d7b中,代码将R0H寄存器的值与直接值0x42c8 = 100.0 进行比较。 仅当R0H > 100.0 时,它才应分支到C$L9。

    但是,R0H寄存器的值为22.44.5724万 :

    文档说明,如果条件“Z=0和N=0”为真,“GT”指令将分支。 st0寄存器中Z和F标记的值从STF的ZF和NF 311d7d "MOVST0 NF,ZF"复制。  
    从上图中可以看出,在STF寄存器中,两个标志都是0,在st0寄存器中

    两个标志也是0。  
    因此,分支 C$L9的代码是要做的最直接的事情。

    据我所见,这就留下了以下可能性:

    1. 说明  CMPF32    R0H,#0x42c8失败,即未向ZF和NF分配正确的值

    2. ZF和/或NF的值在两个指令之间变化

    311d7b:E812.164万 CMPF32 R0H,#0x42c8
    311d7d:AD14 MOVST0 NF,ZF

    导致Z,F标志被分配到ZF和NF的损坏值

    3. 两个指令之间的st0和stf值均已损坏

    311d7d:AD14 MOVST0 NF,ZF
    311d7e:56C2.001万 BF C$L9,GT

    (极不可能)

    最可能的是2号。


    为了实现2号指令,似乎有必要在指令311d7b和311d7d之间进行操作系统上下文更改。

    =>是否有可能? 我不了解管道的细节。 我们的RTOS可以触发与TINT2关联的ISR的上下文更改。  

    =>是否有其他解释?  

    =>在该计划停止时,是否有其他值得调查的地方? 如果有人有任何建议,我会暂停一段时间。  

    提前感谢!

    Laurent

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

    我检查了所有中断,所有这些中断都保存并恢复STF,至少是R0H -鉴于这一点,我看不出任何中断如何修改STF标志。  
    我将尝试在故障部件周围禁用中断的情况下再次运行代码,以查看问题是否确实是由中断引起的。

    顺便说一下,FPU寄存器的保存似乎是由编译器自动生成的(在中断的c代码中没有显式完成),但我不确定原因是什么。

    例如,一个非常简单的中断编译为(这是唯一一个不保存R0x寄存器的中断,但由于它不修改它们,因此我看不出有问题):

    asp
    按 经常预算
    MOV32. *SP++,STF
    SETFLG RNDF32=1,RNDF64=1
    CLRC PAGE0,OVM
    CLRC AMODE
    MOVW dp,#_PieCtrlRegs+1
    MOVB @ CtrlRegs+1,#1,UNC
    MOV32. STF,*--SP
    POP 经常预算
    NASP
    IRET 

    我不知道为什么代码将STF推入堆栈,然后恢复它,即使它不使用它。 对此有没有解释?  

    谢谢!

    Laurent

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

    我已经取得了一些进展-现在似乎很清楚,STF和st0寄存器正被其中一个中断更改。  

    我修改了代码,在CMPF32操作后立即将ZF和NF标志复制到变量中,禁用了中断。
    然后,我重新启用中断并等待一段时间以允许中断启动,然后根据ZF和NF的当前值进行分支。  

    代码如下所示:

    ;禁用中断
    SETC	INTM
    
    ;将变量估计值与100.0 进行比较,并将结果存储在ZF/NF标记中
    MOV32. R0H,@_估计
    CMPF32 R0H,#1.7096万
    
    ;将ZF/NF标志复制到变量STFprev
    SPM #0
    LCR #_getSTF
    MOVW dp,#_STFPrev
    MOV @_STFprev,AL
    
    ;重新启用中断
    CLRC	INTM
    
    ;将ZF/NF标志复制到st0寄存器,并等待一些周期以增加中断的可能性
    MOVST0 ZF,NF
    NOP
    ;许多其他NOP
    NOP
    
    ;如果Z=0且N=0,则为Branch
    BF $BRANC1美元,GT
    
    ;一些代码
    为BF $BRANC2美元,UNC
    
    $BRANC1美元:
    ESTOP0 ;断点
    包括 @ pjump
    MOV32 @_pregvalue,R0H
    MOVL ACC,@预估
    MOVL @ pjumpvalue,acc
    MOVIZ R0H,#1.7096万
    MOV32. @_estimate,R0H
    
    $BRANC2美元:
    ;一些代码并返回
    
    

    在MOVST0 ZF之后添加一系列NOP指令,NF指令具有预期的效果,即增加了程序分支到1美元分支的可能性:它现在始终在几秒钟后停止,而不是几小时前没有NOP。  

    在停止时,变量STFPrev被视为:

    STFprev unsigned int 0万10100100 (1010.01万 (二进制) 0x0000BFCA@Data

    这意味着Z=0和N=1,如果(Estimate > 100.0)为FALSE,则为预期值。 但是,st0/STF寄存器中的Z/ZF和N/NF标志都是0。  

    我还添加了计数器以找出执行了哪些ISR,并发现在CLRC INTM指令和ESTOP0指令之间累计执行了4个ISR 10次。  

    因此,我认为我应该能够逐步解决这个问题。

    编辑:函数getSTF()的代码为

    .sect	".text"
    {\f2 .asmfunc}
    getSTF (_getSTF):
    MOVST0 ZF,NF
    按st0
    POP 铝
    LRETR
    {\f2 .endasmfunc} 

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

    我认为我找到了问题的原因:当发生上下文切换时,RTOS将按以下方式恢复FPU寄存器

    第32款 STF,*--SP
    第32款 R7H,*--SP
    第32款 R6H,*--SP
    第32款 R5H,*--SP
    第32款 R4H,*--SP
    第32款 R3H,*--SP
    第32款 R2H,*--SP
    第32款 R1H,*--SP
    第32款 R0H,*--SP 

    这将被翻译为:

    3135a0:E2.8万BE MOV32 STF,*—SP
    3135a2:E2AF07BE MOV32 R7H,*--SP,UNCF
    3135a4:E2AF06BE MOV32 R6H,*--SP,UNCF
    3135a6:E2AF05BE MOV32 R5H,*--SP,UNCF
    3135a8:E2AF04BE MOV32 R4H,*--SP,UNCF
    3135aa:E2AF03BE MOV32 R3H,*--SP,UNCF
    3135交流:E2AF02BE MOV32 R2H,*--SP,UNCF
    3135 ae:E2AF01BE MOV32 R1H,*--SP,UNCF
    3135b0:E2AF00BE MOV32 R0H,*--SP,UNCF 

    现在,根据文档, MOV32 Rah,mem32,UNCF指令 似乎修改了STF寄存器的一些标志,包括ZF和NF。

    具体而言,文件规定了UNCF条件:

    (2)如果未指定CNDF字段,则这是默认操作。 这种情况将允许修改ZF,NF,ZI和NI标志
    执行条件操作时。 所有其他条件都不会修改这些标志。

    我并不十分清楚这项工作的意义,但我曾观察到,当我进行其中一项MOV32操作时,STF注册表正被修改。  

    这说明了为什么如果上下文切换直接发生在CMPF32指令之后,例如,当上下文稍后恢复时,STF寄存器的状态可能会发生更改。 如果遵循分支指令,则可能会产生意外结果。  

    我认为一个非常简单的解决方案是首先存储STF寄存器,然后最后恢复它,或者在.asm源文件中指定"UNC"条件。 这是否可行? 哪一项应该是首选的?

    谢谢!  

    Laurent

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

    感谢您的更新。 您得出的结论对我来说很有意义。 出于好奇,我检查了TI-RTOS上下文保存/恢复代码,可以确认他们先保存STF,最后再恢复。

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

    您好,Whitney,

    感谢您的回复。

    我在调试器中检查了逐步操作,结果就是这样:“MOV32       R7H,*--SP, UNCF” 指令覆盖恢复的STF寄存器。 只需将"UNC"条件显式添加到源中的所有RAH移动。asm代码保留STF寄存器并解决问题。

    Richard,您最初的感受是正确的!

    再次感谢你们的支持。

    我认为这可以解决问题。

    Laurent