zoukankan      html  css  js  c++  java
  • 手写bootloader(手写*_*)

    思路
    1.关看门狗
    2.设置时钟
    3.初始化sdram
    4.重定位
    5.执行main
    .text 表示代码段
    .global _start (global 表示全局标号)

    关看门狗
    可以调c完成disable_watch_dag 确定看门狗地址0x....
    ldr r0 ,=0x... ldr 违汇编指令
    mov r1,#0
    str r1, [r0]
    设置时钟 可以用 c clock_init()
    CLKDIVN 定义位置board中
    ldr r0, =0x4c00001
    mov r1, #0x03 0x03 分频系数 //FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
    str r1,[r0] asm 如果是c,它是标志嵌入汇编 读芯片手册,调整异步模式,根据芯片具体情况
    mrc 指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中。如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断
    MCR{} p15, 0, , , {,<opcode_2>}
    <opcode_1>为协处理器将执行的操作的操作码。对于CP15协处理器来说, <opcode_1>永远为0b000,当<opcode_1>不为0b000时,该指令操作结果不可预知
    作为元寄存器的ARM寄存器,其值被传<
    Rd>不能为PC,当其为PC时,指令操作结果不可预知送到得协处理器寄存器中
    作为目标寄存器的协处理器寄存器,其编号可能为C0,C1....C15。 附加的目标寄存器或者原操作数寄存器,用于区分同一个编号的不同物理寄存器。当指令中不需要提供附加信息时,将C0指定为,否则指令操作结果不可预知。 <opcode_2>提供附加信息,用于区别同一个编号的不同物理寄存器。当指令中指定附加信息时,省略<opcode_2>或者将其指定为0,否则指令操作结果不可预知
    orr ORR指令的格式为: ORR{条件}{S} 目的寄存器,操作数1,操作数2
    ORR指令用于在两个操作数上进行逻辑戒运算,并把结果放置到目的寄存器中
    操作数1应该是一 个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
    该指令常用于设置操 作数1的某些位。

    MRC指令将协处理器的寄存器中数值传送到ARM处理器的寄存器中。如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断

    指令示例: ORR R0,R0,#3 ;
    该指令设置R0的0、1位,其余位保持不变。
    orr r0,r0,#0xd3
    0xd3=1101 0111
    将r0与0xd3作算数或运算,然后将结果返还给r0,即把r0的bit[7:6]和bit[4]和bit[2:0]置为1

    初始化sdram 可用c语言写,memsetup
    要先设置栈
    sdram_config: 标号
    .long 寄存器 .long 相当于数组

    ldr r0,=sdram寄存器首地址
    adr r1, sdram_config /* 得到当前地址 /
    add r3,r0,#(13
    4)
    1:
    ldr r2,r0,#4
    sdr r2,[r0],#4
    cmp r0,r3 比较r0,r3
    bne 1b 如果不相等 1f 前面的1标

    重定位 :把bootloader 本身的代码从flash复制到它的连接地址去
    用c写这段,用才前要先设置栈

    ldr sp, =0x3400000

    bl nand_init
    mov r0 ,#0
    ldr r1, =[_start] 把boot copy 到 sdram 中 长度需读取连接脚本
    ldr r2, = _bss_start 没有= 号为读内存指令,读_bss_start 内存 .word _bss _start 这个变量
    如何引用这个变量这里的用法表示:在当前位置存放一个字,
    可能有些人会觉得就是放一个字word,这个要怎么看了,
    一般一个word是两个字节,跟CPU的型号有关,所以不要管word的限制,
    直接理解成,在当前位置存放一个字,这个字是32位的即可
    sub r2,r2,r1

    bl copy_code_to_sdram 之后清零bss
    bl clear_bss
    执行mian
    ldr lr , =halt 设置返回地址
    ldr pc , =main bl main 相对跳转,根据当前指令找到偏差,再跳

    假设main 能返回跳到
    halt:
    b halt

    完成copy_code_to_sdram nor flash 不能简单地写 sd 卡 属于nand flash nand 不能像内存一样随即读取
    {
    src copy dsc len
    }

    连接文件
    boot.lds
    SECTIONS{
    . = 0X30000000 当前地址等于多少 boot 不要放在sdram的起始位置,因为要留着放内核
    .text : {(.text)} 所有代码code 段
    . =ALIGN(4) 用于代码对齐,使当前地址取整
    .rodata :{
    (.rodata)} 所有代码只读数据段
    .data : {
    (.data)} 所有代码数据段
    __bss_start = .;
    .bass : {
    (.bss*)} 所有bss数据段 当前初始值为0的数据,给他们统一数据地址,避免冗余的0
    __bss_end = .;

    }
    计算boot 文件大小 就是 __bass_start - start

    claen_bss{
    extern int __bss_start, __bss_end;
    int *p = &__bss_start;

    for (: p <&_bss_end;p++)
       *p = 0;
    

    }

    nand_init {

    }

  • 相关阅读:
    Android 操作系统架构开篇
    《构建之法》读后感
    《梦断代码》读后感
    学习日报
    学习日报
    记账本开发4
    记账本开发3
    学习日报
    学习日报
    记账本开发2
  • 原文地址:https://www.cnblogs.com/DemonMaster/p/11869435.html
Copyright © 2011-2022 走看看