前言:
为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。
1. __ attribute __((at)) 绝对定位
__ attribute __( at(绝对地址) )的作用:
(1)绝对定位到 Flash;
(2)绝对定位到 RAM。
__ attribute __ :用来指定变量或结构位域的特殊属性,关键字后的双括弧中的内容是属性说明;
at:用来设置变量的绝对地址,指定某个变量处于内存或 FLASH 里面的某个给定的地址。
1.1 定位到 FLASH
定位到 flash 中,常用于固化信息,例如:设备的出厂信息,FLASH 标记等;
const uint8_t usFlashInitVal[] __attribute__((at(0x00030000))) = {0x11,0x22,0x33,0x44,0x55,0x66};//定位在flash中,0x00030000开始的6个字节信息固定
1.2 定位到 RAM
常用于数据量较大的缓存,如:串口接收数据。也用于某个位置的特定变量。
uint8_t ucUsartRecvBuffer[USART_RECV_LEN] __attribute__ ((at(0x00025000))); //接收缓冲,最大USART_RECV_LEN个字节,起始地址为 0x00025000
注:
-
绝对定位不能在函数中定义,局部变量是定义在栈区,栈区是自动分配、释放,不能定义为绝对地址,只能于函数外定义;
-
定义的长度不能超过栈或 Flash 的大小,否则导致栈、Flash 溢出。
1.3 测试
比如:在 0x08010000 的 flash 地址上固定写入数据,如下图:
如果不加 const 修饰,则定位到了 RAM 。
编译出来各部分文件大小:
打开编译出来二进制文件,如下图:
最后,我们来看一下加与不加 const uint8_t ucaSysFlashVal[] attribute((at(0x08010000))) =
{0x11, 0x22, 0x33, 0x44}; 的 map 表的区别:
原编译结束的 map 文件各部分文件大小:
添加定位代码后的 map 文件各部分的大小:
可以发现添加后,RO Data 的大小发生了变化,即定位后 FLASH 的空间占用加大,并且打开 bin 文件,可以发现中间部分由全 0 填充。