esp32 c2蓝牙wifi芯片模块乐鑫科技代理商嵌入式系统存储资源,嵌入式系统通常包含多种类型的存储器,例如 RAM,ROM 和寄存器等。而RAM又包括 CPU 内部RAM被外部 RAM。同一系统中,不同类型存储器映射到处理器存储空间的不同地址区间。嵌入式系统中存储设备的多样性和地址的不连续性,增加了在程序中管现内存的复杂程度。
C 语言存储修饰符
在C语言中,可以使用修饰符指定变量的存储特性。在声明变量前加上特定修饰符,可以限定该变量的存储类型。esp32 c2蓝牙wifi芯片模块乐鑫科技代理商常用的修饰符有 auto、static、extern、const、register 和 volatile。在嵌人式 C语言序中,const、register 和 volatile 有特殊的作用。
const 修饰的对象为常量。修饰对象可以是数据,也可以是指针。esp32 c2蓝牙wifi芯片模块乐鑫科技代理商在下列例子中,第 1行声明常量k;第 2行声明指针常量 ptr;第 3 行声明常量数据。
1 const int k= 1024; //k 的值不可改变
2 int * const ptr; //ptr 地址不可改变
3 const int *ptr; //ptr 位置的数据不可改变
在嵌入式系统中,常把 const 修饰的全局和静态变量分配到 ROM 空间。例如,“int;”中的 k分配在可写的 RAM空间中,“const int k;”中的k分配在不可写的 ROM空间。
用 register 修饰使用频率较高的局部变量,命令编译器尽可能地将变量存在CPU 内部寄存器中,而不是通过内存寻址访问,以提高效率。RISC-V 有 32 个通用寄存器,可以同时存储多个变量。esp32 c2蓝牙wifi芯片模块乐鑫科技代理商在示例 8.1 中,左侧列出了使用修饰符 register后C 语言源程序编译生成的汇编语言,右侧是未使用 register C 语言源程序编译后生成的汇编语言。可以看出,没有使用修饰符时,变量 a 和 b 保存在栈中;添加修饰符后,变量 a 保存在寄存器 ra 中,变量 b 保存在寄存器 s0 中。
示例8.1: register 修饰符对编译后生成代码的影响。
/*
int main(void)
( register int a= 50, b = 150;
int value = max(a,b) ;
......}
*/
Main:
......
li ra,50 //ra= 50,ra寄存器变量
ali s0,150 //s0=150,s0 寄存器变量 b
mv a1,s0 //al = b
mv a0,ra //a0 = a
call max //调用函数 max
......
--------------------------------------------------------------------------------------------------
/*
int main(void)
( int a= 50, b = 150;
int value = max(a,b) ;
......}
*/
Main:
......
li a5,50 //a5 = 50
sw a5,8(sp) //a=a5,a在栈中
li a5,150 //a5 = 150
sw a5,4(sp) //b= 150,b在栈中
lw al,4(sp) //a1 = b
lw a0,8(sp) //a0 =a
call max //调用函数 max
......
使用register 修饰变时,要求变量必须是处理内核所支持的数据类型,并且数据不大于不大于处理器所支持的整数。esp32 c2蓝牙wifi芯片模块乐鑫科技代理商另外,使用 register修饰的变量不能使用“&”操作获取地址。
如果使用 register 修饰的变量数目大于 RISC-V 可用的寄器数,则编译器将自动忽略所添加的修饰符register。
在嵌入式系统应用程序中,通常在 I/0 端口指针变量前添加修饰符 volatile,保证访问数据的时效性。常见的使用场景包括中断服务程序、访问系统中的外部器件以及多个任务访问共享变量。
读取 volatile 修饰后的变量时,将直接读取目标内存地址或 I/0 寄存器中的内容,而不是从临时寄存器、栈中的临时变量以及系统缓存中复制内容。
经 volatile 修饰的任何变量的读/写操作语句都不会被优化。esp32 c2蓝牙wifi芯片模块乐鑫科技代理商例如,在示例 8.2中,使用赋值语句 ioport 产生脉冲,前 3 条写语句可能被编译器优化删除,从而导致输出波形错误。如果将“char * ioport”改写成“volatile char * ioport”,那么前3条写语句就不会被编译器删除。
示例8.2:I/O模拟输出时序。
volatile unsigned char * ioport;
*ioport = 0;
*ioport = 1;
*ioport = 1;
*ioport= 0;