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.

[参考译文] MSP430F149:mspgcc 优化了易失性变量访问

Guru**** 2524550 points
Other Parts Discussed in Thread: MSP430F149

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/981774/msp430f149-mspgcc-optimizes-out-volatile-variable-accesses

器件型号:MSP430F149

您好!
我正在为定制版本的 MSP430F149芯片开发程序、并面临以下问题:

有映射到0x104、0x106地址的外设器件(读取 FIFO)。 GCC 仅编译对其的首次访问、并优化所有其他访问。

我接下来尝试了:

[版本_0]

func.h:

uint8_t read_fifo (uint16_t * d_l、uint16_t * d_h);


func.c:

extern volatile uint16_t RFIFO_L;
extern volatile uint16_t RFIFO_H;

uint8_t read_fifo (uint16_t * d_l、uint16_t * d_h){
*d_l = RFIFO_L;
*d_h = RFIFO_H;
返回0;
} 


main.c:

#include "func.h"

int main (){
//停止看门狗
WDTCTL = WDTPW + WDTHOLD;

uint16_t d[2];
while (1){
read_fifo (d、d + 1);

if (d[0]= some 值0 && d[1]= anote_value0){
//进行一些处理
}
否则、如果(d[0]= some 值1 && d[1]= anote_value1){
//另一个处理处理
}
}


/some/path/ti/msp430-gcc/include/msp430f149_symbols.ld:

//添加了两行
提供(RFIFO_L       = 0x0104);
提供(RFIFO_H       = 0x0106);

结果:只有 FIFO 的首次读取访问、它返回的值为预期值零、但没有任何其他访问(我希望它在关闭电源之前将读取 FIFO)。

[版本_1 ]

从 func.c 中删除 extern volatile 声明并将两行添加到/some/path/ti/msp430-gcc/include/msp430f149.h:

SFR_w (RFIFO_L);
SFR_w (RFIFO_H);


结果:相同

[版本_2 ]

将/some/path/ti/msp430-gcc/include/msp430f149.ld 中的 SFR 条目长度修改为0x110地址:

SFR             :origin = 0x0000、length = 0x0110

结果:相同

[版本_3]

恢复 MSP430F149_symbols.ld、MSP430F149.ld 和 MSP430F149.h、在 func.c 中添加了定义而不是 extern volatile:

#define RFIFO_L (*(volatile uint16_t *)(0x0104)
)#define RFIFO_H (*(volatile uint16_t *)(0x0106))


结果:相同

我犯了什么错误、以及如何告知 MSPGCC 未优化对这些易失性变量的访问?

编译命令:
/some/path/ti/msp430-gcc/bin/msp430-elf-gcc -i/some/path/ti/msp430-gcc/include -mmcu=MSP430F149 -Wall -O0 -msmall -flto -fwrapv -mTina-printf -I./-L/some/path/ti/msp430-gwl/include -hex、-cc、test.map、-gc-sections、-mce-fice-gc、-gc、-gwl=m.c、-gwl.c、-g.c、-gwl.c、-g.c、-gwl.c、-g.c、-gv.

GCC 版本输出:
GCC 版本9.2.0 (Mitto Systems Limited - MSP430-gcc 9.2.0.50)
配置为:./../gcc/configure --target=MSP430-elf --enable-languages=c、c++--disable-NLS --enable-initfini-array --build=x86_64-PC-Linux-0.50 --host=x86_64-PC-Linux-GNU --enable-target-optspace --enable-newlib-nanime-icht-mctran-gichtsystems=msp4c.2-msp4c-限制格式化的 msp430-msp4c.2
Thread 模型:单个

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

    我认为这里的问题不是声明为易失性的位置、而是通过函数进行访问、这会导致该易失性规范丢失。 即使在中间数组 d[]的声明中添加了"volatile"、它也不会起作用。

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

    嗯、好的、我将具有这些 volatile vars 的代码移动到主函数中、直到我将优化标志从-O0切换到-OS 为止、这一切都正常。 使用相同的-OS 行为-首次访问正常、所有后续操作均已优化。

    此外、我认为仅在 main 函数中使用全局易失性变量的限制 是怪异的、看起来像是 GCC 错误。

    [引用用户="David Schultz36"]

    我认为这里的问题不是声明为易失性的位置、而是通过函数进行访问、这会导致该易失性规范丢失。 即使在中间数组 d[]的声明中添加了"volatile"、它也不会起作用。

    [/报价]

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

    汇编代码(--save-temps)看起来是什么样子? 我在 v7.3.2.154 (Mitto)中看不到这种行为、至少根据汇编代码判断。 (我没有 F149。)

    由于易失性、READ_FIFO()需要从 R_FIFO_x 中读取、但需要写入* d_X、因为它们是指针(在大多数情况下、优化器必须假定通过指针的赋值存储在"任何地方和任何地方")。 或者 main 是否根本没有调用 read_fifo()?

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

    非常感谢您提供了-save-temps 选项、这是我真正需要的选项。 在检查汇编器代码后、我发现这个问题不在易失性访问中。 它是延迟函数:

    内联空 delayNtick (uint32_t ntick){
    volatile unsigned long i = ntick;
    while (i-);
    } 

    已编译为:

    ;开始序言
    Sub.W #4、R1
    ;序言结束
    MOV.W #0、@R1
    MOV.W #0、2 (R1)
    .L2:
    MOV.W @R1、R12
    MOV.W 2 (R1)、R13
    MOV.W R12、R14
    添加 #1,R14;cy
    MOV.W R13、R15
    ADDC #1、R15
    MOV.W R14、@R1
    MOV.W R15、2 (R1)
    BIS.W R13、R12
    CMP.W #0、R12{JNE .L2
    ;结束开始
    ADD.W #4、R1
    可重置
    

    因此、调用 delayNtick (0)以实现最小延迟将导致最大延迟。 将延迟函数重写到 while (i)--i;解决了问题。

    [引用用户="Bruce McKenney47378"]

    汇编代码(--save-temps)看起来是什么样子? 我在 v7.3.2.154 (Mitto)中看不到这种行为、至少根据汇编代码判断。 (我没有 F149。)

    由于易失性、READ_FIFO()需要从 R_FIFO_x 中读取、但需要写入* d_X、因为它们是指针(在大多数情况下、优化器必须假定通过指针的赋值存储在"任何地方和任何地方")。 或者 main 是否根本没有调用 read_fifo()?

    [/报价]