【问题标题】:Const Char array being modified to all 0s for AVR micro written in C对于用 C 编写的 AVR micro,Const Char 数组被修改为全 0
【发布时间】:2011-11-23 02:48:03
【问题描述】:

我正在帮助一个朋友在他的 AVR 上安装一个图形 LCD,几个月前一切正常,从那以后就没有动过。该芯片现已从 ATMega32 换成 ATMega164P。基本上相同的芯片具有更多的闪存,因为这种变化很多代码已经停止工作。

我们已缩小错误发生的范围,但无法纠正。这是我们传递一个指向 const char 字符串的指针,并尝试打印该字符串的地方,但是由于某种原因,堆栈(堆,其他东西?)被破坏并且指针包含所有零。有谁知道这是怎么发生的?我们启用了正确时序所需的 -O1 级优化,我们也切换到了 winAVR 编译器,没有任何更改。我们也无法使用调试器,只能进行有限的“打印”样式调试。

这是导致问题的代码部分:

//in the header file that is included
int SGCTEXTStringF(int column, int row, int font, int colour, const char* text);

//Call the function
SGCTEXTStringF(0, 0, 0x10, SGCColour(255,255,255), "text");

//Function
int SGCTEXTStringF(int column, int row, int font, int colour, const char* text){

unsigned char bytes[23]={0};

//...Code to communicate with LCD and set up a 'print string'

if(text[0] == 0) {
    bytes[6] = 'a'; 
    bytes[7] = 't';
    bytes[8] = 'e';
    bytes[9] = 's';
    bytes[10] = 't';
}

//..more code to finish sending the array
}

现在,当代码运行时,显示屏会打印出“atest”,这表明 const char 数组已经被归零了?我还尝试了以下行,这些行也都打印了'atest'

if(text[1] == 0)   //prints 'atest'
if(*text== 0)      //prints 'atest'
if(text != 0)      //prints 'atest'

这表明它获得了一个有效的指针,但它似乎指向全零。

我们还尝试将方法调用更改为:

const char * string = "test";
SGCTEXTStringF(0, 0, 0x10, SGCColour(255,255,255), string);

这个代码几个月前就已经知道可以运行了,我们甚至有一段它运行的视频,现在程序中的每个函数都出现了同样的问题,char 数组被传递(在堆栈上?)似乎没有工作并清零。

如果有人感兴趣,我可以安排提供完整源代码的副本。任何帮助或指点都表示赞赏!

【问题讨论】:

  • 看起来像是某种链接器问题。也许字符串文字没有链接到正确的地址,或者根本没有链接。我会查看生成的二进制文件并验证它确实包含所有需要的文字。还可以尝试打印并验证他们的地址。
  • 检查堆栈的大小。如果它太小,你会得到这种奇怪的行为。另外,你能给出 SGCColour 的定义吗?
  • 并重新检查您的地图文件(链接器可以生成它)。 “常量数据”部分(放置 C 字符串的位置)可能有问题。

标签: c++ c pointers avr microprocessors


【解决方案1】:

ATMega164P 不是 ATMega32 的替代品,而是 ATMega16 的替代品。对于 ATMega32,您需要 ATMega324P。 如果您正在使用 ATMega32 的内存映射(具有双 EEPROM、SRAM 和闪存),您的字符串可能已落在根本不存在的内存中。 对于移植问题,您可以查看 Atmel 的 porting guide

【讨论】:

  • 编译的时候已经选择了正确的芯片,还有哪些选项可以改?
  • 一定是内存不足。
  • 设备:atmega164p 程序:3398 字节(20.7% 已满)(.text + .data + .bootloader) 数据:886 字节(86.5% 已满)(.data + .bss + .noinit)看起来喜欢充足的可用空间?
  • 检查链接器选项或配置文件是否正确匹配164P内存映射,它必须与32不同。如果定位器将一些变量放入不存在的内存区域,你会遇到问题,即使链接器报告没有问题并且有大量可用内存。引用我的链接:“ATmega164P/324P/644P 内部数据 SRAM 寻址从 0x100 开始,而不是 ATmega16/32 中的 0x60。”并且您可能需要不同版本的 crt0.s(或通常由编译器供应商提供的适当启动代码)用于 164P。
  • 我们检查了输出,更改后 SRAM 已满 114%,但它认为这不是错误并成功对芯片进行了编程。 SRAM 只有 1kb,因此问题是,超过 1 或 2 个嵌套函数调用具有 256 字节缓冲区,并且堆栈溢出。通过将我们程序中的每个数组设为静态和全局强制将其存储在程序内存而不是 SRAM 中来解决此问题。
猜你喜欢
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
  • 2012-02-27
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多