2. 驱动初步-------裸机启动流程

一、裸机的概念

裸机就是没有操作系统的程序,裸机有些情况下执行效率是比较高的,但裸机也有弊端,就是它不能做大型的功能。

二、exynos4412内部存储器

要想写一段代码去驱动led灯,要具备两个条件:① 代码存放在什么位置     ② 代码运行在什么位置

stm32 芯片里有个cpu自带的存储  ROM和RAM

                     cpu的外部  挂了两个个DDR3 512M的内存 和一个4G大小的EMMC

                     当我的cpu一上电  他能不能直接执行emmc里的程序?不能

                     要想emmc或者ddr3能使用  首先必须要先驱动起来他们

                     要想能执行自己的代码  就要从cpu自身的启动流程来分析

                     cpu是先执行自己自带的存储里的东西  

                     通过自带的存储里的代码  然后驱动其他的外设

                     stm32 自带的存储 512k ROM 64k RAM

                     高端的芯片   exynos4412内部也集成了类似的东西

                     IROM 64K  IRAM 256k

                     芯片不需要有驱动程序就能访问IRAM 和IROM里的东西

                     我们的led灯的裸机代码  就可以放在这个位置

三、exynos4412启动流程分析

第一阶段:BL0

                     固化在cpu内部存储里的

                     这个代码我们无法操作 是由三星公司写好的

                     初始化一些环境信息

                     并且下载BL1的代码

                     校验BL1的代码   并且执行BL1

 第二个阶段:BL1

                     假如启动介质是sd的话

                     他的位置  就是在sd卡的第一个分区的 第1-16扇区

                     这个代码由三星公司提供  我们需要将他烧录到sd的特定位置

                     下载BL2并且校验  运行BL2的代码

第三个阶段:BL2

                     假如启动介质是sd的话

                     他的位置就是sd卡的第一个分区的  第17-48扇区

                     这个代码三星公司并没有提供

                     三星公司只是给了一个建议

                     建议我们的BL2的代码去启动os

                     但是我们可以不遵循他的建议  来在这个位置写我们自己的代码

                     运行位置 0x02023400

四、裸机点亮led灯

要想点亮led灯,首先我们要知道以下信息:

                     led的引脚的位置(是第几个引脚)

                     led灯的有效电平(有效电平是低电平)

                     led相关的寄存器的信息

                            控制寄存器(主要是用来控制引脚的工作模式)

                            数据寄存器(给引脚数据)

五、编写led灯的程序           

#define GPM4_CON (*((unsigned int *)0x110002E0))            //同时打开四个灯
#define GPM4_DAT (*((unsigned int *)0x110002E4))

int main()
{
	//1:设置控制寄存器的工作模式
		GPM4_CON &= ~(0xFFFF);//清零
		GPM4_CON |= 0x1111;  //设置工作模式为输出
	//2:点亮led灯
		GPM4_DAT &= ~(0xF);	//点亮4个LED灯
	return 0;
}
#define GPM4_CON (*((unsigned int *)0x110002E0))            //流水灯及蜂鸣器
#define GPM4_DAT (*((unsigned int *)0x110002E4))
#define GPD0_CON (*((unsigned int *)0x114000A0))
#define GPD0_DAT (*((unsigned int *)0x114000A4))

void mydelay(int msc);

int main()
{
	while(1)
	{
	    //1:设置控制寄存器的工作模式
		GPM4_CON &= ~(0xFFFF); //LED灯清零
		GPD0_CON &= ~(0xF); //蜂鸣器清零
		GPM4_CON |= 0x1111; //设置LED灯工作模式为输出
		GPD0_CON |= 0x1;//设置蜂鸣器工作模式为输出

		//2:点亮led灯、打开蜂鸣器	
		GPM4_DAT &= ~(0x1); //点亮第一个灯
		GPD0_DAT &= ~(0x1); //打开蜂鸣器
		mydelay(50000);
		GPM4_DAT |=0xF; //关闭所有的灯

		GPM4_DAT &= ~(0x1<<1); //点亮第二个灯	
		mydelay(50000);
		GPM4_DAT |=0xF; //关闭所有的灯

		GPM4_DAT &= ~(0x1<<2); //点亮第三个灯		
		mydelay(50000);
		GPD0_DAT |=0xF; //关闭蜂鸣器
		GPM4_DAT |=0xF; //关闭所有的灯

		GPM4_DAT &= ~(0x1<<3); //点亮第四个灯
		GPM4_DAT &= ~(0xF);	
		mydelay(50000);
		GPM4_DAT |=0xF; //关闭所有的灯
	}		
	return 0;
}

//延时函数
void mydelay(int msc)
{
	while(msc--);
}

六、程序下载的说明

我们所写的代码要想能运行  必须放到BL2的位置

                     0号扇区  保留扇区

                     1-16:存放的BL1的代码

                     17-48:存放的是BL2的代码

                     烧录bl1

                     sudo dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=/dev/sdb seek=1

                     烧录BL2

                     sudo dd iflag=dsync oflag=dsync if=./main of=/dev/sdb seek=17

                     led灯并没有像我们想象的那样被点亮

                     为什么

                     问题出在架构问题

                     现在所编译的代码  是在下x86主机上编译的

                     并不能直接的在ARM架构上去执行 

                     要想我们的程序能够在ARM架构上正常的运行

                     就需要我们安装交叉编译工具

七、交叉编译工具的安装(重要)

补充:本次开发使用的编译器为 arm-linux-gcc,使用的为 4.5.1 版本,通过 arm-linux-gcc -v 查看版本号

2. 驱动初步-------裸机启动流程_第1张图片

-E:执行到编译预处理就停止,生成.i 的编译预处理文件。

-S:执行到汇编就停止,生成.s 汇编文件。

-c:只编译不链接。生成.o 文件。

-o:生成目标文件,后面必须接生成的文件。 arm-linux-ld将一个.o文件链接生成可执行程序。

-Ttext 指定代码段编译地址。 arm-linux-objcopy 不同文件之间的格式转换。

bin 文件:纯净的二进制文件,没有地址标记。

hex 文件:有地址标记。Intel HEX 文件是记录文本行的 ASCII 文本文件。16 进制文件。

(1)这里我先新创建了一个目录文件,准备将交叉编译工具的压缩包放在这里

2. 驱动初步-------裸机启动流程_第2张图片

(2)将交叉编译工具的压缩包拷贝到虚拟机中新创建的一个目录中

2. 驱动初步-------裸机启动流程_第3张图片

(3)在压缩包所在目录下解压压缩包:tar xvf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz

2. 驱动初步-------裸机启动流程_第4张图片

(4)将解压后交叉编译工具所在的位置添加到环境变量里

首先通过以下步骤获取bin文件路径,找到后将它复制一下

2. 驱动初步-------裸机启动流程_第5张图片

 然后,进入/etc/profile文件,在这个文件的最后追加上刚才复制的bin文件路径,以方便我们在任意的位置都能执行这个指令

ldw@LDW:~/linux_driver/opt/FriendlyARM/toolschain/4.5.1/bin$ sudo gedit /etc/profile

2. 驱动初步-------裸机启动流程_第6张图片

之后,会出现以下警告,不用管它,重新启动虚拟机

(5)安装兼容库

        sudo apt-get install lib32ncurses5-dev

        sudo apt-get install lib32z1

(6)验证交叉编译工具的安装情况

在任意的位置输入指令:arm-linux-gcc -v

当出现 gcc version 4.5.1 (ctng-1.8.1-FA)   就表示交叉编译工具安装完成了

2. 驱动初步-------裸机启动流程_第7张图片

八、用交叉编译工具编译代码并烧录代码

(1)只编译不链接

        arm-linux-gcc -c main.c -o main.o

(2)将代码的启动位置指定为 0x02023400

        arm-linux-ld -Ttext 0x02023400 -o main.elf main.o

(3)编译成二进制的文件

        arm-linux-objcopy -O binary main.elf main.bin

(4)添加偶校验的工具:三星要求BL2后边必须加上偶校验,偶校验的源码三星已经提供

        gcc V310-EVT1-mkbl2.c -o mkbl2

(5)将代码加上偶校验

        ./mkbl2 main.bin bl2.bin 14336

(6)将BL1、BL2代码烧录到sd卡的17扇区

首先,把BL1的bin文件拷贝到虚拟机中

2. 驱动初步-------裸机启动流程_第8张图片

烧录BL1:sudo dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=/dev/sdb seek=1 

烧录BL2:sudo dd iflag=dsync oflag=dsync if=./bl2.bin of=/dev/sdb seek=17

2. 驱动初步-------裸机启动流程_第9张图片

你可能感兴趣的:(Linux驱动,java,前端,javascript)