基于OK-2440III的u-boot移植

基于OK-2440III的u-boot移植(一)


u-boot的工作过程与硬件关系密切,所以在移植时必须对S3C2440等芯片手册和开发板的硬件有一定的了解。其工作流程主要分为两个部分涉及两个主要的文件:cpu/arm920t/start.S和lib_arm/board.c,先从前面的汇编程序中执行,再跳到后面的C程序中。 

     移植思路参考网上友友分为六个步骤:

(1)建立好开发板相关的文件,并利用交叉编译器编译生成bin文件用于下载到开发板中运行;

(2)修改相关硬件配置,让uboot能在sdram中运行调试;

(3)修改norflash相关配置,让uboot在norflash中启动运行;

(4)修改nandflash相关配置,让uboot在nandflash中启动运行;

(5)增加uboot的功能,如网络、USB等;(6)引导Linux系统启动。


一.移植环境

目标板:飞凌的ok-2440III开发板(ARM9

芯片型号:三星的S3C2440

Uboot版本:u-boot-2009.08

宿主机:RedHat Linux AS5

交叉编译器:arm-linux-gcc-4.3.2


二.编译

1.建立板级文件夹:

(1)在board/samsung目录下新建文件夹ok2440,找到相似的板级文件夹smdk2410,并把该文件夹中的所有文件拷贝到ok2440下;

(2)到ok2440目录下,把文件smdk2410.c重命名为ok2440.c;修改该目录下Makefile中的目标(COBJS),把smdk2410.o改为ok2440.o

2.建立芯片级文件夹:

直接用cpu/arm920t芯片文件夹,不做修改;

3.建立配置文件:

include/configs目录下,找到相似的配置文件smdk2410.h,将其拷贝并重命名为ok2440.h

4.建立编译规则:

在根目录下的Makefile中找到ARM体系架构中smdk2410的编译规则

smdk2410_config : unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0

在此处添加ok2440的编译规则

ok2440_config : unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t ok2440 samsung s3c24x0

(注意Makefile中命令行要以tab键开头)

5.在宿主机linux环境下编译:

在终端进入uboot的根目录下执行两条命令:

# make ok2440_config

# make

(注:执行make命令时,前提是在linuxarm-linux-gcc-4.3.2的安装目录设为PATH环境变量,即交叉工具arm-linux-命令的版本是4.3.2  

或者执行:#make CROSS_COMPILE=(arm-linux-的安装目录)

6.由上面编译生成在根目录下的u-boot.bin就可以下载到开发板中,不过还需修改配置才能运行)


基于OK-2440IIIu-boot移植(二)


三、在SDRAM中调试运行 

(在 基于OK-2440III的u-boot移植(一) 编译通过后修改一下内容)

(注:此移植过程中没有新添加S3C2440的编译条件,都是用原来S3C2410的编译条件)

1.下载到内存中调试时不进行底层初始化、不进行uboot代码拷贝,所以在配置文件include/configs/ok2440.h中加入两句:

#   define CONFIG_SKIP_LOWLEVEL_INIT    1    

#   define CONFIG_SKIP_RELOCATE_UBOOT    1 

2.修改cpu/arm920t/start.S相关部分:

(1).在定义S3C2410的寄存器地址处添加以下寄存器的定义:

#   define LOCKTIME    0x4C000000

#   define MPLLCON     0x4C000004 

#   define UPLLCON     0x4C000008

#   define CAMDIVN     0x4C000018 

(2).修改屏蔽中断的位数,如下:

# if defined(CONFIG_S3C2410)

ldr r1, =0x7fff

ldr r0, =INTSUBMSK

str r1, [r0]

# endif

(3).在中断屏蔽完成后添加下面两个寄存器的配置:

     ldr r0,=LOCKTIME

     mov r1,#0xffffff

     str r1,[r0]

     ldr r0,=CAMDIVN

     mov r1,#0

     str r1,[r0]

(4).修改时钟分配比初始化:

/* FCLK:HCLK:PCLK = 1:4:8 */

ldr r0, =CLKDIVN

mov r1, #5

str r1, [r0]

//以下部分是新添加的

//在2440的手册中指出若HDIVN不为0,则需要添加下面三句: 

     mrc   p15, 0, r1, c1, c0, 0        

     orr    r1, r1, #0xc0000000         

     mcr   p15, 0, r1, c1, c0, 0         

//USB时钟48MHz       

     ldr    r0, =UPLLCON

     ldr    r1, =0x00038022

     str     r1, [r0]

//arm920t为5级流水线,延迟几个周期,使指令生效

        nop

        nop

        nop

        nop

        nop

        nop

        nop

        nop

//写MPLL使pll生效,405MHz

      ldr    r0, =MPLLCON

      ldr    r1, =0x0007f021

      str     r1, [r0]

3.修改board/samsung/ok2440/ok2440.c文件中的时钟部分,如下所示:

      #elif FCLK_SPEED==1         /* Fout = 405MHz, FCLK:HCLK:PCLK = 1:4:8 */

      #define M_MDIV     0x7f

      #define M_PDIV     0x2

      #define M_SDIV     0x1

4.修改cpu/arm920t/s3c24x0/speed.c相关部分:

(1).修改FCLK的计算公式:

把下面的部分:

     m = ((r & 0xFF000) >> 12) + 8;

     p = ((r & 0x003F0) >> 4) + 2;

     s = r & 0x3;

     return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

替换为:

     m = ((r & 0xFF000) >> 12) + 8;

     p = ((r & 0x003F0) >> 4) + 2;

     s = r & 0x3;

     if(pllreg == MPLL)

         return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));

     else

         return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

(2).修改get_HCLK函数:

/* return HCLK frequency */

ulong get_HCLK(void)

{    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

     //return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

return (get_FCLK()/4);     //这里修改的只能用于 s3c2440 1:4:8 !!!

}

5.linux环境下再次编译,下载到内存中就可以运行,终端串口输出信息!


基于OK-2440IIIu-boot移植(三)


四.在Nor Flash中调试运行

   (在 基于OK-2440III的u-boot移植(二) 在内存中运行通过后修改一下内容)

注:ok2440III开发板的norflashIntelJS28F320(4MB)(1device=32blocks,1block=128MB)

1.修改norflash的配置,在include/configs/ok2440.h中关于flash的配置部分都删掉,换成下面的配置:

/*-----------------------------------------------------------------------

* Physical Memory Map

*/

#define CONFIG_NR_DRAM_BANKS     1            /* we have 1 bank of DRAM */

#define PHYS_SDRAM_1          0x30000000        /* SDRAM Bank #1 */

#define PHYS_SDRAM_1_SIZE     0x04000000        /* 64 MB */

#define PHYS_FLASH_1         0x00000000          /* Flash Bank #1 */

#define CONFIG_SYS_FLASH_BASE       PHYS_FLASH_1

#define CONFIG_SYS_MONITOR_BASE    TEXT_BASE

#define FLASH_BASE0_PRELIM           PHYS_FLASH_1

/*------------------------------------------------------------

* FLASH and environment organization

*/

#define CONFIG_SYS_FLASH_PROTECTION    1

#define CONFIG_SYS_MAX_FLASH_BANKS     1       /*max number of memory banks*/

#define CONFIG_SYS_FLASH_SIZE     0x00400000     /*4 MB*/

#define CONFIG_SYS_MAX_FLASH_SECT     32     /*max number of sectors on one chip*/

/*timeout values are in ticks*/

#define CONFIG_SYS_FLASH_ERASE_TOUT     (2*CONFIG_SYS_HZ) 

/*Timeout for Flash Erase*/

#define CONFIG_SYS_FLASH_WRITE_TOUT     (2*CONFIG_SYS_HZ) 

/*Timeout for Flash Write*/

#define CONFIG_ENV_IS_IN_FLASH     1

#define CONFIG_ENV_SIZE         0x20000        /*128KB*/

#define CONFIG_ENV_OFFSET      0x40000

2.下载到norflash中运行时需要进行底层初始化,所以要删除之前在配置文件include/configs/ok2440.h中加入的两句:

//#define CONFIG_SKIP_LOWLEVEL_INIT      1    

//#define CONFIG_SKIP_RELOCATE_UBOOT     1  

3.修改board/samsung/ok2440/lowlevel_init.S文件中SDARM刷新参数为:

#define REFCNT   1258    /* period=7.8125us, HCLK=405/4 Mhz, (2048+1-7.8125*405/4) */

4.修改flash型号相关文件:

(1).用board/cmi/flash.c文件替换board/samsung/ok2440/flash.c文件,使uboot支持IntelJS28F320型号nor

(2).修改board/samsung/ok2440/flash.c中函数申明:

static ulong flash_get_size   (vu_short *addr, flash_info_t *info);

//static int    write_short (flash_info_t *info, ulong dest, ushort data);

static int   write_word   (flash_info_t *info, ulong dest, ushort data);

static void   flash_get_offsets (ulong base, flash_info_t *info);

(3).删除board/samsung/ok2440/flash.cwrite_buffwrite_short两个函数,用下面两个函数代替:

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)

{

    ulong cp, wp;

    ushort data;

    int l;

    int i, rc;

    wp = (addr & ~1);         /* get lower word aligned address */

    /*

     * handle unaligned start bytes

     */

    if ((l = addr - wp) != 0)

    {

       data = 0;

       for (i=0, cp=wp; i<l; ++i, ++cp) {

        data = (data >> 8) | (*(uchar *)cp << 8);

       }

       for (; i<2 && cnt>0; ++i) {

      data = (data >> 8) | (*src++ << 8);

      --cnt;

      ++cp;

       }

       for (; cnt==0 && i<2; ++i, ++cp) {

      data = (data >> 8) | (*(uchar *)cp << 8);

       }

       if ((rc = write_word(info, wp, data)) != 0) {

      return (rc);

       }

       wp += 2;

    }

    /*

     * handle word aligned part

     */

    while (cnt >= 2) {

       data = *((vu_short*)src);

       if ((rc = write_word(info, wp, data)) != 0) {

       return (rc);

       }

       src += 2;

       wp   += 2;

       cnt -= 2;

    }

    if (cnt == 0) {

       return ERR_OK;

    }

    /*

     * handle unaligned tail bytes

     */

    data = 0;

    for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {

       data = (data >> 8) | (*src++ << 8);

       --cnt;

    }

    for (; i<2; ++i, ++cp) {

       data = (data >> 8) | (*(uchar *)cp << 8);

    }

    return write_word(info, wp, data);

}

static int write_word (flash_info_t *info, ulong dest, ushort data) 

{

    vu_short *addr = (vu_short *)dest, val;

    int rc = ERR_OK;

    int flag;

    /* Check if Flash is (sufficiently) erased , fix by kavin*/

    if ((*addr & data) != data)

       return ERR_NOT_ERASED;

    flag = disable_interrupts();

    *addr = 0x50;

    *addr = 0x40;

    *addr = data;

    reset_timer_masked();

    while(((val = *addr) & 0x80) != 0x80)

    {

       if (get_timer_masked() > CONFIG_SYS_FLASH_WRITE_TOUT) {

       rc = ERR_TIMOUT;

       *addr = 0xB0;

       goto outahere;

       }

    }

    if(val & 0x1A) {         /* check for error */

       printf("\nFlash write error %02x at address %08lx\n",

            (int)val, (unsigned long)dest);

       if(val & (1<<3)) {

      printf("Voltage range error.\n");

      rc = ERR_PROG_ERROR;

      goto outahere;

       }

       if(val & (1<<1)) {

      printf("Device protect error.\n");

      rc = ERR_PROTECTED;

      goto outahere;

       }

       if(val & (1<<4)) {

      printf("Programming error.\n");

      rc = ERR_PROG_ERROR;

      goto outahere;

       }

       rc = ERR_PROG_ERROR;

       goto outahere;

    }

outahere:

    *addr = 0xFF;

    if (flag)

       enable_interrupts();

    return rc;

}


基于OK-2440IIIu-boot移植(四)


五.在Nand Flash中调试运行

(在 基于OK-2440III的u-boot移植(三) 在norflash中运行通过后修改一下内容)

注:ok2440III开发板的nandflash是三星的K9F1G08(128M)

注:K9F2G08(256M)nandflash同样可以,不需要更改代码

1.修改nandflash的配置,在include/configs/ok2440.h中添加下面配置:

#define CONFIG_CMD_NAND

#define CONFIG_CMDLINE_EDITING

#ifdef CONFIG_CMDLINE_EDITING

#undef CONFIG_AUTO_COMPLETE

#else

#define CONFIG_AUTO_COMPLETE

#endif

/* NAND flash settings */

#if defined(CONFIG_CMD_NAND)

#define CONFIG_SYS_NAND_BASE 0x4E000000 

#define CONFIG_SYS_MAX_NAND_DEVICE      1     

#define CONFIG_MTD_NAND_VERIFY_WRITE   1 

#define NAND_SAMSUNG_LP_OPTIONS     1     /*注意是大块nand!! */

#undef   CONFIG_ENV_IS_IN_FLASH

#define CONFIG_ENV_IS_IN_NAND      1       /* 环境变量的保存位置 */

#define CONFIG_ENV_SIZE     0x20000     

#define CONFIG_ENV_OFFSET   0x40000

#endif

2.增加uboot对该型号nand的支持,在目录drivers/mtd/nand/下新建C文件并命名为s3c2440_nand.c,然后修改目录drivers/mtd/nand/下的Makefile文件:在相应位置加入:                

COBJS-y += s3c2440_nand.o

COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o 

3.添加drivers/mtd/nand/s3c2440_nand.c文件的内容如下:

#include <common.h>

#if 0

#define DEBUGN     printf

#else

#define DEBUGN(x, args ...) {}

#endif

#include <nand.h>

#include <s3c2410.h>

#include <asm/io.h>

#define __REGb(x)     (*(volatile unsigned char *)(x))

#define __REGi(x)     (*(volatile unsigned int *)(x))

#define NF_BASE   0x4e000000            

#define NFCONF    __REGi(NF_BASE + 0x0)  

#define NFCONT    __REGi(NF_BASE + 0x4) 

#define NFCMD     __REGb(NF_BASE + 0x8)  

#define NFADDR    __REGb(NF_BASE + 0xc)  

#define NFDATA    __REGb(NF_BASE + 0x10)

#define NFMECCD0 __REGi(NF_BASE + 0x14) 

#define NFMECCD1 __REGi(NF_BASE + 0x18) 

#define NFSECCD   __REGi(NF_BASE + 0x1C) 

#define NFSTAT    __REGb(NF_BASE + 0x20) 

#define NFSTAT0   __REGi(NF_BASE + 0x24) 

#define NFSTAT1   __REGi(NF_BASE + 0x28) 

#define NFMECC0   __REGi(NF_BASE + 0x2C) 

#define NFMECC1   __REGi(NF_BASE + 0x30) 

#define NFSECC    __REGi(NF_BASE + 0x34) 

#define NFSBLK    __REGi(NF_BASE + 0x38) 

#define NFEBLK    __REGi(NF_BASE + 0x3c) 

#define S3C2440_NFCONT_nCE   (1<<1)

#define S3C2440_ADDR_NALE    0x0c

#define S3C2440_ADDR_NCLE    0x08

ulong IO_ADDR_W = NF_BASE;

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)

{

     struct nand_chip *chip = mtd->priv;

     DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

     if (ctrl & NAND_CTRL_CHANGE) {

         IO_ADDR_W = NF_BASE;

         if (!(ctrl & NAND_CLE))                 //要写的是地址

             IO_ADDR_W |= S3C2440_ADDR_NALE;

         if (!(ctrl & NAND_ALE))                 //要写的是命令

             IO_ADDR_W |= S3C2440_ADDR_NCLE;

         if (ctrl & NAND_NCE) 

             NFCONT &= ~S3C2440_NFCONT_nCE;     //使能nand flash

         else

             NFCONT |= S3C2440_NFCONT_nCE;      //禁止nand flash

     }

     if (cmd != NAND_CMD_NONE)

         writeb(cmd,(void *)IO_ADDR_W);

}

static int s3c2440_dev_ready(struct mtd_info *mtd)

{

     DEBUGN("dev_ready\n");

     return (NFSTAT & 0x01);

}

int board_nand_init(struct nand_chip *nand)

{

     u_int32_t cfg;

     u_int8_t tacls, twrph0, twrph1;

     S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

     DEBUGN("board_nand_init()\n");

     clk_power->CLKCON |= (1 << 4);

     twrph0 = 4; twrph1 = 2; tacls = 0;

     cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);

     NFCONF = cfg;

     cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);

     NFCONT = cfg;

     /* initialize nand_chip data structure */

     nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

     /* hwcontrol always must be implemented */

     nand->cmd_ctrl = s3c2440_hwcontrol;

     nand->dev_ready = s3c2440_dev_ready;

     return 0;

}

4.修改cpu/arm920t/u-boot.lds文件,使lowlevel_init.o在前4K范围(因为ubootnandflash中只能运行前4KB的内容,所以要保证底层初始化在前4KB之内):

.text :

     {

         cpu/arm920t/start.o     (.text)

         board/samsung/ok2440v3/lowlevel_init.o (.text)

         *(.text)

}

5.修改cpu/arm920t/start.Suboot代码的搬移部分(因为ubootnandflash中只能运行前4KB的内容,所以要把uboot搬移到内存中去才能完整的运行):

(1).删除或注释掉该文件中原来的relocate 部分,改成下面:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

#define NFCONF   0x4E000000

relocate_nand:                 /* 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     r5, =NFCONF 

     //set timing value 

     ldr     r0,     =(7<<12)|(7<<8)|(7<<4) 

     str     r0,     [r5] 

     //enable control 

     ldr     r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0) 

     str     r0, [r5, #4] 

     bl     ReadNandID 

     mov     r6, #0 

     ldr     r0, =0xecF1 

     cmp     r5,     r0 

     beq     1f 

     ldr     r0, =0xec76 //似乎多余

     cmp     r5, r0 

     beq     1f 

     mov     r6, #1 

1:     

     bl     ReadNandStatus   

     mov     r8, #0 

     ldr     r9, =_start 

     mov    r10, #128           /*u-boot 256k,128页     --这里原来是32!! */

2:     

     ands     r0, r8, #0x3f     /*如果是第一页,则检测坏块 */

     bne         3f 

     mov         r0, r8 

     bl         CheckBadBlk 

     cmp         r0, #0 

     addne     r8, r8, #64     /*每块的页数  */ 

     addne     r10,r10,#64      /* +081010 feiling */

     bne         4f 

3:     

     mov     r0, r8 

     mov     r1, r9 

     bl     ReadNandPage 

     add     r9, r9, #2048     /*每页的字节数*/ 

     add     r8, r8, #1         /* 页数+1 */

4:     

     cmp     r8, r10    /*要拷贝的页数 081010 pht:#32->r10   */

     bcc     2b   

     ldr    r5, =NFCONF             /*DsNandFlash   */

     ldr     r0, [r5, #4] 

     bic r0, r0, #1 

     str     r0, [r5, #4]

#endif

(2).在(cpu/arm920t/start.S)文件最后添加下面子函数:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

ReadNandID:

ldr       r7,=NFCONF

ldr       r0,[r7,#4] 

bic       r0,r0,#2

str       r0,[r7,#4]

mov       r0,#0x90 

strb      r0,[r7,#8]

mov       r4,#0 

strb      r4,[r7,#0xc]

1: 

ldr       r0,[r7,#0x20]

tst       r0,#1

beq       1b

ldrb      r0,[r7,#0x10] 

mov       r0,r0,lsl #8

ldrb      r1,[r7,#0x10] 

orr       r5,r1,r0

ldr       r0,[r7,#4] 

orr       r0,r0,#2

str       r0,[r7,#4]

mov pc,lr 

ReadNandStatus:

ldr r7,=NFCONF

ldr       r0,[r7,#4] 

bic       r0,r0,#2

str       r0,[r7,#4]

mov       r0,#0x70 

strb      r0,[r7,#8] 

ldrb      r1,[r7,#0x10] 

ldr       r0,[r7,#4] 

orr       r0,r0,#2

str       r0,[r7,#4]

mov pc,lr

WaitNandBusy:

mov       r0,#0x70 

ldr       r1,=NFCONF

strb      r0,[r1,#8]

1: 

ldrb      r0,[r1,#0x10]

tst       r0,#0x40

beq 1b

mov       r0,#0 

strb      r0,[r1,#8]

mov       pc,lr

CheckBadBlk: 

mov r7, lr

ldr r5, =NFCONF

bic       r0,r0,#0x3f 

ldr       r1,[r5,#4] 

bic       r1,r1,#2

str       r1,[r5,#4]

mov       r1,#0x00 

strb      r1,[r5,#8]

mov       r1, #0 

strb      r1,[r5,#0xc] 

mov       r1, #8 

strb      r1,[r5,#0xc]

strb      r0,[r5,#0xc] 

mov       r1,r0,lsr #8 

strb      r1,[r5,#0xc]

/****************nand为256M时,需要加以下代码***************/

cmp      r6,#0 ;if(NandAddr)

movne    r1,r0,lsr #16 ;WrNFAddr(addr>>16)

strb

/****************nand为256M时,需要加以上代码***************/

mov       r1,#0x30 

strb      r1,[r5,#8] 

mov r0, #100

1:

subs r0, r0, #1

bne 1b

2:

ldr r0, [r5, #0x20]

tst r0, #1

beq 2b 

ldrb r0, [r5,#0x10] 

sub r0, r0, #0xff

ldr       r1,[r5,#4] 

orr       r1,r1,#2

str       r1,[r5,#4]

mov pc, r7

ReadNandPage: 

mov r7,lr

mov       r4,r1

ldr       r5,=NFCONF

ldr       r1,[r5,#4] 

bic       r1,r1,#2

str       r1,[r5,#4] 

mov       r1,#0 

strb      r1,[r5,#8] 

strb      r1,[r5,#0xc] 

strb      r1,[r5,#0xc] 

strb      r0,[r5,#0xc] 

mov       r1,r0,lsr #8 

strb      r1,[r5,#0xc] 

/****************nand为256M时,需要加以下代码***************/

cmp      r6,#0 ;if(NandAddr)

movne    r1,r0,lsr #16 ;WrNFAddr(addr>>16)

strb

/****************nand为256M时,需要加以上代码***************/

mov       r1,#0x30 

strb      r1,[r5,#8]

ldr       r0,[r5,#4] 

orr       r0,r0,#0x10

str       r0,[r5,#4]

bl        WaitNandBusy 

mov       r0,#0 

1: 

ldrb      r1,[r5,#0x10] 

strb      r1,[r4,r0]

add       r0,r0,#1

bic       r0,r0,#0x10000   

cmp       r0,#0x800

bcc       1b

ldr       r0,[r5,#4] 

orr       r0,r0,#2

str       r0,[r5,#4]

mov pc,r7

#endif

你可能感兴趣的:(基于OK-2440III的u-boot移植)