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.

[参考译文] MSP430FR2355:代码中有关 volatile uint 的错误??

Guru**** 2524460 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/967050/msp430fr2355-bug-in-code-with-respect-to-volatile-uint

器件型号:MSP430FR2355

我有两个对讲机每半秒来回发送数据。  周期性地是一个错误、它会停止客户端上运行的代码。  每次它停止时、调试器都会报告一个较大的整数。  

易失性 uint joinSwitchFlag = 0; 

该 uint 只会被分配为1或0。  它可以分配两个位置。  第一个是 ISR:

#pragma vector = TIMER3_B0_vector
_中断 void 去抖(void)
{
TB3CCTL0 &=~CCIE;
if (joinSwitchFlag = 1)
joinSwitchFlag = 0;
其他
joinSwitchFlag = 1;
flags.swlockout = F;
P1IE |= BIT2;
LPM3_EXIT;
}

第二个位置在代码内,它在一个加入过程后被分配为0。。 对讲机的工作如下...对讲机在加入信道上通信一次、成功通信/接受后、对讲机将更改其 ID 并移动到数据信道。  这些是 MSP 中当前的硬编码数字、并根据需要加载到无线电中、以便在每个通道上进行通信。  一旦进入数据信道、对讲机不应再次移动到加入。  代码必须有错误、因为客户端似乎总是在某个点移动到联接。  我的问题是、该变量如何可能是0或1以外的值?  我缺少什么或调试器只是拧紧了???

谢谢

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

    如何声明"uint"? 具体而言、它是否<=16位、即原子?

    在 main()中设置 joinSwitchFlag 使用了什么序列?

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

    代码执行一组初始化、然后加载无线电寄存器并从无线电中捕获当前通道编号..... 客户端与主机之间的关系由 P2.1确定(即主机与!host)

    以下代码预测 while (1) LPM3循环.....

    if (!(host))
    {
    strcpy (发送、r_enable_groupID);
    WakeRadio(T);
    RadioMachine (strncat (Send、"3422"、4));//硬编码组 ID
    memcpy (radioID、(const void *)&RXData[9]、sizeof (radioID));
    P1OUT &=~BIT0;
    }
    if (主机)
    WakeRadio(F);
    
    /*
    *客户机:不应以联接模式出现
    * host:可以加入任一联接
    *或数据模式、具体取决于读取的对讲机 ID
    *
    if (!strncmp ((const char *) radioID、default_Info、sizeof (default_Info)))
    {
    joinSwitchFlag = 1;
    flags.clientJoinFlag = T;
    }
    其他
    joinSwitchFlag = 0;
    

    LPM3之后有一个条件标志,最初为0,如果 P1.2上有击键,则该标志会被转至...即 swlock... 这适用于主机和客户端。  我的方案是在上电后,通过将 P1.2推入加入通道(写入无线电)将主机加入到客户端 然后将 P1.2推送到客户端...一些握手消息以及数据通道 ID 将被传输到主机,然后主机将此新通道权限赋予其无线电,然后切换并开始数据传输... 客户端将保持联接状态、直到再次推送 p1.2、此时它将其无线电更改为数据信道并开始通信数据。  这种方法可以使用一段时间,但当它停止时,它总是显示在客户端端,joinSwitchFlag 是一个大整数....我已经设置了断点,但我肯定永远不会在 them...no停止....

    以下是 LPM3之后的代码:

    如果(!flags.swlockout)
    {
    memset ((char*) RXData、'\0'、sizeof (RXData));
    flags.swlockout = T;//在 P1.2开关上记录的上升沿
    WakeRadio(T);
    RadioMachine (r_get_groupID);
    strcpy (发送、r_enable_groupID);
    // WakeRadio(T);
    IF (joinSwitchFlag)
    {
    P1OUT |= BIT0;
    RadioMachine (strncat (Send、default_Info、sizeof (default_Info)));
    }
    else //数据
    {
    P1OUT &=~BIT0;
    RadioMachine (strncat (Send、permany_Info、4));
    }
    memcpy (radioID、(const void *)&RXData[9]、sizeof (radioID));
    UCA1IFG &= UCRXIFG;
    IF (主机)
    WakeRadio(F);
    }
    

    定时器 ISR (上面的)是一个100ms 到 P1.2的去抖。  在代码的客户端部分(LPM3之后)中、如果(flags.joinSwitchFlag)查找 ID 正确的消息...如果它能找到所有消息并且它确认、 等等...如果这不是说对讲机 ID 与加入信道以外的内容匹配、则代码会发出以下信息:

    WakeRadio(T);
    RadioMachine (r_get_groupID);
    WakeRadio(F);
    memcpy (radioID、(const void *)&RXData[9]、sizeof (radioID));
    if (!memcmp (radioID、permanental_Info、sizeof (radioID)))(如果(!memcmp (radioID、permanental_Info、sizeof (
    P1IFG |= BIT2;
    其他
    flags.swlockout = F;
    

    基本来说...如果联接发生在联接信道以外的其他地方、则代码会到达此处 (即数据通道)...如果 ID 与 MSP 数据 ID 匹配,则会出现一个错误,我们在此发出 P1.2的“软”按钮,该按钮应将我们翻转回节点所在的数据通道...如果不匹配,则 swlockout 允许执行上述代码 加入渠道,因为 ID 是其他的

    很抱歉,所有信息都是... 我认为这可能有助于理解我当时真正想知道的是,这就是为什么加入的 SwitchFlag 成为这个怪兽整数,当它从未设置为1或0以外的任何东西时..... 希望你能读出重读的内容…

    谢谢

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

    您看到哪些值出现在 joinSwitchFlag 中?

    我现在要做的两件事是:

    1) 1)将这些值粘贴到计算器中并以十六进制显示、以查看它们是否看起来像 ASCII 或其他一些可识别的模式。

    2)检查.map 文件("按地址排序"部分)以查看变量前面紧跟的变量。

    这可能表示缓冲区溢出、只需几分钟。

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

    如果您怀疑代码错误、则应查看代码。 我一直使用"msp430-elf-objdump -S elf-filename|less"。

    这样做时、您会发现使用位字段的注释优点(如果有)以牺牲代码效率为代价。 编译器倾向于移动和屏蔽字段:

    4540: 5C 42 16 1c MOV.b &0x1c16、R12 ;0x1c16
    4544: 12 C3 CLRC
    4546: 0°C 10. RRC R12. ;
    4548: 7C f0 03 00 和.b #3、 R12. ;
    454c: 5C 93. CMP.b #1、 R12. ;R3 As=01
    

    我还可以看到、当它设置该2位字段时、它正在改变3位、这有点神秘。

    4558: 5C 42 16 1c MOV.b &0x1c16、R12 ;0x1c16
    455c: 7C f0 f9 ff 和.b #-7、R12 ;#0xFF9.
    4560: 6C D3 BIS.b #2、 R12. ;R3 As=10
    4562: C2 4c 16 1c MOV.b R12,&0x1c16;
    

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

    启动并运行几分钟后,代码中的停止将产生0,这正是我们所期望的...这就是连接的发生,我们生活在数据通道中...当它停止工作(LED 停止闪烁)时,我停止代码并看到像27568这样的数字...太大了

    明天晚上我将查看您的建议...在我识别到消息有效后,ASCII 模式(接收数据)总是被清除...发送数组似乎总是显示正确的模式...

    我每1/3秒只发送一次数据...只有8-9个字节...我已经将 TX 周期延长到1秒,但仍然有同样的问题。

    我在现场代码中有:

    中频(UCA1STATW 和 UCRXERR)
    垃圾= UCA1RXBUF;
    

    这发生在 incomingMssg 标志被置位后(这意味着我们收到了一个以字符'\n'结尾的数据流。。。之后、消息的 CRC 将与发送来验证的 CRC 进行比较...

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

    在 CCS GUI 中该设置的哪个位置可以看到该设置?  我会感兴趣的… 是的、我看到了一个仅将0和1视为分配以某种方式创建3的2位字段??  我已经把这个从位字段移出了,把它定义为一个无符号整型,它是0或1,但很低,看到我仍然看到问题....我已经反复过代码,似乎不能捕捉到这个奇怪的....

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

    比原始速度更重要的可能是、这甚至不接近于原子速度。 人们可以用类似于"a |= 3;"的方式来挥手、因为它(可能)会变成 BIS 指令、但这里的读取/修改/写入窗口至少有10个时钟长。

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

    不太理解"原子"的含义(我是一个硬件人员)...但在我看来、它是一个简单的开/关变量、这就是...我确实将它声明为易失性、作为对编译器的建议、bcz 它正在 ISR 内进行更改

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

    您可以使用"Build Options->Build->Compiler->Advanced->Assembler -> Generate Listing File"在每个构建上生成一个列表(.lst)文件。 我怀疑它不使用 objdump、但格式类似。

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

    这是不是...不确定我看的是什么???? 或用于???

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

    我指的是 David 提出的位域内容(更适用于另一个线程)。  

    一般而言、"原子"只是指"无法部分捕捉"。 在软件中、这通常意味着"不能中断"。 如果 main 位于非原子更新序列的中间、并且 ISR 更新正在更新的项目、则会出现混乱。

    这就是为什么我问"uint"--如果它是32位类型,那么它需要两条指令,因此可以被中断。 16位常量分配通常是原子的;"易失性"仍然有用、因为它会强制写入存储器。 (这就是我开始怀疑缓冲区溢出的原因。)

    我不是自愿使用位字段(我在30年前做了简短的口授)、但我认为恒定分配会变成 BIS 或其他原子分配。 David 的观察结果改变了所有这些。

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

    哎呀。 我意识到我在这些 and.b 指令中,在某种程度上错过了7前面的“-”。 这意味着代码将按应有的方式处理2位宽字段。 我应该仔细看一下右侧提供的十六进制表示法。

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

    [quote user="Steve Wenner">我的问题是、该变量如何可以不是0或1??可以设置"监视点与数据"来捕获除零或一个值以外的任何值写入、 如果存在写入其他值的软件错误、则尝试进行陷阱。 为此、请执行以下操作:

    1.在 Breakpoints 视图中、右键点击并选择 Breakpoint (Code Composer Studio)-> Watchpoint with Data。

    2.将对话框填充为:

    3、以上设置了写入值2时的观察点。 由于我们希望捕获除零或正在写入的值以外的值、因此在 Breakpoints 视图中右键单击观察点、然后选择 Breakpoint Properties。 对于存储器数据总线上的触发器1、将运算符从"="更改为">=":

    如果软件尝试向 join_flag 变量写入零值或一个值以外的值、这将停止程序。

    与 Code Composer Studio 版本6一起使用增强型仿真模块(EEM)进行高级调试 时、可获得与其它 EEM 特性相关的更多信息。

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

    这已经成为我新的最爱的朋友了……谢谢给我展示 this....no,我还没有发现这个错误,而且已经切换到另一个现在有类似 issues....running 的标志了……将继续发布  

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

    切斯特…

    我是在你的 dwg 展示的一个标志是1或0… joinSwitchFlag……我发现,虽然调试器从未停止过,但代码确实通过打开红色 LED 而中断, 当电路板上的东西停止工作时、通过触发我的逻辑分析仪来查看、虽然发送器仍在发送数据包、但接收器(客户端)已进入其他一些领域。  然后我暂停了调试器(记得我把它设置为在>=2处停止),正如您看到的那样,标志显示的是>15000……我在这里做了什么错?  在我看来,调试器从未停止标志...查看所包含的图片...然后我点击调试器上的播放按钮,射频通信再次启动(我没有重置任何内容)(通过逻辑分析仪证明) 闪烁的绿色 LED……然后我再次暂停、标志现在= 0????? 非常混乱  

    顶部显示断点

    底部显示 joinSwitchFlag 15191e2e.ti.com/.../4762.Mem.docx

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

    我认为我的代码中有一些错误会影响您的'buffer overflow' comment....using strcpy 和 memcpy (这是一个 prolic 9x)... strcpy 看起来不错...也就是说我正在复制字符串(始终在""内) 但是 memcpy 看起来我有目标的实例<大小的源...我怀疑这是一个真正的问题?!

    这是 memcpy 的问题

    memcpy (radioID、(const void *) RXData、sizeof (radioID));
    

    radioID 是4深阵列

    RXData 为32深

    请注意、我确实使用了小数组的大小

    我发现自己在代码中以这种方式执行此操作大约需要6倍

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

    [引用 user="Steve Wenner">在我看来、调试器从未捕捉到标志关闭您是否在程序中使用了 DMA?

    我认为具有建议的数据设置的观察点将用于 CPU 的陷阱写入。 还有其他用于陷阱 DMA 访问的选项。

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

    [引用 user="Steve Wenner">请注意、我确实使用了小数组的大小这不是问题、因为不会注销目标数组的末尾。

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

    我不使用 DMA....

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

    memcpy 是安全的。 通常的错误是使用源的大小、而不是目标的大小、但您在这里做的是正确的。

    我的计算器显示15191=0x3B57、这是 ASCII ";Q"。 这是否看起来很熟悉? 是的、这是黑暗中的一个镜头、但有时这里有线索。

    只从源进行内插、我怀疑前面的变量是"pResult"、作为"uint *"不是溢出的明显候选项。  

    编译器是否会向您提供任何警告?

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

    您的缓冲区溢出注释一直很有意义,昨晚我在查看 memcpy 和 strcpy 时,我决定查看 我的无线电 ISR ...在这里,我意识到我的接收数据缓冲区有时会被垃圾传入,我没有条件检查这里是否溢出。  我只检查了一个终止字符..... 长故事简短介绍是我把这项检查放在 ISR 中,并在一整晚成功运行代码...... 缓冲区溢出是个问题!!

    感谢本论坛上的每个人提供的帮助和见解...