主题 : 给210裸机程序添加启动代码(同时支持NandFlash和SD卡启动) 复制链接 | 浏览器收藏 | 打印
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
贡献值: 5 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
楼主  发表于: 2013-06-25 17:41

 给210裸机程序添加启动代码(同时支持NandFlash和SD卡启动)

管理提醒: 本帖被 xoom 执行加亮操作(2013-06-25)
(说明:本贴适用于tiny210v2且NandFlash型号为:K9GAG08U0F,其他暂不支持_不知道这算不算标题党:) )

本文这里也有:http://blog.csdn.net/kangear/article/details/9172339
CSDN的编辑器要好用一些。可以在上边看。
友善提供了全套的210裸机代码的确很好,代码编写风格也是值得学习的。不过裸机代码是用不开源的Superboot引导的,这样学习裸机总有一种穿着棉裤洗澡的感觉,很不爽。还好了解了S5PV210的启动方式后,对于小于16k的裸机代码都可以将链接地址改为0xd0020010,sp指针设置到0xD0037D80,然后用mkv210_image.c将bin文件制作成210.bin。再用Minitools下载u-boot的方式下载这个裸机程序。S5PV210的IROM中的BL0程序会从NandFlash拷贝代码到iram中的0xd0020000处,然后跳到0xd0020010处运行。裸机就可以跑起来了。

但是对于大于16k的代码,就不能完全靠IROM中BL0程序拷贝了。就要自己写一下BL1的启动代码了,自己拷贝。
经过《分析一下tiny210v2的16bitECC校验(已经实现u-boot for tiny210v2)》和《u-boot for tiny210v2 (NandFlash:K9GAG08U0F)》其实“BL1”代码已经做好了,并且经过引导u-boot的验证的。下面就说说怎么添加到友善的裸机代码中,实现整个裸机代码完全开源。下面以13.uart_stdio这个裸机代码添加“BL1”启动的过程说明一下。(烧写方式同上)

1.添加“BL1”目录(目录中包含了Makefile和mkv210_image.c)
2.添加nand_cp.c memory.S s5pv210.h
3.修改原工程的Makefile添加如下红色内容

CC      = arm-linux-gcc
LD      = arm-linux-ld
AR      = arm-linux-ar
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump

CONFIG_SYS_TEXT_BASE :=0X20000000
COPY_BL2_SIZE :=0x80000


INCLUDEDIR := $(shell pwd)/include
CFLAGS :=-g -Wall -O2 -fno-builtin -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \
-DCOPY_BL2_SIZE=$(COPY_BL2_SIZE)

CPPFLAGS   :=-g -nostdinc -I$(INCLUDEDIR) -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \
-DCOPY_BL2_SIZE=$(COPY_BL2_SIZE)

export CC AR LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS

objs := start.o memory.o nand_cp.o main.o uart.o clock.o lib/libc.a


all: stdio.bin
make -C ./BL1
cat ./BL1/BL1.bin stdio.bin > 210.bin
stdio.bin: $(objs)
${LD} -Ttext ${CONFIG_SYS_TEXT_BASE} -Tstdio.lds -o stdio.elf $^
${OBJCOPY} -O binary -S stdio.elf $@
${OBJDUMP} -D stdio.elf > stdio.dis


.PHONY : lib/libc.a
lib/libc.a:
cd lib; make; cd ..
%.o:%.c
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S
${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:
make  clean -C lib
make clean -C ./BL1/
rm -f *.bin *.elf *.dis *.o

4.保证工程目录已经实现uart.c 和 start.S,并在start.S中添加如下红色内容:

@******************************************************************************
@ File:start.S
@ 功能:启动代码,设置栈,拷贝代码到CONFIG_SYS_TEXT_BASE处
@******************************************************************************  
.text
.global _start
_start:
/*
* set the cpu to SVC32 mode
*/
mrs    r0, cpsr
bic    r0, r0, #0x1f
orr    r0, r0, #0xd3
msr    cpsr,r0
/*
* Invalidate L1 I/D
*/
mov    r0, #0     @ set up for MCR
mcr    p15, 0, r0, c8, c7, 0    @ invalidate TLBs
mcr    p15, 0, r0, c7, c5, 0    @ invalidate icache
mcr    p15, 0, r0, c7, c5, 6    @ invalidate BP array
mcr p15, 0, r0, c7, c10, 4    @ DSB
mcr p15, 0, r0, c7, c5, 4    @ ISB
/*
* disable MMU stuff and caches
*/
mrc    p15, 0, r0, c1, c0, 0
bic    r0, r0, #0x00002000    @ clear bits 13 (--V-)
bic    r0, r0, #0x00000007    @ clear bits 2:0 (-CAM)
orr    r0, r0, #0x00000002    @ set bit 1 (--A-) Align
orr    r0, r0, #0x00000800    @ set bit 11 (Z---) BTB
bic    r0, r0, #0x00001000    @ clear bit 12 (I) I-cache
mcr    p15, 0, r0, c1, c0, 0

ldr    sp, =0xD0037D80       @ 设置栈,以便调用c函数
adr r0, _start                        @ 重定位
                                      @ _start当前所位于的地址
ldr r1, =_start                  @ _start的链接地址:CONFIG_SYS_TEXT_BASE
cmp r0, r1
beq run_on_dram             @ 如果在是链接地址处,则直接运行

bl  uart_init                     @ 初始化串口
bl  nand_asm_init            @ NandFlash初始化
bl  mem_init                   @ dram初始化


bl  board_init_f_nand     @ 拷贝bl2代码到dram中,并运行

run_on_dram:      
bl  main                  @ 跳转
/* Setting GPIO for NAND */
/* This setting is NAND initialze code at booting time in iROM. */
nand_asm_init:
/*
* Nand Interface Init for SMDKC110
*/

#define ELFIN_GPIO_BASE     0xE0200000
#define ELFIN_NAND_BASE     0xB0E00000
#define NFCONF_VAL        (2<<23)|(7<<12)|(7<<8)|(7<<4)|(1<<3)|(0<<2)|(1<<1)|(0<<0)
#define NFCONT_VAL      (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)

//#define  NFCONF_VAL     (0<<25)|(0x3<<23)|(7<<12)|(7<<8)|(7<<4)|(1<<3)|(0<<2)|(1<<1)|(0<<0)
//#define NFCONT_VAL      (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(1<<5)|(0x2<<1)|(1<<0)

#define MP01CON_OFFSET 0x2E0
#define MP01PUD_OFFSET 0x2E8
#define MP03CON_OFFSET      0x320
#define MP03PUD_OFFSET      0x328
#define NFCONF_OFFSET       0x00
#define NFCONT_OFFSET       0x04


ldr    r0, =ELFIN_GPIO_BASE

ldr    r1, [r0, #MP01CON_OFFSET]
bic    r1, r1, #(0xf<<8)
orr    r1, r1, #(0x3<<8)
str    r1, [r0, #MP01CON_OFFSET]

ldr    r1, [r0, #MP01PUD_OFFSET]
bic    r1, r1, #(0x3<<4)
str    r1, [r0, #MP01PUD_OFFSET]

ldr    r1, [r0, #MP03CON_OFFSET]
bic    r1, r1, #0xFFFFFF
ldr    r2, =0x22222222
orr    r1, r1, r2
str    r1, [r0, #MP03CON_OFFSET]

ldr    r1, [r0, #MP03PUD_OFFSET]
ldr    r2, =0x3fff
bic    r1, r1, r2
str    r1, [r0, #MP03PUD_OFFSET]

ldr    r0, =ELFIN_NAND_BASE

ldr    r1, [r0, #NFCONF_OFFSET]
ldr    r2, =0x777F
bic    r1, r1, r2
ldr    r2, =NFCONF_VAL
orr    r1, r1, r2
str    r1, [r0, #NFCONF_OFFSET]

ldr    r1, [r0, #NFCONT_OFFSET]
ldr    r2, =0x707C7
bic    r1, r1, r2
ldr    r2, =NFCONT_VAL
orr    r1, r1, r2
str    r1, [r0, #NFCONT_OFFSET]

ldr    r1, [r0, #NFCONF_OFFSET]
orr    r1, r1, #0x70
orr    r1, r1, #0x7700
str     r1, [r0, #NFCONF_OFFSET]

ldr    r1, [r0, #NFCONT_OFFSET]
orr    r1, r1, #0x03
str     r1, [r0, #NFCONT_OFFSET]

mov    pc, lr

例子源代码:
本部分内容设定了隐藏,需要回复后才能看到

运行截图:


=============================================================================================================
13-06-26更新:
1.在start.S中添加了启动方式的判断,可以判断是从NandFlash启动还是SD卡启动:

    
//判断启动方式
#define PRO_ID_BASE            0xE0000000
#define PRO_ID_OFFSET            0x00
#define OMR_OFFSET            0x04

#define BOOT_ONENAND        0x1
#define BOOT_NAND        0x2
#define BOOT_MMCSD        0x3
#define BOOT_NOR        0x4
#define BOOT_SEC_DEV        0x5

#define INF_REG_BASE            0xE010F000
#define INF_REG3_OFFSET            0x0c

        ldr    r0, =PRO_ID_BASE
        ldr    r1, [r0,#OMR_OFFSET]
        bic    r2, r1, #0xffffffc1

        /* NAND BOOT */
        cmp    r2, #0x0        @ 512B 4-cycle
        moveq    r3, #BOOT_NAND

        cmp    r2, #0x2        @ 2KB 5-cycle
        moveq    r3, #BOOT_NAND

        cmp    r2, #0x4        @ 4KB 5-cycle    8-bit ECC
        moveq    r3, #BOOT_NAND

        cmp    r2, #0x6        @ 4KB 5-cycle    16-bit ECC
        moveq    r3, #BOOT_NAND

        cmp    r2, #0x8        @ OneNAND Mux
        moveq    r3, #BOOT_ONENAND

        /* SD/MMC BOOT */
        cmp     r2, #0xc
        moveq   r3, #BOOT_MMCSD    

        /* NOR BOOT */
        cmp     r2, #0x14
        moveq   r3, #BOOT_NOR    

        /* Uart BOOTONG failed */
        cmp     r2, #(0x1<<4)
        moveq   r3, #BOOT_SEC_DEV

        ldr    r0, =INF_REG_BASE
        str    r3, [r0, #INF_REG3_OFFSET]
    
        ldr    r1, [r0, #INF_REG3_OFFSET]
        cmp    r1, #BOOT_NAND        /* 0x0 => boot device is nand */
        beq    nand_boot_210
        cmp     r1, #BOOT_MMCSD
        beq     mmcsd_boot_210
    
nand_boot_210:
        mov r0, #'N'
        bl  putc
        bl  board_init_f_nand     @ 拷贝bl2代码到dram中,并运行

mmcsd_boot_210:
        mov r0, #'S'
        bl  putc
        bl  board_init_f_mmc

2.添加了mmc_cp.c其中有从SD卡copy到dram中的程序:
typedef unsigned int (*copy_sd_mmc_to_mem) (\
            unsigned int  channel, \
            unsigned int  start_block, \
            unsigned short block_size, \
            unsigned int  *trg, \
            unsigned int  init);

void copy_code_to_dram(void)
{
    unsigned long ch;
    void (*BL2)(void);
    ch = *(volatile unsigned int *)(0xD0037488);
    unsigned char channel = 0;
    
    putc('\n');putc('\r');
    putc('B');putc('L');putc('1');putc(' ');putc('V');putc('e');putc('r');putc(':');
    putc('1');putc('3');putc('0');putc('6');putc('2');putc('6');
    putc('\n');putc('\r');
    putc('S');putc('t');putc('a');putc('r');putc('t');putc(' ');putc('c');putc('p');putc(' ');
    putc('\n');putc('\r');

    // 函数指针
    copy_sd_mmc_to_mem copy_bl2 = (copy_sd_mmc_to_mem) (*(unsigned int *) (0xD0037F98));

    unsigned int ret;
    
    // 通道0
    if (ch == 0xEB000000)
        channel = 0;

    // 通道2
    else if (ch == 0xEB200000)
        channel = 2;
        
    else
        return;
        
    // 0:channel 0
    // 33:源,代码位于扇区33,1 sector = 512 bytes
    // COPY_BL2_SIZE/512:长度,拷贝COPY_BL2_SIZE/512 sector,即COPY_BL2_SIZE K
    // CONFIG_SYS_TEXT_BASE:目的,链接地址CONFIG_SYS_TEXT_BASE    
    ret = copy_bl2(channel, 33, COPY_BL2_SIZE/512,(unsigned int *)CONFIG_SYS_TEXT_BASE, 0);

    putc('R');putc('u');putc('n');putc('n');putc('i');putc('n');putc('g');putc('!');putc(' ');
    putc('\n');putc('\r');
    
    // 跳转到DRAM
    BL2 = (void *)CONFIG_SYS_TEXT_BASE;
    (*BL2)();
}

void board_init_f_mmc()
{
    copy_code_to_dram();    
}
这个程序来自210的裸机中,红色的地方原来是unsigned char型的改为了unsigned short型的。
从NandFlash启动:

从SD卡启动:(SD卡烧写可以用dd命令或者用这个“SD-Flasher for Linux v1.0(210版本)”)

这次的代码:
本部分内容设定了隐藏,需要回复后才能看到
[ 此帖被kangear在2013-06-26 16:32重新编辑 ]
级别: 禁止发言
UID: 98835
精华: 0
发帖: 48
金钱: 265 两
威望: 53 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-12-09
最后登录: 2014-09-16
1楼  发表于: 2013-12-10 17:53
用户被禁言,该主题自动屏蔽!