RT-Thread论坛
直播中

胖子的逆袭

13年用户 1184经验值
私信 关注
[问答]

GD32F470使用__attribute__语句,keil编译通过但是scons编译不通过,为什么?

问题语句:

  • uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR)));


上述语句在keil编译结果:

scons命令编译结果:

我目前使用的解决办法是使用scons命令的时候屏蔽__attribute__,编译通过后再取消屏蔽,请问有更好的解决办法吗?

回帖(1)

张莉

2025-10-21 17:55:56

针对您在GD32F470开发中遇到的编译问题,Keil(ARMCC)支持 __attribute__((at(...))) 语法,但SCons(通常使用GCC)不支持此语法。以下是系统化的解决方案:


终极解决方案:使用条件编译 + 链接脚本


通过 条件编译 区分编译器环境,并配合 链接脚本 实现地址定位,完美兼容Keil和SCons/GCC。


步骤1:修改代码(条件编译)


#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
    // Keil ARM Compiler
    uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR)));
#elif defined(__GNUC__)
    // GCC Compiler - 使用section属性
    uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((section(".framebuffer")));
#else
    #error "Unsupported compiler"
#endif

步骤2:修改GCC链接脚本(.ld文件)


在链接脚本中定义显存段的位置:


MEMORY
{
    RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
    FRAMEBUFFER (rw) : ORIGIN = 0xC0000000, LENGTH = 768K  /* 假设的显存地址 */
}

SECTIONS
{
    .framebuffer (NOLOAD) :
    {
        . = ALIGN(4);
        *(.framebuffer)   /* 捕获所有.framebuffer段的变量 */
        . = ALIGN(4);
    } > FRAMEBUFFER
}

备选方案:纯宏定义简化版


如果不想修改链接脚本,可使用此方案(需编译器支持):


#if defined(__CC_ARM)
    #define FRAMEBUFFER_SECTION __attribute__((at(LCD_FRAME_BUF_ADDR)))
#elif defined(__GNUC__)
    #define FRAMEBUFFER_SECTION __attribute__((section(".framebuffer")))
#else
    #error "Unsupported compiler"
#endif

uint16_t ltdc_lcd_framebuf0[800][480] FRAMEBUFFER_SECTION;

关键点解析




  1. 条件编译标识符



    • __CC_ARM:Keil ARMCC 编译器标识

    • __GNUC__:GCC 编译器标识

    • __ARMCC_VERSION:新版Keil编译器标识




  2. GCC实现原理



    • section(".framebuffer") 将变量放入自定义段

    • 链接脚本中的 > FRAMEBUFFER 将段映射到指定地址

    • (NOLOAD) 告诉加载器不初始化该段(显存无需初始化)




  3. 地址计算
    显存大小计算:800×480×2(uint16_t) = 768,000 字节 ≈ 750KB,需确保:



    • 链接脚本中 LENGTH 足够大

    • 地址 ORIGIN 与硬件要求一致(如0xC0000000)




验证要点




  1. Keil环境



    • 检查map文件中变量地址是否为 LCD_FRAME_BUF_ADDR




  2. SCons/GCC环境



    • 编译时添加链接脚本:LDFLAGS += -T your_linker_script.ld

    • 使用 arm-none-eabi-objdump -h 确认 .framebuffer 段地址正确





替代方案警告:某些教程建议GCC使用 __attribute__((aligned)) + 手动偏移,这种方法存在地址错位风险,强烈不推荐用于硬件外设映射。



此方案彻底解决编译兼容性问题,同时确保:



  • 代码版本统一(无需手动注释/取消注释)

  • 硬件地址精确控制

  • 跨编译器兼容性

  • 符合嵌入式最佳实践

举报

更多回帖

发帖
×
20
完善资料,
赚取积分