纹身改运:ARM的开发经验

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 15:22:23

#1  学习ARM开发(1)
做任何事情之前,一定要想好目标。没有目标的事情是做不好的,也做不成。我的目标就是学习ARM开发,当然是深入的学习。
目标如下 :
1、学习ARM开发环境。
2、学习ARM指令。
3、学习ARM汇编。
4、学习BOOTLOADER.
5、学习uClinux编译和使用。
所有上面这些都基于三星的s3c44b0开发板进行的。
学习ARM开发(2)
今天是星期天,刚好在家里休息。又是学习ARM的大好时机了。
早上起得很早,因为都想着怎么样搞好这个ARM开发环境,总是心急的。搞得睡觉,也睡不好。立即把电脑打开,为了更加快点,把家里两台电脑都打开,用一台比较快的电脑装LINUX。目前因为两台电脑都已经安装WINDOWS系统,又装了很多软件。为了没有什么风险,就装了VMWARE软件,就是虚拟机软件,这个软件的虚拟速度确实快很多,它跑图形的操作系统也不慢。如果BOCHS,一运行图形的操作系统,就会很慢,因此放弃了这个自由软件。如果我的电脑速度也很快,比如用AMD64位的最新CPU或许用BOCHS也不慢。哈哈。。。。。
装好VMWARE软件,然后就是在里面安装LINUX,那么用什么LINUX比较好呢?目前,我是用最流行的REDHAT。并且用的是9.0版本,这个版本确实不错。一路下来,几乎不用动什么手,就可以装完了。
吸取了上几次的经验,所以这次我选择了全部安装所有软件,硬盘的空间还有10G,所以我虚拟机硬盘
就分配10G硬盘空间。这样全部安装LINUX后,大小也才3G左右。这个LINUX已经把图形和网络,开发源程序和所有工具,全部安装完成。像我很少使用LINUX的用户,一定不会再回到像DOS那种环境的,或许很久没有用DOS了,所以打命令总是很艰难的,总记不住LINUX下的命令,所以我选择了图形的方式。目前在LINUX下,使用图形的方式,已经很方便了。跟WIN95的水平已经不相上下了,如果WINDOWS真的要收我的钱,就改到LINUX下了,REDHAT9.0已经使用起来很方便了。如果是只办公,用LINUX,已经很好用。在这之前,我安装LINUX时没有选图形的方式,确实是痛苦。从1997年开始安装LINUX,当时用软盘安装,太难了,还搞坏我的硬盘。到了2005年,LINUX确实进步了很大。REDHAT9.0已经很实用了,LINUX肯定可以成为办公的PC标准配置了。
装好LINUX后,就要配置它的网络部份。以前几次都配置不成功,是因为不了解LINUX,或许它的帮助太少,以为每个都是高手。现在用REDHAT9.0的中文版,总算比较了解。设置网卡的IP地址为192.168.0.2,掩码:255.255.255.0,网关是192.168.0.1。这样就配置好了LINUX的网络了。
接着下来,就要设置VMWARE的网络部份,我选用NAT的方式。所以我找到那个VNET8那个虚拟网卡,然后设置它的IP地址为192.168.0.8,掩码:255.255.255.0,网关是192.168.0.1。这个是在WINDOWS的网络里配置的。这样设置好之后,在WINDOWS里,就可PING到虚拟机里的LINUX的192.168.0.2了。
在LINUX访问WINDOWS的IP是多少呢?这个问题刚开始,我也是不知道的。后来试了一下,只能PING到WINDOWS的192.168.0.8这个地址。不过,只要PING得通这个地址,就证明LINUX和WINDOWS的网络已经设置好。
接着下来,就是解决WINDOWS与LINUX共享文件的问题。这个有很多的解决方案。我的选择是用FTP。
因为我对LINUX不了解,所以我试着配置LINUX的VSFTPD总是配置得不好,达到不我的要求,而我的要求就是简单,任何文件都可以上传也可以下载,但LINUX缺省的方式是很安全,搞得我有时候能上传,就不能下载,有时能上传了而不能删除文件,是因为权限太复杂,总算了解为什么WINDOWS好用,就是因WINDOWS没有那么多权限控制。
既然配置LINUX不成功,我就选择了WINDOWS的FTP服务器。拿出WINDOWS的光盘,然后添加WINDOWS的FTP服务器,在WINDOWS后只选择两个设置,就可以设置任何人都可登录,任何文件都可上传和下载。这样太快了,还是WINDOWS方便,全是界面的。因为目前安全是不用考虑的,用LINUX那个,要改为不安全,很难设置。
设置好WINDOWS的FTP服务器之后,就可以用LINUX后那个图形的GFTP工具连接到WINDOWS了。只要在WINDOWS的FTP目录里,放任何文件,都可以在虚拟机的LINUX里用GFTP来拷贝入去,也可以从LINUX里拷贝文件出来了。
这样的操作系统装好之后,就是安装ARM的开发环境了。这个就是下载arm-elf的交叉编译器。这个以后再说了。
到这里,就完成LINUX的安装和文件共享的问题。这样的好处是,可以在LINUX下编译程序,可以WINDOWS上用VC等工具写源程序和修改源程序,速度快,并且写中文的注释也很方便了。并且可以
把uClinux的目标文件拿WINDOWS下用SKYEYE等运行。如果还在虚拟机的LINUX下,再用SKYEYE的话,就
会变得非常慢的。
下一次再继续ARM学习。[br]

+3 RD币

--------------------------------------------------------------------------------

harbincampus Post at 2007-5-26 21:35:28
学习ARM开发(3)

上一次说到装好LINUX后,就要装开发环境了,因为编译在LINUX下,当然是用GCC,但这个GCC跟LINUX本身带的又不一样。目标代码是ARM,而LINUX带的,一般是I386的目标代码。因此,一定要安装ARM的编译器。到网上下载 arm-elf-tools-20030314.sh,然后运sh ./arm-elf-tools-20030314.sh运行,就可以安装好ARM的GCC编译器了。你在LINUX下,就可以用arm-elf-gcc -v就可测试一下,是否安装成功了。这个编译器已经包括了as,ld,gcc等三个编译器,已经可以编译汇编和C代码,并且可以连接成目标文件。
编译器已经安装好之后,就说明整个开发环境已经建立起来,就做你想要做的事情了。至于怎么样写MAKEFILE文件,我就不说了。因为这些都是很基础的东西,并且都是细节的东西,记不住那么多,要用到的时候再去查手册行了。并且一个项目或许只用写一个MAKEFILE的格式,然后其它的都可以从这个基础上修改而来。我不会从头去建立一个MAKEFILE的,那需要太多时间了。只要到其它项目里拷贝一个,自己进行修改,就可以使用。
接着下来,就要写程序,那怎么样写呢?这是一个问题。写程序的目标机器是什么呢?用什么语言来写呢?应从那里下手呢?其实是有很多问题在这里的。
因为我以前没有学习过ARM,只学习过80X86的微机原理,我想这个ARM也是计算机,只要是一样的东西,就要用一样的方法来学习。以前我在大学里学习微机原理的流程是这样的:
学习二进制表示法,学习中央处理器组成,学习汇编,学习CPU的内存管理,学习CPU的IO口。
那么我也要用这种方法来学习才对。
二进制表示方法是一样的,所以不用学习了。那么我为什么CPU写程序呢?这个一定要搞清楚的,否则也不会怎么样写。ARM的CPU是与X86的CPU是不一样的。它是采用了RISC设计,以前也不懂这个是什么,所以就到网上查下,在《维基百科,自由的百科全书》里说明如下:

精简指令集,计算机CPU的一种设计模式,也被称为RISC(Reduced Instruction Set Computing 的缩写)。

早期,这种CPU指令集的特点是指令数目少,每条指令都采用标准字长、执行时间短、CPU的实现细节对于机器级程序是可见的等等。

实际上在后来的发展中,RISC与CISC在争吵的过程中相互学习,现在的RISC指令集也达到数百条,运行周期也不再固定...... 虽然如此,RISC设计的根本原则--针对流水线化的处理器优化--没有改变。

原来如此,RISC的一般特性是什么呢?采用RISC指令的CPU,大多数都是定长指令,采用加载与储存操作数据的办法。就是所有要操作的数,都要保存到寄存器才能作运算,不像X86的CPU,可以直接操作内存里的数据。这个在写汇编时需要了解的。其它的区别,对于写程序来说,是没有区别的。
ARM的CPU执行代码是三步进行的,取指---译码----执行。

下一个目标学习ARM汇编。

学习ARM开发(4)

已经把CPU大体架构学会了,当然我之前已经学习过80X86的结构,所以对于像RISC的计算机,也能想像到它是什么样的东西。如果没有学习过《微机原理》,那最好去看看,或者去看看RISC的CPU设计,就是龙芯的设计,在清华上面有很多关于龙芯的设计文档,这些都是CPU的功能。
为什么要学习汇编呢?现在不是大多数用C编写的了吗?是的,目前嵌入式软件大多数都是用C开发的。其实学习汇编,是为了更好了解CPU的处理,这个只是为了了解,为了更深入的了解,而不是用它来开发大部份的应用。当然它也是有用的地方,比如BOOTLOADER这样的程序,没有汇编,是不可能完成的。还有那些有特殊的指令,没有汇编也是不可能写得出来的。目前,我学习汇编,就是为了写BOOTLOADER。我也没有为了全部去学习它,而去学习,而是拿BOOTLOADER的源程序出来,从上面了解汇编,看懂别人的BOOTLOADER,或者能修改它的汇编,就算学习完成,而不必要每条指令都去死记它,去了解它。只要BOOTLOADER中有的指令,才去看它,去了解它,把一个BOOTLOADER看完下来,就相当于把汇编学习完成,而不必要自己动手去新写什么汇编,只要能修改目前已经有的BOOTLOADER,就已经完成了任务。
下一次,接着就去看看U-BOOT的源程序了。当然是基于S3C44B0的BOOTLOADER进行的。

学习ARM开发(5)

蔡军生 2005/07/16 写于深圳

上一次说到要学习UBOOT的代码,但在看之前,首先要知道目标机器的编程资源,这里的资源,是指S3C44B0所提供的运行程序的资源,对任何嵌入式软件开发,都首先要对硬件有一个很好的了解,这跟PC机的编程是大不一样的。因为PC机都已经发展了30多年,但整个编程的体系是没有很大的变化,就是说现在的PC都是在虚拟机上编写了,跟硬件打交道的机会很少,所以不用去了解它。但是在嵌入式的软件里,每样硬件都是千差万别的,所以一定要去看原版的S3C44B0说明手册,一定要看英文原版的,不能看那种中文版的,哈哈,为什么要看英文原版的呢?第一,每个CPU都有很多特别寄存器,而这些寄存器都是用英文缩写的,看中文,就不知道它是什么意思了,并且还要死记,没有英文整句好记。第二,中文是经过翻译的,并且都不是三星厂家进行翻译,都是一些业余水平的人来做,很难保证按原文的意思进行。有一次,我看中文的S3C44B0资料找特别寄存器,就找不到,我说为什么没有呢,原来别人都不翻译那些,结果在英文原版中,一看就找到了。因此,喜欢看英文原版的。并且只要学习过几个CPU之后,发现嵌入式软件就那几样东西了。
对开发软件的人来说,最重要的东西是什么呢?哈哈,当然是存储器和寄存器了。每次拿到开发板之后,一定要去了解存储器是怎么样分配的,是从什么地址开始,存储器有多大。是什么样的存储器,是FLASH的,还是SDRAM的。FLASH的存储器映射在S3C44B0的什么地址空间呢?SDRAM又是映射在什么地址空间呢?一定要把这些问题搞清楚,否则就很难对它开发软件。所以看S3C44B0的手册时,就要注意看它的存储管理。目前,S3C44B0的存储器管理,分为很多BANK的。BANK0一般用来映射FLASH存储器,并且在BANK0后面一段空间里进行特别寄存器映射,它的空间是4M大小。并且一般的开发板,都是把FLASH存储器映射在0x0000_0000 到 0x001F_FFFF,这里的地址空间,就是2M大小。把SDRAM映射在BANK6里面,地址空间就是0x0c00_0000 到 0x0c7f_ffff,这里就是8M的SDRAM了。
特别寄存器的地址空间是从 0x01c0_0000到0x0200_0000的4M空间里,这里的寄存器,大多数都是跟IO有关的。比如串行通讯,DMA,PWM,看门狗,IO口等等。
看懂了存寄器和存储器,就可以进行汇编练习。当然S3C44B0它还有ARM标准的寄存器,共有37个吧。这些是所有ARM的CPU都具有的。
把CPU和S3C44B0特别的功能深入了解之后,就可以去看UBOOT代码。
下一次,开始看UBOOT代码,并且动编译它,运行它,测试它,这样一定能学习好的。当然,也是在开发产品,不久,我们的产品,就可以开发出来了。

 

--------------------------------------------------------------------------------

harbincampus Post at 2007-5-26 21:35:56
学习ARM开发(6)

上一次,说到要学习ARM汇编,好,现在就开始。目前我的引导程序是在UBOOT1.1.2上修改过来的,大家可以下载UBOOT的源程序,也许你们会问在那里有下呢?这个问题不用我回答了,用GOOGLE,直接找u-boot,就可以找到了。
由于这个引导程序是从u-boot1.1.2修改过来的,所以还是采用uboot的编译工具,它就是arm-linux-tools-20031127.tar.gz,这个可以uboot的网站下载,然后在linux下安装好,就可以编译引导程序。
编译命令主要:
make clean 是清空所有临时文件,一般是用来清空目录,用来重新编译程序。
make XXXX_config 是编译本引导程序,XXXX是自己定义的开发板,在board目录下。
make backup 是备份引导程序的源程序。

UBOOT编译环境建立起来,就可以去修改和学习UBOOT的源程序,就可以开发自己的boot。源程序已经下载,就可以解开压缩包,在目录u-boot-1.1.3,因目前最新的UBOOT是1.1.2,那个1.1.3是我自己的UBOOT源程序,如果自己想改为1.1.3名称,在LINUX下编译是有点问题的,自己去试试吧。哈哈。。。
接着,我到目录cpu\s3c44b0,这个目录,就是S3C44B0的CPU引导程序,最开始运行的代码就是从这里开始的。那我看代码,也要从这里开始。
看一下这个目录,包括文件有:
G:\Downloads\lichee\lichee\boot\src\u-boot-1.1.3\cpu\s3c44b0 的目录

2005-07-18  12:47   

          .
2005-07-18  12:47              ..
2005-07-16  04:35             4,154 .depend
2004-02-24  08:16             1,066 config.mk
2004-10-18  05:12             9,878 cpu.c
2004-02-24  08:16             4,843 interrupts.c
2004-02-24  08:16             1,303 Makefile
2004-10-18  05:12             4,378 serial.c
2005-07-17  23:48             4,820 start.S
2005-07-17  23:47             4,784 start.S.bak

有好几个文件,它们的作用,大家自己先想想,不懂的再问我,目前我要开始看start.S文件,这个最开始运行的文件。
这个文件是汇编写的,但它是经过c的预处理的,所以像在头文件.h中的宏,也可以使用的,这就是GCC的博大之处。大家看到我的目录,也许很奇怪,为什么会有“lichee”这个名称?我来告知各位,这个是我起的名称,叫做“荔枝”,我的BOOT代码和我的uClinux的代号,都叫“荔枝”。吃过“荔枝”的人,都知道外面红红的,里面的肉是白的,清甜可口。我的BOOT和OS都是外面看起来很好看,里面的功能,就是难看了,但要深入去了解,才会尝到新鲜的味道。
好了,下面就要开始品尝我的“荔枝”了,第一段代码:
/*
* S3C44B0 CPU启动代码。
* 蔡军生 2005/07/17
*
*/

/*
* 包含配置文件。
*/
#include

/*
添加版本说明.
2005/07/16
*/
#include


/*
* 中断向量表.
*/

/*
× 声明标量是全局函数,CPU加电启动后,就从这里执行代码。
*/
.globl _start
_start:        b       reset                   /* 跳到复位中断开始位置。 */
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000
        add        pc, pc, #0x0c000000

        .balignl 16,0xdeadbeef

上面这段代码,看懂了吗?如果有什么不懂,就发问题过来。
这里用到ARM指令,b指令就是无条件地跳到reset的地方运行,reset是一个标记,并且它是相对量。
add        pc, pc, #0x0c000000,这句用到了4G空间跳转技术,因为ARM的CPU下一次值是根据PC的值来进行的。这里修改了PC的值,就相当跳到对应的地址运行了。又由ARM的指令的宽度是4字节的,所以这里的PC值就是0x0c000004。如果这里直接用b指令是不行的,因为它不超出32M的寻址空间,只有修改PC值才可以达到目的,因此采用ADD指令来修改PC值。
.balignl 16,0xdeadbeef
上面这句,就是填充多少字节在后面。

整段代码实现建立中断向量表,这个根据ARM的CPU来编写的。

OK,第一段代码看完了,下一次再接着看第二段代码。

 

--------------------------------------------------------------------------------

harbincampus Post at 2007-5-26 21:36:17
学习ARM开发(7)

上一次,学习到第一段代码,这次接着学习第二段代码,而第二段代码主要作用于保存数据的。
/*
*************************************************************************
*
* 启动代码。
*
* 如果不作内存初始化,就只建立堆栈,重新定位代码到RAM位置。
* 然后就可以跳到第二阶段的代码运行了。
*
*
*
*************************************************************************
*/
/* 保存变量的数据区 */

_TEXT_BASE:
        .word        TEXT_BASE

.globl _armboot_start
_armboot_start:
        .word _start

/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
        .word __bss_start

.globl _bss_end
_bss_end:
        .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
        .word        0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
        .word 0x0badc0de
#endif
上面这段代码,主要保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者其它的使用。
还有一些变量的长度是通过连接脚本里得到,实际上由编译器算出来的。

 学习ARM开发(8)
上一次看了数据区,这次要看从引导那里跳到这里执行时,运行什么东西了。
/*
* 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。
*/

reset:
        /*
         * 设置cpu运行在SVC32模式。
         */
        mrs        r0,cpsr
        bic        r0,r0,#0x1f
        orr        r0,r0,#0x13
        msr        cpsr,r0

具体分析如下:
/*
* 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。
*/

reset:
        /*
         * 设置cpu运行在SVC32模式。S3C44B0共有7种模式。
         */
        mrs        r0,cpsr
取得当前程序状态寄存器cpsr到r0。
        bic        r0,r0,#0x1f
这里使用位清除指令,把中断全部清除,只置位模式控制位。
        orr        r0,r0,#0x13
计算为超级保护模式。
        msr        cpsr,r0
设置cpsr为超级保护模式。

通过设置ARM的CPSR寄存器,让CPU运行在操作系统模式,为后面进行其它操作作好准备了。后面的代码如下:

/*
         * 当是从FLASH启动时,就要进行内存测试,当
         * 是从RAM启动时,一般就是开发本源程序时,就
         * 可以跳过。
         *
         */

#ifdef CONFIG_INIT_CRITICAL
        bl        cpu_init_crit
        /*
         * 在重新定位之前,要进行RAM访问时间测试,因为每个开发
         * 都是不一样的。
         * 可以在文件memsetup.S里看到它的说明。        
         */
        bl        memsetup
#endif

/* 进行重定位 */
relocate:                                /* 重定位Boot代码到RAM内存,比如从FLASH移到RAM            */
        adr        r0, _start                /* 把_start的相对地址移到r0    */
        ldr        r1, _TEXT_BASE                /* 把_TEXT_BASE地址,就是BOOT在RAM中运行地址 */
        cmp     r0, r1         /*  比较两个地址是否相同,如果相同,就已经在RAM运行,否则就是FLASH中运行。        */
        beq     stack_setup

        /* 是在FLASH中运行,要把FLASH中的BOOT代码移到RAM中,然后再运行. */
        ldr        r2, _armboot_start
        ldr        r3, _bss_start
        sub        r2, r3, r2                /* r2保存引导代码大小    */
        add        r2, r0, r2                /* r2保存引导代码最后地址         */

copy_loop:
        ldmia        r0!, {r3-r10}                /* 从源地址[r0]读取8个字节到寄存器,每读一个就更新一次r0地址 */
        stmia        r1!, {r3-r10}                /* 拷贝寄存器r3-r10的值保存到 [r1]指明的地址,每写一个字节,就增加1.    */
        cmp        r0, r2                        /* 判断是否拷贝到[r2]地址,就是引导代码结束位置。   */
        ble        copy_loop       /* 循环拷贝 */

/*
        拷贝中断向量表,实际是建立起二级中断向量表,当CPU中断时,先运行FLASH中断,接着就转移到实际中向表执行中断程序。
*/
        adr        r0, real_vectors
        add        r2, r0, #1024
        ldr        r1, =0x0c000000
        add        r1, r1, #0x08
vector_copy_loop:
        ldmia        r0!, {r3-r10}
        stmia        r1!, {r3-r10}
        cmp        r0, r2
        ble        vector_copy_loop

        /* 建立起堆栈                                                    */
stack_setup:
        ldr        r0, _TEXT_BASE                /* upper 128 KiB: relocated uboot   */
        sub        r0, r0, #CFG_MALLOC_LEN        /* malloc area                      */
        sub        r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#ifdef CONFIG_USE_IRQ
        sub        r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
        sub        sp, r0, #12                /* leave 3 words for abort-stack    */

        ldr        pc, _start_armboot /* 已经准备好了堆栈,就可跳到C写的代码里,
                                  由于我的代码是ARM,就是跳到
                                  lib_arm\board.c(208):void start_armboot (void)中运行。 */

_start_armboot:        .word start_armboot


/*
*************************************************************************
*
* CPU_init_critical临界区寄存器
*
* 设置一些重要的寄存器,并进行内存测试。
*
*
*************************************************************************
*/

#define INTCON (0x01c00000+0x200000) /* 中断控制器 */
#define INTMSK (0x01c00000+0x20000c) /* 中断控制屏蔽寄存器 */
#define LOCKTIME (0x01c00000+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)
cpu_init_crit:
        /* 关闭看门狗 */
        ldr         r0, =WTCON
        ldr        r1, =0x0
        str        r1, [r0]

        /*
         * 清除所有中断位,设置INTMRs实现。
         */
        ldr        r1,=INTMSK
        ldr        r0, =0x03fffeff
        str        r0, [r1]

        ldr        r1, =INTCON
        ldr        r0, =0x05
        str        r0, [r1]

        /* 设置时钟控制寄存器 */
        ldr        r1, =LOCKTIME
        ldrb        r0, =800
        strb        r0, [r1]

        /* 设置锁相环,控制CPU运行速度。 */
        ldr        r1, =PLLCON

#if CONFIG_S3C44B0_CLOCK_SPEED==66
        ldr        r0, =0x34031         /* 66MHz (Quartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
        ldr        r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz  */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif

        str        r0, [r1]

        ldr        r1,=CLKCON
        ldr        r0, =0x7ff8
        str        r0, [r1]

        /* 调用子函数返回 */
        mov        pc, lr


/*************************************************/
/*        实际的中断向量表        */
/*************************************************/
real_vectors:
        b        reset
        b        undefined_instruction
        b        software_interrupt
        b        prefetch_abort
        b        data_abort
        b        not_used
        b        irq
        b        fiq

/*************************************************/

undefined_instruction:
        mov        r6, #3
        b        reset

software_interrupt:
        mov        r6, #4
        b        reset

prefetch_abort:
        mov        r6, #5
        b        reset

data_abort:
        mov        r6, #6
        b        reset

not_used:
        /* we *should* never reach this */
        mov        r6, #7
        b        reset

irq:
        mov        r6, #8
        b        reset

fiq:
        mov        r6, #9
        b        reset


学习ARM开发(9)

上一次把引导的汇编看完,已经准备C的运行环境,下面就开始学习C的源程序,从start.S文件里到跳文件
lib_arm\board.c里运行.
/*
引导程序从汇编start.S里跳到这里执行。
蔡军生 2005/07/19
*/
void start_armboot (void)
{
        /* 声明一个全局指针,它是指向一个数据结构,用于保存参数。
        并且它占用r8寄存器,用它来保存内存地址,达到全局使用目的。
        */
        DECLARE_GLOBAL_DATA_PTR;

        ulong size;
        init_fnc_t **init_fnc_ptr;
        char *s;

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
        unsigned long addr;
#endif

        /* gd指针可写,因为已经分配一个寄存器给它作为变量。
        这里就相当于把后面算出来的地址保存到r8寄存器.
        */
        gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

        /* 下面一句是阻止3.4以上版本的GCC进行代码优化,把后面的代码删除掉。 */
        __asm__ __volatile__("": : :"memory");

        /* 清空gd指向的结构 */
        memset ((void*)gd, 0, sizeof (gd_t));

        /*  */
        gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
        memset (gd->bd, 0, sizeof (bd_t));

        monitor_flash_len = _bss_start - _armboot_start;
这一段准备好保存参数的全局变量区.
后面就是一系列的初始化和获取正确的参数.


本文来自:我爱研发网(52RD.com) - R&D大本营
详细出处:http://www.52rd.com/bbs/Archive_Thread.asp?SID=77740&TID=2