老是受4KB的steppingstone的限制... 往后比较大一些的程序就无法继续进行实验了...
可以利用4KB的steppingstone对nand flash进行初始化, 并将代码从nand flash中读出来拷贝到sdram中。
然后跳转到sdram中执行... 由于自行对nand flash进行编程.. 所以程序的大小就不受限于4KB了...
这4KB真的很像X86里的超级块.当然肯定是磁盘里的第一个扇区了...不过X86里更逊色了...只有512个字节...
不过在X86里可以直接调用BIOS提供的中断函数.来从外设存储器读取程序代码... 而这里只能自己编写这样功能的函数了...
我的板子上的nand flash是256MB,准确的说多于这个数.. 型号为K9F2G08U0A。
结合s3c2440中的nand flash控制器的介绍以及nand flash的芯片手册. 进行对nand flash的编程。
对nand flash编程的代码如下:
nand.c
#define GPACON (*(volatile unsigned long *)0x56000000)
#define NAND_FUNCTION_PIN (0x3f << 17)
#define NFCONF (*(volatile unsigned long *)0x4e000000)
#define NFCONT (*(volatile unsigned long *)0x4e000004)
#define NFCMMD (*(volatile unsigned long *)0x4e000008)
#define NFADDR (*(volatile unsigned long *)0x4e00000c)
#define NFDATA (*(volatile unsigned char *)0x4e000010)
#define NFSTAT (*(volatile unsigned long *)0x4e000020)
#define NAND_RDY 1
#define NAND_SECTOR_SIZE 2048UL
#define NAND_SECTOR_MASK (~(NAND_SECTOR_SIZE - 1))
#define NAND_SELECT_CHIP (~(1 << 1))
#define NAND_DESELECT_CHIP (1 << 1)
#define NAND_PRE_READ_CMD 0x00
#define NAND_END_READ_CMD 0x30
#define NAND_READ_ID_CMD 0x90
#define NAND_RESET_CMD 0xff
static inline void delay (unsigned long loops)
{
__asm__ volatile ("1:\n"
"subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0" (loops));
}
static void nand_wait_complete_cmd(void)
{
while(!(NFSTAT & NAND_RDY))
delay(5);
}
static void nand_select_chip(void)
{
NFCONT &= NAND_SELECT_CHIP;
delay(20);
}
static void nand_deselect_chip(void)
{
NFCONT |= NAND_DESELECT_CHIP;
delay(20);
}
static void nand_write_cmd(int cmd)
{
NFCMMD = cmd;
}
static void nand_reset(void)
{
nand_select_chip();
nand_write_cmd(NAND_RESET_CMD);
nand_wait_complete_cmd();
nand_deselect_chip();
}
static void nand_write_addr(unsigned long addr)
{
NFADDR = (addr & 0xff);
delay(10);
NFADDR = (addr >> 8) & 0x07;
delay(10);
NFADDR = (addr >> 11) & 0xff;
delay(10);
NFADDR = (addr >> 19) & 0xff;
delay(10);
NFADDR = (addr >> 27) & 0x01;
delay(10);
}
static unsigned char nand_read_data(void)
{
volatile unsigned char data = NFDATA;
return data;
}
static unsigned char nand_readID(void)
{
unsigned char id, dummy;
nand_select_chip();
nand_write_cmd(NAND_READ_ID_CMD);
NFADDR = 0x00;
unsigned long *b = (unsigned long *)0x31000000 ;
dummy = nand_read_data();
*b++ = dummy;
id = nand_read_data();
*b++ = id;
dummy = nand_read_data();
*b++ = dummy;
dummy = nand_read_data();
*b++ = dummy;
dummy = nand_read_data();
*b++ = dummy;
nand_deselect_chip();
return id;
}
void nand_init(void)
{
/* set the gpio function pin, nand flash controler needs them */
GPACON = (GPACON & ~NAND_FUNCTION_PIN) | NAND_FUNCTION_PIN;
NFCONF = 0x1310; /* TACLS = 1, TWRPH0 = 3, WRRPH1 = 1 */
NFCONT = 73; /* initECC, disable nand select, enable nand controler */
nand_reset();
}
void nand_read(unsigned char *buf, unsigned long start_addr, unsigned long length)
{
int i, j;
if(!buf || (start_addr & ~NAND_SECTOR_MASK))
return;
nand_select_chip();
for(i = start_addr; i < (start_addr + length);) {
nand_write_cmd(NAND_PRE_READ_CMD);
nand_write_addr(i);
nand_write_cmd(NAND_END_READ_CMD);
nand_wait_complete_cmd();
for(j = 0; j < NAND_SECTOR_SIZE; j++, i++)
*buf++ = nand_read_data();
}
nand_deselect_chip();
}
在start.s中增加对nand flash的初始化,调用nand_init, 然后调用nand_read将目标实验代码从nand flash中读出来.拷贝到目标地址中.即sdram. 然后跳转到sdram中继续执行即可.