基于S3C4510B的系统的Flash擦除与烧写问题(一)

发表于:2007-07-04来源:作者:点击数: 标签:
基于S3C4510B的系统的Flash擦除与烧写问题(一) (也是抄的) 最近看到很多朋友在设计基于S3C4510B的系统时,碰到了Flash不能正确烧写或擦除的问题,下面根据我的理解对这个问题的作一个说明,以期抛砖引玉: 不同于其他的ARM处理器(如44B0),S3C4510B的每一
基于S3C4510B的系统的Flash擦除与烧写问题(一) (也是抄的)

最近看到很多朋友在设计基于S3C4510B的系统时,碰到了Flash不能正确烧写或擦除的问题,下面根据我的理解对这个问题的作一个说明,以期抛砖引玉:
    不同于其他的ARM处理器(如44B0),S3C4510B的每一个bank的地址都是可以通过重映射改变的,因此,系统的存储器,无论是Flash还是SDRAM,其起始地址都不是固定的,而对Flash的擦除,必须知道它的起始地址,否则就不能正确操作,这就是为什么很多朋友不能正确擦除Flash的原因。
    以一般的系统设计为例,Flash使用2M、4M或8M,16位数据宽度,对应到Flash/ROM/SRAM的Bank0,SDRAM采用两片16位宽度的器件,并联构成32位的SDRAM存储器系统,对应到SDRAM的Bank0,那么,在Flash的内容为空时,当系统上电或复位后,能直接访问到的只有特殊功能寄存器(SFR)对应的Bank(其首地址为0x3FF0000),和Flash/ROM/SRAM的Bank0(其首地址为0x0),而SDRAM此时是访问不到的。
   此时,如果我们想对Flash进行编程或擦除操作,该怎么办呢?
   显然,要对Flash进行编程或擦除操作,必须通过编程完成,而程序此时只能在SDRAM中运行(如果程序不太大,也可放在S3C4510B片内的SRAM中运行。),所以,我们要做的第一步,就是通过配置相应的特殊功能寄存器,将SDRAM映射出来,使其可以被访问到。
   下面是我的一个特殊功能寄存器配置文件,名为:mymap.txt,放在C盘根目录下。
      setmem 0x3ff0000,0xE7ffff90,32
      setmem 0x3ff3010,0x00003002,32  
      setmem 0x3ff3014,0x02000060,32
      setmem 0x3ff302c,0x14010380,32
      setmem 0x3ff303c,0xce338360,32
   我使用的硬件是2MB的Flash,16MB的SDRAM。在ADS中打开命令窗口,执行如下命令:
     >obey c:mymap.txt
   此时,2MB的Flash存储器和16MB的SDRAM已分别映射到地址空间的0x0000,0000~(0x0020,0000-1)和0x0040,0000~(0x0140,0000-1)处。
   编写一个Flash的擦除程序,由Init.s文件和Main.c文件构成。
   Init.s文件的代码如下:
         IMPORT Main
AREA    Init,CODE,READONLY

ENTRY
BL Main
B .
END
    
    Main.c文件的代码如下:

#define UINT16 unsigned short
#define AM_START_ADDR          0x0        //此处为Flash的起始地址,设为0
#define AM_ADDR_UNLOCK1        0x555
#define AM_ADDR_UNLOCK2        0x2aa
#define AM_DATA_UNLOCK1        0xaaaa
#define AM_DATA_UNLOCK2        0x5555
#define AM_SETUP_WRITE         0xa0a0
#define AM_SETUP_ERASE         0x8080
#define AM_CHIP_ERASE          0x1010
#define AM_SECTOR_ERASE     0x3030
#define AM_RESET     0xf0f0

int Main()
{
         *((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1;       
*((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK1) = AM_SETUP_ERASE;     
     *((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1;       
*((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
   *((volatile UINT16 *)AM_START_ADDR+ AM_ADDR_UNLOCK1) = AM_CHIP_ERASE;
return(0);
}

注:系统使用的Flash为29LV160B,其他型号的Flash,命令字有一些区别。
    系统使用的SDARM为HY57641620B

     建立一个工程文件,包含以上两个文件。
     由于要将该擦除程序放在SDRAM中运行,而根据前面的映射,SDRAM的起始地址为0x0040,0000,所以要修改连接器的选项,将代码的装入地址改为0x400000(默认为0x8000)。
    编译生成可执行映象文件,装入系统的SDRAM(0x0040,0000处)运行,就可擦除Flash。
 
    您瞧,Flash的擦除多么简单。

    但是,当Flash中已有一个程序在运行时,情况就不太一样了。
    当Flash中有程序运行时,一般都要将系统的存储器由初始化状态进行重映射,常用的方式是将SDARM映射到0x0处,而Flash则被映射到其他地方去了(如uClinux运行时,Flash被重映射到0x100,0000处),此时Flash的首地址也就不再是0x0了,再用以上的程序去擦除,显然就不能成功。
    怎么办???

    要原封不动的使用上面的程序,只有将Flash的首地址再映射回0x0。
    打开ADS的命令窗口,执行如下命令:
     >obey c:mymap.txt
   此时Flash被我们搬回了0x0处,SDRAM被搬回0x40,0000处,运行上述程序,Flash被擦除。

一点小注意:
   有时,Flash中原来的程序初始化了很多中断,而我们的擦除程序为简洁,对中断未作处理,可能会出现当我们装入程序到SDRAM中运行时,一开始就跑飞,这是因为产生了中断。
   在运行之前,先将0x3ff4008(中断屏蔽寄存器)的值改为0x3fffff,屏蔽所有的中断,然后运行,就好了。


     以上是一个最简单的思路,有点班门弄斧,请大家跟贴指正。
     下一部分讨论Flash的烧写。

原文转自:http://www.ltesting.net