Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4534314
  • 博文数量: 252
  • 博客积分: 5347
  • 博客等级: 大校
  • 技术积分: 13838
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-30 10:13
文章分类
文章存档

2022年(12)

2017年(11)

2016年(7)

2015年(14)

2014年(20)

2012年(9)

2011年(20)

2010年(153)

2009年(6)

分类: 嵌入式

2010-03-30 17:33:46

 上一篇文章移植U-Boot2009.08支持从NandFlash启动,但是还没有识别出NorFlash的大小和型号,这篇文章就是移植NorFlash中的部分。
首先,修改/include/configs/mini2440.h文件。在Flash设置部分,把不需要的型号的NorFlash,用条件编译语句,注释掉。我的NorFlash的型号是SST39VF1601U,大小是2MB 。

/*-----------------------------------------------------------------------
 * FLASH and environment organization
 */

#if 0
#define CONFIG_AMD_LV400    1    /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800    1    /* uncomment this if you have a LV800 flash */
#endif
#define CONFIG_SYS_MAX_FLASH_BANKS    1    /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE        0x00100000 /* 1MB */
#define CONFIG_SYS_MAX_FLASH_SECT    (19)    /* max number of sectors on one chip */
#define CONFIG_ENV_ADDR        (CONFIG_SYS_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE        0x00080000 /* 512KB */
#define CONFIG_SYS_MAX_FLASH_SECT    (11)    /* max number of sectors on one chip */
#define CONFIG_ENV_ADDR        (CONFIG_SYS_FLASH_BASE + 0x070000) /* addr of environment */
#endif

#define CONFIG_SST_39VF1601 1              //添加对NorFlash的配置
#define PHYS_FLASH_SIZE 0x200000            //NorFlash的大小是2MB
#define CONFIG_SYS_MAX_FLASH_SECT (512) //
根据SST39VF1601的芯片手册描述,对其进行操作有两种方式:块方式和扇区方式。现采用扇区方式(sector),1 sector = 2Kword = 4Kbyte,所以2M的Nor Flash共有512个sector
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x040000) // 环境变量的首地址

然后,添加对Mini2440NorFlash的支持,其中包括对NorFlash的初始化,写入和,擦出。其文件在上一次,我们建立的frank目录下的,mini2440目录下面的flash.c文件。


#include <common.h>
ulong myflush (void);

#define FLASH_BANK_SIZE    PHYS_FLASH_SIZE
//#define MAIN_SECT_SIZE 0x10000    /* 64 KB */

#define MAIN_SECT_SIZE 0x1000 //
定义为4k,刚好是一个扇区的大小
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];

#define CMD_READ_ARRAY        0x000000F0
#define CMD_UNLOCK1        0x000000AA
#define CMD_UNLOCK2        0x00000055
#define CMD_ERASE_SETUP        0x00000080
#define CMD_ERASE_CONFIRM    0x00000030
#define CMD_PROGRAM        0x000000A0
#define CMD_UNLOCK_BYPASS    0x00000020

#ifdef CONFIG_SST_39VF1601  //根据SST39VF1601NorFlash芯片添加
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +(0x000005555<<1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +(0x000002AAA <<1)))
#else
#define MEM_FLASH_ADDR1        (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2        (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))
#endif

#define BIT_ERASE_DONE        0x00000080
#define BIT_RDY_MASK        0x00000080
#define BIT_PROGRAM_ERROR    0x00000020
#define BIT_TIMEOUT        0x80000000    /* our flag */

#define READY 1
#define ERR 2
#define TMO 4

/*-----------------------------------------------------------------------
 */

ulong flash_init (void)
{
    int i, j;
    ulong size = 0;

    for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
        ulong flashbase = 0;

        flash_info[i].flash_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);
#elif defined(CONFIG_SST_39VF1601)    //仿照LV400添加对SSTVF39VF1601的支持
    (SST_MANUFACT & FLASH_VENDMASK) |
    (SST_ID_xF1601 & FLASH_TYPEMASK);
#else
#error "Unknown flash configured"
#endif
            flash_info[i].size = FLASH_BANK_SIZE;
        flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
        memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
        if (i == 0)
            flashbase = PHYS_FLASH_1;
        else
            panic ("configured too many flash banks!\n");
        for (j = 0; j < flash_info[i].sector_count; j++) {
#ifndef CONFIG_SST_39VF1601  //相当于注释掉下面的代码
            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;
            }
#else
            flash_info[i].start[j] = flashbase + (j) * MAIN_SECT_SIZE;
#endif
        }
        size += flash_info[i].size;
    }

    flash_protect (FLAG_PROTECT_SET,
         CONFIG_SYS_FLASH_BASE,
         CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
         &flash_info[0]);

    flash_protect (FLAG_PROTECT_SET,
         CONFIG_ENV_ADDR,
         CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);

    return size;
}

/*-----------------------------------------------------------------------
 */

void flash_print_info (flash_info_t * info)
{
    int i;

    switch (info->flash_id & FLASH_VENDMASK) {
    case (AMD_MANUFACT & FLASH_VENDMASK):
        printf ("AMD: ");
        break;
    case (SST_MANUFACT & FLASH_VENDMASK): //添加SST39VF1601支持
        printf("SST: ");
        break;
    default:
        printf ("Unknown Vendor ");
        break;
    }

    switch (info->flash_id & FLASH_TYPEMASK) {
    case (AMD_ID_LV400B & FLASH_TYPEMASK):
        printf ("1x Amd29LV400BB (4Mbit)\n");
        break;
    case (AMD_ID_LV800B & FLASH_TYPEMASK):
        printf ("1x Amd29LV800BB (8Mbit)\n");
        break;
    case (SST_ID_xF1601 & FLASH_TYPEMASK): //添加SST39VF1601支持
        printf("1x SST39VF1601 (2MB)\n");
        break;
    default:
        printf ("Unknown Chip Type\n");
        goto Done;
        break;
    }

    printf (" Size: %ld MB in %d Sectors\n",
        info->size >> 20, info->sector_count);

    printf (" Sector Start Addresses:");
    for (i = 0; i < info->sector_count; i++) {
        if ((i % 5) == 0) {
            printf ("\n ");
        }
        printf (" %08lX%s", info->start[i],
            info->protect[i] ? " (RO)" : " ");
    }
    printf ("\n");

      Done:;
}

int flash_erase (flash_info_t * info, int s_first, int s_last)
{
    //ushort result;

    int iflag, cflag, prot, sect;
    int rc = ERR_OK;
//    int chip;

    /* first look for protection bits */

    if (info->flash_id == FLASH_UNKNOWN)
        return ERR_UNKNOWN_FLASH_TYPE;

    if ((s_first < 0) || (s_first > s_last)) {
        return ERR_INVAL;
    }
#ifdef CONFIG_SST_39VF1601
    if((info->flash_id & FLASH_VENDMASK)!=(SST_MANUFACT & FLASH_VENDMASK))
{
    return ERR_UNKNOWN_FLASH_VENDOR;
}
#else
    if ((info->flash_id & FLASH_VENDMASK) !=
     (AMD_MANUFACT & FLASH_VENDMASK)) {
        return ERR_UNKNOWN_FLASH_VENDOR;
    }
#endif
    prot = 0;
    for (sect = s_first; sect <= s_last; ++sect) {
        if (info->protect[sect]) {
            prot++;
        }
    }
    if (prot)
        return ERR_PROTECTED;

    /*
     * Disable interrupts which might cause a timeout
     * here. Remember that our exception vectors are
     * at address 0 in the flash, and we don't want a
     * (ticker) exception to happen while the flash
     * chip is in programming mode.
     */

    cflag = icache_status ();
    icache_disable ();
    iflag = disable_interrupts ();

    /* Start erase on unprotected sectors */
    for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
        printf ("Erasing sector %2d ... ", sect);

        /* arm simple, non interrupt dependent timer */
        reset_timer_masked ();

        if (info->protect[sect] == 0) {    /* not protected */
            vu_short *addr = (vu_short *) (info->start[sect]);

            MEM_FLASH_ADDR1 = CMD_UNLOCK1;
            MEM_FLASH_ADDR2 = CMD_UNLOCK2;
            MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;

            MEM_FLASH_ADDR1 = CMD_UNLOCK1;
            MEM_FLASH_ADDR2 = CMD_UNLOCK2;
            *addr = CMD_ERASE_CONFIRM;
#if 0   //条件编译注释掉
            /* wait until flash is ready */
            chip = 0;

            do {
                result = *addr;

                /* check timeout */
                if (get_timer_masked () >
                 CONFIG_SYS_FLASH_ERASE_TOUT) {
                    MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
                    chip = TMO;
                    break;
                }

                if (!chip
                 && (result & 0xFFFF) & BIT_ERASE_DONE)
                    chip = READY;

                if (!chip
                 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
                    chip = ERR;

            } while (!chip);

            MEM_FLASH_ADDR1 = CMD_READ_ARRAY;

            if (chip == ERR) {
                rc = ERR_PROG_ERROR;
                goto outahere;
            }
            if (chip == TMO) {
                rc = ERR_TIMOUT;
                goto outahere;
            }

            printf ("ok.\n");
        } else {    /* it was protected */

            printf ("protected!\n");
        }
    }
#endif

// 添加下面的代码
        while(1)
    {
        unsigned short i;
        i = *((volatile unsigned short *)addr)& 0x40;
        if( (*((volatile unsigned short *)addr) & 0x40))
            continue;
        if((*((volatile unsigned short *)addr)) & 0x80)
        break;
    }
    printf("ok.\n");
}
    else
{
    printf("protected!\n");
}
}
    if (ctrlc ())
        printf ("User Interrupt!\n");

      //outahere:

    /* allow flash to settle - wait 10 ms */
    udelay_masked (10000);

    if (iflag)
        enable_interrupts ();

    if (cflag)
        icache_enable ();

    return rc;
}

/*-----------------------------------------------------------------------
 * Copy memory to flash
 */


static int write_hword (flash_info_t * info, ulong dest, ushort data)
{
    vu_short *addr = (vu_short *) dest;
    ushort result;
    int rc = ERR_OK;
    int cflag, iflag;
    int chip;

    /*
     * Check if Flash is (sufficiently) erased
     */

    result = *addr;
    if ((result & data) != data)
        return ERR_NOT_ERASED;


    /*
     * Disable interrupts which might cause a timeout
     * here. Remember that our exception vectors are
     * at address 0 in the flash, and we don't want a
     * (ticker) exception to happen while the flash
     * chip is in programming mode.
     */

    cflag = icache_status ();
    icache_disable ();
    iflag = disable_interrupts ();

    MEM_FLASH_ADDR1 = CMD_UNLOCK1;
    MEM_FLASH_ADDR2 = CMD_UNLOCK2;
    //MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;

    //*addr = CMD_PROGRAM;

    *addr = data;

    /* arm simple, non interrupt dependent timer */
    reset_timer_masked ();
#if//条件编译注释掉
    /* wait until flash is ready */
    chip = 0;
    do {
        result = *addr;

        /* check timeout */
        if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
            chip = ERR | TMO;
            break;
        }
        if (!chip && ((result & 0x80) == (data & 0x80)))
            chip = READY;

        if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
            result = *addr;

            if ((result & 0x80) == (data & 0x80))
                chip = READY;
            else
                chip = ERR;
        }

    } while (!chip);

    *addr = CMD_READ_ARRAY;

    if (chip == ERR || *addr != data)
        rc = ERR_PROG_ERROR;
#endif

//自己添加的代码
    while(1)
    {
        unsigned short i = *(volatile unsigned short *)addr & 0x40;
        i = *(volatile unsigned short *)addr & 0x40;
        if( (*((volatile unsigned short *)addr) & 0x40))
            continue;
        if((*((volatile unsigned short *)addr)) & 0x80)
            {
                rc = ERR_OK;
                break;
            }    
    }
    printf("ok.\n");
    if (iflag)
        enable_interrupts ();

    if (cflag)
        icache_enable ();

    return rc;
}

这样,当从NandFlash启动时,就会看到NorFlash的大小为2MB,也可以进行相应的擦除操作了。


 

阅读(4405) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~