liusukai的个人空间 https://bbs.21ic.com/?1017991 [收藏] [复制] [RSS]

日志

学习嵌入式Linux-JZ2440-第一个裸机程序GPIO

已有 578 次阅读2015-5-14 15:13 |个人分类:嵌入式Linux|系统分类:ARM| 嵌入式, 程序

        ARM的裸机程序其实没什么特殊的,和单片机程序是一样的,我之前用过STM32,是ARM Cortex-M系列的。现在的ARM主要分三个,一个Crtex-M,主要用于控制。一个Cortex-A,主要用于应用,比如手机还有一些手持式设备。一个Cortex-R,嵌入式实时处理器,用于对实时性要求比较高的场合。
         现在开发ARM程序是在Linux下面进行的,没有用IDE,所以所有的事情都要自己做,但是这样的好处就是对整个程序的结构以及运行的理解有非常大的帮助,起码让我对Program有了新的认识。
         遇到的第一个难题就是启动代码,就是上电后运行的程序。因为这是一个简单的IO操作的程序,所以启动代码非常的简单。首先要学习的就是一点点汇编的知识,起码能够看得懂吧,不然就算抄也不知道代码用来做什么的。首先要清楚的就是汇编语音不是通用的,不用的处理器用的是不一样的汇编指令,但是写法结构都大同小异。这里介绍一点基本的东西。
.text下面的内容都是代码段,代码编译后的机器指令经常被放在代码段里
.data是数据段,已初始化的全局变量和已初始化的局部静态变量经常放在数据段里
.bss未初始化的全局变量和未初始化局部静态变量一般放在“.bss”段。
         在使用IDE的时候,这些东西一般是不需要考虑的,但是对这些段的理解还有哪些内容存储到哪里的了解,对于写程序是有帮助的,可以理解的更深,程序的结构写的也更加合理,尤其是写底层的程序的时候。
         下面就是地址的概念了,这是一个比较难的东西,起码对于我来讲是这样的,什么虚拟地址啊,物理地址啊,记得当时学微机原理的时候就学的云里雾里的,现在又碰到了,果然就撞墙了。S3C2440有两种启动方式,一种是NOR启动,这种启动方式的0地址位于NOR0地址,因为NOR的访问方式和RAM的访问方式相同,所以程序可以直接在NORFlash中运行。另外一种方式是NandFlash起动,因为NandFlash的访问方式相对比较复杂,有别于RAM的访问方式,所以必须要把NandFlash中的程序复制到RAM中才可以运行,这种启动方式的0地址位于芯片内部的RAM的首地址位置。从NandFlash启动,芯片上电后会强制把NandFlash前面的4K内容复制到芯片内部的RAM,然后从RAM0地址开始执行代码。像GPIO这样的程序比较小,所以不用考虑大于4K以后的内容。但是如果程序大于4K,这时前面4K的程序就要具备这样的功能:把4K以后的程序复制到SDRAM,然后运行。
         再者就是寄存器的概念,芯片内部有很多的外设,包括GPIOUARTIIC等等,这些外设的访问、控制都是通过操作寄存器来完成的,功能寄存器就可以理解成一个开关,搞成0就选择了一个功能,搞成1就选择了另外一个功能,多位控制就可以理解为几个开关的组合,对于芯片的操作,寄存器的理解是很重要的。
         怎么通过C语言操作寄存器呢?每一个寄存器都有一个地址,C语言中和地址有关的那就又扯到指针了,指针就是一个地址,但是这个地址有相应的格式,比如char * p,这个p就是一个指向char类型的指针,而S3C2440内部的寄存器是32位的,所以定义一个寄存器的方式如下(以GPIOFDAT为例,这是GPIOF的数据寄存器,读FIO口的数据以及写FIO口的数据都操作它,它的地址是0X56000054,这些数据在S3C2440的芯片手册上都是可以查的到的):
#define GPFDAT      (*(volatile unsigned long *)0x56000054)
这句是一个宏定义,GPFDAT就代表了(*(volatile unsigned long *)0x56000054)(volatile unsigned long *)0x56000054这是一个强制转换,把0X56000054强制转换成一个指向无符号长整型的指针,地址就是0X56000054,而*是访问指针指向地址中的内容的符号,比如p是一个指向a(它的值为10)的指针,*p就是访问了a的内容,就是10*p=20,这时候a的值就被改成了20。所以(*(volatile unsignedlong *)0x56000054)就是访问了0X56000054这个地址中的内容,就可以对这个寄存器进行读和写的操作了。
         代码的问题解决完了,剩下的就是编译连接的问题了。一个C语言程序从代码到可运行的二进制文件,经历了预处理、汇编、编译、连接的过程。预处理就是处理C语音代码中的一些宏,比如替换#define定义的东西,处理#if这些宏。汇编就是把C语言代码变成汇编代码。编译就是将汇编代码变成OBJ目标文件;连接就是将几个目标文件、系统库的OBJ文件、库文件连接起来,最终生成一个可以在目标平台运行的可执行文件。用到的工具是arm-linux-gcc,这是一个综合工具,可以进行预处理、汇编、编译、连接等工作,根据编译选型进行相应的操作。
         最后把程序下载到开发板子上,LED亮了,当然了,为了显示确实是自己写的程序在起作用,我一般把多个灯弄成亮暗交替的形式,有的时候全亮或者全灭没办法说明问题。因为以前有单片机的开发经验,所以整个逻辑程序的开发过程整体上还算是比较顺利的,只是有些以前没有涉及过的东西要学习一下再进行。在这里我有一个小小的建议就是,学东西要边学边用,边用边学,不要有那种心理:等我全学会了再做东西。那样是学不会的,起码是学不好的,用的过程中可以发现问题,然后再有针对性的去学习,这样理解更加深刻,记的也更持久,不然是很容易早泄的。还有就是学习要慢慢来,肾虚了就慢慢补,靠吃伟哥的方式是不可取的。

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)