s5pv210开发板刷机,分区,SD卡,emmc,nand,fastboot刷机命令,刷uboot,kernel,system,led裸机例子(二)
一、x210开发板的启动机制
SD/inand启动,第一层启动从通道0,SD0(inand/emmc)启动, 当(inand/emmc)启动做校验和时失败才会转为启动通道2,SD2(外接插入sd卡)。而我们做裸机实验时是通过SD2来提供裸机程序镜像的,因此需要先破坏内部iNand的uboot才可以强迫开发板从SD2启动去执行我们的裸机程序。
跳线帽盖住它就可以
装上usb转串口工具
二、刷机准备工作,破坏已烧录的uboot
1、uboot环境下,破坏开发板iNand中的uboot:
开发板中,已烧录过uboot,uboot环境下擦除开发板iNand或emmc中的uboot,用uboot子带的,movi指令操作sd卡,inand
接入到串口,进入uboot环境。
在uboot底下擦除uboot:
执行(输入):movi write u-boot 0x30000000 //将内存0x30000000里面的内容(应该全部是0)写入到u-boot分区(inand)里面
重启X210,发现串口中输出,表明头部校验和失败,已经转入SD卡通道启动了,检查不到sd卡
再插入烧好的SD卡,即可启动,烧录sd卡下面介绍。
2、linux和android系统环境下,擦除uboot:
如果开发板已烧录linux系统,待X210完全启动后,在SecureCRT串口中输入命令:dd命令。
共2条命令.(破坏inand第一个扇区)
busybox dd if=/dev/zero of=/dev/block/mmcblk0 bs=512 seek=1 count=1 conv=sync
输入同步命令:sync
解释:把板载的iNand的第一个扇区用全0来填充,其实就是擦除它,这样我们板载的iNand的bootloader的开始第1个扇区就被破坏了。将来启动时iROM还是会先从iNand中读取前16KB,然后计算校验和。这时候因为有1个扇区被擦掉了,所以校验和不通过,所以启动失败(会从SD2去执行2nd启动)。
注意:破坏板载iNand的bootloader后,不插外部SD卡,启动时串口得到:SD checksum Error
二、烧录uboot到sd卡
1、PC环境下,专用工具,烧录镜像到SD卡:
PC环境下,用专用工具:browse找到镜像后,点击start.将镜像复制到SD卡后,将SD卡插入至SD2口即可.(此方法只能做辅助启动,拔掉SD卡后也不能启动)
2、fastboot 工具烧录uboot:
fastboot:是windows下的一个软件,也是uboot下的一个命令.
注意:如果uboot已经被擦除,则需要将烧好的SD插入,否则X210启动不起来,无法进入控制台.
-1、用开发板,使用USB线传输连接OTG接口到电脑,打开SecureCRT串口,开机后,迅速敲回车进入控制台
在开发板的,uboot下,输入fastboot 进入fastboot刷镜像文件,输入fastboot命令
回到windowd安装驱动如下。
现在假设你已经装好相应的驱动、串口线和USB线已经插上去、DNW也打开。用到的工具fastboot
1、用 fastboot 刷Android4.0
用的镜像文件: uboot.bin,x210.img,zImage-android
还有: x210_usb.bin
2、用 fastboot 刷linux
现在开始烧录,回到Windows,Windows下fastboot工具如下,有一个adb,fastboot应用程序,这是通用下载的。
建立如图Android文件夹,放入镜像
进入windous的cmd控制台DOS下操作,去到fastboot目录下,切换到fastboot.exe所在的文件夹里面(我的电脑文件路径是: E:\fastboot)
相关操作命令:
切换到d盘符如下
然后进入fastboot目录
切换命令:cd E:\fastboot
进入命令:dir //显示当前文件夹里的文件相关信息
查看命令: fastboot devices //命令用来查看当前连接的设备。
表明已经检测到设备,下面就开始烧录镜像文件了.共有3个文件,这3个文件均需自己拷贝至e:\fastboot文件夹里面.
fastboot命令格式
fastboot flash bootloader xxxxx
fastboot flash kernel xxxxx
fastboot flash system xxxxx
fastboot -w
分别执行:
烧uboot:
fastboot flash bootloader android4.0.4/uboot.bin
烧linux kernel:
fastboot flash kernel android4.0.4/zImage-android
烧android rom:
fastboot flash system android4.0.4/x210.img
一般:我们破坏的是uboot,所以我们只需要烧录uboot即可:
重启命令:fastboot reboot //命令用来重启系统
四、从usb启动,dnw刷机
上面刷机出现问题,没有分区,是不能刷机的,所以可以通过dnw,刷机到SDRAM,内存,直接运行,不刷到flash(inand,emmc)
23e00000地址是内存的地址,x210_usb.bin文件时初始化ddr的,使代码可以在上面运行
步骤如下
①:拨码OM5拨上去;如 [OM0:OM5]=[101101]。后面两位不管。
②:按住开机键,DNW配置下载地址d0020010,USB下x210_usb.bin,
③:DNW配置下载地址23e00000,USB下载uboot.bin
④:这时串口终端有信息打印出来,回车进入命令行,这时可以松开 开机键,
⑤: 输入fdisk -c 0 重新分区
⑥:烧录完了之后OM5拨回来,手动重启机器即可。
DNW配置下载地址d0020010,USB下x210_usb.bin,
烧录完,需要快速按回车键,进入uboot下,否则启动完,又不能启动了,因为重启后,又去找flash的uboot,启动不起来
对inand或emmc进行分区
输入fastboot命令,可以看到分区表,同时,进入到Windows下,fastboot烧录镜像了。
五、linux,Ubuntu系统下,dd命令写sd卡,来烧录uboot
用卡套将sd卡插入Windows电脑,接连到ubuntu。
将sd卡链接到Ubuntu下,ls查看下
/dev/sda是电脑的硬盘。/dev/sda1,/dev/sda2是c盘,d盘。/dev/sdb是插入的u盘,sd卡。/dev/sdb1是分区,扇区1
执行shell脚本文件,写入sd卡
#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1
六、补充,各种dnw工具安装失败
在Windows上装成功了,dnw驱动,显示如下
上面是在Windows上,使用dnw,很多电脑是无法装上的,就要使用linux环境来使用dnw。
下面是在linux,ubuntu下,使用命令,使用dnw刷机。
网上下载一个dnw下载驱动代码。编译,安装后,用命令进行下载
把开发板连接到ubuntu下。ls /dev/secbuk0,有这个玩意,就安装成功了。
七、刷写led.bin到sd卡启动程序
x210的三星芯片,启动时,需要校验bl1,把头部16字节加在bl1前面,才能烧录进去,启动,防止被篡改,或烧录错误
led汇编,点亮led,start.s
设置为输出,高电平,点亮led
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
// 第一步:把所有引脚都设置为输出模式,代码不变
ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数
ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令
str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去
// 要实现流水灯,只要在主循环中实现1圈的流水显示效果即可,flsah闪铄
flash:
// 第1步:点亮LED1,其他熄灭
//ldr r0, =((0<<3) | (1<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮
ldr r0, =~(1<<3)
ldr r1, =GPJ0DAT
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
// 然后延时
bl delay // 使用bl进行函数调用
// 第2步:点亮LED2,其他熄灭
ldr r0, =~(1<<4)
ldr r1, =GPJ0DAT
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
// 然后延时
bl delay // 使用bl进行函数调用
// 第3步:点亮LED3,其他熄灭
ldr r0, =~(1<<5)
ldr r1, =GPJ0DAT
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
// 然后延时
bl delay // 使用bl进行函数调用
b flash //跳转到闪烁函数flash,死循环
// 延时函数:函数名:delay
delay:
ldr r2, =9000000
ldr r3, =0x0
delay_loop:
sub r2, r2, #1 //sub 减指令,减1
cmp r2, r3 // cmp比较指令,会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立
bne delay_loop //cmp不相等,继续跳转到delay_loop
mov pc, lr // cmp相等,则函数调用返回,lr放了上面调用返回地址
Makefile
led.bin: led.o
arm-linux-ld -Ttext 0x0 -o led.elf $^
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led_elf.dis
gcc mkv210_image.c -o mkx210
./mkx210 led.bin 210.bin
%.o : %.S
arm-linux-gcc -o $@ $< -c
%.o : %.c
arm-linux-gcc -o $@ $< -c
clean:
rm *.o *.elf *.bin *.dis mkx210 -f
16字节的分布如下,
第1-4字节是bl大小,
第5-8字节是保留写0,
第9-12个是校验和,
第13-16个是保留写0
mkv210_image.c的主要作用就是由usb启动时使用的led.bin制作得到由sd卡启动的镜像210.bin
/*
* mkv210_image.c的主要作用就是由usb启动时使用的led.bin制作得到由sd卡启动的镜像210.bin
*
* 本文件来自于友善之臂的裸机教程,据友善之臂的文档中讲述,本文件是一个热心网友提供,在此表示感谢。
*/
/* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容,
* 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE (16*1024)
#define IMG_SIZE (16*1024)
#define SPL_HEADER_SIZE 16
//#define SPL_HEADER "S5PC110 HEADER "
#define SPL_HEADER "****************"
int main (int argc, char *argv[])
{
FILE *fp;
char *Buf, *a;
int BufLen;
int nbytes, fileLen;
unsigned int checksum, count;
int i;
// 1. 3个参数
if (argc != 3)
{
printf("Usage: %s <source file> <destination file>\n", argv[0]);
return -1;
}
// 2. 分配16K的buffer
BufLen = BUFSIZE;
Buf = (char *)malloc(BufLen);
if (!Buf)
{
printf("Alloc buffer failed!\n");
return -1;
}
memset(Buf, 0x00, BufLen);
// 3. 读源bin到buffer
// 3.1 打开源bin
fp = fopen(argv[1], "rb");
if( fp == NULL)
{
printf("source file open error\n");
free(Buf);
return -1;
}
// 3.2 获取源bin长度
fseek(fp, 0L, SEEK_END); // 定位到文件尾
fileLen = ftell(fp); // 得到文件长度
fseek(fp, 0L, SEEK_SET); // 再次定位到文件头
// 3.3 源bin长度不得超过16K-16byte
count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
// 3.4 buffer[0~15]存放"S5PC110 HEADER "
memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);
// 3.5 读源bin到buffer[16]
nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);
if ( nbytes != count )
{
printf("source file read error\n");
free(Buf);
fclose(fp);
return -1;
}
fclose(fp);
// 4. 计算校验和
// 4.1 从第16byte开始统计buffer中共有几个1
// 4.1 从第16byte开始计算,把buffer中所有的字节数据加和起来得到的结果
a = Buf + SPL_HEADER_SIZE;
for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
checksum += (0x000000FF) & *a++;
// 4.2 将校验和保存在buffer[8~15]
a = Buf + 8; // Buf是210.bin的起始地址,+8表示向后位移2个字,也就是说写入到第3个字
*( (unsigned int *)a ) = checksum;
// 5. 拷贝buffer中的内容到目的bin
// 5.1 打开目的bin
fp = fopen(argv[2], "wb");
if (fp == NULL)
{
printf("destination file open error\n");
free(Buf);
return -1;
}
// 5.2 将16k的buffer拷贝到目的bin中
a = Buf;
nbytes = fwrite( a, 1, BufLen, fp);
if ( nbytes != BufLen )
{
printf("destination file write error\n");
free(Buf);
fclose(fp);
return -1;
}
free(Buf);
fclose(fp);
return 0;
}
write2sd shell脚本文件,写入到镜像到SD卡
#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1