最简陋的Bootloader


本文是基于韦东山视频的学习笔记

汇总点这

u-boot是什么

嵌入式系统,最终目的,是执行用户APP。
开发板的系统怎么运行,谁引导? 引导的就是bootloader。

简单来说,bootlodaer有两种作用。

  • 最终目的就是引导Linux内核
  • 其次,他还要初始化板子的各种设备,包括系统时钟,外设

厉害一点的bootloader就是u-boot,他是裸机程序的集大成者(老生常谈了),他可以把所有外设都初始化,供给内核使用。

那么怎么玩呢?

首先得到u-boot和补丁(有些时候u-boot不一定适用于特定的板子,这时候就会有特定板子的补丁,让u-boot适配板子),“u-boot-1.1.6.tar.bz2” 和 “u-boot-1.1.6_jz2440.patch”,然后解压缩,然后打补丁

tar -xjf u-boot-1.1.6.tar.bz2
cd u-boot-1.1.6
patch -p1 < ../u-boot-1.1.6_jz2440.patch

再然后,配置编译

make 100ask24x0_config	//百问网的补丁,所以用百问网的配置命令
make

硬件相关

uboot干什么。首先是为引导内核做准备,这个流程和写裸机程序差不多的,这是关于s3c2440的uboot,我们写具体一点。

  1. 设置为svc模式
  2. 关看门狗
  3. 屏蔽中断
  4. 初始化sdram
  5. 设置栈
  6. 初始化时钟
  7. 代码重定位
  8. 清除bss段
  9. 调用start_armboot函数

要在uboot初始化串口
为什么要在bootloader初始化呢,虽然在内核都有初始化,但是在启动内核前也要用到,所以启动前也初始化咯。

重定位
问题是从哪里读,读到哪里去。
在韦老师提供的u-boot里,内核的分区是从0x60000开始,但前面是u-image。
在jz2440里,内核分区基本上是0x30008000。大小是2m。

引导内核

给内核传参

setup_start_tag();
setup_memory_tags();
setup_commandline_tag( "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
setup_end_tag();

入口函数

theKernel = (void (*)(int, int, unsigned int))0x30008000;
theKernel(0, 362, 0x30000100);

main函数

int main(void)
{
	void (*theKernel)(int zero, int arch, unsigned int params);
	volatile unsigned int *p = (volatile unsigned int *)0x30008000;

	/* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */
	uart0_init();
	
	/* 1. 从NAND FLASH里把内核读入内存 */
	puts("Copy kernel from nand\n\r");
	nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);
	puthex(0x1234ABCD);
	puts("\n\r");
	puthex(*p);
	puts("\n\r");

	/* 2. 设置参数 */
	puts("Set boot params\n\r");
	setup_start_tag();
	setup_memory_tags();
	setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
	setup_end_tag();

	/* 3. 跳转执行 */
	puts("Boot kernel\n\r");
	theKernel = (void (*)(int, int, unsigned int))0x30008000;
	theKernel(0, 362, 0x30000100);  
	/* 
	 *  mov r0, #0
	 *  ldr r1, =362
	 *  ldr r2, =0x30000100
	 *  mov pc, #0x30008000 
	 */

	puts("Error!\n\r");
	/* 如果一切正常, 不会执行到这里 */

	return -1;
}

strcpy

Copy Kernal from Nand…
Setting Parm for Kernal…
Booting Kernal…
Uncompressing Linux… done, booting the kernel.

原来是自己的strcpy函数写错了

void strcpy(unsigned char *src, unsigned char *dest)  //这里函数src和dest位置写反了...
{

	while ((*dest++ = *src++) != '\0');
}

以后程序不动了多查查循环的语句,不然真的难查

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值