6. 实现NAND flash 的读写,再次修改/include/configs/gt2440.h
这里主要是定义了两个宏和屏蔽了原来的宏,修改
/*
* High Level Configuration Options
* (easy to change)
*/
#defineCONFIG_ARM920T 1 /* This isan ARM920T Core */
//#define CONFIG_S3C2410 1 /*in a SAMSUNG S3C2410 SoC */
//#define CONFIG_SBC2410X 1 /* on a friendly-arm SBC-2410X Board */
#define CONFIG_S3C2440 1 /* 在前面很多地方调用到CONFIG_S3C2440 ,他是在这里定义 */
#define CONFIG_GT2440 1 /* 针对一些本开发板配置的宏控制*/
......
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_PING
#define CONFIG_CMD_NAND /*这个宏和CFG_CMD_LEGACY控制调用nand_init()的地方(是在nand.c还是gt2440.c)问题*/
#define CONFIG_CMD_NET /*在board.c里得到调用,判断是否使用net*/
#define CONFIG_CMD_ENV /*环境变量相关的宏*/
#define CFG_LONGHELP
/* undef to save memory */
#define CFG_PROMPT "[GT2440]#" /*这个就 是你启动开发板后命令行显示的内容了*/
/*Monitor Command Prompt */
#define CFG_CBSIZE 256
/* Console I/O Buffer Size */
......
#define CFG_LOAD_ADDR 0x30008000 /*以后linux kernel就要放在这里执行 */
/* default load address */
......
//#define CFG_ENV_IS_IN_FLASH 1 /这里的flash应该是指nor了/
#define CFG_ENV_IS_IN_NAND 1 /*定义这个宏的目的是为了调用nand flash类型的saveenv,因为还有其它类型存储器的saveenv,在u-boot中查看saveenv的定义,有多少中定义就有多少种*/
/*在linux对nand flash分区的时候,给u-boot分配384k的空间(0~0x60000)
其中 u-boot.bin [0x0~0x40000] 占256K
而 u-boot的参数 [0x40000~0x60000] 占128k
*/
#defineCFG_ENV_OFFSET 0x40000 /*这个宏是表示环境变量在nandflash里的偏移
这里要注意,这个宏必须是nand flash block size的整数倍,例如这里我的是64*2048 = 0x20000,所以这宏必须为这个的整数倍,否则操作是会提示:N AND 256MiB 3,3V 8-bit: MTD Erase failure: -22 */
#define CFG_ENV_SIZE 0x20000 /*环境变量的长度*/
/*注意:网上很多地方都有关于CONFIG_CMD_NAND 、CFG_NAND_LEGACY、drivers/mtd/nand/nand.c中的nand_init()函数以及board/gt2440/GT2440.c中的nand_init()函数这四个东西的关系,他们就是一些宏,在不同的文件中有宏关系,从而实现调用不同的nand_init(),有兴趣可以跟踪一下,附录有他们调用的关系,这里笔者定义了CFG_NAND_LEGACY和CONFIG_CMD_NAND,所以调用的是gt2440.c的nand_init()函数,现在有没有?当然没有,要自己写,下一步骤就是修改这个*/
/*----------------------------------------------------------------------
* NAND flash settings
*/
#if defined (CONFIG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000 /*这个宏在drivers/mtd/nand/nand.c中被调用,它是NAND控制寄存器的基地址*/
/* NandFlash控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
#define LARGE_NAND_FLASH 1 //原因是笔者这使用的是大容量nand为2K每页
#ifndef LARGE_NAND_FLASH
/* 支持的最大Nand Flash数据 */
#define SECTORSIZE 512
/* 1页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK (SECTORSIZE-1) /*本flash一个block的大小-1*/
/* 页掩码 */
#defineADDR_COLUMN 1 /*意思是你所用的nandflash的Column地址占多少个字节*/
/* 一个字节的Column地址 */
#define ADDR_PAGE 3 /*意思是你所用的nandflash的(row)page地址占多少个字节*/
/* 3字节的页块地址!!!!!*/
#define ADDR_COLUMN_PAGE 4 /*意思是你所用的nandflash的column地址+page地址共占多少个字节*/
/* 总共4字节的页块地址!!!!! */
#else
/* 支持的最大Nand Flash数据 */
#defineSECTORSIZE 2048
/* 1页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK (SECTORSIZE-1) /*本flash一个block的大小-1*/
/* 页掩码 */
#define ADDR_COLUMN 2
/* 一个字节的Column地址 */
#define ADDR_PAGE 3
#define ADDR_COLUMN_PAGE 5
#endif
#defineNAND_ChipID_UNKNOWN 0x00
/* 未知芯片的ID号 */
#define NAND_MAX_FLOORS 1 /*怎样算一floor*/
#define NAND_MAX_CHIPS 1
/* Nand Flash命令层底层接口函数 */
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCONT(*(volatile unsigned int *)0x4e000004)
#define rNFCMD(*(volatile unsigned char *)0x4e000008)
#define rNFADDR (*(volatile unsigned char *)0x4e00000c)
#define rNFDATA (*(volatile unsigned char *)0x4e000010)
#define rNFSTAT (*(volatile unsigned int *)0x4e000020)
#define rNFECC (*(volatile unsigned int *)0x4e00002c)
/*下面部分内容是修改的*/
/* Nand Flash命令层底层接口函数 ,函数哪里来?自己定义呗?所以下一步骤还要写这些函数*/
/*
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()
*/ /*由于我们这次的移植是使用cpu/arm920t/s3c24x0/nand.c,这文件里也有定义需要的函数,不过是以NFADDR这种格式出现的,不过宏没多大关系,这样移植性也好点*/
#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}
#define WRITE_NAND(d, adr) {rNFDATA = d;}
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
# if defined(CONFIG_S3C2440)
#define NAND_DISABLE_CE(nand) {rNFCONT |= (1<<1);}
#define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);}
#endif
# if defined(CONFIG_S3C2410)
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
#endif
/* 允许Nand Flash写校验打开下面宏定义*/
#defineCONFIG_MTD_NAND_VERIFY_WRITE 1
......
#endif /* __CONFIG_H */
7. 修改cpu/arm920t/s3c24x0/Nand.c
#define NF_BASE 0x4e000000
#ifdefined(CONFIG_S3C2410)
#defineNFCONF __REGi(NF_BASE + 0x0)
#defineNFCMD __REGb(NF_BASE + 0x4)
#defineNFADDR __REGb(NF_BASE + 0x8)
#defineNFDATA __REGb(NF_BASE + 0xc)
#defineNFSTAT __REGb(NF_BASE + 0x10)
#defineNFECC0 __REGb(NF_BASE + 0x14)
#defineNFECC1 __REGb(NF_BASE + 0x15)
#defineNFECC2 __REGb(NF_BASE + 0x16)
#define S3C2410_NFCONF_EN (1<<15)
#defineS3C2410_NFCONF_512BYTE (1<<14)
#defineS3C2410_NFCONF_4STEP (1<<13)
#defineS3C2410_NFCONF_INITECC (1<<12)
#defineS3C2410_NFCONF_nFCE (1<<11)
#defineS3C2410_NFCONF_TACLS(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#defineS3C2410_NFCONF_TWRPH1(x) ((x)<<0)
#elifdefined(CONFIG_S3C2440)
#defineNFCONF __REGi(NF_BASE + 0x0)
#defineNFCONT __REGi(NF_BASE + 0x4)
#defineNFCMD __REGb(NF_BASE + 0x8)
#defineNFADDR __REGb(NF_BASE + 0xc)
#defineNFDATA __REGb(NF_BASE + 0x10)
#defineNFMECCD0 __REGi(NF_BASE + 0x14)
#defineNFMECCD1 __REGi(NF_BASE + 0x18)
#defineNFSECCD __REGi(NF_BASE + 0x1C)
#defineNFSTAT __REGb(NF_BASE + 0x20)
#defineNFSTAT0 __REGi(NF_BASE + 0x24)
#define NFSTAT1 __REGi(NF_BASE + 0x28)
#defineNFMECC0 __REGi(NF_BASE + 0x2C)
#defineNFMECC1 __REGi(NF_BASE + 0x30)
#defineNFSECC __REGi(NF_BASE + 0x34)
#defineNFSBLK __REGi(NF_BASE + 0x38)
#defineNFEBLK __REGi(NF_BASE + 0x3c)
#defineS3C2440_NFCONT_nCE (1<<1)
#defineS3C2440_ADDR_NALE 0x0c
#defineS3C2440_ADDR_NCLE 0x08
#endif
static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd)
{
struct nand_chip *chip =mtd->priv;
DEBUGN("hwcontrol():0x%02x: ", cmd);
#if defined(CONFIG_S3C2410)
switch (cmd) {
case NAND_CTL_SETNCE:
NFCONF &=~S3C2410_NFCONF_nFCE;
DEBUGN("NFCONF=0x%08x\n", NFCONF);
break;
case NAND_CTL_CLRNCE:
NFCONF |= S3C2410_NFCONF_nFCE;
DEBUGN("NFCONF=0x%08x\n", NFCONF);
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = NF_BASE +0x8;
DEBUGN("SETALE\n");
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = NF_BASE +0x4;
DEBUGN("SETCLE\n");
break;
default:
chip->IO_ADDR_W = NF_BASE +0xc;
break;
}
#elif defined(CONFIG_S3C2440)
switch (cmd) {
case NAND_CTL_SETNCE:
NFCONF &=~S3C2440_NFCONT_nCE;
DEBUGN("NFCONF=0x%08x\n", NFCONF);
break;
case NAND_CTL_CLRNCE:
NFCONF |= S3C2440_NFCONT_nCE;
DEBUGN("NFCONF=0x%08x\n", NFCONF);
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = NF_BASE +S3C2440_ADDR_NALE;
DEBUGN("SETALE\n");
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = NF_BASE +S3C2440_ADDR_NCLE;
DEBUGN("SETCLE\n");
break;
default:
chip->IO_ADDR_W = NF_BASE +0x10; //注意是0x10
break;
}
#endif
return;
}
intboard_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
S3C24X0_CLOCK_POWER * const clk_power =S3C24X0_GetBase_CLOCK_POWER();
DEBUGN("board_nand_init()\n");
clk_power->CLKCON |= (1 << 4);
#if defined(CONFIG_S3C2410)
/* initialize hardware */
twrph0 = 3; twrph1 = 0; tacls = 0;
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls- 1);
cfg |=S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |=S3C2410_NFCONF_TWRPH1(twrph1 - 1);
NFCONF = cfg;
/* initialize nand_chip datastructure */
nand->IO_ADDR_R = nand->IO_ADDR_W= 0x4e00000c;
/* read_buf and write_buf aredefault */
/* read_byte and write_byte aredefault */
/* hwcontrol always must beimplemented */
nand->hwcontrol =s3c2410_hwcontrol;
nand->dev_ready =s3c2410_dev_ready;
#ifdef CONFIG_S3C2410_NAND_HWECC
nand->enable_hwecc =s3c2410_nand_enable_hwecc;
nand->calculate_ecc =s3c2410_nand_calculate_ecc;
nand->correct_data =s3c2410_nand_correct_data;
nand->eccmode =NAND_ECC_HW3_512;
#else
nand->eccmode = NAND_ECC_SOFT;
//nand->eccmode = NAND_ECC_NONE; /*这个ECC先去掉,否则你使用nand write命令和nand read会boot 不起内核*/
#endif
#ifdef CONFIG_S3C2410_NAND_BBT
nand->options =NAND_USE_FLASH_BBT;
#else
nand->options = 0;
#endif
#elif defined(CONFIG_S3C2440)
twrph0 = 6; twrph1 = 2; tacls =0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
cfg =(1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
/* initialize nand_chip data structure */
nand->IO_ADDR_R =nand->IO_ADDR_W = (void *)0x4e000010;
/* read_buf and write_buf aredefault */
/* read_byte and write_byte aredefault */
/* hwcontrol always must beimplemented */
nand->hwcontrol =s3c2410_hwcontrol;
nand->dev_ready =s3c2410_dev_ready;
#ifdef CONFIG_S3C2440_NAND_HWECC
nand->enable_hwecc =s3c2410_nand_enable_hwecc;
nand->calculate_ecc = s3c2410_nand_calculate_ecc;
nand->correct_data =s3c2410_nand_correct_data;
nand->eccmode =NAND_ECC_HW3_512;
#else
nand->eccmode = NAND_ECC_SOFT;
//nand->eccmode = NAND_ECC_NONE; /*这个ECC先去掉,否则你使用nand write命令和nand read会boot 不起内核*/
#endif
#ifdef CONFIG_S3C2440_NAND_BBT
nand->options =NAND_USE_FLASH_BBT;
#else
nand->options = 0;
#endif
#endif
DEBUGN("end of nand_init\n");
return 0;
}
#else
error "U-Boot legacy NAND support notavailable for S3C2410"
#endif
#endif
/*到这里,编译是不能通过的,原因上一节中CONFIG_S3C2410这个宏定义被注释掉,下面要用CONFIG_S3C2440这个宏打开CONFIG_S3C2410所打开的内容*/
8. 在s3c2440与s3c2410能够的文件中添加“CONFIG_S3C2440”,使得原来s3c2410的代码可以编译进来
(1)/include/common.h文件的第492行:/*一些公用的常用函数,例如get_fclk()*/
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ||defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)
(2)/include/s3c24x0.h:文件的第85、95、99、110、148、404行:/*一些关于S3C2440寄存器的结构体*/
#if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
(3)/cpu/arm920t/s3c24x0/interrupts.c文件的第33行:/*主要把一些头文件包含进去*/
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_TRAB) ||defined (CONFIG_S3C2440)
第38行:
#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
(4)/cpu/arm920t/s3c24x0/serial.c文件的第22行:/*主要把一些头文件包含进去*/
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined(CONFIG_S3C2440)
第26行:
#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
(5)/cpu/arm920t/s3c24x0/speed.c文件的第33行:
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_TRAB) || defined (CONFIG_S3C2440)
第37行:
#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
顺便修改源代码,以匹配s3c2440:
static ulong get_PLLCLK(int pllreg)
{
......
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
/*这两个PLL的算法参见S3C2440datasheet的254页*/
#if defined(CONFIG_S3C2440)
if (pllreg == MPLL)
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /*CONFIG_SYS_CLK_FREQ 在qljt2440.h中定义*/
else if (pllreg == UPLL)
#endif
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
}
......
/* return FCLK frequency */
ulong get_FCLK(void)
{
return(get_PLLCLK(MPLL));
}
/* return HCLK frequency */
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power =S3C24X0_GetBase_CLOCK_POWER();
/*看看s3c2410与s3c2440的datasheet就知道s3c2440的HCLK可选择的值多很*/
if (clk_power->CLKDIVN & 0x6)
{
if ((clk_power->CLKDIVN &0x6)==2) return(get_FCLK()/2);
if ((clk_power->CLKDIVN &0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 :get_FCLK()/3); /*注意这里的CAMDIVN还没有被定义,在/include/s3c24x0.h中定义 所以下一个大步骤就去定义*/
if ((clk_power->CLKDIVN &0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 :get_FCLK()/4);
return(get_FCLK());
}
else {
return(get_FCLK());
}
// return((clk_power->CLKDIVN & 0x2) ?get_FCLK()/2 : get_FCLK());
}
......
(6)/cpu/arm920t/s3c24x0/usb_ohci.c文件的第45行:
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
(7)drivers/rtc/s3c24x0_rtc.c文件的第35行:
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
(8)在文件中添加“defined(CONFIG_GT2440)”,使得原来SBC2410X开发板的代码可以编译进来,
/cpu/arm920t/s3c24x0/interrupts.c文件的第181行:
#elif defined(CONFIG_SBC2410X) || \
defined(CONFIG_SMDK2410) || \
defined(CONFIG_VCMA9) || defined(CONFIG_GT2440)
tbclk = CFG_HZ; /*对于CFG_HZ 的值,结合uboot的说明和s3c2440datasheet就比较容易理解*/
#else
(9)/cpu/arm920t/s3c24x0/usb.c文件的第31行:
#elif defined(CONFIG_S3C2410) ||defined (CONFIG_S3C2440)
(10)/cpu/arm920t/s3c24x0/i2c.c文件的第35行:
#elif defined(CONFIG_S3C2410) ||defined(CONFIG_S3C2440)
第66、85、142、150、174行:
将“#ifdef CONFIG_S3C2410”改为
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
(11)drivers/usb/usb_ohci.c文件的第68行附近:
#if defined(CONFIG_ARM920T) || \
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410)|| \
defined(CONFIG_S3C2440)|| \
defined(CONFIG_440EP)|| \
defined(CONFIG_PCI_OHCI) || \
defined(CONFIG_MPC5200)
9. 在/include/s3c24x0.h中加入2440 的NAND FLASH 寄存器定义和CAMDIVN定义:
typedefstruct {
S3C24X0_REG32 LOCKTIME;
S3C24X0_REG32 MPLLCON;
S3C24X0_REG32 UPLLCON;
S3C24X0_REG32 CLKCON;
S3C24X0_REG32 CLKSLOW;
S3C24X0_REG32 CLKDIVN;
S3C24X0_REG32 CAMDIVN;
}S3C24X0_CLOCK_POWER;
......
#ifdefined(CONFIG_S3C2410) //2410 的NAND FLASH 寄存器
typedefstruct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFECC;
}S3C2410_NAND;
#endif
#if defined(CONFIG_S3C2440)
typedef struct{
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFECC;
} S3C2410_NAND;
#endif
10. 修改/lib_arm中的board.c。
#include<common.h>
#include <command.h>
#include <malloc.h>
#include <devices.h>
#include <version.h>
#include <net.h>
#include <s3c2410.h>
/*===========================================================
到这里,应该是可以编译通过的,否则就是编辑的时候出现了错误
===========================================================*/