天天看點

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移植完成。