Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / U-Boot1.3.1移植YC2440

ARM and Linux,一个伟大的行业,鄙人正处于摸索阶段的新手。既然如此,就先从U-Boot下手,在此过程中参考了网上一些高手的资料。下面是他们的链接,感谢他们分享经验让新手快速入门、找到学习方法,再次感谢他们对于技术资料无私奉献、共享。  由于YC2440网卡芯片DM9000AEP,网卡移植参考了Weibing的一位网友。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> U-Boot源码: U-Boot源码下载免费下载地址在 http://linux.linuxidc.com/用户名与密码都是www.linuxidc.com具体下载目录在 /pub/u-boot/ U-Boot-<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1.3.1还没有支持s3c2440,这次移植是用s3c2410的文件修改而成。红色为修改的地方,蓝色为运行指令、重要注释 一、在U-Boot中建立自己开发板类型,测试编译1 进入U-Boot目录,修改Makefile# tar –jxvf  u-boot-1.3.1.tar.bz2# cd u-boot-1.3.1# gedit Makefile//liao2440建立编译项sbc2410x_config: unconfig    @$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0liao2440_config : unconfig        @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao s3c24x0说明:arm: CPU的架构(ARCH)arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。liao2440: 开发板的型号(BOARD),对应于board/liao/liao2440目录。liao: 开发者/或经销商(vender)s3c24x0: 片上系统(SOC) 同时在“ifndef CROSS_COMPILE”之前  加上自己交叉编译器的路径,比如我使用crosstool-0.43制作的基于2.6.24内核和gcc-4.1.1-glibc-2.3.2ARM9TDMI交叉编译器,则: CROSS_COMPILE=CROSS_COMPILE=/home/liao/crosstool/gcc-4.1.1-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu- 2 /board子目录中建立自己开发板liao2440目录 由于上一步板子的开发者/或经销商(vender)中填了liao,所以开发板liao2440目录一定要建在/board子目录liao目录下 ,否则编译会出错。 # cd board# mkdir liao liao/liao2440# cp -arf sbc2410x/*   liao/liao2440/# cd liao/liao2440# mv sbc2410x.c liao2440.c 修改自己开发板liao2440目录下Makefile文件# gedit MakefileCOBJS := sbc2410x.o flash.o COBJS := liao2440.o flash.o 3 建立配置头文件在include/configs/# cd …/u-boot-1.2.0/include/configs# cp include/configs/sbc2410x.h  include/configs/liao2440.h 4 测试编译是否成功# make liao2440_configConfiguring for liao2440 board…如果出现:Makefile:1927: *** 遗漏分隔符 停止。请在Uboot的根目录下的Makefile        @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao)前加上“Tab”键# make     Ok,到这里前期准备工作完成!!!!!!! 二、修改U-Boot中文件,根据开发板YC2440配置1 修改/cpu/arm920t/start.S 1.0 修改一些AT91RM9200定义#include <config.h>#include <version.h>//#include <status_led.h>    /*这是针对AT91RM9200DK开发板*/....../* * the actual start code */start_code:    /*     * set the cpu to SVC32 mode     */    mrs    r0,cpsr    bic    r0,r0,#0x1f    orr    r0,r0,#0xd3    msr    cpsr,r0     //bl coloured_LED_init    //bl red_LED_on 1.1修改寄存器定义#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)/* turn off the watchdog */# if defined(CONFIG_S3C2400)# define pWTCON        0x15300000# define INTMSK        0x14400008    /* Interupt-Controller base addresses */# define CLKDIVN    0x14800014    /* clock divisor register */# else # define pWTCON        0x53000000# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */# define INTSUBMSK    0x4A00001C# define CLKDIVN    0x4C000014    /* clock divisor register */# endif# define CLK_CTL_BASE        0x4C000000# if defined(CONFIG_S3C2440)# define MDIV_405       0x7f << 12# define PSDIV_405       0x21# endif# if defined(CONFIG_S3C2410)# define MDIV_200        0xa1 << 12# define PSDIV_200        0x31# endif/*这一段为后面修改时钟定义的一些参数*/ 1.2修改中断禁止部分# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)    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, =0x7ff     //根据2410芯片手册,INTSUBMSK11位可用,                       //vivi也是0x7ff,不知为什么UBoot一直没改过来。    ldr    r0, =INTSUBMSK    str    r1, [r0]# endif# if  defined(CONFIG_S3C2440)    ldr    r1, =0x7fff   //根据2440芯片手册,INTSUBMSK15位可用    ldr    r0, =INTSUBMSK    str    r1, [r0]# endif 1.3 修改时钟设置/*时钟控制逻辑单元能够产生s3c2440需要的时钟信号,包括CPU使用的主频FCLK,AHB总线使用的HCLK,APB总线设备使用的PCLK2440里面的两个锁相环(PLL),其中一个对应FCLKHCLKPCLK,另外一个对应UCLK(48MHz)*//* FCLK:HCLK:PCLK = 1:4:8 */    ldr    r0, =CLKDIVN    mov    r1, #5    str    r1, [r0]/*下面协处理器指令是用来把CPU的模式设置成Asynchronous 模式,为什么要这样做?s3c2440datasheet说得很清楚,具体可在datasheet中搜索R1_nFR1_iA内容。至于R1_nFR1_iA的值可以在vivi源码的s3c2440.h中得到。单从指令上看,下面指令的作用把协处理器p15的寄存器c1的最高两位置1,仔细看过《arm 体系结构与编程》的朋友可能会发现个问题:《arm 体系结构与编程》里面说 p15 bit30bit31是保留的,那么下面的指令又怎么会有意义呢?其实《arm 体系结构与编程》里面说这两个bit是保留的是针对arm7的,对arm9s3c2440并不适用。《ARM体系结构与编程》杜春雷 PDF 下载地址 http://www.linuxidc.com/Linux/2011-09/43099.htm*/    mrc    p15, 0, r1, c1, c0, 0        /*read ctrl register   liao*/    orr    r1, r1, #0xc0000000         /*Asynchronous  liao*/    mcr    p15, 0, r1, c1, c0, 0      /*write ctrl register liao*/ # if defined(CONFIG_S3C2440)    /*now, CPU clock is 405.00 Mhz  */    mov    r1, #CLK_CTL_BASE    mov    r2, #MDIV_405                   /* mpll_405mhz    liao*/    add    r2, r2, #PSDIV_405             /* mpll_405mhz    liao*/    str    r2, [r1, #0x04]               /* MPLLCON liao */# endif# if defined(CONFIG_S3C2410)    /*now, CPU clock is 202.8 Mhz   liao*/    mov    r1, #CLK_CTL_BASE    /* liao*/    mov    r2, #MDIV_200                   /* mpll_200mhz    liao*/    add    r2, r2, #PSDIV_200             /* mpll_200mhz    liao*/    str    r2, [r1, #0x04]               /* MPLLCON liao */# endif# endif    /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 *//*时钟设置参照vivi代码,主频405MHZ*/ 1.4 Flash启动改为从NAND Flash启动(24102440不同,参照vivi# if 0# ifndef CONFIG_SKIP_RELOCATE_UBOOTrelocate:                   /* 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 */# endif/*参照vivi代码,nandflash拷贝*/# ifdef CONFIG_S3C2440_NAND_BOOT       @ reset NAND    mov    r1, #NAND_CTL_BASE    ldr    r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )    str    r2, [r1, #oNFCONF]     /*这些宏在includes/configs/liao2440.h中定义*/    ldr    r2, [r1, #oNFCONF]     ldr    r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control     str    r2, [r1, #oNFCONT]    ldr    r2, [r1, #oNFCONT]     ldr    r2, =(0x6)        @ RnB Clear    str    r2, [r1, #oNFSTAT]    ldr    r2, [r1, #oNFSTAT]        mov    r2, #0xff        @ RESET command    strb    r2, [r1, #oNFCMD]     mov r3, #0                   @ waitnand1:     add  r3, r3, #0x1    cmp r3, #0xa    blt   nand1 nand2:    ldr   r2, [r1, #oNFSTAT]      @ wait ready    tst    r2, #0x4    beq  nand2      ldr    r2, [r1, #oNFCONT]    orr    r2, r2, #0x2        @ Flash Memory Chip Disable    str    r2, [r1, #oNFCONT]/*汇编调用C函数,初始化栈*/@ get read to call C functions (for nand_read())    ldr   sp, DW_STACK_START       @ setup stack pointer    mov fp, #0                    @ no previous frame, so fp=0 @ copy U-Boot to RAM    ldr   r0, =TEXT_BASE    mov     r1, #0x0  mov  r2, #0x30000    bl    nand_read_ll/*nand_read_lluboot拷贝代码入口函数,r0r1r2为入口参数tst  r0#0x0r0为函数返回值*/    tst    r0, #0x0    beq  ok_nand_read bad_nand_read:loop2:    b     loop2          @ infinite loop  ok_nand_read:@ verify    mov r0, #0    ldr   r1, =TEXT_BASE  mov r2, #0x400     @ 4 bytes * 1024 = 4K-bytesgo_next:    ldr   r3, [r0], #4  ldr   r4, [r1], #4    teq   r3, r4    bne  notmatch    subs r2, r2, #4    beq  stack_setupbne  go_next notmatch:loop3:     b     loop3         @ infinite loop #endif @ CONFIG_S3C2440_NAND_BOOT#ifdef CONFIG_S3C2410_NAND_BOOT @ reset NANDmov r1, #NAND_CTL_BASE    ldr r2, =0xf830 @ initial value    str r2, [r1, #oNFCONF]    ldr r2, [r1, #oNFCONF]     bic r2, r2, #0x800 @ enable chip    str r2, [r1, #oNFCONF]     mov r2, #0xff @ RESET command    strb r2, [r1, #oNFCMD]   mov r3, #0 @ waitnand1:     add r3, r3, #0x1    cmp r3, #0xa    blt nand1 nand2:    ldr r2, [r1, #oNFSTAT] @ wait ready    tst r2, #0x1    beq nand2     ldr r2, [r1, #oNFCONF]    orr r2, r2, #0x800 @ disable chip    str r2, [r1, #oNFCONF] @ get read to call C functions (for nand_read())    ldr sp, DW_STACK_START @ setup stack pointer  mov fp, #0 @ no previous frame, so fp=0 @ copy U-Boot to RAM  ldr r0, =TEXT_BASE    mov r1, #0x0    mov r2, #0x30000    bl nand_read_ll    tst r0, #0x0    beq ok_nand_read bad_nand_read:loop2: b loop2 @ infinite loop  ok_nand_read:@ verify    mov r0, #0    ldr r1, =TEXT_BASE    mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytesgo_next:  ldr r3, [r0], #4    ldr r4, [r1], #4    teq r3, r4  bne notmatch  subs r2, r2, #4  beq stack_setup  bne go_next notmatch:loop3: b loop3 @ infinite loop #endif @ CONFIG_S3C2410_NAND_BOOT 1.5 调出start.S前,利用点灯大法查看程序运行位置 ldr  pc_start_armboot 之前加入LEDmov    r1, #GPIO_CTL_BASEadd    r1, r1, #oGPIO_Fldr    r2,=0x55aastr    r2, [r1, #oGPIO_CON]mov    r2, #0xffstr    r2, [r1, #oGPIO_UP]mov    r2, #0xe0str    r2, [r1, #oGPIO_DAT]/*YC2440开发板有4LEDGPIO_F[4:7],点亮一个LED,下面函数进入第二阶段*/ldr  pc_start_armboot_start_armboot:      .word start_armboot.align     2                  DW_STACK_START:  .word  STACK_BASE+STACK_SIZE-4/*栈空间是从高地址向低地址增长,用于调用nand_read_ll函数时设置占空间,STACK_BASE STACK_SIZE定义在后面/include/configs/liao2440.h */ 2 board/liao/liao2440加入NAND Flash读函数文件,复制vivinand_read.c文件#include <config.h> #define __REGb(x)    (*(volatile unsigned char *)(x))#define __REGi(x)    (*(volatile unsigned int *)(x))#define NF_BASE        0x4e000000 #if defined(CONFIG_S3C2440)         /*s3c2440部分*/ #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 NFSTAT        __REGb(NF_BASE + 0x20) //#define GPDAT        __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT) #define NAND_CHIP_ENABLE  (NFCONT &= ~(1<<1))#define NAND_CHIP_DISABLE (NFCONT |=  (1<<1))#define NAND_CLEAR_RB      (NFSTAT |=  (1<<2))#define NAND_DETECT_RB      { while(! (NFSTAT&(1<<2)) );} #define BUSY 4inline void wait_idle(void) {    while(!(NFSTAT & BUSY));    NFSTAT |= BUSY;} #define NAND_SECTOR_SIZE    512#define NAND_BLOCK_MASK        (NAND_SECTOR_SIZE - 1) /* low level nand read function */intnand_read_ll(unsigned char *buf, unsigned long start_addr, int size){    int i, j;/* 下面if保证对flash的读操作是从某一页的页头开始的,也就是保证start_addr[0:8]位都为0本次flash的一页的大小位512-bytes,也就是从0x00x1ff */    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {        return -1;    /* invalid alignment */    }     NAND_CHIP_ENABLE;     for(i=start_addr; i < (start_addr + size);) {        /* READ0 */        NAND_CLEAR_RB;                NFCMD = 0;         /* Write Address *//*下面这个送地址的过程最难懂的一部分,为什么送进nand flash的地址忽略了bit8,纵观整个for(i) 循环,i并不是一个随机的地址,而应该是每一页的首地址。其实nand flash并不是忽略了bit8这个地址,而是bit8早就被定下来了,就是上面的NFCMD = 0;语句,(K9F1208U0B)支持从半页开始读取,从而它有两个读的命令,分别是0x00(从一页的上半页开始读 0x01(从一页的下半页开始读,当取0x00时,bit8=0,当取0x01 bit8=1*/        NFADDR = i & 0xff;        NFADDR = (i >> 9) & 0xff;        NFADDR = (i >> 17) & 0xff;        NFADDR = (i >> 25) & 0xff;         NAND_DETECT_RB;         for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {            *buf = (NFDATA & 0xff);            buf++;        }    }    NAND_CHIP_DISABLE;    return 0;}#endif #if defined(CONFIG_S3C2410)          /*s3c2410部分*/ #define NFCONF __REGi(NF_BASE + 0x0)#define NFCMD __REGb(NF_BASE + 0x4)#define NFADDR __REGb(NF_BASE + 0x8)#define NFDATA __REGb(NF_BASE + 0xc)#define NFSTAT __REGb(NF_BASE + 0x10)#define BUSY 1 inline void wait_idle(void) {    int i;    while(!(NFSTAT & BUSY))      for(i=0; i<10; i++);}/* low level nand read function */intnand_read_ll(unsigned char *buf, unsigned long start_addr, int size){    int i, j;    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {        return -1; /* invalid alignment */    }    /* chip Enable */    NFCONF &= ~0x800;    for(i=0; i<10; i++);    for(i=start_addr; i < (start_addr + size);) {      /* READ0 */        NFCMD = 0;        /* Write Address */        NFADDR = i & 0xff;        NFADDR = (i >> 9) & 0xff;        NFADDR = (i >> 17) & 0xff;        NFADDR = (i >> 25) & 0xff;        wait_idle();        for(j=0; j < NAND_SECTOR_SIZE; j++, i++){     *buf = (NFDATA & 0xff);                   buf++;        }    }    /* chip Disable */    NFCONF |= 0x800; /* chip disable */    return 0;}# endif