⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand.c

📁 Bootload 程序
💻 C
字号:
#include "dbldr_spec.h"#include "lib.h"#include "2410addr.h"#include "nand.h"#define EnNandFlash()   (rNFCONF |= 0x8000)#define DsNandFlash()   (rNFCONF &= ~0x8000)#define InitEcc()       (rNFCONF |= 0x1000)#define NoEcc()         (rNFCONF &= ~0x1000)#define NFChipEn()      (rNFCONF &= ~0x800)#define NFChipDs()      (rNFCONF |= 0x800)#define WrNFCmd(cmd)    (rNFCMD = (cmd))#define WrNFAddr(addr)  (rNFADDR = (addr))#define WrNFDat(dat)    (rNFDATA = (dat))#define RdNFDat()       (rNFDATA)#define RdNFStat()      (rNFSTAT)#define NFIsBusy()      (!(rNFSTAT & 1))#define NFIsReady()     (rNFSTAT & 1)#define READCMD0        (0x00)#define READCMD1        (0x01)#define READCMD2        (0x50)#define ERASECMD0       (0x60)#define ERASECMD1       (0xd0)#define PROGCMD0        (0x80)#define PROGCMD1        (0x10)#define QUERYCMD        (0x70)#define RdIDCMD         (0x90)static UINT32 _nand_addr_flag;#ifdef _HFRK_LINUX_2_4_struct partition nand_part[] = {    {0x00000000, 0x00030000, "boot"},       //256K    {0x00030000, 0x001d0000, "kernel"},    {0x00200000, 0x00600000, "rootfs"},     //6M    {0x00800000, 0x00800000, "ext-fs1"},    //8M    {0x01000000, 0x01000000, "ext-fs2"},    //16M    {0x02000000, 0x02000000, "ext-fs3"},    //32M    {0,          0         , 0}};#elsestruct partition nand_part[] = {    { 0x00000000, 0x00020000, "boot" },    { 0x00020000, 0x00300000, "kernel" },     { 0x00320000, 0x00500000, "rootfs" },    { 0x00820000, 0x00100000, "etc" },    { 0x00920000, 0x00b00000, "user" },    { 0x01420000, 0x02b00000, "qt" },    { 0,          0,          NULL }};#endifINT32 nand_part_num = 0;static void   _init_nand_part_num(void);static void   _init_cfg(void);static UINT32 _read_id(void);static UINT16 _read_status(void);static UINT32 _wait_busy(void);static INT32  _check_bad_blk(UINT32 addr);static UINT32 _erase_block(UINT32 addr);static void   _mark_bad_blk(UINT32 addr);static void   _read_page(UINT32 addr, UINT8 *buf);static void   _init_nand_flash(void);static void   _write_to_nand_flash(INT32 part_num, UINT8 *buf, INT32 len);static void   _disable_nand_flash(void);static void _init_nand_part_num(void){    INT32 i;    if (!nand_part_num)    {        for (i = 0; nand_part[i].name != NULL; i++)        {            /* nothing */        }        nand_part_num = i;    }}void disp_nand_part(void){    INT32 i;    printf("no.  offset      size        name\n");    for (i = 0; nand_part[i].name != NULL; i++)    {        printf("%d    0x%08x  0x%08x  [%s]\n",            i, nand_part[i].offset, nand_part[i].size, nand_part[i].name);    }    if (!nand_part_num)    {        nand_part_num = i;    }}STATUS nand_write(INT32 part_num, INT8 *buf, INT32 size){    _init_nand_part_num();    if (part_num >= nand_part_num || part_num < 0)    {        printf("invalid partition number\n");        return ERROR;    }    if (!buf || size < 0)    {        printf("invalid parameter(s) in nand_write()\n");        return ERROR;    }    if (!size)    {        return OK;    }    _init_nand_flash();    _write_to_nand_flash(part_num, buf, size);    _disable_nand_flash();    return OK;}STATUS load_prog_from_nand(INT32 part_num, INT8 *dest){    UINT32 start_page, size;    INT8 *ram_addr;    UINT32 i;    _init_nand_part_num();    if (part_num >= nand_part_num || part_num < 0)    {        printf("invalid partition number\n");        return ERROR;    }    if (!dest)    {        printf("invalid parameter(s) in load_prog_from_nand()\n");        return ERROR;    }    _init_nand_flash();    start_page = nand_part[part_num].offset >> 9;    size       = nand_part[part_num].size;    ram_addr   = dest;    for (i = 0; size > 0; )    {        if (!(i & 0x1f))        {            if (_check_bad_blk(i + start_page))            {                printf("skipped bad block at 0x%x\n", i + start_page);                i += 32;                size -= (32 << 9);                continue;            }        }        _read_page((i + start_page), (UINT8 *)ram_addr);        i++;        size -= 512;        ram_addr += 512;    }    DsNandFlash();    return OK;}/*****************************************************************************/static void _init_cfg(void){    //enable nand flash control, initilize ecc, chip disable,    rNFCONF = (1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7);}static UINT32 _read_id(void){    UINT32 id;    NFChipEn();    WrNFCmd(RdIDCMD);    WrNFAddr(0);    while(NFIsBusy());    id  = RdNFDat() << 8;    id |= RdNFDat();    NFChipDs();    return id;}static UINT16 _read_status(void){    UINT16 stat;    NFChipEn();    WrNFCmd(QUERYCMD);    stat = RdNFDat();    NFChipDs();    return stat;}static UINT32 _wait_busy(void){    UINT8 stat;    WrNFCmd(QUERYCMD);    do    {        stat = RdNFDat();    } while(!(stat & 0x40));    WrNFCmd(READCMD0);    return stat & 1;}static INT32 _check_bad_blk(UINT32 addr){    UINT8 dat;    addr &= ~0x1f;    NFChipEn();    WrNFCmd(READCMD2);  //point to area c    WrNFAddr(5);        //mark offset 4,5,6,7    WrNFAddr(addr);    WrNFAddr(addr >> 8);    if(_nand_addr_flag)        WrNFAddr(addr >> 16);    _wait_busy();    dat = RdNFDat();    WrNFCmd(READCMD0);  //point to area a    NFChipDs();    return (dat != 0xff);}static void _mark_bad_blk(UINT32 addr){    addr &= ~0x1f;    NFChipEn();    WrNFCmd(READCMD2);  //point to area c    WrNFCmd(PROGCMD0);    WrNFAddr(4);        //mark offset 4,5,6,7    WrNFAddr(addr);    WrNFAddr(addr >> 8);    if(_nand_addr_flag)    {        WrNFAddr(addr >> 16);    }    WrNFDat(0);         //mark with 0    WrNFDat(0);    WrNFDat(0);         //mark with 0    WrNFDat(0);    WrNFCmd(PROGCMD1);    _wait_busy();       //needn't check return status    WrNFCmd(READCMD0);  //point to area a    NFChipDs();}static UINT32 _erase_block(UINT32 addr){    UINT8 stat;    addr &= ~0x1f;    NFChipEn();    WrNFCmd(ERASECMD0);    WrNFAddr(addr);    WrNFAddr(addr >> 8);    if(_nand_addr_flag)    {        WrNFAddr(addr >> 16);    }    WrNFCmd(ERASECMD1);    stat = _wait_busy();    NFChipDs();#ifdef  ER_BAD_BLK_TEST    if(!((addr + 0xe0) & 0xff))    {        stat = 1;   /* just for testing bad block */    }#endif    printf(".");    return stat;}/* addr = page address */static void _read_page(UINT32 addr, UINT8 *buf){    UINT16 i;    NFChipEn();    WrNFCmd(READCMD0);    WrNFAddr(0);    WrNFAddr(addr);    WrNFAddr(addr >> 8);    if(_nand_addr_flag)        WrNFAddr(addr >> 16);    InitEcc();    _wait_busy();    for(i = 0; i < 512; i++)    {        buf[i] = RdNFDat();    }    NFChipDs();}static UINT32 _write_page(UINT32 addr, UINT8 *buf){    UINT16 i;    UINT8 stat, tmp[3];    NFChipEn();    WrNFCmd(PROGCMD0);    WrNFAddr(0);    WrNFAddr(addr);    WrNFAddr(addr >> 8);    if(_nand_addr_flag)    {        WrNFAddr(addr >> 16);    }    InitEcc();    for(i = 0; i < 512; i++)    {        WrNFDat(buf[i]);    }    tmp[0] = rNFECC0;    tmp[1] = rNFECC1;    tmp[2] = rNFECC2;    WrNFDat(tmp[0]);    WrNFDat(tmp[1]);    WrNFDat(tmp[2]);    WrNFCmd(PROGCMD1);    stat = _wait_busy();    NFChipDs();#ifdef  WR_BAD_BLK_TEST    if((addr&0xff)==0x17)    {        stat = 1; /* just for test bad block */    }#endif    if(stat)    {        printf("write nand flash 0x%08x failed\n", addr);    }    else    {        UINT8 rd_dat[512];        _read_page(addr, rd_dat);        for(i = 0; i < 512; i++)        {            if(rd_dat[i] != buf[i])            {                printf("check data at page 0x%x, offset 0x%x failed\n", addr, i);                stat = 1;                break;            }        }    }    return stat;}/*****************************************************************************/static void _init_nand_flash(void){    UINT32 id;    _init_cfg();    id = _read_id();    printf("nand flash id = 0x%04x\n", id);    if ((0x9873 == id) || (0xec75 == id))    {        _nand_addr_flag = 0;    }    else if (0xec76 == id)    {        _nand_addr_flag = 1;    }    else    {        printf("invalid flash id\n");        DBLDR_PANIC;    }    printf("nand flash status = 0x%08x\n", _read_status());}static void _write_to_nand_flash(INT32 part_num, UINT8 *buf, INT32 len){    UINT32 start_page = nand_part[part_num].offset >> 9;    UINT32 block_cnt  = nand_part[part_num].size >> 14;    INT8 ch;    INT32 skip_blks = 0;    INT32 i;    INT8 *ram_addr;    INT32 size;    printf("are you sure to write at the start page %d, block count %d? [y/n] ",        start_page, block_cnt);    while (1)    {        ch = UART_GETCH();        if (('Y' == ch) || ('y' == ch))        {            printf("%c\n", ch); /* echo */            break;        }        else if (('N' == ch) || ('n' == ch))        {            printf("%c\n", ch); /* echo */            return;        }    }    printf("now write the nand flash page %d from ram address 0x%08x, len = %d\n",        start_page, (UINT32)buf, len);    skip_blks = 0;    ram_addr = buf;    size = len;    for (i = 0; size > 0; )    {        if (!(i & 0x1f))        {            if (_erase_block(i + start_page))            {                nand_part[part_num].size -= (32 << 9); /* one block is broken */                                                       /* partition available size - 1 block size */                if (len > nand_part[part_num].size)                {                    printf("\nprogram nand flash fail\n");                    return;                }                _mark_bad_blk(i + start_page);                skip_blks++;                i += 32;                continue;            }        }        if (_write_page(i + start_page, (UINT8 *)ram_addr)) {            ram_addr -= ((i & 0x1f) << 9);            size += ((i & 0x1f) << 9);            i &= ~0x1f;            nand_part[part_num].size -= (32 << 9);    /* one block is broken */                                                      /* partition available size - 1 block size */            if (len > nand_part[part_num].size)            {                printf("\nprogram nand flash fail\n");                return;            }            _mark_bad_blk(i + start_page);            skip_blks++;            i += 32;            continue;        }        ram_addr += 512;        size -= 512;        i++;    }    printf("\nprogrm nand flash successfully\n");    if (skip_blks)    {        printf("warning: skiped %d bad blocks\n");    }}static void _disable_nand_flash(void){    DsNandFlash();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -