You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

avr-g++ 13.3.0在ATmega4809中传递const char数组参数异常问题

问题结论:这是avr-gcc 13.3.0针对ATmega4809的编译器/链接器问题,而非代码问题

核心原因分析

  • ATmega4809属于AVR-DA系列,采用哈佛架构,程序存储器(Flash)与SRAM是独立的地址空间。const字符串默认被编译器放到Flash的.rodata段,但代码中使用的ld r24, Z是SRAM读取指令,无法正确访问Flash中的数据,导致读到随机垃圾值。
  • 而ATmega328p是AVR经典系列,编译器默认会把.rodata段内容复制到SRAM的.data段,因此ld指令能正常读取字符串,这就是两个平台表现不同的根本原因。

反汇编验证细节

  • .rodata段的61 62 63 00是"abc\0"的正确ASCII值,但汇编器将其解析为ori等指令,说明该地址属于Flash空间;主函数传递的0x414c是Flash地址,函数中用Z寄存器指向该地址后执行ld指令,实际访问的是SRAM的对应地址,自然读不到正确字符。
  • 函数f中对比r24和0x61('a'的ASCII)时,r24的值是SRAM随机内容,因此判断为false,触发PC1引脚LED闪烁。

临时解决方案

  1. 强制放入.data段:如你已经尝试的,用__attribute__((section(".data")))将const字符串放到SRAM,让ld指令能正确读取:
    void f(const char str[]) {
        // ...原有逻辑
    }
    int main() {
        PORTC.DIR |= PIN0_bm | PIN1_bm;
        static const char str[] __attribute__((section(".data"))) = "abc";
        while (1) { f(str); }
    }
    
  2. 使用PROGMEM手动访问Flash:利用AVR的PROGMEM属性和pgm_read_byte函数读取Flash中的字符串:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/pgmspace.h>
    
    void f(const char* str) {
        if (pgm_read_byte(str) == 'a') {
            PORTC.OUT |= PIN0_bm;
            _delay_ms(500);
            PORTC.OUT &= ~PIN0_bm;
            _delay_ms(500);
        } else {
            PORTC.OUT |= PIN1_bm;
            _delay_ms(500);
            PORTC.OUT &= ~PIN1_bm;
            _delay_ms(500);
        }
    }
    
    int main() {
        PORTC.DIR |= PIN0_bm | PIN1_bm;
        while (1) { f(PSTR("abc")); }
    }
    

编译器问题的佐证

针对AVR-DA系列,avr-gcc应该自动识别.rodata段在Flash中,并生成lpm(Load Program Memory)指令来访问,或者在链接阶段处理地址映射。13.3.0版本显然没有正确处理这一平台特性,导致代码生成错误。

内容的提问来源于stack exchange,提问作者Antonio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:32:08