u-boot-2009.11移植(适用于TQ2440和MINI2440)第四篇:完善目标板外设驱动(Nor flash)

时间:2021-11-23 08:10:05

注意:红色标记为修改的地方

4.3修改NorFlash写入功能的代码

(1)针对EN29LV160AB芯片

具体参考:

gongping11的《u-boot-2010.06移植到TQ2440过程2-nor Flash的移植》文章,网址http://home.eeworld.com.cn/my/space-uid-67414-blogid-55044.html

IT_114的csdn博客《u-boot-2011.03在TQ2440上的移植(3)--支持norflash启动》网址:http://blog.csdn.net/it_114/article/details/6264897

 

为flash添加ID号,这个ID 号是一个固定的值,由于是采用了bottom boot block ,从低地址到高地址增长的形式。可知ID 号是2249。添加ID号的函数为:

打开include/flash.h文件194行增加下面两个宏定义

/*添加两种不同扇区方式的ID标号,标号在手册中可以找到*/
 #define EON_ID_LV160AB_T 0x22C422C4 /*LV160AB ID (16 M, top boot sector) */
 #define EON_ID_LV160AB_B 0x22492249 /*LV160AB ID (16 M, bottom boot sect) */

top boot sect 是第一个分区在最高位,bottom boot sect 是第一个分区在最低位

修改board/sunzl/sunzl2440/flash.c这个文件

//#defineMAIN_SECT_SIZE 0x10000 /* 64 KB */

#defineMAIN_SECT_SIZE 0x8000 /* 32 K Word */

………………

ulong flash_init(void)

{

………………….

#elifdefined(CONFIG_AMD_LV800)

                            (AMD_MANUFACT &FLASH_VENDMASK) |

                            (AMD_ID_LV800B &FLASH_TYPEMASK);

#elifdefined(CONFIG_EON_29LV160AB)

                            (EON_MANUFACT &FLASH_VENDMASK) |/*添加厂商*/

                            (EON_ID_LV160AB_B& FLASH_TYPEMASK);/*添加芯片的ID*/

#else

#error "Unknownflash configured" 

………………….

if (j <= 3) {

                                     /* 1st one is 8 KB,第一分区的大小是8K*/

                                     if (j == 0){

                                               flash_info[i].start[j]=

                                                        flashbase+ 0;

                                     }

 

                                     /* 2nd and 3rd are both 4 KB */

                                     if ((j ==1) || (j == 2)) {

                                               flash_info[i].start[j]=

                                                        flashbase+ 0x2000 + (j -

                                                                                 1) *

                                                        0x1000;

                                     }

 

                                     /* 4th 16 KB */

                                     if (j == 3){

                                               flash_info[i].start[j]=

                                                        flashbase + 0x4000;

                                     }

……………….

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(EON_MANUFACT & FLASH_VENDMASK):

                   printf("EON: ") ;

                   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(EON_ID_LV160AB_B & FLASH_TYPEMASK):

                   printf ("1xEON_29LV160AB (16Mbit)\n");

                   break;

 

         default:

                   printf ("Unknown ChipType\n");

……………..

int flash_erase(flash_info_t * info, int s_first, int s_last)

{

……………………..

if ((s_first < 0)|| (s_first > s_last)) {

                   return ERR_INVAL;

         }

 

         if ((info->flash_id &FLASH_VENDMASK) !=

                   /*(AMD_MANUFACT & FLASH_VENDMASK)) {*/

            (EON_MANUFACT & FLASH_VENDMASK)) {

                   returnERR_UNKNOWN_FLASH_VENDOR;

         }

         prot = 0;


(2)针对SST39VF1601芯片(芯片型号不同,移植有区别,请对应好自己板子上的芯片做相应的移植)

在虽然S3C2440 和S3C2410 对于Nor Flash 的链接都是一样的,但是SBC2410 使用的AMD 的Nor Flash 芯片,而mini2440 使用的SST 的Nor Flash。这两款芯片在写入时所使用的块大小、时序和指令代码有差别,所以必须根据芯片的数据手册进行修改。主要的差别请看数据手册的对比:

SST39VF1601:

Am29LV160:

除了上面的不同以外,SST39VF1601 每个SECTOR 的大小都是一样的,而

Am29LV160 的头几块比较小。需要做的修改集中在board/sunzl/sunzl2440/flash.c这个文件上,修改如下:

#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_ERASE_CONFIRM   0x00000050

#define CMD_PROGRAM     0x000000A0

#define CMD_UNLOCK_BYPASS   0x00000020

 

#ifdef CONFIG_SST_VF1601

#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

 

…………..

ulong flash_init (void)

{

…………..

#elif defined(CONFIG_AMD_LV800)

            (AMD_MANUFACT& FLASH_VENDMASK) |

            (AMD_ID_LV800B& FLASH_TYPEMASK);

#elif defined(CONFIG_SST_VF1601)

            (SST_MANUFACT& FLASH_VENDMASK) |

            (SST_ID_xF1601& FLASH_TYPEMASK);

#else

#error "Unknown flash configured"

…………

panic ("configured too many flashbanks!\n");

        for (j =0; j < flash_info[i].sector_count; j++) {

#ifndef CONFIG_SST_VF1601

            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;

    }

…………

void flash_print_info (flash_info_t * info)

{

……………

case (AMD_MANUFACT & FLASH_VENDMASK):

        printf("AMD: ");

        break;

    case (SST_MANUFACT & FLASH_VENDMASK):

        printf("SST: ");

        break;

    default:

        printf("Unknown Vendor ");

        break;

    }

…………

case (AMD_ID_LV800B & FLASH_TYPEMASK):

        printf("1x Amd29LV800BB (8Mbit)\n");

        break;

    case (SST_ID_xF1601 & FLASH_TYPEMASK):

        printf("1x SST39VF1601 (2MB)\n");

        break;

 

    default:

        printf("Unknown Chip Type\n");

        gotoDone;

……………

int flash_erase (flash_info_t * info, int s_first, ints_last)

{

//  ushortresult;

    int iflag,cflag, prot, sect;

    int rc =ERR_OK;

//  intchip;

……………

if ((s_first < 0) || (s_first > s_last)) {

        returnERR_INVAL;

    }

#ifdef CONFIG_SST_VF1601

    if((info->flash_id & FLASH_VENDMASK) !=

        (SST_MANUFACT & FLASH_VENDMASK)) {

        returnERR_UNKNOWN_FLASH_VENDOR;

    }

#else

    if((info->flash_id & FLASH_VENDMASK) !=

        (AMD_MANUFACT & FLASH_VENDMASK)) {

        returnERR_UNKNOWN_FLASH_VENDOR;

    }

#endif   

    prot = 0;

……………….

MEM_FLASH_ADDR1= CMD_UNLOCK1;

            MEM_FLASH_ADDR2= CMD_UNLOCK2;

            *addr= CMD_ERASE_CONFIRM;

 

#if 0

            /*wait until flash is ready */

            chip= 0;

……………

printf("protected!\n");

        }

    }

#endif

                       /* waituntil flash is ready */

                     while(1){

                            unsigned short i;

                            i = *((volatileunsigned short *)addr) & 0x40;

                            if(i != (*((volatile unsigned short*)addr) & 0x40))

                                   continue;

                            if((*((volatileunsigned short *)addr)) & 0x80)

                                   break;

                     }

                     printf ("ok.\n");

 

             } else {   /* it was protected */

                     printf("protected!\n");

             }

      }

if (ctrlc ())

        printf("User Interrupt!\n");

 

//     outahere:

……………….

static int write_hword (flash_info_t * info, ulongdest, ushort data)

{

……………

    int cflag,iflag;

//  intchip;

………..

MEM_FLASH_ADDR1 = CMD_UNLOCK1;

    MEM_FLASH_ADDR2= CMD_UNLOCK2;

//  MEM_FLASH_ADDR1= CMD_UNLOCK_BYPASS;

//  *addr= CMD_PROGRAM;

    MEM_FLASH_ADDR1= CMD_PROGRAM;

 

    *addr = data;

 

    /* armsimple, non interrupt dependent timer */

    reset_timer_masked();

#if 0

    /* wait untilflash is ready */

    chip = 0;

………….

if (chip == ERR || *addr != data)

        rc =ERR_PROG_ERROR;

#endif

 

           /* wait until flash is ready */

      while(1){

             unsigned short i = *(volatile unsigned short *)addr & 0x40;

             if(i != (*(volatile unsigned short *)addr & 0x40))   //D6 == D6

                     continue;

             if((*(volatile unsigned short *)addr & 0x80) == (data & 0x80)){

                     rc = ERR_OK;

                     break;     //D7 == D7

             }

      }

if (iflag)

        enable_interrupts();

 

    if (cflag)

        icache_enable();

 

    return rc;

}

 

(3)针对S29AL016芯片

具体参考yuesichiu的csdn博客《S3C2440U-Boot移植--Norflash驱动支持- S29AL016》,网址http://blog.csdn.net/yuesichiu/article/details/8267015

AM29LV160B与S29AL016J的厂商id和芯片id相同,那我们就可以直接根据AM29LV160B来移植。

修改board/sunzl/sunzl2440/flash.c这个文件

一:flash_init(void) 函数中

#if defined(CONFIG_AMD_LV400)
                    (AMD_MANUFACT &FLASH_VENDMASK) |
                    (AMD_ID_LV400B &FLASH_TYPEMASK);
#elif defined(CONFIG_AMD_LV1800)
                    (AMD_MANUFACT &FLASH_VENDMASK) |
                    (AMD_ID_LV800B &FLASH_TYPEMASK);

之后 加入
#elif defined(CONFIG_AMD_LV160)
                    (AMD_MANUFACT &FLASH_VENDMASK) |
                    (AMD_ID_LV160B &FLASH_TYPEMASK);
 

 

二:flash_print_info(flash_info_t *info)函数中

 

case (AMD_ID_LV400B&FLASH_TYPEMASK):
             printf ("1xAmd29LV400BB (4Mbit)\n");
             break;
case (AMD_ID_LV800B & FLASH_TYPEMASK):
             printf ("1xAmd29LV800BB (8Mbit)\n");
             break;

之后加入    
       case(AMD_ID_LV160B &FLASH_TYPEMASK):
             printf ("1x S29AL016J(16Mbit ) \n");
             break;


三种芯片剩下的修改都在最后include/configs/sunzl2440.h配置文件中修改   具体参考 

u-boot-2009.11移植(适用于TQ2440和MINI2440)第五篇:修改配置文件