我在 Linux 环境(Ubuntu,msp430-gcc 4.6.3)中使用 TI Launchpad (msp430g2211)。
我有一个奇怪的问题:当我尝试分配超过固定数量的内存时,微控制器会在启动时停止。
更准确地说:我在 main() 中有一个包含 25 个元素的数组,创建如下:
color img0[25] = {
off, cyan, cyan, cyan, off,
cyan, red, violet, orange, cyan,
cyan, red, violet, orange, cyan,
off, cyan, cyan, cyan, off,
off, off, off, off, off,
};
(为了完整性:
typedef struct color {
uint8_t r;
uint8_t g;
uint8_t b;
} color;
static color red = {25, 0, 0}; ...
)
一切正常,但如果我尝试使用 30 个(或任何大于 25 个)元素而不是 25 个元素,那么 uC 似乎已经死了。(编译和编程过程中没有错误)
在 TI Wiki 中,我发现了这个,这似乎符合我的经历:
C 启动代码期间 WDT 触发
如果应用程序是用 C 语言编写的,另一个最常见的问题是启动期间的看门狗超时。默认情况下,所有 MSP430 上的看门狗定时器在启动后都设置为活动状态。因此,如果不需要,则必须在应用程序代码开始时关闭 WDT。如果应用程序代码使用 需要在启动期间初始化的大变量,这可能导致看门狗定时器在启动期间已经触发并且代码将永远不会运行。
此问题的解决方案是使用编译器的低级 C 初始化函数,该函数甚至在 C 变量初始化之前就被调用。在 CCS 编译器中,它被称为“int _system_pre_init(void)”,而在 IAR 中,该函数被称为 int __low_level_init(void)。返回值用于确定是否执行 C/C++ 全局数据初始化(返回值 0 绕过 C/C++ 自动初始化)。有关此问题的更多详细信息,请参阅 MSP430 软件编码技术应用报告,第 3.6 章“使用低级初始化函数”。
所以我尝试添加以下函数(为了在分配内存之前停止 WDT):
__attribute__((naked, section(".init5"))) void __low_level_init()
{
WDTCTL = WDTPW + WDTHOLD; //Stop WDT
}
但问题仍然存在......
我做过的其他测试: - 更改了编译器的版本 - 将数组拆分为 15 个元素中的两个或多个 - 在主函数或“.init3”、“.init1”、“.init7”中停止 WDT
任何想法 ?谢谢你。
编辑:按照建议,我分析了 GCC 输出 ASM 代码(用“##”注释为无效版本):
.file "main.c"
.arch msp430g2211
.cpu 430
.mpy none
.text
.Ltext0:
.comm dir,2,2
.comm colors,2,2
.section .init9,"ax",@progbits
.p2align 1,0
.global main
.type main,@function
/***********************
* Function `main'
***********************/
main:
.LFB0:
.file 1 "main.c"
.loc 1 61 0
mov r1, r4
.LCFI0:
add #2, r4
.LCFI1:
add #llo(-100), r1 ## add #llo(-150), r1
.LCFI2:
.loc 1 63 0
mov #23168, &__WDTCTL
.loc 1 66 0
mov.b &__CALBC1_1MHZ, r15
mov.b r15, &__BCSCTL1
.loc 1 67 0
mov.b &__CALDCO_1MHZ, r15
mov.b r15, &__DCOCTL
.loc 1 68 0
mov.b &__P1DIR, r15
bis.b #127, r15
mov.b r15, &__P1DIR
.loc 1 90 0
mov r4, r15
add #llo(-102), r15 ## add #llo(-152), r15
mov #100, r14 ## mov #150, r14
mov r14, r13
mov #0, r14
call #memset
mov.b #llo(-64), -102(r4) ## mov.b #llo(-64), -152(r4)
mov.b #llo(-64), -101(r4) ## mov.b #llo(-64), -151(r4)
...
diff 命令还说:
106c106
< add #llo(-102), r15
---
> add #llo(-152), r15
187c187
< cmp #20, r15
---
> cmp #30, r15
193c193
< add #llo(-100), r15
---
> add #llo(-150), r15
541c541
< .sleb128 -102
---
> .sleb128 -152
548c548
< .byte 0x63
---
> .byte 0x95
我不是 ASM 专家,但 WDT 说明似乎在正确的位置。我不明白问题出在哪里...谢谢。