1.完善saveenv功能(ENV保存于NAND Flash)
在执行saveenv命令时,出现“MTD Erase failure: -22”的问题
原因是erase是nand的整个block,而设置的CONFIG_ENV_SIZE小于block。于是设置:
#define CONFIG_ENV_OFFSET 0x0080000
#define CONFIG_ENV_SIZE 0x80000
该问题解决了,但启动后一直出现“bad CRC,using default environment”
通过查找发现,uboot没有找到复制到CONFIG_NAND_ENV_DST处的环境变量。
我的uboot image放在NAND的第一个BLOCK(512K),而ENV放在第二块BLOCK。
系统启动第一阶段时env_init会查找指到CONFIG_NAND_ENV_DST处的环境变量,如果没有找到则gd->env_valid=0
系统启动第二阶段的env_relocat根据gd->env_valid=0而env_set_defaut("!bad CRC");
再来看nand启动的nand_boot函数,该函数里面只有
nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE,CONFIG_SYS_UBOOT_SIZE, CONFIG_SYS_NAND_PAGE_SIZE);
进一步发现nand_boot启动过程只复制了第一个block到内存(uboot image),所以还需要 把第二个block也复制到内存CONFIG_NAND_ENV_DST处。
修改nand_boot.c中几个函数,内容如下:
#include <common.h>
#include <nand.h>
#include <asm/io.h>
#include <asm/arch/s3c6410.h>
#define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
#define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
static void nandll_read_page (uchar *buf, ulong addr, uint nand_page_size)
{
int i;
/*
int page_size = 512;
if (large_block==1)
page_size = 2048;
if (large_block==2)
page_size = 4096;
if(large_block==3)
page_size = 8192;
*/
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READ0;
/* Write Address */
NFADDR_REG = 0;
if (nand_page_size>=2048)
NFADDR_REG = 0;
NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;
if (nand_page_size>=2048)
NFCMD_REG = NAND_CMD_READSTART;
NF_TRANSRnB();
/* for compatibility(2460). u32 cannot be used. by scsuh */
for(i=0; i < nand_page_size; i++) {
*buf++ = NFDATA8_REG;
}
NAND_DISABLE_CE();
//return 0;
}
/*
* Read data from NAND.
*/
static void nandll_read_blocks (ulong dst_addr, ulong offs,ulong read_size, uint nand_page_size)
{
unsigned char *buf = (unsigned char *)dst_addr;
unsigned i;
unsigned page_shift = 9;
unsigned int block, lastblock;
unsigned int page;
if(nand_page_size == 4096)
{
page_shift = 12;//4k page
block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
lastblock = (offs + read_size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
if(block==0)//we always use first block for uboot image
{
/* Read step 1 */
for (i = 2; i < 4; i++, buf+=(1<<(page_shift-1)))
nandll_read_page(buf, i, nand_page_size);
/* Read step 2 */
for (i = 4; i < (read_size>>page_shift); i++, buf+=(1<<page_shift))
nandll_read_page(buf, i, nand_page_size);
}
else
{
while (block <= lastblock)
{
while (page < CONFIG_SYS_NAND_PAGE_COUNT)
{
i=page+block*CONFIG_SYS_NAND_PAGE_COUNT;
nandll_read_page(buf, i, nand_page_size);
buf += CONFIG_SYS_NAND_PAGE_SIZE;
page++;
}
page=0;
block++;
}
}
}
else if(nand_page_size == 8192) //K9GAG08U0E
{
page_shift = 13;//8k page
/* Read pages */
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-2))) {
nandll_read_page(buf, i, nand_page_size);
}
/* Read pages */
for (i = 4; i < (read_size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, nand_page_size);
}
}
else //if (nand_page_size==2048)
{
page_shift = 11; //2k page
for (i = 0; i < (read_size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, nand_page_size);
}
}
//return 0;
}
void nand_boot(void)
{
int large_block = 0;
int i;
vu_char id;
__attribute__((noreturn)) void (*uboot)(void);
NAND_ENABLE_CE();
NFCMD_REG=NAND_CMD_RESET;
NF_TRANSRnB();
NFCMD_REG = NAND_CMD_READID;
NFADDR_REG = 0x00;
NF_TRANSRnB();
/* wait for a while */
for (i=0; i<200; i++);
int factory = NFDATA8_REG;
id = NFDATA8_REG;
int cellinfo=NFDATA8_REG;
int tmp= NFDATA8_REG;
//int childType=tmp & 0x03; //Page size
int childType=cellinfo; //Page size
/* read NAND Block
* 128KB ->240KB because of U-Boot size increase. by scsuh
* So, read 0x3c000 bytes not 0x20000(128KB).
*/
//led test
writel(0x0023,0x7f008824);
nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE,
CONFIG_SYS_NAND_U_BOOT_OFFS,
CONFIG_SYS_UBOOT_SIZE,
CONFIG_SYS_NAND_PAGE_SIZE);
#ifdef CONFIG_NAND_ENV_DST
//led test
writel(0x002a,0x7f008824);
nandll_read_blocks(CONFIG_NAND_ENV_DST,
CONFIG_ENV_OFFSET,
CONFIG_ENV_SIZE,
CONFIG_SYS_NAND_PAGE_SIZE);
#endif
uboot = (void *)CONFIG_SYS_PHY_UBOOT_BASE;
(*uboot)();
}
重新启动后,bad CRC的提示没有了。
#md 57e80000可以查看到环境变量都已经复制到内存,从而解决了该问题。