目录
一.基本概念
1处理器
2.两种结构
3.芯片是如何外扩的RAM
4.编址
5.裸机开发与系统开发
6.EMMC与NAND flash
7.EMMC与SD启动数据存储
8.SRAM与DRAM
9.硬件层与软件层
二.裸机SD卡启动流程(不加载uboot)
1.芯片内部地址分布(向上)
2.外部存储设备地址(第0扇区与第1扇区)
三.实现
1.编写程序
2.编译
3.扩展bin文件到14k
4.下载BL1和BL2到SD卡
5.选择SD卡启动
四.注意点
采用Tiny4412
一.基本概念
1处理器
CPU:中央处理器
MCU:微处理器 (内部涵盖CPU,一些片内外设)
MPU:微控制器(性能更强的微处理器)
SOC:system on chip 片上系统(涵盖MCU(MPU)、外设、RAM ROM等---是一个系统)
ARM基本上采用SOC架构
2.两种结构
哈弗结构:指令总线和数据总线分开分开(流水线处理)。指令存储在flash中,数据存储到RAM中。CPU从flash中取指令,从RAM中取数据
MCU的指令和数据需求量都不大,配置不高且ARM能用相同的指令,不同的地址值,分别获取 数据 和 程序 的值,就说明它只是一个地址空间。(ARM Cortex-M系列)
MCU也就是单片机中几乎都是用哈佛结构,譬如广泛使用的51单片机、典型的STM32单片机(核心是ARM Cortex-M系列的)都是哈佛结构
冯诺依曼结构:数据空间和地址空间不分开。运行的时候程序和数据放在同一个存储器(RAM中),共用一条存储总线。当系统没电的时候,程序和数据存储硬盘中,当系统上电,会在硬盘中执行一小段程序,将所有数据和程序搬运到RAM中运行
PC和服务器芯片(譬如Intel AMD那些出的),ARMCortex-A系列嵌入式芯片(譬如核心是ARM CortexA8的三星S5PV210,譬如华为的麒麟970等手机芯片)等都是冯诺依曼结构
3.芯片是如何外扩的RAM
拿32位芯片来讲,能访问的地址空间是2^32次方(4G地址空间),4G空间内拿出一部分给串口、IIC等片内外设以及RAM,剩下的地址空间就可以外扩RAM。
4.编址
独立编址:ROM 寄存器相互独立互不影响。CPU通过某些协议访问ROM
统一编址:片内RAM和外扩RAM可以被CPU直接访问
5.裸机开发与系统开发
裸机:程序直接在开发板自带的RAM运行,代码大小小于14K
操作系统:加载操作系统后代码大于14K,需要运行在外扩RAM上
6.EMMC与NAND flash
EMMC:消费电子领域 抗干扰能力差---手机
NAND flash:电子类,抗干扰能力强 贵
7.EMMC与SD启动数据存储
EMMC:从第0扇区开始 0x0202_0000
SD:从第1扇区开始 0x0206_0000 差256kb
还有NAND、USB
存储地址:加载地址,位于启动设备中的地址(sd\emmc\nand) BL2位于第17扇区(EMMC是16)。
运行地址:链接地址,运行的内存地址 BL2位于0x02023400
8.SRAM与DRAM
SRAM:静态存储器 位于SOC内 成本较高、运存少、运行速度快
DRAM:动态存储器 外扩RAM
9.硬件层与软件层
硬件层:为了解决字节传输问题
软件层:解释每个字节代表含义
二.裸机SD卡启动流程(不加载uboot)
BootLoader1:芯片厂家提供bin文件
BootLoader2:BL2是用户代码,大小为14K,其中最后4个字节为和校验
芯片上电后,先运行iROM中的出厂固件,该程序会通知CPU从(SD卡、EMMC、NAND等)搬运BootLoader1到SRAM的0x02021400地址中运行。BL1会从SD卡的第17块开始搬运BootLoader2(14K)到SRAM的0x02023400运行
1.芯片内部地址分布(向上)
2.外部存储设备地址(第0扇区与第1扇区)
三.实现
1.编写程序
#define GPM4CON (*(volatile unsigned int *)0x110002E0)
#define GPM4DAT (*(volatile unsigned int *)0x110002E4)
//KEY有关寄存器 按下按下输入低电平
#define GPX3CON (*(volatile unsigned int *)0x11000C60)
#define GPX3DAT (*(volatile unsigned int *)0x11000C64)
#define GPX3PUD (*(volatile unsigned int *)0x11000C68)
#define Led1(x) x?(GPM4DAT &= ~(1<<0)):(GPM4DAT|=1<<0)
#define Led2(x) x?(GPM4DAT &= ~(1<<1)):(GPM4DAT|=1<<1)
#define Led3(x) x?(GPM4DAT &= ~(1<<2)):(GPM4DAT|=1<<2)
#define Led4(x) x?(GPM4DAT &= ~(1<<3)):(GPM4DAT|=1<<3)
void Led_Init(void);
void Key_Init(void);
void delay_ms(unsigned int num);
int main(void)
{
int value = 0;
Led_Init();
Key_Init();
Led1(1);
delay_ms(1000);
Led1(0);
while(1)
{
value = GPX3DAT; //读取GPX3电平状态
if(value & (1<<2)) //Key1 --> GPX3_2
{
Led1(0);
}else{
Led1(1);
}
if(value & (1<<3)) //Key2 --> GPX3_3
{
Led2(0);
}else{
Led2(1);
}
if(value & (1<<4)) //Key3 --> GPX3_4
{
Led3(0);
}else{
Led3(1);
}
if(value & (1<<5)) //Key4 --> GPX3_5
{
Led4(0);
}else{
Led4(1);
}
}
return 0;
}
void Led_Init(void)
{
GPM4CON &= ~((0xf<<3*4)|(0xf<<2*4)|(0xf<<1*4)|(0xf<<0*4));
GPM4CON |= ((1<<3*4)|(1<<2*4)|(1<<1*4)|(1<<0*4));
GPM4DAT |= (1<<0)|(1<<1)|(1<<2)|(1<<3);
}
void Key_Init(void)
{
GPX3CON &= ~((0xf<<2*4)|(0xf<<3*4)|(0xf<<4*4)|(0xf<<5*4));
//GPX3PUD |= (0x3<<2*2)|(0x3<<3*2)|(0x3<<4*2)|((0x3<<5*2));
}
void delay_ms(unsigned int num)
{
int i,j;
for(i=num; i>0;i--)
{
for(j=1000;j>0;j--)
{
;
}
}
}
2.编译
- 将.c文件链接成.o文件 链接作用:链接的主要内容就是将各个模块之间相互引用的部分正确的衔接起来。它的工作就是把一些指令对其他符号地址的引用加以修正。链接过程主要包括了地址和空间分配、符号决议和重定向
- -Ttext:绑定裸机代码在SRAM运行的地址
- elf就是.o基础上加了数据头 如果存在多个函数,0x02023400 会在给定程序的第一个函数执行(解决:main下定义,main上声明)
- bin文件是纯粹的二进制文件
使用的时候指定make file=编译文件名
file?=2
$(file).bin:$(file).o
arm-linux-ld -Ttext 0x02023400 $(file).o -o $(file).elf
arm-linux-objcopy -O binary $(file).elf $(file).bin
$(file).o:$(file.c
arm-linux-gcc -c $(file).c -o $(file).o
clean:
rm *.o *.elf *.bin -f
3.扩展bin文件到14k
裸机启动要求BL2必须为14k,当用户代码不足14k,需要扩展成14K代码
先把V310-EVT1-mkbl2.c源代码编译成mkbl2。在sd_fuse目录下执行make
再使用mkbl2程序把led.bin变为14k的bl2.bin。./mkbl2 ./test.bin bl2.bin 14336(14k)
4.下载BL1和BL2到SD卡
下载之前先把SD挂接到虚拟机,并且查看挂机的节点名是什么
把BL1(E4412_N.bl1.bin)下载到SD卡的第1块
dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=/dev/sdb seek=1
把BL2(bl2.bin)下载到SD卡的第17块
dd iflag=dsync oflag=dsync if=./bl2.bin of=/dev/sdb seek=17
5.选择SD卡启动
shell
输入节点名与bin文件名
ls /dev/sd* -l
read A
read B
./mkbl2 ../${B}.bin bl2.bin 14336
dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=/dev/${A} seek=1
dd iflag=dsync oflag=dsync if=./bl2.bin of=/dev/${A} seek=17
四.注意点
系统复位后:
iROM运行从启动设备(sd卡,emmc)中加载BL1到SRAM
BL1运行后从启动设备中加载BL2(用户代码的前14K)到SRAM
如果用户代码小于14K,就直接在iRAM中运行,如果大于14K,BL2负责完成把所有用户程序搬运到外部运存(DDR3)运行的工作
iROM:固化在片内的一段代码,用户不能修改。
1、关看门狗,关中断和MMU,关D-cache,I-cache,失效TLB表和cache,让CORE1进入空闲,初始化栈,初始化Zi,RW段,注册函数指针。
2、判断启动方式,从对应启动设备中加载BL1到SRAM中,然后对BL1进行校验和检测,加密校验,解密处理,最后跳转到BL1代码执行。
BL1:和平台无关的代码,由三星提供的,属于芯片级的代码。
1、重新初始化IRQ,SVC模式的栈,判断启动设备,然后从对应的启动设备中加载BL2到SRAM中,
2、然后判断是否启动安全模式,如果是,则对BL2进行校验,校验通过则跳转到BL2代码中执行。
BL2:是平台相关的一部分代码。由开发平台厂家自己编写。
1、重新初始化IRQ,SVC模式的栈,设置时钟,初始化外扩的DRAM,判断启动设备,然后从相应的启动设备中读取用户代码到DRAM中,
2、然后判断是否启动安全模式,如果是,则对BL2进行校验,校验通过则跳转到用户代码中执行。