gcc 在嵌入式软件中一些常见的用法(待补充)

发布时间 2023-12-01 18:13:12作者: sureZ_ok

大多数情况,嵌入式软件工程师并不需要知道gcc编译器是工作的,但是随着调试深入,了解gcc在软件中的一些常见的用法大有裨益。

这里列一下遇到的一些嵌入式软件中用到的一些gcc知识。

1 GCC关闭某函数的优化

软件库使用O2/O3优化,有时debug时,需要关闭其中某些函数的优化(即使用此函数使用O0优化),可以采用如下方式:

注意:只能放到函数外,不能放到函数内部。在特定代码前保存当前的编译选项,然后对特定的代码使用O0优化级别,最后再恢复之前保存的编译选项。

示例如下:

#pragma GCC push_options
#pragma GCC optimize("O0")
void conv_test()
{
  ...
}
#pragma GCC pop_options

2 怎么声明某个数组多少字节对齐?

为了效率,CPU从内存取数据并不是一字节一字节去读的,而是一次读取多个字节(如4字节),如果变量地址不对齐(不是4的倍数),则会降低CPU效率。

声明某个数组16Byte对齐:

 int32_t __attribute__((aligned(16))) a_array[1024];

这样,编译后a_array的地址能被16整除(地址低16bit全为0)

3 怎么将某数组定义到外部flash或ram上?

有时数组太大,直接放到片内ram放不下,需要放到外部SDRAM中,可以使用如下方法:

方法1:__ attribute __( at(绝对地址) )

例如:

const uint8_t bigArray[] __attribute__((at(0x30000000))) 

注意:有可能 GNU GCC 不再支持at方法,方法1不行时,请采用方法2。

方法2:__ attribute __((section(“块名”)))

这种方法稍显麻烦,需要修改链接脚本。

例如:

修改C代码

const uint8_t bigArray[] __attribute__((section(".bigArray"))) 

修改lds链接文件,假设外部SDRAM起始地址0x30000000,大小为30MB

/* Program Entry, set to mark it as "used" and avoid gc */
MEMORY
{
    ROM (rx) : ORIGIN =0x08000000,LENGTH =128k
    RAM (rw) : ORIGIN =0x20000000,LENGTH =512k
    EXTSDRAM (rw) : ORIGIN =0x30000000,LENGTH =32M  /* 新增 */
}

/* 在SECTIONS里新增段,段名要与C代码中的字段一致 */

    .bigArray (NOLOAD) : ALIGN(4)
    {
        . = ALIGN(4);
        *(.bigArray)
            *(.bigArray.*)
            . = ALIGN(4);
        __bigArray_free__ = .;
    } > EXTSDRAM

参考:

  1. 【管中窥豹集】听到“对齐”这两个字你能想到什么?

  2. 来了解一下GNU C __attribute__机制

  3. C语言再学习24——attribute (at())地址定位

  4. RTthread_Studio IDE怎么将数组定义到外部SDRAM中