2

我在 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 说明似乎在正确的位置。我不明白问题出在哪里...谢谢。

4

1 回答 1

0

听起来像是一个编译器错误,在这种情况下,如果您查看 GCC 生成的 asm,可能很明显出了什么问题。

在你发布它之后我查看了 asm,我突然想到你只有 128 字节的 SRAM 可以使用。我不熟悉这个 uC 的汇编程序,但在我看来它已经被超越了。不是单独分配颜色数组,而是结合堆栈?

于 2013-01-10T00:02:57.190 回答