一闪一闪亮晶晶,满天都是小星星……
今天,我为你摘下一颗星,闪给你看……只有一颗喔……
《exynos4412 启动过程》一文中讲过,bootloader的作用主要是初始化操作系统启动所需的环境,并引导操作系统。
现在不需要操作系统,我们仅需要让LED闪灯,能不能把引导操作系统,变成引导我们的裸机程序main呢?
我们的u-boot,其实就是一个大的裸机程序,只要把它改成我们的led闪灯程序就行了。
《uboot 编译、生成、运行》一文中讲到,最终烧录入sd卡的u-boot,是这样得来的:
cat E4412.S.BL1.SSCR.EVT1.1.bin E4412.BL2.TZ.SSCR.EVT1.1.bin all00_padding.bin u-boot.bin E4412.TZ.SSCR.EVT1.1.bin > u-boot-iTOP-4412.bin
这句生成最终的 u-boot-iTOP-4412.bin 文件,是我们最终烧录进板卡的 bootloader。
其中,
4412.S.BL1.SSCR.EVT1.1.bin 大小 8k,是由三星提供的 BL1;
E4412.BL2.TZ.SSCR.EVT1.1.bin+all00_padding.bin,总共16K,是由三星提供的 BL2;
u-boot.bin 大小328k,是自个源码编译生成的,如果我们的源码不够328k,sdfuse_q/add_padding会自动补足(在Makefile中有一句@./sdfuse_q/add_padding),所以,u-boot.bin不管怎么编译,都是 328k;
所以,我们只要把我们的led闪灯程序,编译成led.bin,再把4412.S.BL1.SSCR.EVT1.1.bin+ E4412.BL2.TZ.SSCR.EVT1.1.bin+all00_padding.bin+led.bin+E4412.TZ.SSCR.EVT1.1.bin拼成我们最终.bin,再写进SD卡里面就行了。
编写程序前,应该先
1、查看原理图,确定LED灯所对应的IO口;
2、查看芯片资料,确定如何初始化IO,以及控制IO高和低(灯亮和灯灭);
1、查看原理图,确定LED灯所对应的IO口;
LED3对应的IO口是GPK1_1,从电路图可以看出,VDD50_EN高电平时,三极管通,LED3亮,低电平时,三极管不通,LED3灭。
2、查看芯片资料,确定如何初始化IO,以及控制IO高和低(灯亮和灯灭);
GPK1CON寄存器的地址是0x1100_0000+0x0000_0060,对应的IO口GPK1_1在[7:4]位,应配置为0x1(output),所以,初始化GPK1_1可以:
*(volatile unsigned long *)0x11000060 &= (~0xf0);
*(volatile unsigned long *)0x11000060 |= (0x1<<4);
GPK1DAT寄存器的地址是0x1100_0000+0x0000_0064,对应的IO口GPK1_1在[1]位,配置为1时,高电平,灯亮,配置为0时,低电平,灯灭,所以,控制灯可以:
*(volatile unsigned long *)0x11000064 |= (0x2); // IO高,灯亮
*(volatile unsigned long *)0x11000064 &= (~0x2); // IO低,灯灭
知道如何初始化,以及如何操作IO口,使灯亮灭后,可以开始编写闪灯程序了,编写闪灯程序分几个步骤:
1、main文件,由C语言编写,主要负责初始化led,以及闪灯;
2、start文件,由汇编语言编写,主要负责设置堆栈,并跳转至main;
3、Makefile,主要负责make,不熟悉的同学,请移步《Makefile 基础》;
4、./build.sh,linux shell文件,由一些命令组成,主要负责编译,把led.bin补足 328k,拼bl1+bl2+led.bin,等等;
5、mkuboot,linux shell文件,由一些命令组成,主要负责把最终的bin文件,写进SD卡里;
1、main文件,由C语言编写,主要负责初始化led,以及闪灯;
#define GPK1CON (*(volatile unsigned long*)0x11000060)
#define GPK1DAT (*(volatile unsigned long*)0x11000064)
enum
{
OFF,
ON,
};
static void user_delay(unsigned int val)
{
unsigned i, j;
for(i=0; i
2、start文件,由汇编语言编写,主要负责设置堆栈,并跳转至main;
.text
.globl _start
_start:
b reset
reset:
/* i don't know why init GPX0CONF?*/
/* but if you don't init it, it will reset system every few seconds */
ldr r0, =0x11000c08
ldr r1, =0x0
str r1, [r0]
ldr sp, = 0x02050000 // 设置堆栈
bl main // 跳转至入口函数 main
3、Makefile,主要负责make,不熟悉的同学,请移步《Makefile 基础》;
.PHONY: led.bin
led.bin:start.o led.o
arm-none-linux-gnueabi-ld -Ttext 0x0 -o led.elf $^
arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
arm-none-linux-gnueabi-objdump -D led.elf > led.dis
.PHONY: %.o
%.o:%.S
arm-none-linux-gnueabi-gcc -g -c -o $@ $< -nostdlib
%.o:%.c
arm-none-linux-gnueabi-gcc -g -c -o $@ $< -nostdlib
.PHONY: clean
clean:
rm *.o *.elf *.bin *.dis -f
4、./build.sh,linux shell文件,由一些命令组成,主要负责编译,把led.bin补足 328k,拼bl1+bl2+led.bin,等等;
需要把 ./add_padding 拷进去,用于补足 led.bin 328k大小;
需要把4412.S.BL1.SSCR.EVT1.1.bin、E4412.BL2.TZ.SSCR.EVT1.1.bin、all00_padding.bin、E4412.TZ.SSCR.EVT1.1.bin 拷进去,用来拼成最终烧录的文件;
#!/bin/sh
#执行 make,编译生成 led.bin
make
#把 led.bin 拷进 sdfuse_q,名为 u-boot.bin,方便补全和拼接
cp -r led.bin sdfuse_q/u-boot.bin
#进入 sdfuse_q目录,并执行./add_padding,补全,执行后,u-boot.bin大小为328k
cd sdfuse_q
./add_padding
#拼接,bl1+bl2+u-boot.bin+tzsw = u-boot-final.bin
cat E4412.S.BL1.SSCR.EVT1.1.bin E4412.BL2.TZ.SSCR.EVT1.1.bin all00_padding.bin u-boot.bin E4412.TZ.SSCR.EVT1.1.bin > u-boot-final.bin
#把最终文件移到上一级目录下
mv u-boot-final.bin ../
rm u-boot.bin
5、mkuboot,linux shell文件,由一些命令组成,主要负责把最终的bin文件,写进SD卡里;
其实这个文件就是执行./sd_fusing_exynos4x12.sh,./sd_fusing_exynos4x12.sh就是执行 linux cc 命令
#!/bin/bash
#
# This script will create a u-boot binary for movinand/mmc boot
#
#改权限
chmod 777 sdfuse_q -R
echo "Fuse iTOP-4412 trustzone uboot file into SD card"
cd ./sdfuse_q
if [ -z $1 ]
then
./sd_fusing_exynos4x12.sh /dev/sdb u-boot-final.bin
else
./sd_fusing_exynos4x12.sh $1 u-boot-final.bin
fi
cd ..
这就把u-boot-final.bin写进SD卡了。
把拨码开关拔到SD卡启动,插入SD卡,上电,看,LED闪了喔~~~
这就是我们的闪灯u-boot啊,源代码包:https://download.csdn.net/download/foreverit/11248103