Chinaunix首页 | 论坛 | 博客
  • 博客访问: 206032
  • 博文数量: 33
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1277
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-03 10:03
个人简介

现于杭州电子科技大学攻读硕士学位

文章分类

全部博文(33)

文章存档

2013年(33)

我的朋友

分类: 嵌入式

2013-09-07 21:35:30

函数头部进行注释,列出函数功能、输入参数、输出参数、返回值、调用关系等信息



按位与操作:可以实现将特定为清零,也可以提取出某数的指定位



按位或操作:可以实现将特定位的置位操作,也可以用于提取出某数的指定位



按位异或操作:可以实现将特定位的取反(与0异或保留原值,与1异或取反),也可以实现在不引入第三变量的情况下,交换量变量的内容(a=a^b,b=b^a,a=a^b



取反操作:主要用于将操作数的某位或某些位取反,为其他操作提供数据准备



左移:操作常常用于将特定的位置1,也可用于代替乘法和除法操作,嵌入式编程中,左移操作常用作某寄存器对应位进行设置(如:# define BIT_UTXD0 (0x1<<3),这样使程序可移植性好



volatile的本意为“暂态”和“易变的”,该说明符主要起到抑制编译器优化的作用。由于访问内部高速CACHE或寄存器的速度比访问外部RAM快得多,所以编译器一般都会做减少存取外部RAM的优化,对于一个变量,如果编译器发现复制后没有变化,编译器就可能优化代码,直接从内部高速缓存CACHE或寄存器获取数据,而不是从内存中读取。如果在这段时间里,变量被中断或外围设备输入等编译器未知的原因改变,程序可能没有获取最新的值而导致运行结果异常



如果在声明时用volatile进行修饰,遇到这个关键字声明的变量,编译器对访问该变量的代码不再进行优化,从而可以提供特殊地址的稳定访问,一般volatile限制符长用于下面几种情况说明:



1:存储器映射的硬件寄存器通常要加volatile说明,因为每次对他的读写都可能具有不同的意义



2:中断服务程序修改的供其他程序检测的变量需要加volatile



3:多任务环境下各任务间共享的标志应该加volatile进行说明



地址强制转换:在C语言中,绝对地址被当成整型数,如果把它当成一个地址来使用就需要进行地址强制转换,如定义一个整型指针int *p,然后把绝对地址0X0FA00转换成一个整型的地址值赋给这个整型指针p=(int *)0x0FA00



   因此在嵌入式设计中,经常可以看到寄存器用如下方式进行定义:



      
# define rPCONA   (*(volatile  unsigned 
*)0x1D20000)



中断处理程序:



   标准C不包含中断服务的自动处理,许多编译器开发商在标准C上增加了对中断的支持,提供了自定义的一些关键字用于说明中断服务程序(Interrupt Service Routine ,ISR,比如常见的有_Interrupt# program interrupt等,如果一个函数被说明为中断服务程序,编译器会自动添加中断处理所需要的现场保护盒出栈代码



  在编写中断服务程序时需要满足如下要求:



1:不能向中断服务程序传递参数



2:中断服务程序没有返回值



3:中断服务程序要尽可能的短,来减少中断服务程序的处理时间,保证实时系统的性能



模块化程序设计:将系统内的任务合理的划分,将具有同一属性或相同类别的代码归为一类组成模块



嵌入式软件系统主要有两类模块:硬件驱动模块,一种特定硬件对应一个模块;系统控制功能模块



一般每个模块都是由一个.c源文件和一个.h头文件组合而成,硬件相关的模块里,源文件一般是对接口功能的封装,将硬件功能定义的定义为功能代码段,供应用程序调用,头文件是对于该模块硬件接口寄存器的地址定义和宏定义;在应用模块里,源文件用来实现控制任务,头文件用来对相应模块所用到的外部变量或函数进行声明



如果某模块提供给其他模块调用的外部函数或外部变量,则要在.h文件中用extern关键字进行声明,并在该模块的.c源文件中定义该变量

子程序调用通过寄存器R0~R3传递参数,当参数不超过4个时,可以使用寄存器R0~R3来传递参数,参数依次存放到R0~R3中,当参数超过四个时,还可以使用数据栈来进行参数传递,入栈的顺序与参数顺序相反,即最后一个参数先入栈



 汇编语言与C的混合编程通常有以下几种:



  1:在C程序中嵌入汇编指令



  2:在汇编程序中访问C定义的全局变量



  3:在C程序中调用汇编函数



  4:汇编程序中调用C函数





  1:在C程序中嵌入汇编指令



  在此情况中,使用关键字_ _asm来标识一段汇编指令程序



  如:_ _asm



     
{
汇编语言



      
…….



      
汇编语言



}



例如:



if   _ _asm  volatile…………….


2:在汇编程序中访问C定义的全局变量



在此情况中,在汇编代码中使用   IMPORT 全局变量名   ,然后才能在汇编代码中把此全局变量当成立即数来使用



例如:



汇编:AREA asmfie,CODE,READONLY          
C
语言:#
include



      EXPORT asmDouble                             int qvar_1=12;



      IMPORT qvar_1                                 extern asmDouble(void);



      asmDouble                                     int main()



            ldr r0,qvar_1                              {printf(………..);



             ……                                   
asmDouble();



             …….                                   …………..



  3:在C程序中调用汇编函数



在此情况中,在C中声明函数原型,并加extern,此外在汇编中用EXPORT导出函数名并用该函数作为汇编代码段的标识(在GUN汇编中用.global来导出函数名),最后用mov PC lr 
来返回,然后就可以在C中使用函数了



例如:AREA
asmfile,CODE,READONLY       
#include



    
EXPORT asm_strcopy           
extern void asm_strcopy(const char *src , char *dest )



    
asm_strcopy                    int main ()  



    
loop:                           {…………



       
ldrb r4,[r0],#1                 
asm_strcopy(s,d);



       
cmp R4,#0                     ………….}



       
beq over



       
strb r4,[r1],#1



       
b loop



    
over:



     
mov pc,lr



end



    



  4:汇编程序中调用C函数



需要在汇编中IMPORT对应的C函数名(GUN汇编是用.extern对应的C函数名),然后将C的代码放在一个独立的C文件中编译



例如:EXPORT asmfile                     
int cfun(int a , int b , int c)



      AREA asmfile ,CODE,READONLY      {return a+b+c;}



     IMPORT cfun



     ENTRY



         mov r0,#11



         mov r1,#22



         mov r2,#33



      bl cfun



     end



过程调用结果返回:



 1:结果为一个32位的整数时,通过寄存器R0返回;结果为一个64为整数时,通过寄存器R0R1返回



 2:结果为一个浮点数时,可以通过浮点运算部件寄存器F0D0或者S0来返回,结果为复合型的浮点数时(复数),可以通过寄存器F0~Fn或者D0~Dn来返回



 3:对于更多的结果,需要通过内存来返回






 
 
 
 
 
 
 
 
 
 
 
 






























 















































































































阅读(2498) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~