操作系统:ubuntu10.04
前言:
在上一章节中,详细分析了uboot中的顶级makefile,了解了uboot的编译流程,在本章节中,将要详细分析的是uboot 的执行流程。
而uboot的第一条执行,是在 start.S 的。
一,start.S的详细分析。
点击(此处)折叠或打开
-
/*
-
* armboot - Startup Code for ARM920 CPU-core
-
*
-
* Copyright (c) 2001 Marius Gr鰃er
-
* Copyright (c) 2002 Alex Z黳ke
-
* Copyright (c) 2002 Gary Jennejohn
-
*
-
* 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/config.h */
-
#include <version.h> /* ./include/version.h */
-
-
-
/*
-
*************************************************************************
-
*
-
* Jump vector table as in table 3.1 in [1]
-
*
-
*************************************************************************
-
*/
-
-
/*
-
global声明一个符号可被其他文档引用,相当于声明了一个全局变量,.globl和.global相同。
-
详情请看:http://blog.chinaunix.net/uid-28458801-id-3554759.html
-
-
_start就是整个start.S的最开始,即整个uboot的代码的开始。
-
_start后面加上一个冎号’:’,表示其是一个标号Label,类似亍C诧言goto后面的标号。
-
而同时,_start的值,也就是返个代码的位置了,此处即为代码的最开始,相对的0的位置。
-
-
b reset :表示跳转到 reset 执行,并且不返回
-
-
ldr: LDR伪指令-----大范围的地址读取
-
详情请看:1,http://blog.chinaunix.net/uid-28458801-id-3753775.html
-
2,http://blog.chinaunix.net/uid-28458801-id-3753657.html
-
-
.word .word expr {,expr}… 分配一段字内存单元,幵用expr初始化字内存单元(32bit)
-
以_undefined_instruction为例,就是,此处分配了一个word=32bit=4字节
-
的地址空间,里面存放的值是undefined_instruction。
-
而此处_undefined_instruction也就是该地址空间的地址了。用C诧言来表达就是:
-
_undefined_instruction = &undefined_instruction。
-
在后面的代码,我们可以看到,undefined_instruction也是一个标号,即一个地址值,对应着
-
就是在发生“未定义指令”的时候,系统所要去执行的代码。
-
所以:
-
ldr pc, 标号1
-
。。。
-
标号1:.word 标号2
-
标号2:
-
。。。(具体要执行的代码)
-
的意思就是,将地址为标号1中内容载入到pc,而地址为标号1中的内容,正好装的是标号2。
-
用C诧言表达其实很简单:
-
PC = *(标号1) = 标号2
-
对PC赋值,即是实现代码跳转,所以整个返段汇编代码的意思就是:
-
跳转到标号2的位置,执行对应的代码。
-
-
.balignl 16,0xdeadbeef 意思就是,接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充。
-
*/
-
.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
-
-
-
/*
-
*************************************************************************
-
*
-
* 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,代码的基地址.
-
TEXT_BASE 定义在 \board\xx\config.mk,假设为 TEXT_BASE = 0x33D00000
-
-
*(_armboot_start) = _start
-
*/
-
_TEXT_BASE:
-
.word TEXT_BASE
-
-
.globl _armboot_start
-
_armboot_start:
-
.word _start
-
-
/*
-
* These are defined in the board-specific linker script.
-
*/
-
/*
-
_bss_start和_bss_end都叧是两个标号,对应着此处的地址。
-
而两个地址里面分别存放的值是__bss_start和_end,这两个的值,定义在 \board\xx\u-boot.lds 中。
-
而关亍_bss_start和_bss_end定义为.glogl即全局变量,是因为uboot的其他源码中要用到这两个变量。
-
-
FREE_RAM_END和FREE_RAM_SIZE,PreLoadedONRAM,IRQ_STACK_START,FIQ_STACK_START,之所以也是声明为全局变量,
-
是因为uboot的源码中会用到这些变量。
-
*/
-
.globl _bss_start
-
_bss_start:
-
.word __bss_start
-
-
.globl _bss_end
-
_bss_end:
-
.word _end
-
-
.globl FREE_RAM_END
-
FREE_RAM_END:
-
.word 0x0badc0de
-
-
.globl FREE_RAM_SIZE
-
FREE_RAM_SIZE:
-
.word 0x0badc0de
-
-
.globl PreLoadedONRAM
-
PreLoadedONRAM:
-
.word 0
-
-
#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
-
-
-
/*
-
* the actual reset code
-
*/
-
/*
-
对 mrs 和msr 有疑问的请看:http://blog.chinaunix.net/uid-28458801-id-4083956.html
-
*/
-
reset:
-
/*
-
* set the cpu to SVC32 mode.设置cpu为 SVC模式。
-
* 如果对arm的个模式有疑问的请看:1,http://blog.chinaunix.net/uid-28458801-id-3788554.html
-
* 2,http://blog.chinaunix.net/uid-28458801-id-3494646.html
-
*/
-
-
mrs r0,cpsr /* 传送CPSR的内容到R0 */
-
bic r0,r0,#0x1f /* 清除r0的bit[4:0]位 */
-
orr r0,r0,#0xd3 /* 把r0的bit[7:6]和bit[4]和bit[2:0]置为1 */
-
msr cpsr,r0 /* 将r0的值赋给CPSR */
-
-
/* 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 INTMOD 0X4A000004
-
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
-
# define INTSUBMSK 0x4A00001C
-
# define CLKDIVN 0x4C000014 /* clock divisor register */
-
#endif
-
-
-
/*
-
以上是看门狗的相关寄存器的地址。
-
-
对 ldr伪指令 有疑惑的请看:http://blog.chinaunix.net/uid-28458801-id-4084264.html
-
-
先是用r0寄存器存pWTCON的值,然后r1=0,再将r1中的0写入到pWTCON寄存器中,其实就是
-
*((int *)pWTCON) = 0;
-
*/
-
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
-
ldr r0, =pWTCON /* 宏pWTCON的值赋值给r0寄存器 */
-
mov r1, #0x0
-
str r1, [r0]
-
-
/*
-
* mask all IRQs by setting all bits in the INTMR - default
-
* 关闭所有中断。
-
* INTMSK寄存器设置为0xffffffff
-
*/
-
mov r1, #0xffffffff
-
ldr r0, =INTMSK
-
str r1, [r0]
-
/* 将INTSUBMSK寄存器的值设置为0x3ff。*/
-
# if defined(CONFIG_S3C2410)
-
ldr r1, =0x3ff
-
ldr r0, =INTSUBMSK
-
str r1, [r0]
-
# endif
-
-
#if 0 /* 不编译*/
-
/* FCLK:HCLK:PCLK = 1:2:4 */
-
/* default FCLK is 120 MHz ! */
-
ldr r0, =CLKDIVN
-
mov r1, #3
-
str r1, [r0]
-
#endif
-
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
-
-
/*
-
* we do sys-critical inits only at reboot,
-
* not when booting from ram!
-
*/
-
/*
-
ADR伪指令--- 小范围的地址读取
-
*/
-
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-
adr r0, _start /* r0 <- current position of code ,将_start的地址赋值给r0 */
-
ldr r1, _TEXT_BASE /* test if we run from flash or RAM*/
-
cmp r0, r1 /* don't reloc during debug , 比较r0和r1是否相等 */
-
blne cpu_init_crit /* 如果r0和r1不相等,则执行 cpu_init_crit*/
-
#endif
-
-
/* Set up the stack
-
CFG_MALLOC_LEN,CFG_GBL_DATA_SIZE 定义在\include\configs\xx.h
-
-
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
-
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
-
-
#define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
-
-
#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
-
#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
-
-
*/
-
stack_setup:
-
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot ,地址为_TEXT_BASE的内存中的内容给r0 */
-
sub r0, r0, #CFG_MALLOC_LEN /* malloc area ,256 kb */
-
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo ,128 byte */
-
-
/* cpu/arm920t/cpu.c 中的 cpu_init 中真正的为 IRQ,FIQ模式划分了栈*/
-
#ifdef CONFIG_USE_IRQ
-
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) /* 4kb + 4kb*/
-
#endif
-
sub sp, r0, #12 /* leave 3 words for abort-stack ,12 byte */
-
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-
bl clock_init /* 初始化系统时钟*/
-
#endif
-
-
#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 clear_bss
-
-
ldr r2, _armboot_start /* _start */
-
ldr r3, _bss_start
-
sub r2, r3, r2 /* r2 <- size of armboot */
-
#if 1
-
bl CopyCode2Ram /* r0: source, r1: dest, r2: size */
-
#else
-
add r2, r0, r2 /* r2 <- source end address */
-
-
copy_loop:
-
ldmia {r3-r10} /* copy from source address [r0] */
-
stmia {r3-r10} /* copy to target address [r1] */
-
cmp r0, r2 /* until source end addreee [r2] */
-
ble copy_loop
-
#endif
-
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
-
-
/* 清除 bss 段*/
-
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
-
-
SetLoadFlag:
-
/* Set a global flag, PreLoadedONRAM */
-
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 */
-
ldr r2, =PreLoadedONRAM
-
mov r3, #1
-
streq r3, [r2]
-
-
#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 /* 进入c函数阶段 ./lib_arm/board.c */
-
-
-
/*
-
*************************************************************************
-
*
-
* 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 /* 设置存储控制器,使得外接的sdram可用*/
-
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
-
-
@ thisway.diy, 2006.06.24
-
.globl Launch
-
.align 4
-
Launch:
-
mov r7, r0
-
@ diable interrupt
-
@ disable watch dog timer
-
mov r1, #0x53000000
-
mov r2, #0x0
-
str r2, [r1]
-
-
ldr r1,=INTMSK
-
ldr r2,=0xffffffff @ all interrupt disable
-
str r2,[r1]
-
-
ldr r1,=INTSUBMSK
-
ldr r2,=0x7ff @ all sub interrupt disable
-
str r2,[r1]
-
-
ldr r1, = INTMOD
-
mov r2, #0x0 @ set all interrupt as IRQ (not FIQ)
-
str r2, [r1]
-
-
@
-
mov ip, #0
-
mcr p15, 0, ip, c13, c0, 0 @ /* zero PID */
-
mcr p15, 0, ip, c7, c7, 0 @ /* invalidate I,D caches */
-
mcr p15, 0, ip, c7, c10, 4 @ /* drain write buffer */
-
mcr p15, 0, ip, c8, c7, 0 @ /* invalidate I,D TLBs */
-
mrc p15, 0, ip, c1, c0, 0 @ /* get control register */
-
bic ip, ip, #0x0001 @ /* disable MMU */
-
mcr p15, 0, ip, c1, c0, 0 @ /* write control register */
-
-
@ MMU_EnableICache
-
@mrc p15,0,r1,c1,c0,0
-
@orr r1,r1,#(1<<12)
-
@mcr p15,0,r1,c1,c0,0
-
-
@ clear SDRAM: the end of free mem(has wince on it now) to the end of SDRAM
-
ldr r3, FREE_RAM_END
-
ldr r4, =PHYS_SDRAM_1+PHYS_SDRAM_1_SIZE @ must clear all the memory unused to zero
-
mov r5, #0
-
-
ldr r1, _armboot_start
-
ldr r2, =On_Steppingstone
-
sub r2, r2, r1
-
mov pc, r2
-
On_Steppingstone:
-
2: stmia {r5}
-
cmp r3, r4
-
bne 2b
-
-
@ set sp = 0 on sys mode
-
mov sp, #0
-
-
@ add by thisway.diy 2006.06.26, switch to SVC mode
-
msr cpsr_c, #0xdf @ set the I-bit = 1, diable the IRQ interrupt
-
msr cpsr_c, #0xd3 @ set the I-bit = 1, diable the IRQ interrupt
-
ldr sp, =0x31ff5800
-
-
nop
-
nop
-
nop
-
nop
-
-
mov pc, r7 @ Jump to PhysicalAddress
-
nop
-
mov pc, lr
-
-
#ifdef CONFIG_USE_IRQ
-
-
.align 5
-
irq:
-
/* add by to use IRQ for USB and DMA */
-
sub lr, lr, #4 @ the return address
-
ldr sp, IRQ_STACK_START @ the stack for irq
-
stmdb { r0-r12,lr } @ save registers
-
-
ldr lr, =int_return @ set the return addr
-
ldr pc, =IRQ_Handle @ call the isr
-
int_return:
-
ldmia { r0-r12,pc }^ @ return from interrupt
-
-
.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
最后得到的内存分别如下:
二,my_uboot的实现思路
根据以上分析,总结了my_uboot的实现思路:
(1)设置 CPU 模式
(2)关闭看门狗
(3)关闭中断
(4)设置堆栈 sp 指针
(5)清除 bss 段
(6)异常中断处理
(7)跳转到 start_armboot 函数中执行。
(1)设置 CPU 模式
总的来说,就是将 CPU 设置为 SVC 模式。
(2)关闭看门狗
就是去设置对应的寄存器,将看门狗关闭。
(3)关闭中断
关闭中断,也是去设置对应的寄存器,即可。
(4)设置堆栈 sp 指针
设置堆栈以便 C 程序执行。
(5)清除 bss 段
此处很简单,就是将对应 bss 段,都设置为,0,即清零。
其对应的地址空间,就是那些未初始化的全局变量的地址。
(6)异常中断处理
异常中断处理,就是实现对应的常见的那些处理中断的部分内容。
说白了就是实现一个个中断凼数。 uboot在初始化的时候,主要目的叧是为了初始化系统,及引
导系统,所以,此处的中断处理部分的代码,往往相对比较简单,丌是很复杂
(7)跳转到 start_armboot 函数中执行
前面的6个操作都是汇编语言实现的,开发难度高,移植性低,因此在实现uboot的真正的引导linux内核的实现,还是由C语言来实现。
在此,初步的思路是:1,初始化。2,串口,以便调试。3,实现linux内核的引导。
三,疑问
在这实现中,有个很重要的疑问:通过什么方式来烧写uboot,linux内核,文件系统程序。
初步设想:通过 SEGGER的 J-Flash ARM 程序,把编译好的需要的3个文件烧写到Flash中对于的位置。
如果这个设想不通过,则需要在my_uboot中添加uboot的一下命令的实现。
阅读(6009) | 评论(0) | 转发(7) |