前言:这是本人在学习u-boot期间的初级移植笔记,故功能较简陋、代码较粗略,后续会有高级篇完善。
u-boot版本:1.1.6
交叉编译器:3.4.5
开发板:友善之臂mini2440
开发板配置:SoC s3c2440 、网卡 DM9000 、 Nor Flash AM29LV160DB (2M) 、NAND FLash (256M) 、SDRAM (64M)
以源文件已存在的 smdk2410项目为基础进行移植工作
1.移植准备工作
1).下载u-boot-1.1.6源码,并解压;
2).建立u-boot的source insight工程,方便查找及分析;
3).安装arm-Linux交叉编译器,版本3.4.5;
2.修改顶层Makefile
1).打开 /Makefile ,找到smdk2410板配置选项:
- smdk2410_config: unconfig @$(MKCONFIG)$(@:_config=)armarm920tsmdk2410NULLs3c24x0
smdk2410_config:unconfig@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
各项参数意义:
arm:CPU架构
arm920t:CPU型号
smdk2410:开发板名称
NULL:开发者
s3c24x0:片上系统
类比此项添加配置选项:
- mini2440_config: unconfig @$(MKCONFIG)$(@:_config=)armarm920tmini2440NULLs3c24x0
mini2440_config:unconfig@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
3.建立主代码
1).找到 /board/smdk2410 目录,将此目录复制为 /board/mini2440 ,打开mini2440目录,将smdk2410.c文件重命名为mini2440.c。打开同目录下Makefile文件,修改代码
- COBJS :=smdk2410.oflash.o
COBJS:= smdk2410.o flash.o
为
- COBJS :=mini2440.oflash.o
COBJS:= mini2440.o flash.o
2).建立开发板配置头文件。将 /include/configs/smdk2410.h 复制为 /include/configs/mini2440.h ,打开此文件,添加
- #defineCONFIG_S3C2440 1 /*inaSAMSUNGS3C2440SoC */
#defineCONFIG_S3C24401/* in a SAMSUNG S3C2440 SoC */
4.修改CPU频率设置
1).将以上步骤建立的代码编译测试:
- root@book-desktop:/home/book/Desktop/u-boot-1.1.6#makemini2440_config Configuringformini2440board...
- root@book-desktop:/home/book/Desktop/u-boot-1.1.6#make
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make mini2440_configConfiguring for mini2440 board...root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make
生成u-boot.bin 下载至开发板运行,发现并未打印出任何信息。原因是2410和2440在频率设置方面有所不同。
2). 打开 /board/mini2440/mini2440.c ,屏蔽下列代码
- #if0 #defineFCLK_SPEED1
- #ifFCLK_SPEED==0 /*Fout=203MHz,Fin=12MHzforAudio*/
- #defineM_MDIV 0xC3 #defineM_PDIV 0x4
- #defineM_SDIV 0x1 #elifFCLK_SPEED==1 /*Fout=202.8MHz*/
- #defineM_MDIV 0xA1 #defineM_PDIV 0x3
- #defineM_SDIV 0x1 #endif
- #defineUSB_CLOCK1
- #ifUSB_CLOCK==0
- #defineU_M_MDIV 0xA1 #defineU_M_PDIV 0x3
- #defineU_M_SDIV 0x1 #elifUSB_CLOCK==1
- #defineU_M_MDIV 0x48 #defineU_M_PDIV 0x3
- #defineU_M_SDIV 0x2 #endif
- #endif
#if 0#define FCLK_SPEED 1#if FCLK_SPEED==0/* Fout = 203MHz, Fin = 12MHz for Audio */#define M_MDIV0xC3#define M_PDIV0x4#define M_SDIV0x1#elif FCLK_SPEED==1/* Fout = 202.8MHz */#define M_MDIV0xA1#define M_PDIV0x3#define M_SDIV0x1#endif#define USB_CLOCK 1#if USB_CLOCK==0#define U_M_MDIV0xA1#define U_M_PDIV0x3#define U_M_SDIV0x1#elif USB_CLOCK==1#define U_M_MDIV0x48#define U_M_PDIV0x3#define U_M_SDIV0x2#endif#endif
然后修改board_init函数
- intboard_init(void) {
- S3C24X0_CLOCK_POWER*constclk_power=S3C24X0_GetBase_CLOCK_POWER(); S3C24X0_GPIO*constgpio=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" );//异步总线
- /*toreducePLLlocktime,adjusttheLOCKTIMEregister*/
- clk_power->LOCKTIME=0xFFFFFF;
- /*configureMPLL*/ clk_power->MPLLCON=((0x5c<<12)+(0x01<<4)+0x01);//400MHz
- /*somedelaybetweenMPLLandUPLL*/
- delay(4000);
- /*configureUPLL*/ clk_power->UPLLCON=((0x38<<12)+(0x02<<4)+0x02);//48MHz
- /*somedelaybetweenMPLLandUPLL*/
- delay(8000);
- /*setuptheI/Oports*/ 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;
- /*archnumberofSMDK2410-Board*/
- gd->bd->bi_arch_number=MACH_TYPE_SMDK2410;
- /*adressofbootparameters*/ gd->bd->bi_boot_params=0x30000100;
- icache_enable();
- dcache_enable();
- return0; }
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;}
3).串口初始化时需要获取系统时钟,这里修改 /cpu/arm920t/s3c24x0/speed.c ,
get_PLLCLK()中
- return((CONFIG_SYS_CLK_FREQ*m)/(p<<s));
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
改为
- return((CONFIG_SYS_CLK_FREQ*m*2)/(p<<s));
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
这是因为2410和2440主频计算公式的差异。其他修改:
- /*returnHCLKfrequency*/ ulongget_HCLK(void)
- { return(get_FCLK()/4);
- }
- /*returnPCLKfrequency*/ ulongget_PCLK(void)
- { return(get_HCLK()/2);
- }
/* return HCLK frequency */ulong get_HCLK(void){ return(get_FCLK()/4 );}/* return PCLK frequency */ulong get_PCLK(void){ return(get_HCLK()/2 );}
再次进行编译测试,出现打印信息:
- U-Boot1.1.6(Jan262017-17:10:05)
- DRAM: 64MB Flash:512kB
- ***Warning-badCRC,usingdefaultenvironment
- In: serial Out: serial
- Err: serial SMDK2410#
5.支持Nor Flash AM29lv160DB
打开 mini2440.h 头文件,发现flash配置项只有CONFIG_AMD_LV400和CONFIG_AMD_LV800,没有本型号,因为AM29lv160DB符合CFI接口标准,故使用 /drivers/cfi_flash.c 中的接口函数。进行下列修改:
1).屏蔽代码
- /*-----------------------------------------------------------------------*FLASHandenvironmentorganization
- */ #if0
- #defineCONFIG_AMD_LV400 1 /*uncommentthisifyouhaveaLV400flash*/ #defineCONFIG_AMD_LV800 1 /*uncommentthisifyouhaveaLV800flash*/
- #endif
/*----------------------------------------------------------------------- * FLASH and environment organization */#if 0#define CONFIG_AMD_LV4001/* uncomment this if you have a LV400 flash */#define CONFIG_AMD_LV8001/* uncomment this if you have a LV800 flash */#endif
增加宏定义
- #defineCFG_FLASH_CFI_DRIVER 1
修改代码
- #defineCFG_MAX_FLASH_BANKS1 /*maxnumberofmemorybanks*/ #ifdefCONFIG_AMD_LV800
- #definePHYS_FLASH_SIZE 0x00100000/*1MB*/ #defineCFG_MAX_FLASH_SECT (19) /*maxnumberofsectorsononechip*/
- #defineCFG_ENV_ADDR (CFG_FLASH_BASE+0x0F0000)/*addrofenvironment*/ #endif
- #ifdefCONFIG_AMD_LV400 #definePHYS_FLASH_SIZE 0x00080000/*512KB*/
- #defineCFG_MAX_FLASH_SECT (11) /*maxnumberofsectorsononechip*/ #defineCFG_ENV_ADDR (CFG_FLASH_BASE+0x070000)/*addrofenvironment*/
- #endif
为
- #defineCFG_MAX_FLASH_BANKS1 /*maxnumberofmemorybanks*/ #ifdefCONFIG_AMD_LV800
- #definePHYS_FLASH_SIZE 0x00100000/*1MB*/ #defineCFG_MAX_FLASH_SECT (19) /*maxnumberofsectorsononechip*/
- #defineCFG_ENV_ADDR (CFG_FLASH_BASE+0x0F0000)/*addrofenvironment*/ #elif definedCONFIG_AMD_LV400
- #definePHYS_FLASH_SIZE 0x00080000/*512KB*/ #defineCFG_MAX_FLASH_SECT (11) /*maxnumberofsectorsononechip*/
- #defineCFG_ENV_ADDR (CFG_FLASH_BASE+0x070000)/*addrofenvironment*/ #else
- #definePHYS_FLASH_SIZE 0x00200000/*2MB*/ #defineCFG_MAX_FLASH_SECT (99) /*maxnumberofsectorsononechip*/
- #defineCFG_ENV_ADDR (CFG_FLASH_BASE+0x1F0000)/*addrofenvironment*/ #endif
#define CFG_MAX_FLASH_BANKS1/* max number of memory banks */#ifdef CONFIG_AMD_LV800#define PHYS_FLASH_SIZE0x00100000 /* 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_SIZE0x00080000 /* 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_SIZE0x00200000 /* 2MB */#define CFG_MAX_FLASH_SECT(99)/* max number of sectors on one chip */#define CFG_ENV_ADDR(CFG_FLASH_BASE + 0x1F0000) /* addr of environment */#endif
2) 在 /board/mini2440/makefile 中COBJS:= mini2440.o flash.o去掉flash.o ,再次编译测试,出现错误:
- cfi_flash.c:411:error:`CFG_MONITOR_BASE'undeclared(firstuseinthisfunction)
在mini2440.h中加入宏定义
- #defineCFG_MONITOR_BASE 0
- #defineCFG_FLASH_CFI 1
再次编译,通过!烧写至开发板,打印出信息:
- Flash: 2MB
Flash: 2 MB
输入命令 flinfo
得到信息:
- SMDK2410#flinfo
- Bank#1:CFIconformantFLASH(16x16) Size:2MBin35Sectors Erasetimeout8192ms,writetimeout1ms,bufferwritetimeout1ms,buffersize1
- SectorStartAddresses: 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#
至此nor flash支持移植成功。
6.支持DM9000网卡
smdk2410支持cs8900网卡,本开发板使用DM9000网卡,/drivers/dm9000x.c 是对应的网卡驱动。
1) 在mini2440.h中,将以下关于cs8900的宏注释掉,并添加DM9000宏定义:
- /**Hardwaredrivers
- */ #if0
- #defineCONFIG_DRIVER_CS8900 1 /*wehaveaCS8900on-board*/ #defineCS8900_BASE 0x19000300
- #defineCS8900_BUS16 1/*theLinuxdriverdoesaccessesasshorts*/ #endif
- #defineCONFIG_DRIVER_DM9000 1编译,出现错误提示:
- dm9000x.c:374:error:`DM9000_IO'undeclared(firstuseinthisfunction)
- dm9000x.c:445:error:`DM9000_DATA'undeclared(firstuseinthisfunction) dm9000x.c:144:error:`CONFIG_DM9000_BASE'undeclared
以此继续增加宏定义:
- #defineCONFIG_DM9000_BASE 0x20000000 #defineDM9000_IO 0x20000000
- #defineDM9000_DATA (DM9000_IO+0x4) #defineCONFIG_DM9000_USE_16BIT1
查看原理图可得本开发板网卡片选线接在BANK4,故基地址为0x20000000,IO为基地址,DATA与基地址偏移0x04,此外定义16BIT表示网卡使用16BIT模式。
2) 修改默认网络参数,mini2440.h 中修改代码:
- #defineCONFIG_NETMASK 255.255.255.0 #defineCONFIG_IPADDR 192.168.31.111
- #defineCONFIG_SERVERIP 192.168.31.245
#define CONFIG_NETMASK 255.255.255.0#define CONFIG_IPADDR192.168.31.111#define CONFIG_SERVERIP192.168.31.245
还有取消屏蔽:
- #defineCONFIG_ETHADDR 08:00:3e:26:0a:5b
再次编译,通过!下载至开发板,运行测试ping和tftp命令:发现ping无效,tftp可用。原因是未添加PING命令宏定义,故在mini2440.h中添加相关宏:
- #defineCONFIG_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#ping192.168.31.245 dm9000。。。。。
- host192.168.31.245isalive
SMDK2410 # ping 192.168.31.245dm9000 。。。。。host 192.168.31.245 is alive
至此,dm9000支持移植成功。
7.支持NAND FLASH
nand的驱动代码在 /drivers/nand 目录下面,打开此目录下的nand.c文件,看到如下代码
- #include<common.h>
- #if(CONFIG_COMMANDS&CFG_CMD_NAND)&&!defined(CFG_NAND_LEGACY)
- #include<nand.h>
所以判断使用nand驱动的宏开关为CFG_CMD_NAND。
1) 在mini2440.h中的CONFIG_COMMANDS中加入宏定义CFG_CMD_NAND
- #defineCONFIG_COMMANDS\ (CONFIG_CMD_DFL |\
- CFG_CMD_CACHE |\ CFG_CMD_NAND |\
- /*CFG_CMD_EEPROM|*/\ /*CFG_CMD_I2C |*/\
然后启动编译,错误如下:
- nand.c:35:error:`CFG_MAX_NAND_DEVICE'undeclaredhere(notinafunction) nand.c:38:error:`CFG_NAND_BASE'undeclaredhere(notinafunction)
- home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412:error:`NAND_MAX_CHIPS'undeclaredhere(notinafunction)
home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)
在mini2440.h中添加以上宏定义:
- /*NANDFLASH*/ #defineCFG_MAX_NAND_DEVICE1
- #defineCFG_NAND_BASE 0x0 #defineNAND_MAX_CHIPS 1
/*NAND FLASH*/#define CFG_MAX_NAND_DEVICE1#define CFG_NAND_BASE0x0#define NAND_MAX_CHIPS1
三者分别表示:
nand设备数量;
nand基地址,无实际意义,在board_nand_init函数中会被重新指定;
每个nand设备有1个nand芯片;
再次编译,出现错误为:
- drivers/nand/libnand.a(nand.o)(.text+0x24):Infunction`nand_init': /home/book/Desktop/u-boot-1.1.6/drivers/nand/nand.c:50:undefinedreferenceto`board_nand_init'
意思是board_nand_init函数未定义。上电后nand的初始化过程为:start_armboot函数调用nand_init,nand_init函数在 /drivers/nand/nand.c中实现,nand_init函数调用同文件中nand_init_chip函数,nand_init_chip函数会首先调用board_nand_init函数来初始化nand设备。此函数是硬件相关,需要自己写。下一步实现此函数。
2) 实现board_nand_init函数。
在 /cpu/arm920t/s3c24x0/ 目录下建立文件nand_flash.c,文件内容为:
- /**Nandflashinterfaceofs3c2410/s3c2440
- */
- #include<common.h>
- #if(CONFIG_COMMANDS&CFG_CMD_NAND)&&!defined(CFG_NAND_LEGACY) #include<s3c2410.h>
- #include<nand.h>
- DECLARE_GLOBAL_DATA_PTR;
- #defineS3C2410_NFSTAT_READY (1<<0) #defineS3C2410_NFCONF_nFCE (1<<11)
- #defineS3C2440_NFSTAT_READY (1<<0)
- #defineS3C2440_NFCONT_nFCE (1<<1)
- /*selectchip,fors3c2410*/
- staticvoids3c2410_nand_select_chip(structmtd_info*mtd,intchip) {
- S3C2410_NAND*consts3c2410nand=S3C2410_GetBase_NAND();
- if(chip==-1){ s3c2410nand->NFCONF|=S3C2410_NFCONF_nFCE;
- }else{ s3c2410nand->NFCONF&=~S3C2410_NFCONF_nFCE;
- } }
- /*commandandcontrolfunctions,fors3c2410
- **Note,theseallusetglx'smethodofchangingtheIO_ADDR_Wfield
- *tomakethecodesimpler,andusethenandlayer'scodetoissuethe*commandandaddresssequencesviatheproperIOports.
- **/
- staticvoids3c2410_nand_hwcontrol(structmtd_info*mtd,intcmd) {
- S3C2410_NAND*consts3c2410nand=S3C2410_GetBase_NAND(); structnand_chip*chip=mtd->priv;
- switch(cmd){
- caseNAND_CTL_SETNCE: caseNAND_CTL_CLRNCE:
- printf("%s:calledforNCE\n",__FUNCTION__); break;
- caseNAND_CTL_SETCLE:
- chip->IO_ADDR_W=(void*)&s3c2410nand->NFCMD; break;
- caseNAND_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()
- **returns0ifthenandisbusy,1ifitisready
- */ staticints3c2410_nand_devready(structmtd_info*mtd)
- { S3C2410_NAND*consts3c2410nand=S3C2410_GetBase_NAND();
- return(s3c2410nand->NFSTAT&S3C2410_NFSTAT_READY);
- }
- /*selectchip,fors3c2440*/
- staticvoids3c2440_nand_select_chip(structmtd_info*mtd,intchip) {
- S3C2440_NAND*consts3c2440nand=S3C2440_GetBase_NAND();
- if(chip==-1){ s3c2440nand->NFCONT|=S3C2440_NFCONT_nFCE;
- }else{ s3c2440nand->NFCONT&=~S3C2440_NFCONT_nFCE;
- } }
- /*commandandcontrolfunctions*/
- staticvoids3c2440_nand_hwcontrol(structmtd_info*mtd,intcmd) {
- S3C2440_NAND*consts3c2440nand=S3C2440_GetBase_NAND(); structnand_chip*chip=mtd->priv;
- switch(cmd){
- caseNAND_CTL_SETNCE: caseNAND_CTL_CLRNCE:
- printf("%s:calledforNCE\n",__FUNCTION__); break;
- caseNAND_CTL_SETCLE:
- chip->IO_ADDR_W=(void*)&s3c2440nand->NFCMD; break;
- caseNAND_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()
- **returns0ifthenandisbusy,1ifitisready
- */ staticints3c2440_nand_devready(structmtd_info*mtd)
- { S3C2440_NAND*consts3c2440nand=S3C2440_GetBase_NAND();
- return(s3c2440nand->NFSTAT&S3C2440_NFSTAT_READY);
- }
- /**Nandflashhardwareinitialization:
- *Setthetiming,enableNANDflashcontroller*/
- staticvoids3c24x0_nand_inithw(void) {
- S3C2410_NAND*consts3c2410nand=S3C2410_GetBase_NAND(); S3C2440_NAND*consts3c2440nand=S3C2440_GetBase_NAND();
- #defineTACLS 0
- #defineTWRPH0 4 #defineTWRPH1 2
- if(0)
- { /*EnableNANDflashcontroller,InitializeECC,enablechipselect,Setflashmemorytiming*/
- s3c2410nand->NFCONF=(1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); }
- else {
- /*Setflashmemorytiming*/ s3c2440nand->NFCONF=(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
- /*InitializeECC,enablechipselect,NANDflashcontrollerenable*/ s3c2440nand->NFCONT=(1<<4)|(0<<1)|(1<<0);
- } }
- /*
- *Calledbydrivers/nand/nand.c,initializetheinterfaceofnandflash*/
- voidboard_nand_init(structnand_chip*chip) {
- S3C2410_NAND*consts3c2410nand=S3C2410_GetBase_NAND(); S3C2440_NAND*consts3c2440nand=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
/* * 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
还要在 /include/s3c24x0.h文件中增加本文件中使用到的S3C2440_NAND数据结构,在s3c2410_nand的下面,
- /*NANDFLASH(seeS3C2410manualchapter6)*/ typedefstruct{
- S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCMD;
- S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA;
- S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC;
- }/*__attribute__((__packed__))*/S3C2410_NAND;
/* NAND FLASH (see S3C2410 manual chapter 6) */typedef struct {S3C24X0_REG32NFCONF;S3C24X0_REG32NFCMD;S3C24X0_REG32NFADDR;S3C24X0_REG32NFDATA;S3C24X0_REG32NFSTAT;S3C24X0_REG32NFECC;} /*__attribute__((__packed__))*/ S3C2410_NAND;
增添2440nand的结构体:
- typedefstruct{ 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; }/*__attribute__((__packed__))*/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;} /*__attribute__((__packed__))*/ S3C2440_NAND;
然后打开同目录下的s3c2410.h,找到
- staticinlineS3C2410_NAND*constS3C2410_GetBase_NAND(void) {
- return(S3C2410_NAND*const)S3C2410_NAND_BASE; }
static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void){return (S3C2410_NAND * const)S3C2410_NAND_BASE;}
在其下面添加
- staticinlineS3C2440_NAND*constS3C2440_GetBase_NAND(void) {
- return(S3C2440_NAND*const)S3C2410_NAND_BASE; }
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void){return (S3C2440_NAND * const)S3C2410_NAND_BASE;}
最后将新建的nand_flash.c文件编入u-boot之中。打开 /cpu/arm920t/s3c24x0/Makefile ,在COBJS中增加nand_flash.o:
- COBJS =i2c.ointerrupts.oserial.ospeed.o\ usb_ohci.onand_flash.o
COBJS= i2c.o interrupts.o serial.o speed.o \ usb_ohci.o nand_flash.o
编译,通过!下载至开发板运行,控制台打印出:NAND : 256MiB,输入命令nand info,打印信息:
- NAND256MiB3.3V8-bit,sectorsize128KiB
NAND 256MiB 3.3V 8-bit, sector size 128 KiB
至此,NAND flash支持移植成功!
U-Boot源代码下载地址 http://www.xuebuyuan.com/Linux/2011-07/38897.htm
本文永久更新链接地址:http://www.xuebuyuan.com/Linux/2017-01/140034.htm
以上就上有关u-boot-1.1.6移植笔记(初级篇)的全部内容,学步园全面介绍编程技术、操作系统、数据库、web前端技术等内容。