嵌入式学习笔记101-uboot_1.1.6移植(1)

  1. 根据前篇博文(嵌入式学习笔记100-uboot1.1.6初体验)最后的结论,现在开始将其实现:

    a. 修改makefile的CROSS_COMPILE指定编译器

    1. arm-linux-gcc -v –> gcc version 3.4.5
    2. CROSS_COMPILE = /opt/EmbedSky/crosstools_3.4.5_softfloat/gcc-3.4.5-glibc-2.3.6/arm-linux/bin/arm-linux-
    3. chmod -R 777 u-boot-1.1.6/

    b. 在makefile里增加类似该配置

    1.tq2440_config : unconfig

    @(MKCONFIG)(@:_config=) arm arm920t tq2440 NULL s3c24x0

    c. 在board目录下新增板子的名称为目录

    1. cd board/
    2. cp -ar smdk2410/ tq2440
    3. mv smdk2410.c tq2440.c
    4. Makefile smdk2410.o –> tq2440.o

    d. 在include/configs下新增板子的头文件,文件名是配置第一个参数名

    1. cd include/configs/
    2. cp smdk2410.h tq2440.h

    e. make xxx_config 配置板子

    1. make tq2440_config –> Configuring for tq2440 board…

    f. make all 编译配置信息

    1. make all –> 会在跟目录生成bin等文件
  2. 启动流程分析:

    a.删除不必要的文件以免干扰

    根目录下lib开头的库,其中保留lib_arm lib_generic

    删除board下除smdk2410 和tq2440 外所有文件

    删除include下除asm-arm外的asm-xx目录 include下configs下除smdk2410.h 和tq2440.h外的所有头文件

    删除cpu下除arm920t外所有的cpu

    重新建立一个新的project或者在原有的project sync

    b.第一阶段code分析

/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001  Marius Gr鰃er <[email protected]>
 *  Copyright (c) 2002  Alex Z黳ke <[email protected]>
 *  Copyright (c) 2002  Gary Jennejohn <[email protected]>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <config.h>
#include <version.h>
/*============ ===  代码分析======================
*
*还记得P28的config.h怎么来的么,前篇博文有提到
*mkconfig 会在include下生成config.h,最终里面指向
*#include <configs/tq2440.h>,所以接下来的很多宏定义都是
*在include/configs/tq2440.h里定义的
*
*=================================================*/

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

.globl _start
_start: b       reset
    ldr pc, _undefined_instruction
    ldr pc, _software_interrupt
    ldr pc, _prefetch_abort
    ldr pc, _data_abort
    ldr pc, _not_used
    ldr pc, _irq
    ldr pc, _fiq

_undefined_instruction: .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:      .word not_used
_irq:           .word irq
_fiq:           .word fiq

    .balignl 16,0xdeadbeef

/*============ ===  代码分析======================
*
*P41-P57 主要设置了中断和异常的向量
*对应的处理函数其实除了IRQ,FIQ其他并没有做啥
*
*=================================================*/
/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don‘t start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */

_TEXT_BASE:
    .word   TEXT_BASE

.globl _armboot_start
_armboot_start:
    .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start

.globl _bss_end
_bss_end:
    .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
    .word   0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
    .word 0x0badc0de
#endif

/*============ ===  代码分析======================
*
*很明显想要使能IRQ/FIQ的话要在tq2440.h里
*定义这个CONFIG_USE_IRQ,不过stack的值就不是
*这个0x0badc0de,要更改成合适的
*
*=================================================*/

/*
 * the actual reset code
 */

reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs r0,cpsr
    bic r0,r0,#0x1f
    orr r0,r0,#0xd3
    msr cpsr,r0

/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON     0x15300000
# define INTMSK     0x14400008  /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014  /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON     0x53000000
# define INTMSK     0x4A000008  /* Interupt-Controller base addresses */
# define INTSUBMSK  0x4A00001C
# define CLKDIVN    0x4C000014  /* clock divisor register */
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    ldr     r0, =pWTCON
    mov     r1, #0x0
    str     r1, [r0]

    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr r1, =0x3ff
    ldr r0, =INTSUBMSK
    str r1, [r0]
# endif

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr r0, =CLKDIVN
    mov r1, #3
    str r1, [r0]
#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 */

/*============ ===  代码分析======================
*
*P131-P174无非就是跟之前裸奔程序一样
*关闭看门狗,设置时钟和中断
*
*=================================================*/

    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_crit
#endif

/*============ ===  代码分析======================
*
*P188-P190会做一次系统更基本的初始化
*根据上面的注释可知如果是直接从RAM
*启动的话不能调用cpu_init_crit 因为他会对RAM做
*清零的动作,code download到RAM结果自己清自己
*明显不行,否则程序跑到cpu_init_crit就挂了
*
*=================================================*/

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:               /* relocate U-Boot to RAM       */
    adr r0, _start      /* r0 <- current position of code   */
    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */
    cmp     r0, r1                  /* don‘t reloc during debug         */
    beq     stack_setup

    ldr r2, _armboot_start
    ldr r3, _bss_start
    sub r2, r3, r2      /* r2 <- size of armboot            */
    add r2, r0, r2      /* r2 <- source end address         */

copy_loop:
    ldmia   r0!, {r3-r10}       /* copy from source address [r0]    */
    stmia   r1!, {r3-r10}       /* copy to   target address [r1]    */
    cmp r0, r2          /* until source end addreee [r2]    */
    ble copy_loop
#endif  /* CONFIG_SKIP_RELOCATE_UBOOT */

/*============ ===  代码分析======================
*
*P202-P219会判断此时正在跑的code是否就是指定的地址
*其中adr  r0, _start的用法就是获得真正的运行地址
*比如_start会等于board/tq2440/config.mk
* TEXT_BASE = 0x33F80000
*但是程序刚跑是前面的博文讲过PC是从0开始+4的,所以
*地址无关的PC减去_start偏移最后_start=0,而
*_TEXT_BASE = 0x33F80000,所以会执行后面的copy动作,
*如果我们直接将code download到RAM的0x33F80000处,这部分的
*code则相当于无效
*
*=================================================*/

    /* Set up the stack                         */
stack_setup:
    ldr r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot   */
    sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
    sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#ifdef CONFIG_USE_IRQ
    sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub sp, r0, #12     /* leave 3 words for abort-stack    */

/*============ ===  代码分析======================
*
*P237-P245跟之前的裸奔一样设置好栈,为第二阶段的C准备
*这里需要注意的是,由于栈是对_TEXT_BASE往下偏移的,这就
*要求_TEXT_BASE不能为RAM的基址,如果将_TEXT_BASE设置成
*0x30000000,那再往下就不是RAM了! 这是要注意的,同时_TEXT_BASE
*下还作为CFG_MALLOC_LEN的buffer,CFG_GBL_DATA_SIZE等用于
*传给linux的参数
*
*=================================================*/

clear_bss:
    ldr r0, _bss_start      /* find start of bss segment        */
    ldr r1, _bss_end        /* stop here                        */
    mov     r2, #0x00000000     /* clear                            */

clbss_l:str r2, [r0]        /* clear loop...                    */
    add r0, r0, #4
    cmp r0, r1
    ble clbss_l

#if 0
    /* try doing this stuff after the relocation */
    ldr     r0, =pWTCON
    mov     r1, #0x0
    str     r1, [r0]

    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov r1, #0xffffffff
    ldr r0, =INTMR
    str r1, [r0]

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr r0, =CLKDIVN
    mov r1, #3
    str r1, [r0]
    /* END stuff after relocation */
#endif

    ldr pc, _start_armboot

_start_armboot: .word start_armboot

/*============ ===  代码分析======================
*
*设置好栈后直接调用_start_armboot,由于采用的是
*ldr    pc, _start_armboot ldr是赋值绝对地址,最终导致
*跑到运行地址处
*
*=================================================*/

/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
    /*
     * flush v4 I/D caches
     */
    mov r0, #0
    mcr p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
    mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

    /*
     * disable MMU stuff and caches
     */
    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
    bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
    orr r0, r0, #0x00000002 @ set bit 2 (A) Align
    orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
    mcr p15, 0, r0, c1, c0, 0

    /*
     * before relocating, we have to setup RAM timing
     * because memory timing is board-dependend, you will
     * find a lowlevel_init.S in your board directory.
     */
    mov ip, lr
    bl  lowlevel_init
    mov lr, ip
    mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72

#define S_OLD_R0    68
#define S_PSR       64
#define S_PC        60
#define S_LR        56
#define S_SP        52

#define S_IP        48
#define S_FP        44
#define S_R10       40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0

#define MODE_SVC 0x13
#define I_BIT    0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

    .macro  bad_save_user_regs
    sub sp, sp, #S_FRAME_SIZE
    stmia   sp, {r0 - r12}          @ Calling r0-r12
    ldr r2, _armboot_start
    sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    sub r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
    ldmia   r2, {r2 - r3}           @ get pc, cpsr
    add r0, sp, #S_FRAME_SIZE       @ restore sp_SVC

    add r5, sp, #S_SP
    mov r1, lr
    stmia   r5, {r0 - r3}           @ save sp_SVC, lr_SVC, pc, cpsr
    mov r0, sp
    .endm

    .macro  irq_save_user_regs
    sub sp, sp, #S_FRAME_SIZE
    stmia   sp, {r0 - r12}          @ Calling r0-r12
    add     r8, sp, #S_PC
    stmdb   r8, {sp, lr}^                   @ Calling SP, LR
    str     lr, [r8, #0]                    @ Save calling PC
    mrs     r6, spsr
    str     r6, [r8, #4]                    @ Save CPSR
    str     r0, [r8, #8]                    @ Save OLD_R0
    mov r0, sp
    .endm

    .macro  irq_restore_user_regs
    ldmia   sp, {r0 - lr}^          @ Calling r0 - lr
    mov r0, r0
    ldr lr, [sp, #S_PC]         @ Get PC
    add sp, sp, #S_FRAME_SIZE
    subs    pc, lr, #4          @ return & move spsr_svc into cpsr
    .endm

    .macro get_bad_stack
    ldr r13, _armboot_start     @ setup our mode stack
    sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack

    str lr, [r13]           @ save caller lr / spsr
    mrs lr, spsr
    str     lr, [r13, #4]

    mov r13, #MODE_SVC          @ prepare SVC-Mode
    @ msr   spsr_c, r13
    msr spsr, r13
    mov lr, pc
    movs    pc, lr
    .endm

    .macro get_irq_stack            @ setup IRQ stack
    ldr sp, IRQ_STACK_START
    .endm

    .macro get_fiq_stack            @ setup FIQ stack
    ldr sp, FIQ_STACK_START
    .endm

/*
 * exception handlers
 */
    .align  5
undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl  do_undefined_instruction

    .align  5
software_interrupt:
    get_bad_stack
    bad_save_user_regs
    bl  do_software_interrupt

    .align  5
prefetch_abort:
    get_bad_stack
    bad_save_user_regs
    bl  do_prefetch_abort

    .align  5
data_abort:
    get_bad_stack
    bad_save_user_regs
    bl  do_data_abort

    .align  5
not_used:
    get_bad_stack
    bad_save_user_regs
    bl  do_not_used

#ifdef CONFIG_USE_IRQ

    .align  5
irq:
    get_irq_stack
    irq_save_user_regs
    bl  do_irq
    irq_restore_user_regs

    .align  5
fiq:
    get_fiq_stack
    /* someone ought to write a more effiction fiq_save_user_regs */
    irq_save_user_regs
    bl  do_fiq
    irq_restore_user_regs

#else

    .align  5
irq:
    get_bad_stack
    bad_save_user_regs
    bl  do_irq

    .align  5
fiq:
    get_bad_stack
    bad_save_user_regs
    bl  do_fiq

#endif
时间: 2024-12-26 17:21:40

嵌入式学习笔记101-uboot_1.1.6移植(1)的相关文章

嵌入式学习笔记104-uboot_1.1.6移植(4)

前面的4篇uboot博文基本概括了uboot的整体flow,现在使能支持启动linux,至此之前请先阅读<嵌入式学习笔记200-Linux kernel初体验>和<嵌入式学习笔记201-Linux kernel动起来>.准备kernel的镜像文件才可以立马检测uboot是否能够启动kernel.在u-boot-1.1.6\include\configs\tq2440.h 最后添加如下几行code: /****************** boot kernel setup ****

嵌入式学习笔记103-uboot_1.1.6移植(3)

经过之前对uboot的整体flow分析,现在开始针对2440移植,需要注意的是移植的code可能包含支持部分的2410code 不过并没有在s3c2410板子实测过. 主要概括:第一阶段的汇编code尽量短小,能用C实现的就用C,由于2440的board和头文件是从2410 copy过来的 里面会有很多信息或者宏关于2410,并且很多.c文件的头文件由于include的是2410,所以新增的一些关于2440的结构体也会一并放在2410.h,移植的思想与前文类似, 根据code的执行流程来移植.

嵌入式学习笔记202-Linux kernel跑起来

在<嵌入式学习笔记104-uboot_1.1.6移植(4)>.<嵌入式学习笔记300-linux根文件系统搭建>uboot和根文件系统都准备好的前提下,此时的kernel已基本可以跑起来,不过还差正确的挂起文件系统,其中uboot传给kernel的挂载处是root=/dev/mtdblock2 ,而在<嵌入式学习笔记201-Linux kernel动起来>的打印分区信息是: mtd: partition "Boot Agent" doesn't en

嵌入式学习笔记008-裸奔篇之串口

串口是个好东西,前几篇裸奔程序由于没有串口,自己调试都是有led等来表示的,比较"苦逼",终于可以用串口了~~~,这里主要采用上一篇博文(嵌入式学习笔记007-裸奔篇之定时器),也就是串口也是用中断实现的,而且也只是在前一篇博文增加串口的初始化uart0_init(),以及在中断处理函数增加对串口的处理.只要稍微改造前一篇博文就是一个通用的中断处理程序! 这里主要实现在串口输入一个字符,接受后+2再发送到串口,所以在串口输入a 会返回c---. 由于code都有相应的注释,读者自行查看

嵌入式学习笔记201-Linux kernel动起来

在前篇博文<嵌入式学习笔记200-Linux kernel初体验>在已经确保环境编译是ok的,接下来让kernel能够最基本的动起来,起码可以看到基本的启动打印! 修改外部输入时钟频率, 修改 linux-2.6.30.4\arch\arm\mach-s3c2440\mach-smdk2440.c 在大概163行将16934400改成12000000. static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iod

ucos实时操作系统学习笔记——操作系统在STM32的移植

使用ucos实时操作系统是在上学的时候,导师科研项目中.那时候就是网上找到操作系统移植教程以及应用教程依葫芦画瓢,功能实现也就罢了,没有很深入的去研究过这个东西.后来工作了,闲来无聊就研究了一下这个只有几千行代码的操作系统,也没所有的代码都看,只是看了其中部分内容.自己还自不量力的尝试着去写过简单的操作系统,最后写着写着就被带到了ucos的设计思路上了,后来干脆就“copy”代码了,虽说对操作系统内核的理解有很大的帮助,但是很是惭愧啊,智力不够,对操作系统内核的设计者更加仰慕,O(∩_∩)O哈哈

[原创]java WEB学习笔记101:Spring学习---Spring Bean配置:IOC容器中bean的声明周期,Bean 后置处理器

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

嵌入式学习笔记102-uboot_1.1.6移植(2)

接下来分析uboot的第二阶段,在第一阶段的start.S的末尾有: ldr pc, _start_armboot _start_armboot: .word start_armboot 而start_armboot()就是第二阶段的入口,首先我们要认识两个重要的结构体,start_armboot()函数的一系列初始化可以说都是以这个结构体为主线的: typedef struct global_data { bd_t *bd; unsigned long flags; unsigned long

cortex_m3_stm32嵌入式学习笔记(十三):USMART调试组件移植(调试神器)

当我们学了TFTLCD显示之后遇到一个很明显的问题是:参数估计不准确,比如说我们想在屏幕的中央部分画一个圆,但往往坐标把握不准导致一次一次的往MCU里面烧程序,一次一次调,但没烧一次烧的可以MCU的命啊..显然这样是很浪费的,于是牛逼的人就想了办法了(orz),我是用的原子写的USMART组件,该组件移植很简单,只需要将USMART文件夹拉到工程里面,然后把文件添加到工程里去,里面有一个文件 usmart_config.c文件需要用户自己添加函数声明以及函数所需头文件: 第一个区域用户自己添加所