云顶娱乐官方入口-www.40081.com-云顶娱乐网址4118112
做最好的网站
您的位置:云顶娱乐官方入口 > 云顶娱乐网址4118112 > 需要初始化nandflash,现在把移植过程记录下来

需要初始化nandflash,现在把移植过程记录下来

2019-10-05 15:27

目标:

开发环境:Ubuntu 12.04
开发板:JZ2440  256M NandFlash  64M SDRAM
交叉编译器:arm-linux-gcc-4.3.2
u-boot:u-boot-2012.04.01  

第一阶段:

 

1.关看门狗
2.设置时钟
3.初始化SDRAM (初始化寄存器以及清除bss段)
4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash)

 

5.执行main 

 

进入第二阶段:

 

6.写main函数,在main()中设置要传给内核的参数,然后跳转内核基地址处

 

7.制作uboot.lds链接脚本

 


 

 

 

编写步骤:

  最近在学习BootLoader,移植u-boot-2012.04.01到JZ2440开发板,现在把移植过程记录下来,一来梳理思路,二来方便以后更进一步学习。

1.创建个名为"my_bootloader"根目录,方便编写uboot

 

2.新建my_bootloader/si目录,创建source insight工程

一、  u-boot分析过程

2.1 新建my_bootloader/start.S (后缀名必须是大写的S,或者后面编译会报错)

    a、 初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH

编写start.S (第一阶段初始硬件文件):
start.s任务:
1.关看门狗
2.设置时钟
3.初始化SDRAM
4.重定位(把bootloader本身的代码从flash复制到它的链接地址(c函数编写),然后清空bss段(c函数编写))
5.执行main

    b、如果bootloader比较大,要把它重定位到SDRAM

/*  看门狗寄存器            */
#define WTCON      0x53000000

/*  2.时钟寄存器            */
#define CLKDIVN    0x4C000014        //设置FCLK,HCLK,PCLK比例
#define MPLLCON   0x4C000004          //设置FCLK频率
#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))  //设置FCLK=200MHZ
#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))  //设置FCLK=400MHZ

/*  3.bank寄存器       */
#define BWSCON      0x48000000

.text                                /*设置代码段*/
.global   _start                  /*定义全局变量,要被连接脚本用到*/
_start:                           /*_start跳转到这里实现硬件初始化*/

    /*  1.关看门狗            */
       ldr r0,=WTCON
       mov r1,#0
       str r1,[r0]

    /*  2.设置时钟(必须设为异步总线模式)  */

       ldr r0,=CLKDIVN
       mov r1,#3                                  /*FCLK:HCLK:PCLK=1:2:4*/ 
       str r1,[r0]        
       mrc  p15, 0, r1, c1, c0                 /* 读出控制寄存器 */   
       orr   r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */
       mcr    p15, 0, r1, c1, c0, 0             /* 写入控制寄存器 */       
       ldr r0,=MPLLCON
       ldr r1,=S3C2440_MPLL_200MHZ      //使用复杂的数不能用mov,需要用ldr
       str r1,[r0]

    /*  3.初始化SDRAM       */
       ldr r0,=BWSCON                   //r0=SDRAM寄存器基地址
       adr r1,SDRAM_CONFIG           //使用adr相对跳转,因为SDRAM未初始化
       add r2,r0,#(13*4)               //r2等于 SDRAM尾地址+4

0:
       ldr r3,[r1],#4                      //r3=r1里的  内容, &r1+=4;
       str r3,[r0],#4                      //*r0=r3,&r0+=4
       cmp r0,r2
       bne 0b                               //(ne:no equal   b:bank)   若r0!=r2,跳转到后面的0处

 /*  4.重定位                 */
        ldr sp,=0x34000000                     //64Msdram,所以设置栈SP=0x34000000,避免堆栈溢出
        mov r0,#0                           //r0->src
    ldr r1,=_start                     //r1->dest
    ldr r2,=__bss_start            //r2->len->__bss_start-_start
    sub r2,r2,r1
    bl copy_code_to_sdram          //复制代码到SDRAM连接地址dest上
    bl clear_bss                         //清除bss段 

   /*  5.执行main                */
        ldr lr,=halt                         //执行一个子程序调用返回时,需要先将返回地址赋给lr链接寄存器
        ldr pc,=main                              //初始化SDRAM后,可以使用pc 绝对跳转到SDRAM地址上
        mov pc,lr                             //若main函数跳出后,使PC等于lr链接寄存器,避免程序跑飞 

halt:                                   //死循环,避免跑飞
     b halt               

SDRAM_CONFIG:
    .long 0x22011110;     //BWSCON
    .long 0x00000700;     //BANKCON0
    .long 0x00000700;     //BANKCON1
    .long 0x00000700;     //BANKCON2
    .long 0x00000700;     //BANKCON3  
    .long 0x00000700;     //BANKCON4
    .long 0x00000700;     //BANKCON5
    .long 0x00018005;     //BANKCON6
    .long 0x00018005;     //BANKCON7
    .long 0x008C04F4;     //REFRESH
    .long 0x000000B1;     //BANKSIZE 
    .long 0x00000030;     //MRSRB6
    .long 0x00000030;     //MRSRB7

    c、把内核从NAND FLASH读到SDRAM

3 新建my_bootloader/init.c,用于重定位,bss段清除,初始化NandFlash等

    d、设置"要传给内核的参数"

在重定位函数中的nand驱动在(入口:http://www.cnblogs.com/lifexy/p/7097695.html)里详细介绍了,这里就不描述了.

    e、跳转执行内核

3.1编写copy_code_tosdram() 重定位函数

具体代码分析

void copy_code_to_sdram(unsigned char *src,unsigned char *dest,unsigned int len)            //复制代码到SDRAM连接地址dest上
{
      unsigned int i;
        /*判断nor启动还是nand启动*/
    if(is_boot_from_norflash())                 //nor启动,直接复制
    {
              for(i=0;i<len;i++)
              {
               dest[i]=src[i];
              }
    }
    else
    {
       nand_init();

    nand_read((unsigned int)src,dest,len);

    }
} 

1、set the cpu to SVC32 mode

3.2编写isBootFramNorFlash()函数,来判断nand启动还是nor启动

2、turn off the watchdog

/*判断nor启动还是nand启动*/
unsigned char is_boot_from_norflash(void)
{
         volatile unsigned int *p=(volatile unsigned int *)0;
     unsigned int i;
     i=*p;
     *p=0x12345678;
     if(*p==0x12345678)    //nand
     {
     *p=i;
     return 0;
     }
     else                    //nor
     {
        *p=i;
     return 1;
     }

3、mask all IRQs by setting all bits in the INTMR

3.3编写clear_bss()函数

4、设置时钟比例

void clear_bss(void)  //清除BSS段
{
  extern int __bss_start,__bss_end;
  int  *p=&__bss_start;
  for( ;p<&__bss_end;p++)
  {
  *p=0;
  }
}

5、设置内存控制器

4编写连接脚本uboot.lds (参考硬件实验里的uart.lds和u-boot-1.1.6里的u-boot.lds)

6、设置栈,调用C函数board_init_f

SECTIONS {
    . = 0x33f80000; //0地址里存放0X33F80000
    . = ALIGN(4);

    .text : { *(.text) }
    . = ALIGN(4);

    .rodata : { *(.rodata)  }
    . = ALIGN(4);

    .data : {   *(.data)    }
    . = ALIGN(4);

    __bss_start = .; 
    .bss : { *(.bss) *(COMMON) }
    __bss_end = .;
}

7、调用函数数组init_sequence里的各个函数

其中0x33f80000就是链接地址首地址,共512K空间存放bootloader
定义__bss_start和__bss_end符号,是用来程序开始之前将这些未定义的变量清0,节省内存
且bss_start-0x33f80000就等于代码的大小(copy_code_tosdram函数中len值)

    7.1 board_early_init_f : 设置系统时钟、设置GPIO

 

......................................

8、重定位代码

    8.1 从NOR FLASH把代码复制到SDRAM

    8.2 程序的链接地址是0,访问全局变量、静态变量、调用函数时是使"基于0地址编译得到的地址",现在把程序复制到了SDRAM,需要修改代码,把"基于0地址编译得到的地址"改为新地址。

    8.3 程序里有些地址在链接时不能确定,要到运行前才能确定:fixabs

9、clear_bss

10、调用C函数board_init_r:第2阶段的代码

 

二、初始编译

 1、  解压 u-boot-2012.04.01.tar.bz2

tar xjf u-boot-2012.04.01.tar.bz2

进入解压后文件目录

cd u-boot-2012.04.01

2、在解压后文件目录下根据靠近的单板,配置

make smdk2410_config
make

这个时候编译完成后是不能在JZ2440上正常运行

三、建立自己的单板,定制适合自己单板的bootloader

1、新建一个单板

    cd board/samsung/
    cp smdk2410 smdk2440 -rf
     cd ../../include/configs/
    cp smdk2410.h smdk2440.h

修改boards.cfg

仿照2410,添加2440

smdk2410                     arm         arm920t     -                  samsung        s3c24x0

添加

smdk2440                     arm         arm920t     -                   samsung        s3c24x0

make , 烧写调试

2、根据需求进一步配置

make menuconfig  

3、修改Makefile ,开头指定架构和编译器

 ARCH=arm
 CROSS_COMPILE=arm-linux-

4、修改uboot代码,适合单板

  uboot里先以60MHZ的时钟计算参数来设置内存控制器,但是MPLL还未设置

  处理措施: 把MPLL的设置放到start.S里,取消board_early_init_f里对MPLL的设置

a、设置PLL的时钟的函数在_main中的board_init_f中初始化函数列表中的  boad_early_init_f 中,设置MPLL倍频值。它应该要在设置分频系数和初始化内存控制器之前来设置。

做如下修改: 在smdk2410.c文件中找到设置MPLL部分的代码,注释掉。

    /* to reduce PLL lock time, adjust the LOCKTIME register */
         //writel(0xFFFFFF, &clk_power->locktime);

      /* configure MPLL */
         //writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
           //     &clk_power->mpllcon);

然后在start.S中再设置MPLL

 

图片 1图片 2

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
#if 0
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
  #else
        /* 2. 设置时钟 400MHz */
        ldr r0, =0x4c000014
        //  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
        mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8
        str r1, [r0]
        /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
        mrc p15, 0, r1, c1, c0, 0       /* 读出控制寄存器 */
        orr r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */
        mcr p15, 0, r1, c1, c0, 0       /* 写入控制寄存器 */

        #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
        /* MPLLCON = S3C2440_MPLL_200MHZ */
        ldr r0, =0x4c000004
        ldr r1, =S3C2440_MPLL_400MHZ
        str r1, [r0]

        /* 启动ICACHE */
        mrc p15, 0, r0, c1, c0, 0   @ read control reg
        orr r0, r0, #(1<<12)
        mcr p15, 0, r0, c1, c0, 0   @ write it back
  #endif

View Code

 

关闭看门狗、关中断

图片 3图片 4

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
#if 0
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
  #else
        /* 2. 设置时钟 400MHz */
        ldr r0, =0x4c000014
        //  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
        mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8
        str r1, [r0]
        /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
        mrc p15, 0, r1, c1, c0, 0       /* 读出控制寄存器 */
        orr r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */
        mcr p15, 0, r1, c1, c0, 0       /* 写入控制寄存器 */

        #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
        /* MPLLCON = S3C2440_MPLL_200MHZ */
        ldr r0, =0x4c000004
        ldr r1, =S3C2440_MPLL_400MHZ
        str r1, [r0]

        /* 启动ICACHE */
        mrc p15, 0, r0, c1, c0, 0   @ read control reg
        orr r0, r0, #(1<<12)
        mcr p15, 0, r0, c1, c0, 0   @ write it back
  #endif
关闭看门狗、关中断

#ifdef CONFIG_S3C24X0
    /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON    0x15300000
#  define INTMSK    0x14400008    /* Interrupt-Controller base addresses */
#  define CLKDIVN    0x14800014    /* clock divisor register */
#else
#  define pWTCON    0x53000000
#  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
#  define INTSUBMSK    0x4A00001C
#  define CLKDIVN    0x4C000014    /* clock divisor register */
# endif

    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
#endif

View Code

b、内存控制器的设置值改为如下

在/board/samsung/smdk2410/lowlevel_init.S文件中做一下修改

图片 5图片 6

SMRDATA:
#if 0
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0x32
    .word 0x30
    .word 0x30
#else

  .long 0x22011110     //BWSCON
  .long 0x00000700     //BANKCON0
  .long 0x00000700     //BANKCON1
  .long 0x00000700     //BANKCON2
  .long 0x00000700     //BANKCON3
  .long 0x00000700     //BANKCON4
  .long 0x00000700     //BANKCON5
  .long 0x00018005     //BANKCON6
  .long 0x00018005     //BANKCON7
  .long 0x008C04F4     //REFRESH
  .long 0x000000B1     //BANKSIZE
  .long 0x00000030     //MRSRB6
  .long 0x00000030     //MRSRB7

 #endif

View Code

c、设置串口波特率(get_HCLK函数),乱码,查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440宏

处理措施:在include/configs/smdk2440.h中

//#define CONFIG_S3C2410        /* specifically a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410        /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440        /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_SMDK2440        /* on a SAMSUNG SMDK2440 Board */

d、修改UBOOT支持NAND启动,原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)"

    使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)

arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行

把init.c放入board/samsung/smdk2440目录,修改Makefile,使init.c编译进去

修改smdk2440.h ,修改CONFIG_SYS_TEXT_BASE为0x33f80000

#define CONFIG_SYS_TEXT_BASE    0x33f00000

 

init.c

图片 7图片 8

/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))

/* GPIO */
#define GPHCON              (*(volatile unsigned long *)0x56000070)
#define GPHUP               (*(volatile unsigned long *)0x56000078)

/* UART registers*/
#define ULCON0              (*(volatile unsigned long *)0x50000000)
#define UCON0               (*(volatile unsigned long *)0x50000004)
#define UFCON0              (*(volatile unsigned long *)0x50000008)
#define UMCON0              (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
#define UTXH0               (*(volatile unsigned char *)0x50000020)
#define URXH0               (*(volatile unsigned char *)0x50000024)
#define UBRDIV0             (*(volatile unsigned long *)0x50000028)

#define TXD0READY   (1<<2)


void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);


int isBootFromNorFlash(void)
{
    volatile int *p = (volatile int *)0;
    int val;

    val = *p;
    *p = 0x12345678;
    if (*p == 0x12345678)
    {
        /* 写成功, 是nand启动 */
        *p = val;
        return 0;
    }
    else
    {
        /* NOR不能像内存一样写 */
        return 1;
    }
}

void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{    
    int i = 0;

    /* 如果是NOR启动 */
    if (isBootFromNorFlash())
    {
        while (i < len)
        {
            dest[i] = src[i];
            i++;
        }
    }
    else
    {
        //nand_init();
        nand_read((unsigned int)src, dest, len);
    }
}

void clear_bss(void)
{
    extern int __bss_start, __bss_end;
    int *p = &__bss_start;

    for (; p < &__bss_end; p++)
        *p = 0;
}

void nand_init(void)
{
#define TACLS   0
#define TWRPH0  1
#define TWRPH1  0
    /* 设置时序 */
    NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
    /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
    NFCONT = (1<<4)|(1<<1)|(1<<0);    
}

void nand_select(void)
{
    NFCONT &= ~(1<<1);    
}

void nand_deselect(void)
{
    NFCONT |= (1<<1);    
}

void nand_cmd(unsigned char cmd)
{
    volatile int i;
    NFCMMD = cmd;
    for (i = 0; i < 10; i++);
}

void nand_addr(unsigned int addr)
{
    unsigned int col  = addr % 2048;
    unsigned int page = addr / 2048;
    volatile int i;

    NFADDR = col & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR = (col >> 8) & 0xff;
    for (i = 0; i < 10; i++);

    NFADDR  = page & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR  = (page >> 8) & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR  = (page >> 16) & 0xff;
    for (i = 0; i < 10; i++);    
}

void nand_wait_ready(void)
{
    while (!(NFSTAT & 1));
}

unsigned char nand_data(void)
{
    return NFDATA;
}

void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
    int col = addr % 2048;
    int i = 0;

    /* 1. 选中 */
    nand_select();

    while (i < len)
    {
        /* 2. 发出读命令00h */
        nand_cmd(0x00);

        /* 3. 发出地址(分5步发出) */
        nand_addr(addr);

        /* 4. 发出读命令30h */
        nand_cmd(0x30);

        /* 5. 判断状态 */
        nand_wait_ready();

        /* 6. 读数据 */
        for (; (col < 2048) && (i < len); col++)
        {
            buf[i] = nand_data();
            i++;
            addr++;
        }

        col = 0;
    }

    /* 7. 取消选中 */        
    nand_deselect();
}

#define PCLK            50000000    // init.c中的clock_init函数设置PCLK为50MHz
#define UART_CLK        PCLK        //  UART0的时钟源设为PCLK
#define UART_BAUD_RATE  115200      // 波特率
#define UART_BRD        ((UART_CLK  / (UART_BAUD_RATE * 16)) - 1)

/*
 * 初始化UART0
 * 115200,8N1,无流控
 */
void uart0_init(void)
{
    GPHCON  |= 0xa0;    // GPH2,GPH3用作TXD0,RXD0
    GPHUP   = 0x0c;     // GPH2,GPH3内部上拉

    ULCON0  = 0x03;     // 8N1(8个数据位,无较验,1个停止位)
    UCON0   = 0x05;     // 查询方式,UART时钟源为PCLK
    UFCON0  = 0x00;     // 不使用FIFO
    UMCON0  = 0x00;     // 不使用流控
    UBRDIV0 = UART_BRD; // 波特率为115200
}

/*
 * 发送一个字符
 */
void putc(unsigned char c)
{
    /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
    while (!(UTRSTAT0 & TXD0READY));

    /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
    UTXH0 = c;
}

void puts(char *str)
{
    int i = 0;
    while (str[i])
    {
        putc(str[i]);
        i++;
    }
}

void puthex(unsigned int val)
{
    /* 0x1234abcd */
    int i;
    int j;

    puts("0x");

    for (i = 0; i < 8; i++)
    {
        j = (val >> ((7-i)*4)) & 0xf;
        if ((j >= 0) && (j <= 9))
            putc('0' + j);
        else
            putc('A' + j - 0xa);

    }

}

View Code

 

 修改start.S

    修改board_init_f, 把relocate_code去掉

    修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面,

    在./arch/arm/cpu/u-boot.lds文件中

修改为

board/samsung/smdk2440/libsmdk2440.o

e、代码重定位

    修改board.c文件中的board_init_f函数如下

    /*
     * reserve memory for U-Boot code, data & bss
     * round down to next 4 kB limit
     */
    //addr -= gd->mon_len;
    //addr &= ~(4096 - 1);
    addr = CONFIG_SYS_TEXT_BASE;

    base_sp = addr_sp;
    //relocate_code(addr_sp, id, addr);
    return ( unsigned int )id;
    /* NOTREACHED - relocate_code() does not return */

f、支持NOR-FLASH: 在driversmtdjedec_flash.c 加上新的型号, jedec_table[] 中增加一项匹配板子上的NOR-Flash厂商ID和设备ID

图片 9图片 10

static const struct amd_flash_info jedec_table[] = {
#ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8
    {
        .mfr_id        = (u16)SST_MANUFACT,
        .dev_id        = SST39LF020,
        .name        = "SST 39LF020",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_256KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x01000,64),
        }
    },
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx8
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV040B,
        .name        = "AMD AM29LV040B",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000,8),
        }
    },
    {
        .mfr_id        = (u16)SST_MANUFACT,
        .dev_id        = SST39LF040,
        .name        = "SST 39LF040",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x01000,128),
        }
    },
    {
        .mfr_id        = (u16)STM_MANUFACT,
        .dev_id        = STM_ID_M29W040B,
        .name        = "ST Micro M29W040B",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000,8),
        }
    },
    {
        .mfr_id        = (u16)MX_MANUFACT,
        .dev_id        = MX29LV040,
        .name        = "MXIC MX29LV040",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)WINB_MANUFACT,
        .dev_id        = W39L040A,
        .name        = "WINBOND W39L040A",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)AMIC_MANUFACT,
        .dev_id        = A29L040,
        .name        = "AMIC A29L040",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)EON_MANUFACT,
        .dev_id        = EN29LV040A,
        .name        = "EON EN29LV040A",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29F400BB,
        .name        = "AMD AM29F400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 7),
        }
    },
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV400BB,
        .name        = "AMD AM29LV400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000,1),
            ERASEINFO(0x02000,2),
            ERASEINFO(0x08000,1),
            ERASEINFO(0x10000,7),
        }
    },
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV800BB,
        .name        = "AMD AM29LV800BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_1MiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 15),
        }
    },
    {
        .mfr_id        = (u16)STM_MANUFACT,
        .dev_id        = STM29F400BB,
        .name        = "ST Micro M29F400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize        = SIZE_512KiB,
        .CmdSet            = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions    = 4,
        .regions        = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 7),
        }
    },
#endif

    //JZ2440
    {
        .mfr_id        = (u16)MX_MANUFACT,  
        .dev_id        = 0x2249,
        .name        = "MXIC MX29LV160DB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_2MiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(16*1024,1),
            ERASEINFO(8*1024,2),
            ERASEINFO(32*1024,1),
            ERASEINFO(64*1024,31),
        }
    }

};

View Code

 

在上面代码中最后增加JZ2440的Nor flash

在smdk2440.h 中修改

#define CONFIG_SYS_MAX_FLASH_SECT    (128)

验证是否支持Nor flash

flinfo : 查看flash信息,RO块通过"protect off all"指令后擦写。

    测试一下norflash能否正确读写,用以下u-boot命令:

    cp.b 0 30000000 80
    cmp.b 0 30000000 80 
    发现读norflash没有问题。再用以下几条命令测试写norflash:
    mw.b 30000000 12 3
    protect off all
    erase 0 ffff
    cp.b 30000000 0 3
    md.b 0 3
    发现也是121212;因此写norflash成功,至此u-boot已经支持JZ2440开发板的norflash。

 

g、修改UBOOT支持NAND FLASH

修复了重定时留下来的BUG:SP要重新设置,在start.S文件中做如下修改

/* Set stackpointer in internal RAM to call board_init_f */

call_board_init_f:

    ldr    r0,=0x00000000
    bl    board_init_f

/* unsigned int的值存在r0,正好给board_init_r作为参数用 */
    ldr r1,_TEXT_BASE
    ldr sp,base_sp
/* 调用第二阶段的代码 */
    bl board_init_r

.globl base_sp
base_sp:
    .long 0

启动cache后就初始化nandflash

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

bl nand_init_ll

修改:include/configs/smdk2440.h: #define CONFIG_CMD_NAND,把driversmtdnands3c2410_nand.c复制为s3c2440_nand.c

修改此文件里代码如下:将以s3c2410开头函数名或变量名修改为以s3c2440开头

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    if( ctrl&NAND_CLE)
    {
        /* 发命令 */
        writeb(cmd,&nand->nfcmd);
    }
    else if( ctrl&NAND_ALE)
    {
        /* 发地址 */
        writeb(cmd,&nand->nfaddr);
    }

}

图片 11图片 12

int board_nand_init(struct nand_chip *nand)
{
    u_int32_t cfg;
    u_int8_t tacls, twrph0, twrph1;
    struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
    struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();

    debug("board_nand_init()n");

    writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);

    /* initialize hardware */
#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
    tacls  = CONFIG_S3C24XX_TACLS;
    twrph0 = CONFIG_S3C24XX_TWRPH0;
    twrph1 =  CONFIG_S3C24XX_TWRPH1;
#else
    tacls = 4;
    twrph0 = 8;
    twrph1 = 8;
#endif
#if 0
    cfg = S3C2410_NFCONF_EN;
    cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
#endif
    /* 设置时序 */
    cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);    
    writel(cfg, &nand_reg->nfconf);
    /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
    writel((1<<4)|(1<<1)|(1<<0), &nand_reg->nfcont);

    /* initialize nand_chip data structure */
    nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
    nand->IO_ADDR_W = (void *)&nand_reg->nfdata;

    nand->select_chip = s3c2440_nand_select;

    /* read_buf and write_buf are default */
    /* read_byte and write_byte are default */
#ifdef CONFIG_NAND_SPL
    nand->read_buf = nand_read_buf;
#endif

    /* hwcontrol always must be implemented */
    nand->cmd_ctrl = s3c2440_hwcontrol;

    nand->dev_ready = s3c2440_dev_ready;

#ifdef CONFIG_S3C2410_NAND_HWECC
    nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
    nand->ecc.calculate = s3c2410_nand_calculate_ecc;
    nand->ecc.correct = s3c2410_nand_correct_data;
    nand->ecc.mode = NAND_ECC_HW;
    nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
    nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
    nand->ecc.mode = NAND_ECC_SOFT;
#endif

#ifdef CONFIG_S3C2410_NAND_BBT
    nand->options = NAND_USE_FLASH_BBT;
#else
    nand->options = 0;
#endif

    debug("end of nand_initn");

    return 0;
}

View Code

 

h、支持DM9000网卡

启动uboot,打印出Net: CS8900-0,而我们的网卡是DM9000,于是在代码中搜索“Net:”,定位到common/board_r.c的initr_net函数,一路追踪eth_initialize, eth_common_init,一直到 boardsamsungsmdk2440smdk2440.c的board_eth_init函数,这里是对CS8900进行了初始化,我们要对DM9000进行初始化,通过查看drivers/net/Makefile,发现要包含dm9000x.c的文件,要定义CONFIG_DRIVER_DM9000这个宏,我们也要注释掉CONFIG_CS8900宏。同时查看dm9000x.c,里面有一个dm9000_initialize函数,于是仿照cs8900来写dm9000的初始化函数。

#ifdef CONFIG_CMD_NET
int board_eth_init(bd_t *bis)
{
    int rc = 0;
#ifdef CONFIG_CS8900
    rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef CONFIG_DRIVER_DM9000
    rc = dm9000_initialize(&bis);
#endif
    return rc;
}
#endif

配置文件smdk2440.h修改如下:

/*
 * Hardware drivers
 */

#if 0
#define CONFIG_CS8900        /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE    0x19000300
#define CONFIG_CS8900_BUS16    /* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA CONFIG_DM9000_BASE + 4

#endif

设置CONFIG_ETHADDR宏,根据自己情况配置

#define CONFIG_ETHADDR 00:0c:29:8d:73:b1

保存,编译,烧写,启动Uboot,网卡正常启动。

四、nand flash 分区

在smdk2440.h文件中,修改以下代码

#if 0
#define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE            0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00040000
#define CONFIG_ENV_SIZE 0x20000
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE

#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT        "nand0=jz2440-0" /* 哪一个设备 */

#define MTDPARTS_DEFAULT    "mtdparts=jz2440-0:256k(bootloader),"    
                        "128k(params),"        
                        "4m(kernel),"    
                        "-(rootfs)"        

至此u-boot的移植基本完成。

本文由云顶娱乐官方入口发布于云顶娱乐网址4118112,转载请注明出处:需要初始化nandflash,现在把移植过程记录下来

关键词:

  • 上一篇:没有了
  • 下一篇:没有了