ARM C嵌入式编程中一些常见的标识符

1、访问绝对地址的内存位置:
     #define pISR_EINT0 (*(unsigned *) (_ISR_STARTADDRESS+0x74))
     上述语句把代表地址的无符号整数 _ISR_STARTADDRESS+0x74强制转换为指针,指向RAM,用下面的语句可以访问它:
     pISR_EINT0 = (int)Eint0_ISR
     为了访问一个绝对地址,把一个整形数表示的地址值强制转换(typecast)为一指针。

2、__irq:
     为了方便使用高级语言编写异常处理函数,ARM编译器对异常处理函数做了特定扩展,只要使用关键字_irq,这样编译出来的函数就满足异常响应对现场保护 和恢复的需要;

3、编写中断服务程序的一些基本原则:
       避免在中断服务程序中做浮点运算:好的终端服务程序应该遵循短小有效这一原则,在中断服务程序中做浮点运算大大违背这一原则,同时有些处理器/编译器就 是不允许在中断服务程序中做浮点运算;
       中断服务程序不能有返回值:所以中断服务程序都定义为返回类型为void,即:void _irq Eint0_ISR(void);
       中断服务函数不能传递参数:故参数列表为void,即:void _irq Eint0_ISR(void);

4、Static:
     一个static变量,其实就是全局变量,只不过它有作用域,它可用于保存变量所在函数被调用期间的中间状态,比如:
int cCout()
{
Static int loop = 0;
.......
loop++;
.......
  }
     loop变量的值会跟随着函数的调用次数而递增,函数退出后,loop的值还存在,只是loop只能在函数中才能被访问(函数作用域),而loop的内存 空间也只会在函数第一次被调用时才会被分配和初始化,以后每次进入函数,都不为static分配了,而直接使用上一次的值。在模块内,一个被声明为静态的 函数只可被这一模块内的其他函数调用,模块外其它函数无权访问,是一个本地全局变量。

5、Constant:
     将一个变量或对象定义成constant类型,则定义之后不能被更新(可读不可写),即在定义或说明类型时必须给他一个初始值。
     几种须要注意的地方:
        如果const位于星号(*)的左侧,则const修饰指针所指向的变量,即指针指向常量;如:const int *a; 或int const *a;这两种情况相同(const放在变量声明符的位置无关),指针指向一个常量,此时不能对内容进行更改,即不能有写操作语句*a=3;
        如果const位于型号的右侧,const就是修饰指针本身,即指针本身是常量;如:int* const a;语句表示指针本身是常量,所指向内容不是常量,即a++是错误的。
        如果星号左右侧都有const修饰,如:const int* const a;表示指针本身和指针指向的内容均为常量。

6.、Volatile:
     定义一个易失性变量,编译器有一种技术叫数据流分析,分析程序中的变量在哪里被赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化。当编译器检查到代码没有修改字段的值,就有可能在你访问字段时提供上次访问的缓存值,这能够提高程序的效率,但有时这些优化会带来问题,不是我们程序 所需要的,特点是对硬件寄存器操作的程序,这时可以用volatile关键字禁止做这些优化。

     volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读 取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变 量由别的程序更新了的话,将出现不一致的现象。
     使用volatile变量的场合:
        硬件寄存器通常要加volatile说明,因为每次对它的读写都可能有不同的意义;
        在中断服务程序中修改的供其他程序检测用的变量需要加volatile声明;否则编译器可能对变量更新一次后每次都使用缓存值不再立即更新;
        多任务环境下各任务间共享的标志应该加voatile关键字:在多线程访问某字段时,代码希望这些访问能够操作到操作(读取)到字段的最新值,同时写到 变量的操作能立即更新;对字段加上volatile关键字,那么对该字段的任何请求(读/写)都会立刻得到执行。

 

#define rGPACON(*(volatile unsigned long *)0x56000000)

对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的 。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的“端口”的 概念。如果是内存映射,那就方便的多了。

举个例子,比如像寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了。

#define A (*(volatile unsigned long *)0x48000000)
...
     A = 0x01;
...

    这实际 上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long *)0x48000000的意思是把0x48000000强制转换成volatile unsigned long类 型的指针,暂记为p, 那么就是#define A *p, 即A为P指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作。

 

 

 

用GCC编译时。 volatile所指示的寄存器不进行优化!

 

你可能感兴趣的:(编程,c,优化,嵌入式,语言,编译器)