目录

  • 简单BootLoader
  • 概述
  • NOR与NAND启动
  • 链接脚本规划
  • 初始化规划
  • 参数设置

简单BootLoader

概述

目标: 启动内核,也就是需要读取内核到内存,也就是操作flash和内存

一个最基本的BootLoader应该有以下步骤:

  1. 初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH
  2. 如果bootloader比较大,要把它重定位到SDRAM
  3. 把内核从NAND FLASH读到SDRAM
  4. 设置要传给内核的参数
  5. 跳转执行内核

优化: 为了加快运行速度,应该提高主频,打开Icach

    /* 启动ICACHE */mrc p15, 0, r0, c1, c0, 0   @ read control regorr r0, r0, #(1<<12)mcr p15, 0, r0, c1, c0, 0   @ write it back

NOR与NAND启动

参考文档 ARM裸机>启动流程

  • NAND 启动自动复制到4KRAM

  • NOR启动,片内RAM为0x4000,0000

链接脚本规划

我们从上图可以看到,SDRAM的起始地址为0x3000,0000,SDRAM大小为64M,也就是地址顶端为0x3400,0000.预留512K给Bootloader,也就是规划hex(0x34000000-512*1024)=0x33f8,0000为Bootloader的起始地址.链接脚本考虑字节对齐.

SECTIONS {. = 0x33f80000;.text : { *(.text) }. = ALIGN(4);.rodata : {*(.rodata*)} . = ALIGN(4);.data : { *(.data) }. = ALIGN(4);__bss_start = .;.bss : { *(.bss)  *(COMMON) }__bss_end = .;
}

链接脚本中有个COMMON段,这是未初始化的全局变量,一般情况下也是直接在链接阶段放在bss段进行清零.但是注意未初始化的全局变量与初始化为0的全局变量,并不对等.[未初始化的全局变量(COMMON段)为弱符号,如果有同名的全局变量,可能会存在覆盖的情况]

对于全局变量来说,如果初始化了不为0的值,那么该全局变量则被保存在data段,如果初始化的值为0,那么将其保存在bss段,如果没有初始化,则将其保存在common段,等到链接时再将其放入到BSS段。关于第三点不同编译器行为会不同,有的编译器会把没有初始化的全局变量直接放到BSS段。

链接脚本中值的获取,具体参考./链接脚本.md

//汇编方法1
.global _bss_start
_bss_start:.word __bss_start
ldr r1, _bss_start  //读取内存,这里是读取label所在内存的数据
//汇编方法2
ldr r1, =__bss_start
//C方法
extern int __bss_start;
int val =&__bss_start;  //!< 获得__bss_start的值

初始化规划


#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
#define MEM_CTL_BASE    0x48000000.text
.global _start
_start:/* 1. 关看门狗 */ldr r0, =0x53000000mov r1, #0str r1, [r0]/* 2. 设置时钟 */ldr r0, =0x4c000014//  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8str r1, [r0]/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */mrc p15, 0, r1, c1, c0, 0       /* 读出控制寄存器 */ orr r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */mcr p15, 0, r1, c1, c0, 0       /* 写入控制寄存器 *//* MPLLCON = S3C2440_MPLL_200MHZ */ldr r0, =0x4c000004ldr r1, =S3C2440_MPLL_400MHZstr r1, [r0]/* 启动ICACHE */mrc p15, 0, r0, c1, c0, 0   @ read control regorr r0, r0, #(1<<12)mcr p15, 0, r0, c1, c0, 0   @ write it back/* 3. 初始化SDRAM */ldr r0, =MEM_CTL_BASEadr r1, sdram_config     /* sdram_config的当前地址 */add r3, r0, #(13*4)
1:ldr r2, [r1], #4str r2, [r0], #4cmp r0, r3bne 1b/* 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */ldr sp, =0x34000000bl nand_initmov r0, #0ldr r1, =_startldr r2, =__bss_startsub r2, r2, r1bl copy_code_to_sdrambl clear_bss/* 5. 执行main */ldr lr, =haltldr pc, =main
halt:b haltsdram_config:.long 0x22011110     //BWSCON.long 0x00000700     //BANKCON0.long 0x00000700     //BANKCON1.long 0x00000700     //BANKCON2.long 0x00000700     //BANKCON3  .long 0x00000700     //BANKCON4.long 0x00000700     //BANKCON5.long 0x00018005     //BANKCON6.long 0x00018005     //BANKCON7.long 0x008C04F4     // REFRESH.long 0x000000B1     //BANKSIZE.long 0x00000030     //MRSRB6.long 0x00000030     //MRSRB7

参数设置

nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);
setup_start_tag();
setup_memory_tags();
setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
setup_end_tag();void setup_start_tag(void)
{params = (struct tag *)0x30000100;params->hdr.tag = ATAG_CORE;params->hdr.size = tag_size (tag_core);params->u.core.flags = 0;params->u.core.pagesize = 0;params->u.core.rootdev = 0;params = tag_next (params);
}

内核存储在0x60000+64,读取到运行地址0x30008000,参数存储在0x30000100,最后传入机器ID=362

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

转载:https://www.cnblogs.com/zongzi10010/p/10023691.html

简单BootLoader相关推荐

  1. linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader

    直接看代码,即使已经理解了代码,但是还是会有种没有学到手的感觉.真正的掌握来自实践,来自己动手做出来."简单AB任务切换程序"系列文章的目的是,在bochs下,实践出简单AB两个任 ...

  2. stm32 通用bootloader_stm32最简单的实现BootLoader

    BootLoader大家应该都知道是干什么的,简单的来说就是程序开始运行前的一段程序. 在成熟的产品中,通常都是采用BootLoader方式来升级产品的程序.也就是IAP升级. 在了解完基本的实现原理 ...

  3. 从零开始写一个简单的bootloader(1)

    前言 之前学习嵌入式裸板程序也有一定的时间了,而一个bootloader则是裸板程序的一个集大成者,能包含很多的知识点,所以编写一个bootloader能巩固之前的所学.废话少讲,下面就开始正式的编写 ...

  4. 自己动手写一个简单的bootloader

    自己动手写一个简单的bootloader 15年10月31日19:44:27 (一) start.S 写这一段代码前,先要清楚bootloader开始的时候都做什么了.无非就是硬件的初始化,我们想要写 ...

  5. 【实现操作系统 01】CentOS 9 安装配置 Bochs 2.7 虚拟机,及编写简单的 bootloader 并写入软盘启动

    系统环境: OS:CentOS Stream release 9 (cmd: cat /etc/redhat-release) Linux Kernel:Linux 5.14.0-142.el9.x8 ...

  6. ARM的位置无关程序设计在Bootloader中的应用

    http://www.mcuol.com/tech/107/26052.htm 引言 基于位置无关代码PIC(PositionIndependent Code)的程序设计在嵌入式应用系统开发中具有重 ...

  7. Bootloader

    在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行.可以初始化硬件设备.建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境.在嵌入 ...

  8. bootloader烧写

    http://blog.chinaunix.net/space.php?uid=7313069&do=blog&id=1676091 关于bootloader,先简要地总结一下.经过了 ...

  9. Linux内核启动速度优化,嵌入式Linux启动时间优化的秘密之五-Bootloader

    描述 本文主要讲述嵌入式Linux启动时间优化的秘密,我们继续上篇没有讲完的嵌入式Linux启动时间优化方法,本文主要会讲Bootloader.想看上一篇的请查看本文结尾的链接. Bootloader ...

最新文章

  1. 【已解决】Win7搭建Python环境:Eclipse + PyDev插件
  2. TCP协议可靠性保证(确认应答机制,超时重传机制,流量控制,拥塞窗口)
  3. c语言小游戏贪吃神,[原创]自己编的一个贪吃蛇小游戏
  4. c++ 删除二叉树的子树_数据结构—树|二叉树|前序遍历、中序遍历、后序遍历【图解实现】...
  5. How To Install IonCube Loader
  6. jquery on()绑定的点击事件在js动态新添加的元素上无效
  7. MySQL/MariaDB数据库备份与恢复
  8. lamp一键安装包+linux,linux下的lanmp/lamp/lnmp一键安装包
  9. 阵列卡在服务器什么位置,阵列卡是什么
  10. sqlserver2000局域网无法远程访问
  11. 曾拯救Apple Watch的苹果工程师如今后继无人,美国制造业回流的人才之痛
  12. Chrome隐私设置错误,您的链接不是私密连接
  13. android 编译
  14. CoBOT检测出AI开源框架TensorFlow中的缺陷
  15. 华为过程可信cib是指_华为流程规范考.doc
  16. 转载:80,90后需要提前领悟的至高心法
  17. android控件属性padding
  18. Landsat5数据下载中国地区1988年
  19. Oracle 用户无法登录 LOCKED(TIMED)
  20. 一些关于通信拓扑、图论的内容笔记

热门文章

  1. asm.js的陷阱1
  2. Visual Studio 智能提示功能消失解决办法
  3. JS配合css实现slide文字框缩放伸展效果
  4. UA MATH567 高维统计I 概率不等式3 亚高斯性与亚高斯范数
  5. 图解在emu8086中学习几条汇编语言常用语句
  6. CentOS搭建C++开发环境
  7. Win32 API 显示鼠标坐标位置
  8. panda3d中文网文档翻译
  9. MFC版本链表演示程序
  10. byte数组和正数BigInteger之间的相互转换