K9F1G08R0A举例说明:1056Mbits,128M×8bits
通过命令来控制8个I/O来进行地址和数据的传送,X,Y列的读取
关于一个基础:http://baike.baidu.com/view/64506.html看看(1GB ,1个区块是128kbytes,1024个区块,每个区块有64页,每一页有2K的空间还有64byte的空闲区)
概况
进来,因为NOR Flash的成本太高(NOR Flash 可以直接跑程序),而使用SDRAM以及NAND Flash成本更经济,因此很多用户都是先将代码放在NAND Flash中,然后放到SDRAM中跑。
S3C2440的boot code能够在外部的nand flash内存中执行。为了支持nand flash 的boot 引导,S3C2440有一个内部的SDRAM缓存称为“Steppingstone”,当booting的时候,Nand Flash的首4kbyte会被导入到Steppingstone并且开始执行。(****这个stepstone 可以这么理解,因为nand flash不能直接运行,因此只能自动的先拷贝代码到RAM里面,然后再执行,这个bootload 就是这样,映射为GCS0地址,运行起来后就可以跑到RAM里面了)
一般来说 ,这个bootcode将会拷贝Nand Flash内容到SDRAM中,使用硬件的ECC校验和,Nand FLash数据是否合法可以得到验证。一旦完成了拷贝,那么主程序就能够在SDRAM中执行程序了。(这里可以查看Start.S中的relocate重 入部分代码,首先比较指令地址,是在flash=0x00000000,还是sdram=TXET_BASE ,然后拷贝,重定位,开始从SDRAM开始执行,看不懂没关系-----如果可以在网上查找Start.S的注释,有关这部分的内容非常多,多多学习 ing)
特征
1)auto boot: boot code 在reset后会传到SteppingStone中,传完后,就开始执行(**因为nand flash是不能够直接开始执行的,一定要转到RAM执行*)。
2)Nand Flash 内存I/F: 支持 256 words, 512 bytes,1 K Words and 2Kbyte Page.
3)软件模式: 用户可以直接进入Nand Flash, 读、擦写、编程等等
4)接口:8/16bit的内存接口总线;
5)SFR I/F :支持小端模式,byte/half word /word 数据以及ECC数据寄存器,特征寄存器和其他寄存器是word位读取
6)SetppingStone I/F:支持小端大端模式,字节、半子节、字。
7)SetppingStone 4-KB内部的SDRAM缓冲能够做其他用
在reset期间,S3C2440 Nand Flash控制器通过和nand flash相连的管脚pin的状态获得信息(NCON,GPG13,GPG14,GPG15).启动电源或者系统复位后,NAND Flash控制器 会自动的下载4Kboot loader代码,下载了的boot loader 代码之后就在setppingstone 开始执行了。
接口信号:nFCE,CLE ,ALE,nFRE,nFWE,FRnB, IO0-IO15
见图6--1,6--2
还有2440的几个脚位的配置:正常情况下,这几个脚一定要设置为输入,INPUT状态,见page 188表
PIN CONFIGURATION
O M[1:0] = 00: Enable NAND flash memory boot
NCON : NAND flash memory selection(Normal / Advance)
0: Normal NAND flash(256Words/512Bytes page size, 3/4 address cycle)
1: Advance NAND flash(1KWords/2KBytes page size, 4/5 address cycle)
NCON:输入,NAND Flash内存地址步长选择,0:表示3步长地址,1:表示4步长地址(NAND flash中地址要通过d[7:0]送多次,每送一次就为一步长)
GPG13 : NAND flash memory page capacitance selection
0: Page=256Words(NCON = 0) or Page=1KWords(NCON = 1)
1: Page=512Bytes(NCON = 0) or Page=2KBytes(NCON = 1)
GPG14: NAND flash memory address cycle selection
0: 3 address cycle(NCON = 0) or 4 address cycle(NCON = 1)
1: 4 address cycle(NCON = 0) or 5 address cycle(NCON = 1)
GPG15 : NAND flash memory bus width selection
0: 8-bit bus width
1: 16-bit bus width
SDRAM连接比较简单,只需将nGCS6或nGCS7接到/CS即可,SDRAM控制器其余引脚芯片内部已经接好了,不需操作。NANDFLASH接法稍微复杂点,要接7个引脚:
××××××××××××××××××以下是我挑选的一些最精简程序做了一些简单的注释××××××××××××××××××××
void NF_Init(void)
{
// NFCONF是Flash最小时序组合,以及NCON0,GPG13,14,15等几个脚位的状态读取
NFCONF |= 0xFFF0; /* Max TACLS, TWRPH0, TWRPH1 :将这几个设置为最大,那么当然肯定符合大多数flash的最小时序,但是读取的速度就变慢了,看三星的datasheet就知道了,地址等需要分开几个 周期来进行,而这几个参数就密切相关了 */
NFCONT |= (1 << 0) ; /* Activate NAND Controller 使能Nand Flash控制器*/
}
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW); //CE信号为从高跳变到低,那么选中该Flash芯片。NFCONT[0]
NF_ClearRB(); //Ready or busy 的清除,见page 203
NF_Cmd(0xff); //查看你所使用的Flash,这个是nand flash的复位指令
for(i=0;i<10;i++); //复位过后每个芯片都需要等待一恢复时间,这个极其重要,关系到系统的稳定性问题
NF_WaitRB();//查看是否busy状态,若busy则waiting until not busy
NF_SetCE(NFCE_HIGH);//不选
}
ulong flash_init(void); //U-boot的函数 包含在board/smdk2440/flash.c
//*-----------------------------------------------------------------------
*/
/**1GB=128M*8bits=128Mbytes=**/
ulong flash_init(void)
{
int i, j;
ulong size = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) /**查看三星手册说明bank0~bank5 ...**/
{
ulong flashbase = 0;
flash_info[i].flash_id = /**器件产商等的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);
#else
#error "Unknown flash configured"
#endif
flash_info[i].size = FLASH_BANK_SIZE; //#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
flash_info[i].sector_count = CFG_MAX_FLASH_SECT; //19
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); /**做保护,将.protect保存在xs**/
if (i == 0)
flashbase = PHYS_FLASH_1; //Flash bank #1 0xbec00000
else
panic("configured too many flash banks!/n"); /***仅需要定义一个bank地址的flash,128M*/
for (j = 0; j < flash_info[i].sector_count; j++) /*定义了每个区的大小*/
{
if (j <= 3)
{
/* 1st one is 16 KB */
if (j == 0)
{
flash_info[i].start[j] = flashbase + 0;
}
/* 2nd and 3rd are both 8 KB */
if ((j == 1) || (j == 2))
{
flash_info[i].start[j] = flashbase + 0x4000 + (j-1)*0x2000;
}
/* 4th 32 KB */
if (j == 3)
{
flash_info[i].start[j] = flashbase + 0x8000;
}
}
else
{
flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE; /**10000=64*1024=64KB**/
}
}
size += flash_info[i].size;
/******printf("%d",size)**我这里打印输出结果为1024576=1M***/
}
/******将Flash做保护***此函数包含在/common/flash.c中****/
flash_protect(FLAG_PROTECT_SET, /**0x01---指保护开**/
CFG_FLASH_BASE, /**0x00000000**/
CFG_FLASH_BASE + monitor_flash_len - 1, /**monitor_flash_len=arm_end_data-arm_start**/
&flash_info[0]); /****/
/***Flash环境变量设置**/
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
return size;
}
/*-----------------------------------------------------------------------
* Set protection status for monitor sectors
*
* The monitor is always located in the _first_ Flash bank.
* If necessary you have to map the second bank at lower addresses.
*/
//包含在tool/updater/flash.c
//***Flash的from开始地址to结束地址,info**可以加入puts(),或者printf();函数来打印信息**/
void
flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
{
ulong b_end = info->start[0] + info->size - 1; /* bank end address */
short s_end = info->sector_count - 1; /* index of last sector =127*/
int i;
/* Do nothing if input data is bad. */
if (info->sector_count == 0 || info->size == 0 || to < from) {
return;
}
/* There is nothing to do if we have no data about the flash
* or the protect range and flash range don't overlap.
*/
if (info->flash_id == FLASH_UNKNOWN ||
to < info->start[0] || from > b_end) {
return;
}
for (i=0; i<info->sector_count; ++i) { /***定义了19个sector****/
ulong end; /* last address in current sect */
end = (i == s_end) ? b_end : info->start[i + 1] - 1;/**每个块的结束地址**/
/* Update protection if any part of the sector
* is in the specified range.
*/
//本函数没有定义CFG_FLash_protection,并且只是保护了最前面的4个sector
//
if (from <= end && to >= info->start[i]) {
if (flag & FLAG_PROTECT_CLEAR) {
#if defined(CFG_FLASH_PROTECTION)
/***进入指令式的真正的Flash保护**/
flash_real_protect(info, i, 0);
#else
info->protect[i] = 0;
#endif /* CFG_FLASH_PROTECTION */
}
else if (flag & FLAG_PROTECT_SET) {
#if defined(CFG_FLASH_PROTECTION) //包含在include/configs/?.h
flash_real_protect(info, i, 1); //包含在board/?
#else
info->protect[i] = 1;
#endif /* CFG_FLASH_PROTECTION */
通过命令来控制8个I/O来进行地址和数据的传送,X,Y列的读取
关于一个基础:http://baike.baidu.com/view/64506.html看看(1GB ,1个区块是128kbytes,1024个区块,每个区块有64页,每一页有2K的空间还有64byte的空闲区)
概况
进来,因为NOR Flash的成本太高(NOR Flash 可以直接跑程序),而使用SDRAM以及NAND Flash成本更经济,因此很多用户都是先将代码放在NAND Flash中,然后放到SDRAM中跑。
S3C2440的boot code能够在外部的nand flash内存中执行。为了支持nand flash 的boot 引导,S3C2440有一个内部的SDRAM缓存称为“Steppingstone”,当booting的时候,Nand Flash的首4kbyte会被导入到Steppingstone并且开始执行。(****这个stepstone 可以这么理解,因为nand flash不能直接运行,因此只能自动的先拷贝代码到RAM里面,然后再执行,这个bootload 就是这样,映射为GCS0地址,运行起来后就可以跑到RAM里面了)
一般来说 ,这个bootcode将会拷贝Nand Flash内容到SDRAM中,使用硬件的ECC校验和,Nand FLash数据是否合法可以得到验证。一旦完成了拷贝,那么主程序就能够在SDRAM中执行程序了。(这里可以查看Start.S中的relocate重 入部分代码,首先比较指令地址,是在flash=0x00000000,还是sdram=TXET_BASE ,然后拷贝,重定位,开始从SDRAM开始执行,看不懂没关系-----如果可以在网上查找Start.S的注释,有关这部分的内容非常多,多多学习 ing)
特征
1)auto boot: boot code 在reset后会传到SteppingStone中,传完后,就开始执行(**因为nand flash是不能够直接开始执行的,一定要转到RAM执行*)。
2)Nand Flash 内存I/F: 支持 256 words, 512 bytes,1 K Words and 2Kbyte Page.
3)软件模式: 用户可以直接进入Nand Flash, 读、擦写、编程等等
4)接口:8/16bit的内存接口总线;
5)SFR I/F :支持小端模式,byte/half word /word 数据以及ECC数据寄存器,特征寄存器和其他寄存器是word位读取
6)SetppingStone I/F:支持小端大端模式,字节、半子节、字。
7)SetppingStone 4-KB内部的SDRAM缓冲能够做其他用
在reset期间,S3C2440 Nand Flash控制器通过和nand flash相连的管脚pin的状态获得信息(NCON,GPG13,GPG14,GPG15).启动电源或者系统复位后,NAND Flash控制器 会自动的下载4Kboot loader代码,下载了的boot loader 代码之后就在setppingstone 开始执行了。
接口信号:nFCE,CLE ,ALE,nFRE,nFWE,FRnB, IO0-IO15
见图6--1,6--2
还有2440的几个脚位的配置:正常情况下,这几个脚一定要设置为输入,INPUT状态,见page 188表
PIN CONFIGURATION
O M[1:0] = 00: Enable NAND flash memory boot
NCON : NAND flash memory selection(Normal / Advance)
0: Normal NAND flash(256Words/512Bytes page size, 3/4 address cycle)
1: Advance NAND flash(1KWords/2KBytes page size, 4/5 address cycle)
NCON:输入,NAND Flash内存地址步长选择,0:表示3步长地址,1:表示4步长地址(NAND flash中地址要通过d[7:0]送多次,每送一次就为一步长)
GPG13 : NAND flash memory page capacitance selection
0: Page=256Words(NCON = 0) or Page=1KWords(NCON = 1)
1: Page=512Bytes(NCON = 0) or Page=2KBytes(NCON = 1)
GPG14: NAND flash memory address cycle selection
0: 3 address cycle(NCON = 0) or 4 address cycle(NCON = 1)
1: 4 address cycle(NCON = 0) or 5 address cycle(NCON = 1)
GPG15 : NAND flash memory bus width selection
0: 8-bit bus width
1: 16-bit bus width
SDRAM连接比较简单,只需将nGCS6或nGCS7接到/CS即可,SDRAM控制器其余引脚芯片内部已经接好了,不需操作。NANDFLASH接法稍微复杂点,要接7个引脚:
1.nFCE接到/CE
2.NCON0上拉10K(3.3V),配置为Advance
3.GPG13(PAGE)上拉10K(3.3V),配置为2K bytes
4.GPG14(ADDR)下拉4.7K ,配置为
4 address cycle
5.GPG15(WIDTH)下拉4.7K ,配置为
8-bit bus width
6.FRNB(R/B)上拉4.7k(1.8V)
7./WP上拉4.7k(1.8V)
稍微详细的看一下时序,以后用示波器查看的时候有个映象。Page 189
SOFTWARE MODE
软件编写模式过程
S3C2440A supports only software mode access. Using this mode, you can completely access the NAND flash
memory. The NAND Flash Controller supports direct access interface with the NAND flash memory.
1) Writing to the command register = the NAND Flash Memory command cycle
2) Writing to the address register = the NAND Flash Memory address cycle
3) Writing to the data register = write data to the NAND Flash Memory (write cycle)
4) Reading from the data register = read data from the NAND Flash Memory (read cycle)
5) Reading main ECC registers and Spare ECC registers = read data from the NAND Flash Memory
后面是
/********后面一部分烦请高手翻译了,特别是ECC模块这部分,晦涩啊!*********/
data register 配置
Steppingstone(4-kbyte SRAM)
ECC(错误校验码)*******
包含了4个模块 ECC部分校验码(28bit)=22 Bit Line +6bit Column
ECC模块特征
ECC编程指导
最后就是一些寄存器了
稍微详细的看一下时序,以后用示波器查看的时候有个映象。Page 189
SOFTWARE MODE
软件编写模式过程
S3C2440A supports only software mode access. Using this mode, you can completely access the NAND flash
memory. The NAND Flash Controller supports direct access interface with the NAND flash memory.
1) Writing to the command register = the NAND Flash Memory command cycle
2) Writing to the address register = the NAND Flash Memory address cycle
3) Writing to the data register = write data to the NAND Flash Memory (write cycle)
4) Reading from the data register = read data from the NAND Flash Memory (read cycle)
5) Reading main ECC registers and Spare ECC registers = read data from the NAND Flash Memory
后面是
/********后面一部分烦请高手翻译了,特别是ECC模块这部分,晦涩啊!*********/
data register 配置
Steppingstone(4-kbyte SRAM)
ECC(错误校验码)*******
包含了4个模块 ECC部分校验码(28bit)=22 Bit Line +6bit Column
ECC模块特征
ECC编程指导
××××××××××××××××××以下是我挑选的一些最精简程序做了一些简单的注释××××××××××××××××××××
void NF_Init(void)
{
// NFCONF是Flash最小时序组合,以及NCON0,GPG13,14,15等几个脚位的状态读取
NFCONF |= 0xFFF0; /* Max TACLS, TWRPH0, TWRPH1 :将这几个设置为最大,那么当然肯定符合大多数flash的最小时序,但是读取的速度就变慢了,看三星的datasheet就知道了,地址等需要分开几个 周期来进行,而这几个参数就密切相关了 */
NFCONT |= (1 << 0) ; /* Activate NAND Controller 使能Nand Flash控制器*/
}
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW); //CE信号为从高跳变到低,那么选中该Flash芯片。NFCONT[0]
NF_ClearRB(); //Ready or busy 的清除,见page 203
NF_Cmd(0xff); //查看你所使用的Flash,这个是nand flash的复位指令
for(i=0;i<10;i++); //复位过后每个芯片都需要等待一恢复时间,这个极其重要,关系到系统的稳定性问题
NF_WaitRB();//查看是否busy状态,若busy则waiting until not busy
NF_SetCE(NFCE_HIGH);//不选
}
ulong flash_init(void); //U-boot的函数 包含在board/smdk2440/flash.c
//*-----------------------------------------------------------------------
*/
/**1GB=128M*8bits=128Mbytes=**/
ulong flash_init(void)
{
int i, j;
ulong size = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) /**查看三星手册说明bank0~bank5 ...**/
{
ulong flashbase = 0;
flash_info[i].flash_id = /**器件产商等的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);
#else
#error "Unknown flash configured"
#endif
flash_info[i].size = FLASH_BANK_SIZE; //#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
flash_info[i].sector_count = CFG_MAX_FLASH_SECT; //19
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); /**做保护,将.protect保存在xs**/
if (i == 0)
flashbase = PHYS_FLASH_1; //Flash bank #1 0xbec00000
else
panic("configured too many flash banks!/n"); /***仅需要定义一个bank地址的flash,128M*/
for (j = 0; j < flash_info[i].sector_count; j++) /*定义了每个区的大小*/
{
if (j <= 3)
{
/* 1st one is 16 KB */
if (j == 0)
{
flash_info[i].start[j] = flashbase + 0;
}
/* 2nd and 3rd are both 8 KB */
if ((j == 1) || (j == 2))
{
flash_info[i].start[j] = flashbase + 0x4000 + (j-1)*0x2000;
}
/* 4th 32 KB */
if (j == 3)
{
flash_info[i].start[j] = flashbase + 0x8000;
}
}
else
{
flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE; /**10000=64*1024=64KB**/
}
}
size += flash_info[i].size;
/******printf("%d",size)**我这里打印输出结果为1024576=1M***/
}
/******将Flash做保护***此函数包含在/common/flash.c中****/
flash_protect(FLAG_PROTECT_SET, /**0x01---指保护开**/
CFG_FLASH_BASE, /**0x00000000**/
CFG_FLASH_BASE + monitor_flash_len - 1, /**monitor_flash_len=arm_end_data-arm_start**/
&flash_info[0]); /****/
/***Flash环境变量设置**/
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
return size;
}
/*-----------------------------------------------------------------------
* Set protection status for monitor sectors
*
* The monitor is always located in the _first_ Flash bank.
* If necessary you have to map the second bank at lower addresses.
*/
//包含在tool/updater/flash.c
//***Flash的from开始地址to结束地址,info**可以加入puts(),或者printf();函数来打印信息**/
void
flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
{
ulong b_end = info->start[0] + info->size - 1; /* bank end address */
short s_end = info->sector_count - 1; /* index of last sector =127*/
int i;
/* Do nothing if input data is bad. */
if (info->sector_count == 0 || info->size == 0 || to < from) {
return;
}
/* There is nothing to do if we have no data about the flash
* or the protect range and flash range don't overlap.
*/
if (info->flash_id == FLASH_UNKNOWN ||
to < info->start[0] || from > b_end) {
return;
}
for (i=0; i<info->sector_count; ++i) { /***定义了19个sector****/
ulong end; /* last address in current sect */
end = (i == s_end) ? b_end : info->start[i + 1] - 1;/**每个块的结束地址**/
/* Update protection if any part of the sector
* is in the specified range.
*/
//本函数没有定义CFG_FLash_protection,并且只是保护了最前面的4个sector
//
if (from <= end && to >= info->start[i]) {
if (flag & FLAG_PROTECT_CLEAR) {
#if defined(CFG_FLASH_PROTECTION)
/***进入指令式的真正的Flash保护**/
flash_real_protect(info, i, 0);
#else
info->protect[i] = 0;
#endif /* CFG_FLASH_PROTECTION */
}
else if (flag & FLAG_PROTECT_SET) {
#if defined(CFG_FLASH_PROTECTION) //包含在include/configs/?.h
flash_real_protect(info, i, 1); //包含在board/?
#else
info->protect[i] = 1;
#endif /* CFG_FLASH_PROTECTION */