天天看点

u-boot-1.1.6在mini2440开发板上的移植

uboot版本:u-boot-1.1.6

交叉编译器:3.4.5

开发板:友善之臂mini2440

开发板配置:SoC s3c2440 、网卡 DM9000 、 Nor Flash AM29LV160DB (2M) 、NAND FLash (256M) 、SDRAM (64M)

1.移植准备工作

1)下载u-boot-1.1.6源码:

u-boot-1.1.6的官方下载地址为:ftp://ftp.denx.de/pub/u-boot/

我们需要下载的文件是:u-boot-1.1.6.tar.bz

2)解压u-boot-1.1.6源码到当前文件夹

解压命令是:# tar xvfj u-boot-1.1.6.tar.bz -C ./

3)进入u-boot-1.1.6目录开始移植工作

在当前目录下执行:# cd u-boot-1.1.6 回车,即可进入u-boot-1.1.6源文件目录。

4)测试源代码和编译环境

执行命令 :#make smdk2410_config后,系统显示:Configuring for smdk2410 board…。

执行命令:#make 后开始编译,编译完成,如何没有错误,则会生成u-boot.bin文件。

5)删除源文件目录里不需要的文件(此步骤可以不做),删除后文件结构更清晰

  • 删除board目录下除smdk2410文件夹外的所有文件夹

    #cd board

    #rm -fr !(smdk2410)

    #cd …

  • 删除cpu目录下除arm920t文件夹外的所有文件夹

    #cd cpu

    #rm -fr !(arm920t)

    #cd …

  • 删除include/configs/目录下除smdk2410.h外的所有文件

    #cd inclue/configs/

    #rm -fr !(smdk2410.h)

    #cd …

    #cd …

  • 删除include/目录下除asm-arm文件夹外的所有asm-xxx文件夹
  • 删除源文件根目录下除lib_arm和lib_generic文件夹外的所有lib_xxx文件夹

2.修改顶层Makefile,增加mini2440开发板配置选项

打开 源文件根目下的Makefile ,找到smdk2410板配置选项:

命令是#vim Makefile +1881

内容如下:

smdk2410_config :   unconfig 
    @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
           

各项参数意义:

arm:CPU架构

 arm920t:CPU型号

smdk2410:开发板名称

NULL:开发者

s3c24x0:片上系统
           

参照此项添加mini2440的配置选项:

mini2440_config :   unconfig 
    @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
           

3.建立mini2440开发板相关主代码

1)找到 /board/smdk2410 目录,将此目录复制为 /board/mini2440 ,打开mini2440目录,将smdk2410.c文件重命名为mini2440.c。打开同目录下Makefile文件,修改代码

COBJS   := smdk2410.o flash.o 
           

改为

COBJS   := mini2440.o flash.o 
           

2)将include/configs目录下的smdk2410.h文件复制为mini2440.h

将以上步骤建立的代码编译测试:

#make mini2440_config

Configuring for mini2440 board…

#make

将生成u-boot.bin 下载至开发板运行,发现并未打印出任何信息。原因是2410和2440在频率设置方面有所不同。

4 修改CPU频率设置

1)打开 /board/mini2440/mini2440.c ,然后修改board_init函数

int board_init (void) 
{ 
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); 
    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); 
     
    clk_power->CLKDIVN = 0x05; /* 1 : 4 : 8 */ 
     
    __asm__(    "mrc    p15,0,r1,c1,c0,0\n" 
                "orr    r1,r1,#0xc0000000\n" 
                "mcr    p15,0,r1,c1,c0,0\n" 
                :::"r1" 
                );//异步总线
     
    /* to reduce PLL lock time, adjust the LOCKTIME register */ 
    clk_power->LOCKTIME = 0xFFFFFF; 
 
    /* configure MPLL */ 
    clk_power->MPLLCON = ((0x5c << 12) + (0x01 << 4) + 0x01); //400MHz
 
    /* some delay between MPLL and UPLL */ 
    delay (4000); 
 
    /* configure UPLL */ 
    clk_power->UPLLCON = ((0x38 << 12) + (0x02 << 4) + 0x02); //48MHz
 
    /* some delay between MPLL and UPLL */ 
    delay (8000); 
 
    /* set up the I/O ports */ 
    gpio->GPACON = 0x007FFFFF; 
    gpio->GPBCON = 0x00044555; 
    gpio->GPBUP = 0x000007FF; 
    gpio->GPCCON = 0xAAAAAAAA; 
    gpio->GPCUP = 0x0000FFFF; 
    gpio->GPDCON = 0xAAAAAAAA; 
    gpio->GPDUP = 0x0000FFFF; 
    gpio->GPECON = 0xAAAAAAAA; 
    gpio->GPEUP = 0x0000FFFF; 
    gpio->GPFCON = 0x000055AA; 
    gpio->GPFUP = 0x000000FF; 
    gpio->GPGCON = 0xFF95FFBA; 
    gpio->GPGUP = 0x0000FFFF; 
    gpio->GPHCON = 0x002AFAAA; 
    gpio->GPHUP = 0x000007FF; 
 
    /* arch number of SMDK2410-Board */ 
    gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; 
 
    /* adress of boot parameters */ 
    gd->bd->bi_boot_params = 0x30000100; 
 
    icache_enable(); 
    dcache_enable(); 
 
    return 0; 
} 
           

2)串口初始化时需要获取系统时钟,这里修改 /cpu/arm920t/s3c24x0/speed.c ,

get_PLLCLK()中

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

改为

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

这是因为2410和2440主频计算公式的差异。

其他修改:

/* return HCLK frequency */ 
ulong get_HCLK(void) 
{ 
    return(get_FCLK()/4 ); 
} 
 
/* return PCLK frequency */ 
ulong get_PCLK(void) 
{ 
    return(get_HCLK()/2 ); 
} 
           

再次进行编译测试,烧录测试,出现打印信息:

U-Boot 1.1.6 (Feb 2 2019 - 15:45:14)

DRAM: 64 MB

Flash: 512 kB

*** Warning - bad CRC, using default environment

In: serial

Out: serial

Err: serial

SMDK2410 #

5 移植Nor Flash AM29lv160DB驱动(有两种移植方法,移植只需选择一种即可)

5.1 不使用CFI接口的移植方法(AM29lv160DB和AMD_ID_LV160B兼容)

5.1.1 修改Nor Flash的相关头文件

打开include/configs/mini2440.h中加入对AM29lv160DB芯片支持相关宏:

#define CONFIG_AMD_LV400        1       /* uncomment this if you have a LV400 flash */
#if 0
#define CONFIG_AMD_LV800        1       /* uncomment this if you have a LV800 flash */
#endif
           

改成:

#if 0
#define CONFIG_AMD_LV400        1       /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800        1       /* uncomment this if you have a LV800 flash */
#endif
           

增加如下宏定义:

#define CONFIG_AMD_LV160 1
#ifdef   CONFIG_AMD_LV160
#define PHYS_FLASH_SIZE 0x00200000 /* 2MB */
#define CFG_MAX_FLASH_SECT (35) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1E0000) /* addr of environment */
#endif
           

5.1.2 修改flash.c文件中对AM29lv160DB的识别代码

打开board/mini2440/flash.c文件,修改ulong flash_init (void) ,使其可以识别FLASH的ID,代码如下:

ulong flash_init (void)
{
        int i, j;
        ulong size = 0;

        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) 
       {
                ulong flashbase = 0;

                flash_info[i].flash_id =
				#if defined(CONFIG_AMD_LV400)
                        (AMD_MANUFACT & FLASH_VENDMASK) |
                        (AMD_ID_LV400B & FLASH_TYPEMASK);
				#elif defined(CONFIG_AMD_LV800)
                        (AMD_MANUFACT & FLASH_VENDMASK) |
                        (AMD_ID_LV800B & FLASH_TYPEMASK);
				#elif defined(CONFIG_AMD_LV160)
                     (AMD_MANUFACT & FLASH_VENDMASK)|
                     (AMD_ID_LV160B & FLASH_TYPEMASK);
           

该函数剩余语句不变。

修改 void flash_print_info (flash_info_t * info) 函数,以打印出芯片信息,代码修改如下:

void flash_print_info (flash_info_t * info)
 {
           int i;
           switch (info->flash_id & FLASH_VENDMASK) 
           {
           			case (AMD_MANUFACT & FLASH_VENDMASK):
                    		printf ("AMD: ");
                    		break;
              		default:
                       		printf ("Unknown Vendor ");
                      	 	break;
            }

            switch (info->flash_id & FLASH_TYPEMASK)
             {
                   case (AMD_ID_LV400B & FLASH_TYPEMASK):
                       printf ("1x Amd29LV400BB (4Mbit)\n");
                       break;
                   case (AMD_ID_LV800B & FLASH_TYPEMASK):
                       printf ("1x Amd29LV800BB (8Mbit)\n");
                       break;
                   case (AMD_ID_LV160B &FLASH_TYPEMASK):
                       printf ("1x AM29lv160DB(2Mbyte) \n");
                       break;
                   default:
                      printf ("Unknown Chip Type\n");
                       goto Done;
                       break;
            }
           

该函数其余部分不变,至此,修改完毕。

再次编译,通过!烧写至开发板,打印出信息:

U-Boot 1.1.6 (Feb 2 2019 - 17:32:32)

DRAM: 64 MB

Flash: 2 MB

*** Warning - bad CRC, using default environment

In: serial

Out: serial

Err: serial

SMDK2410 #

输入命令:flinfo ,得到如下输出

SMDK2410 # flinfo

Bank # 1: AMD: 1x AM29lv160DB(2Mbyte)

Size: 2 MB in 35 Sectors

Sector Start Addresses:

00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)

00020000 00030000 00040000 00050000 00060000

00070000 00080000 00090000 000A0000 000B0000

000C0000 000D0000 000E0000 000F0000 00100000

00110000 00120000 00130000 00140000 00150000

00160000 00170000 00180000 00190000 001A0000

001B0000 001C0000 001D0000 001E0000 (RO) 001F0000

使用命令:setenv ipaddr 192.168.x.xxx,修改默认的IP地址,使用命令saveenv保存。

断电重启后,使用:print 命令测试是否地址修改成功。

如果成功,则移植成功。

5.2 使用CFI接口的移植方法

打开 mini2440.h 头文件,发现flash配置项只有CONFIG_AMD_LV400和CONFIG_AMD_LV800,没有本型号,因为AM29lv160DB符合CFI接口标准,故使用 /drivers/cfi_flash.c 中的接口函数。进行下列修改:

5.2.1 屏蔽代码

/*----------------------------------------------------------------------- 
 * FLASH and environment organization 
 */ 
#if 0 
#define CONFIG_AMD_LV400    1   /* uncomment this if you have a LV400 flash */ 
#define CONFIG_AMD_LV800    1   /* uncomment this if you have a LV800 flash */ 
#endif
增加宏定义
#define CFG_FLASH_CFI_DRIVER    1
           

修改代码

#define CFG_MAX_FLASH_BANKS 1   /* max number of memory banks */ 
#ifdef CONFIG_AMD_LV800 
#define PHYS_FLASH_SIZE     0x00100000 /* 1MB */ 
#define CFG_MAX_FLASH_SECT  (19)    /* max number of sectors on one chip */ 
#define CFG_ENV_ADDR        (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */ 
#endif 
#ifdef CONFIG_AMD_LV400 
#define PHYS_FLASH_SIZE     0x00080000 /*512KB   */
#define CFG_MAX_FLASH_SECT  (11)    /* max number of sectors on one chip */ 
#define CFG_ENV_ADDR        (CFG_FLASH_BASE + 0x070000) /* addr of environment */ 
#endif
           

改为:

#define CFG_MAX_FLASH_BANKS 1   /* max number of memory banks */ 
#ifdef CONFIG_AMD_LV800 
#define PHYS_FLASH_SIZE     0x00100000 /* 1MB */ 
#define CFG_MAX_FLASH_SECT  (19)    /* max number of sectors on one chip */ 
#define CFG_ENV_ADDR        (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */ 
#elif   defined CONFIG_AMD_LV400 
#define PHYS_FLASH_SIZE     0x00080000 /* 512KB */ 
#define CFG_MAX_FLASH_SECT  (11)    /* max number of sectors on one chip */ 
#define CFG_ENV_ADDR        (CFG_FLASH_BASE + 0x070000) /* addr of environment */ 
#else 
#define PHYS_FLASH_SIZE     0x00200000 /* 2MB */ 
#define CFG_MAX_FLASH_SECT  (99)    /* max number of sectors on one chip  */ 
#define CFG_ENV_ADDR        (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */ 
#endif
           

5.2.2 在 /board/mini2440/makefile 中COBJS := mini2440.o flash.o去掉flash.o ,再次编译测试,出现错误:

cfi_flash.c:411: error: `CFG_MONITOR_BASE’ undeclared (first use in this function)

在mini2440.h中加入宏定义

#define CFG_MONITOR_BASE    0 
#define CFG_FLASH_CFI   1 
           

再次编译,通过!烧写至开发板,打印出信息:

Flash: 2 MB

输入命令 flinfo

得到信息:

SMDK2410 # flinfo

Bank # 1: CFI conformant FLASH (16 x 16) Size: 2 MB in 35 Sectors

Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1

Sector Start Addresses:

00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)

00020000 00030000 00040000 00050000 00060000

00070000 00080000 00090000 000A0000 000B0000

000C0000 000D0000 000E0000 000F0000 00100000

00110000 00120000 00130000 00140000 00150000

00160000 00170000 00180000 00190000 001A0000

001B0000 001C0000 001D0000 001E0000 001F0000 (RO)

SMDK2410 #

使用命令:setenv ipaddr 192.168.x.xxx,修改默认的IP地址,使用命令saveenv保存。

断电重启后,使用:print 命令测试是否地址修改成功。

如果成功,则移植成功。

至此,nor flash两种方式均移植成功。

6 支持DM9000网卡

smdk2410支持cs8900网卡,本开发板使用DM9000网卡,/drivers/dm9000x.c 是对应的网卡驱动。

1) 在mini2440.h中,将以下关于cs8900的宏注释掉,并添加DM9000宏定义:

/* 
 *Hardware drivers 
 */ 
#if 0 
#define CONFIG_DRIVER_CS8900    1  /*we have a CS8900 on-board */
#define CS8900_BASE     0x19000300 
#define CS8900_BUS16        1              /*the Linux driver does accesses as shorts */
#endif 
#define CONFIG_DRIVER_DM9000    1
           

编译,出现错误提示:

dm9000x.c:374: error: DM9000_IO’ undeclared (first use in this function)

dm9000x.c:445: error: DM9000_DATA’ undeclared (first use in this function)

dm9000x.c:144: error: CONFIG_DM9000_BASE’ undeclared

以此继续增加宏定义:

#define CONFIG_DM9000_BASE      0x20000000 
#define DM9000_IO               0x20000000 
#define DM9000_DATA             (DM9000_IO + 0x4) 
#define CONFIG_DM9000_USE_16BIT 1 
           

查看原理图可得本开发板网卡片选线接在BANK4,故基地址为0x20000000,IO为基地址,DATA与基地址偏移0x04,此外定义16BIT表示网卡使用16BIT模式。

2) 修改默认网络参数,mini2440.h 中修改代码:

#define CONFIG_NETMASK          255.255.255.0 
#define CONFIG_IPADDR             192.168.12.217  /* 设置成自己需要的IP地址*/
#define CONFIG_SERVERIP        192.168.12.216  /* 设置成自己服务器的IP地址*/
#define CONFIG_GATEWAYIP      192.168.12.254  /* 设置成自己的网关地址*/
           

还有取消屏蔽:

#define CONFIG_ETHADDR  08:00:3e:26:0a:5b 
           

再次编译,通过!下载至开发板,运行测试ping命令:发现ping无效。原因是未添加PING命令宏定义,故在mini2440.h中添加相关宏:

#define CONFIG_COMMANDS \ 
            (CONFIG_CMD_DFL  | \ 
            CFG_CMD_CACHE    | \ 
            /*CFG_CMD_NAND |*/ \ 
            /*CFG_CMD_EEPROM |*/ \ 
            /*CFG_CMD_I2C    | */ \ 
            /*CFG_CMD_USB    |*/ \ 
            CFG_CMD_REGINFO  | \ 
            CFG_CMD_DATE     | \ 
            CFG_CMD_PING     | \ 
           

再次测试,得到打印结果:

SMDK2410 # ping 192.168.12.254

dm9000 i/o: 0x20000000, id: 0x90000a46

MAC: 00:80:00:80:00:80

could not establish link

host 192.168.12.254 is alive

至此,发现虽然能够ping通,但是MAC地址不对,报could not establish link错误。

3) 修正MAC地址,因为在显示 MAC之前没有获取 envaddr这个环境变量

修改 drivers/dm9000x.c的303行

for (i = 0; i < 6; i++) 
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
           

改为:

char *tmp = getenv("ethaddr"); 
char *end; 
for (i = 0; i  < 6; i++) 
 { 
           		bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; 
 			    if(tmp) 
   					 tmp = (*end) ? end+1 : end; 
 }
           

再次测试,得到打印结果:

SMDK2410 # ping 192.168.12.254

dm9000 i/o: 0x20000000, id: 0x90000a46

MAC: 08:00:3e:26:0a:5b

could not establish link

host 192.168.12.254 is alive

至此,MAC地址已经正确显示,但是还有could not establish link错误。

4) 修复could not establish link错误,这是因为在网卡驱动中drivers/dm9000x.c,有一段程序试图连接网卡的MII接口,而实际上MII接口并未使用,所以报错,将此段程序注释掉即可。修改 drivers/dm9000x.c的327行

#if 0   
 	 i = 0; 
 	 while (!(phy_read(1) & 0x20)) 
 	 {  
 	 		/* autonegation complete b
   	       udelay(1000); 
   	        i++; 
   	       if (i == 10000) {  
     	 		printf("could not establish link\n"); 
      	 		return 0; 
    		}
	} 
	/* see what we've got */ 
	lnk = phy_read(17) >> 12; 
	printf("operating at "); 
	switch (lnk) {  
	case 1:  
  	     printf("10M half duplex "); 
         break; 
    case 2:  
         printf("10M full duplex "); 
         break; 
    case 4:  
         printf("100M half duplex "); 
         break; 
    case 8:  
         printf("100M full duplex "); 
         break; 
    default:
         printf("unknown: %d ", lnk);  
         break; 
    } 
    printf("mode\n"); 
#endif
           

再次测试,得到打印结果:

SMDK2410 # ping 192.168.12.254

dm9000 i/o: 0x20000000, id: 0x90000a46

MAC: 08:00:3e:26:0a:5b

host 192.168.12.254 is alive

至此,网卡dm9000移植成功。

7 移植NAND FLASH

1) 在mini2440开发板的头文件include/configs/mini2440.h中的增加NAND FLASH 相关的宏定义和配置选项:

增加NAND FLASH相关宏定义如下:

#define	CFG_NAND_BASE		0  //无实际意义:基地址,在board_nand_init中重新定义
#define  CFG_MAX_NAND_DEVICE  1  //“设备”的数目为1
#define	NAND_MAX_CHIPS	   1    // “设备”由1个NAND Flash “芯片”组成
           

将环境变量相关设置从NOR FLASH变更为NAND FLASH:

#define CFG_ENV_IS_IN_FLASH     1
#define CFG_ENV_SIZE            0x10000 /* Total Size of Environment Sector */
           

改成

//#define		CFG_ENV_IS_IN_FLASH		1 /* 注销掉FLASH环境变量的配置*/
#define		    CFG_ENV_IS_IN_NAND		1
#define		    CFG_ENV_OFFSET			0x40000
#define 		CFG_ENV_SIZE			0xc000
           

取消CONFIG_COMMANDS里面CFG_CMD_NAND的注释,如下所示:

#define CONFIG_COMMANDS \
                        (CONFIG_CMD_DFL  | \
                        CFG_CMD_CACHE    | \
                        CFG_CMD_NAND     | \
                        /*CFG_CMD_EEPROM |*/ \
                        /*CFG_CMD_I2C    |*/ \
                        /*CFG_CMD_USB    |*/ \
                        CFG_CMD_REGINFO  | \
                        CFG_CMD_DATE     | \
                        CFG_CMD_PING     | \
                        CFG_CMD_ELF)
           

2)在include/s3c24x0.h文件的168行,增加S3C2440_NAND的结构体定义:

typedef struct
 { 
	S3C24X0_REG32   NFCONF;
    S3C24X0_REG32   NFCONT;
    S3C24X0_REG32   NFCMD;
    S3C24X0_REG32   NFADDR;
    S3C24X0_REG32   NFDATA;
    S3C24X0_REG32   NFMECCD0;
    S3C24X0_REG32   NFMECCD1;
    S3C24X0_REG32   NFSECCD;
    S3C24X0_REG32   NFSTAT;
    S3C24X0_REG32   NFESTAT0;
    S3C24X0_REG32   NFESTAT1;
    S3C24X0_REG32   NFMECC0;
    S3C24X0_REG32   NFMECC1;
    S3C24X0_REG32   NFSECC;
    S3C24X0_REG32   NFSBLK;
    S3C24X0_REG32   NFEBLK;
} S3C2440_NAND;
           

3) 在include/s3c2410.h头文件中增加获取NAND FLASH基地址的函数:

static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void) 
{ 
  	 return (S3C2440_NAND * const)S3C2410_NAND_BASE; 
}
           

4)在cpu/arm920t/s3c24x0/目录下增加文件nand_flash.c,并修改同目录下的Makefile文件如下:

COBJS   = i2c.o interrupts.o serial.o speed.o \
          usb_ohci.o nand_flash.o
           

nand_flash.c文件内容如下:

/* 
 * Nand flash interface of s3c2410/s3c2440 
 */ 
 
#include <common.h> 
 
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) 
#include <s3c2410.h> 
#include <nand.h> 
 
DECLARE_GLOBAL_DATA_PTR; 
 
#define S3C2410_NFSTAT_READY    (1<<0) 
#define S3C2410_NFCONF_nFCE     (1<<11) 
 
#define S3C2440_NFSTAT_READY    (1<<0) 
#define S3C2440_NFCONT_nFCE     (1<<1) 
 
 
/* select chip, for s3c2410 */ 
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) 
{ 
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND(); 
 
    if (chip == -1) { 
        s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE; 
    } else { 
        s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE; 
    } 
} 
 
/* command and control functions, for s3c2410  
 * 
 * Note, these all use tglx's method of changing the IO_ADDR_W field 
 * to make the code simpler, and use the nand layer's code to issue the 
 * command and address sequences via the proper IO ports. 
 * 
*/ 
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) 
{ 
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND(); 
    struct nand_chip *chip = mtd->priv; 
 
    switch (cmd) { 
    case NAND_CTL_SETNCE: 
    case NAND_CTL_CLRNCE: 
        printf("%s: called for NCE\n", __FUNCTION__); 
        break; 
 
    case NAND_CTL_SETCLE: 
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD; 
        break; 
 
    case NAND_CTL_SETALE: 
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR; 
        break; 
 
        /* NAND_CTL_CLRCLE: */ 
        /* NAND_CTL_CLRALE: */ 
    default: 
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA; 
        break; 
    } 
} 
 
/* s3c2410_nand_devready() 
 * 
 * returns 0 if the nand is busy, 1 if it is ready 
 */ 
static int s3c2410_nand_devready(struct mtd_info *mtd) 
{ 
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND(); 
 
    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY); 
} 
 
 
/* select chip, for s3c2440 */ 
static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip) 
{ 
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); 
 
    if (chip == -1) { 
        s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE; 
    } else { 
        s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE; 
    } 
} 
 
/* command and control functions */ 
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd) 
{ 
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); 
    struct nand_chip *chip = mtd->priv; 
 
    switch (cmd) { 
    case NAND_CTL_SETNCE: 
    case NAND_CTL_CLRNCE: 
        printf("%s: called for NCE\n", __FUNCTION__); 
        break; 
 
    case NAND_CTL_SETCLE: 
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD; 
        break; 
 
    case NAND_CTL_SETALE: 
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR; 
        break; 
 
        /* NAND_CTL_CLRCLE: */ 
        /* NAND_CTL_CLRALE: */ 
    default: 
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA; 
        break; 
    } 
} 
 
/* s3c2440_nand_devready() 
 * 
 * returns 0 if the nand is busy, 1 if it is ready 
 */ 
static int s3c2440_nand_devready(struct mtd_info *mtd) 
{ 
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); 
 
    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY); 
} 
 
/* 
 * Nand flash hardware initialization: 
 * Set the timing, enable NAND flash controller 
 */ 
static void s3c24x0_nand_inithw(void) 
{ 
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND(); 
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); 
 
#define TACLS   0 
#define TWRPH0  4 
#define TWRPH1  2 
 
    if (0) 
    { 
        /* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */ 
        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); 
    } 
    else 
    { 
        /* Set flash memory timing */ 
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); 
        /* Initialize ECC, enable chip select, NAND flash controller enable */ 
        s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0); 
    } 
} 
 
/* 
 * Called by drivers/nand/nand.c, initialize the interface of nand flash 
 */ 
void board_nand_init(struct nand_chip *chip) 
{ 
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND(); 
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); 
 
    s3c24x0_nand_inithw(); 
 
    if (0) { 
        chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA; 
        chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA; 
        chip->hwcontrol    = s3c2410_nand_hwcontrol; 
        chip->dev_ready    = s3c2410_nand_devready; 
        chip->select_chip  = s3c2410_nand_select_chip; 
        chip->options      = 0; 
    } else { 
        chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA; 
        chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA; 
        chip->hwcontrol    = s3c2440_nand_hwcontrol; 
        chip->dev_ready    = s3c2440_nand_devready; 
        chip->select_chip  = s3c2440_nand_select_chip; 
        chip->options      = 0; 
    } 
 
    chip->eccmode       = NAND_ECC_SOFT; 
} 
 
#endif 
           

编译烧写开发板测试,打印信息如下:

U-Boot 1.1.6 (Feb 3 2019 - 10:07:48)

DRAM: 64 MB

Flash: 2 MB

NAND: 256 MiB

*** Warning - bad CRC or NAND, using default environment

In: serial

Out: serial

Err: serial

SMDK2410 #

输入命令:#nand info,打印信息:

Device 0: NAND 256MiB 3,3V 8-bit, sector size 128 KiB

到此,NAND FLASH移植完成。

8 引导Linux内核的相关设置

  1. 在include/configs/mini2440.h文件中增加引导所需的宏定义:
#define CONFIG_SETUP_MEMORY_TAGS        1  //新增加
#define CONFIG_CMDLINE_TAG              1  //新增加
#define CONFIG_CMDINITRD_TAG            1 //新增加
#define CONFIG_BOOTDELAY                3   
#define CONFIG_BOOTARGS    "root=/dev/nfs rw nfsroot=192.168.12.216:/home/ucnano/roof_mini2440 ip=192.168.12.217:192.168.12.216::255.255.255.0  console=ttySAC0,115200 init=/linuxrc mem=64M" 
           

2)修改include/configs/mini2440.h文件中宏定义CFG_LOAD_ADDR

#define CFG_LOAD_ADDR  0x30008000
           

9 将tool/目录下的mkimage工具拷贝到ubuntu系统usr/bin目录下面,为以后做内核镜像使用。

到此,整个u-boot-1.1.6移植完成。