大多数情况,嵌入式软件工程师并不需要知道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
参考: