NOR-FLASH驱动文档(SST39VF1601)

合集下载

SST39VF1601简介

SST39VF1601简介

1、产品描述(PRODUCT DESCRIPTION)SST39VF160x/320x/640x设备提供了7 us的Word-program时间。

这些设备用Toggle Bit或者Data# Polling来表明编程操作的完成。

为了保护inadvertent write,它们有偏上硬件和Software Data Protection机制。

2、设备操作(Device Operation)命令被用来发起设备的存储器操作功能。

通过标准的微处理器写序列,命令被写到设备中。

通过asserting WE# low同时保持CE#为低,一条命令被写到设备中。

地址总线最后在WE#或者CE#上升沿的时候被占用。

而数据总线首先在WE#或者CE#上升沿的时候占用。

SST39VF160x/320x/640x也有一种Auto Low Power模式,这种模式在一次有效的读操作访问数据以后让设备进入一种standby模式。

它把IDD活动读电流(active read current)从典型的9mA 减小到典型的3uA。

Auto Low Power模式减少典型的IDD活动度电流到2mA/mHZ的读周期时间。

设备通过任何的被用来发起另一个读周期的地址转换或者控制信号转换退出auto low power模式,这是不花费时间的。

注意在开机后CE#一直稳定在低电平的时候,设备不会进入auto-low power模式,知道第一次地址转换或者CE#被转换为高电平。

3、读操作(Read)SST39VF160x/320x/640x的读操作被CE#和OE#控制。

系统为了从输出获得数据,这两者必须都为低电平。

CE#被用来作为设备选择。

当CE#为高时,芯片取消选择,只有standby电源被消耗。

OE#是输出控制,被用来从输出管脚gate数据。

当CE#或者OE#为高电平的时候,数据总线处于高impedance状态。

4、字编程操作(Word-Program Operation)SST39VF160x/320x/640x以字为单位编程。

Mini2440 Uboot移植

Mini2440 Uboot移植

第一部分根据uboot-2008.10,移植出能在mini2440 nor flash上运行的uboot1 修改Makefile:在uboot-2008.10顶层目录中的Makefile中,参考smdk2410_config,添加新的配置选项。

# add,flyrizmini2440_config : unconfig@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x02 修改cpu/arm920t/start.S:2.1添加支持S3C2440的编译条件/* #if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410) *//*modify,flyriz*/#if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) 2.2添加S3C2440寄存器的定义#else# define pWTCON 0x53000000# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */# define INTSUBMSK 0x4A00001C# define CLKDIVN 0x4C000014 /* clock divisor register */# endif/*add,flyriz,for 2440,register define*/#define CLK_CTL_BASE 0x4C000000#define MDIV_405 0x7f<<12#define PSDIV_405 0x21#define UPLL_MDIV_48 0x38<<12#define UPLL_PSDIV_48 0x22#define MDIV_200 0xa1<<12#define PSDIV_200 0x31/****************************/2.3修改中断禁止代码# if defined(CONFIG_S3C2410)ldr r1, =0x3ffldr r0, =INTSUBMSKstr r1, [r0]# endif/*add,flyriz*/# if defined(CONFIG_S3C2440)ldr r1, =0x7fff /* S3C2440有15个子中断[0...14] */ldr r0, =INTSUBMSKstr r1, [r0]# endif2.4 修改时钟设置/********************* FCLK:HCLK:PCLK = 1:2:4 ** default FCLK is 120 MHz ! *ldr r0, =CLKDIVNmov r1, #3str r1, [r0]#endif * CONFIG_S3C2400 || CONFIG_S3C2410 *********************//*modify,flyriz*/#if defined(CONFIG_S3C2440)/*FCLK:HCLK:PCLK=1:4:8*/ldr r0,=CLKDIVNmov r1,#5str r1,[r0]mrc p15,0,r1,c1,c0,0 /* CP15中的寄存器C1是一个控制寄存器,用于配置MMU中的一些操作 */orr r1,r1,#0xc0000000mcr p15,0,r1,c1,c0,0mov r1,#CLK_CTL_BASE /* 0x4C000000 LOCKTIME:PLL lock time counter */mov r2,#UPLL_MDIV_48add r2,r2,#UPLL_PSDIV_48str r2,[r1,#0x08] /* 0x4C000008 UPLLCON=0x38<<12||0x22,output 48MHz */mov r2,#MDIV_405add r2,r2,#PSDIV_405str r2,[r1,#0x04] /* 0x4C000004 MPLLCON=0x7f<<12||0x21,output 405MHz */ #elseldr r0,=CLKDIVNmov r1,#3str r1,[r0]mrc p15,0,r1,c1,c0,0orr r1,r1,#0xc0000000mcr p15,0,r1,c1,c0,0mov r1,#CLK_CTL_BASEmov r2,#MDIV_200add r2,r2,#PSDIV_200str r2,[r1,#0x04]#endif#endif /*CONFIG_S3C2400||CONFIG_S3C2410||CONFIG_S3C2440*//**********************************************************/3 修改cpu/arm920t/s3c24x0/interrupts.c3.1 在条件编译的宏定义里加入对s3c2440的支持:/* #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) *//*modify,flyriz*/#if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)||defined(CONFIG_TRAB)/* #elif defined(CONFIG_S3C2410) *//*modify,flyriz*/#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)3.2 在get_tbclk函数中,添加对mini2440的支持:#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)tbclk = timer_load_val * 100;#elif defined(CONFIG_SBC2410X) || \defined(CONFIG_SMDK2410) || \defined(CONFIG_MINI2440) || \defined(CONFIG_VCMA9) /*modify,flyriz,add:CONFIG_MINI2440*/tbclk = CFG_HZ; /*get_tbclk函数的作用?CFG_HZ又是什么?*/4 修改cpu/arm920t/s3c24x0/speed.c4.1 在条件编译的宏定义里加入对s3c2440的支持:/*#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410)|| defined (CONFIG_TRAB)*//*modify,flyriz*/#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_S3C2440) || defined (CONFIG_TRAB) /*#elif defined(CONFIG_S3C2410)*//*modify,flyriz*/#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)4.2 修改get_PLLCLK函数:m = ((r & 0xFF000) >> 12) + 8;p = ((r & 0x003F0) >> 4) + 2;s = r & 0x3;/*add,flyriz*/#if defined(CONFIG_S3C2440)if(pllreg==MPLL)return ((CONFIG_SYS_CLK_FREQ*m*2)/(p<<s)); /*S3C2440中,UPLL与MPLL的计算公式不同*/ else if(pllreg==UPLL)#endif4.3 修改get_HCLK函数:ulong get_HCLK(void){S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();/*return ((clk_power->CLKDIVN&0x2)?get_FCLK()/2:get_FCLK()); delete,flyriz*//*add,flyriz*/#if defined(CONFIG_S3C2440)if(clk_power->CLKDIVN & 0x6){if((clk_power->CLKDIVN & 0x6)==2)return (get_FCLK()/2);if((clk_power->CLKDIVN & 0x6)==6)return ((clk_power->CAMDIVN&0x100)?get_FCLK()/6:get_FCLK()/3);if((clk_power->CLKDIVN & 0x6)==4)return ((clk_power->CAMDIVN&0x200)?get_FCLK()/8:get_FCLK()/4);return (get_FCLK());}else return (get_FCLK());#elsereturn ((clk_power->CLKDIVN&0x2)?get_FCLK()/2:get_FCLK());#endif}5 修改include/asm-arm/mach-types.h,添加mini2440的机器ID(必须与内核提供的ID保持一致):#define MACH_TYPE_GENEVA 1873#define MACH_TYPE_MINI2440 1999 /*add,flyriz,mini2440机器ID,必须与内核提供的ID相同*/6 修改cpu/arm920t/s3c24x0/serial.c/*#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)*//*modify,flyriz*/#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_S3C2440) || defined (CONFIG_TRAB) /*#elif defined(CONFIG_S3C2410)*//*modify,flyriz*/#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)7 修改drivers/rtc/s3c24x0_rtc.c/* #elif defined(CONFIG_S3C2410) */#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /*modify,flyriz*/8 修改include/s3c24x0.h/*#ifdef CONFIG_S3C2410*/#if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /*modify,flyriz*/(所有ifdef CONFIG_S3C2410全部替换)/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) *//* (see S3C2410 manual chapter 7) */typedef struct {S3C24X0_REG32 LOCKTIME;S3C24X0_REG32 MPLLCON;S3C24X0_REG32 UPLLCON;S3C24X0_REG32 CLKCON;S3C24X0_REG32 CLKSLOW;S3C24X0_REG32 CLKDIVN;/*add,flyriz*/#if defined(CONFIG_S3C2440)S3C24X0_REG32 CAMDIVN; /*增加CAMDIVN的定义*/#endif} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;9 为开发板新建一个目录在board目录中新建一个目录mini2440,将board/smdk2410下的所有文件拷贝到board/mini2440中,然后对mini2440中的文件做修改:将smdk2410.c改为mini2440.c;将Makefile中的代码COBJS :=smdk2410.o flash.o 改为COBJS :=mini2440.o flash.o10 修改board/mini2440/mini2440.c10.1 修改PLL的配置/*****************#elif FCLK_SPEED==1 // Fout = 202.8MHz#define M_MDIV 0xA1#define M_PDIV 0x3#define M_SDIV 0x1#endif#define USB_CLOCK 1*//*modify,flyriz*/#elif FCLK_SPEED==1#if defined(CONFIG_S3C2410)/*Fout=202.8MHz*/#define M_MDIV 0xA1#define M_PDIV 0x3#define M_SDIV 0x1#endif#if defined(CONFIG_S3C2440)/*Fout=405MHz*/#define M_MDIV 0x7f#define M_PDIV 0x2#define M_SDIV 0x1#endif#endif#define USB_CLOCK 1/*****************/10.2 修改UPLL的配置/***************#if USB_CLOCK==0#define U_M_MDIV 0xA1#define U_M_PDIV 0x3#define U_M_SDIV 0x1#elif USB_CLOCK==1#define U_M_MDIV 0x48#define U_M_PDIV 0x3#define U_M_SDIV 0x2#endif*//*modify,flyriz*/#if USB_CLOCK==0#define U_M_MDIV 0xA1#define U_M_PDIV 0x3#define U_M_SDIV 0x1#elif USB_CLOCK==1#if defined(CONFIG_S3C2410) #define U_M_MDIV 0x48#define U_M_PDIV 0x3#endif#if defined(CONFIG_S3C2440) #define U_M_MDIV 0x38#define U_M_PDIV 0x2#endif#define U_M_SDIV 0x2#endif/*****************/10.3 修改board_init函数,以引导内核/* arch number of SMDK2410-Board *//* gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; *//*modify,flyriz*/gd->bd->bi_arch_number = MACH_TYPE_MINI2440;11 修改board/mini2440/lowlevel_init.S中REFRESH的刷新周期/* REFRESH parameter */#define REFEN 0x1 /* Refresh enable */#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh *//* #define Trp 0x0 2clk *//*modify,flyriz*/#define Trp 0x2 /* 4clk */#define Trc 0x3 /* 7clk */#define Tchr 0x2 /* 3clk *//* #define REFCNT 1113 period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) *//*modify,flyriz*/#define REFCNT 1012/**************************************/12 添加并修改配置文件为开发板添加新的配置文件,复制include/configs/smdk2410.h,另存为include/configs/mini2440.h,并对其进行修改12.1 添加s3c2440的宏定义#define CONFIG_ARM920T 1 /* This is an ARM920T Core *//* #define CONFIG_S3C2410 1 in a SAMSUNG S3C2410 SoC *//* #define CONFIG_SMDK2410 1 on a SAMSUNG SMDK2410 Board *//*modify,flyriz*/#define CONFIG_S3C2440 1#define CONFIG_MINI2440 112.2 修改命令提示符#defineCFG_LONGHELP /* undef to save memory *//* #define CFG_PROMPT "SMDK2410 # " Monitor Command Prompt *//*modify,flyriz*/#define CFG_PROMPT "Mini2440 # "一个具备基本功能的UBOOT代码修改部分已经完成。

JLINK使用指南

JLINK使用指南

第二十三章:JLINK仿真调试器的使用首先JLINK只能对NOR FLASH 进行烧写。

如何用JLINK将uboot烧写到NOR FLASH为例来讲解JLINK的用法。

假定已经装好了JLINK驱动程序。

第一步:检测JLINK 是否和电脑连接上,用USB线连接JLINK和电脑打开J-Link Commander观察相关信息,看到如下信息证明JLINK已经和电脑连接上。

第二步:关掉上面的窗口,将JLINK和目标板连接,再次打开J-Link Commander观察相关信息,看到如下信息证明JLINK已经找到目标板的芯片。

第三步JLINK 相关设置首先打开J-Flash ARM 看到后选择Options Project Settings 或者直接按Alt+F7进入工程设置。

在CPU选项中按下图进行选择。

内核选择为ARM9,选Use target RAM(faster)Addr栏中填40000000 4KB在FLASH选项中进行如下设置首先勾掉Automatically detect flash memory看到如下界面后点select flash-----Device选择SST39VF1601。

设置完以后点击确认。

注意BASE ADDR 为00000000.第四步:点击file —>open或直接按Clt+O找到存放已经生成好的uboot.bin的文件,并打开uboot.bin。

此时软件会提示Start address点击OK.点击OK后的界面。

下载主界面第五步按F7让JLINK软件实现自动下载。

下图为程序下载完成后的界面。

整个过程到此结束,需要注意的是下载完成后必须拔掉JLINK程序才会跑起来。

说明:如果出现以下错误提醒,解决方法及可能原因:1)注意BASE ADDR为00000000.可能设置错误了;2)J-LINK复位时间短了或长了;3)NOR FLASH里面有坏区或烧写误操作导致(通过H-JTAG清空,一般很少出现)。

关于nor flash烧写失败的原因

关于nor flash烧写失败的原因

关于nor flash烧写失败的原因本文主要是关于nor flash烧写的相关介绍,并着重对nor flash烧写原理及应用进行了详尽的阐述。

nor flashnor flash是现在市场上两种主要的非易失闪存技术之一。

Intel于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Erasable Programmable Read-Only-Memory 电可编程序只读存储器)和EEPROM(电可擦只读存储器Electrically Erasable Programmable Read - Only Memory)一统天下的局面。

紧接着,1989年,东芝公司发表了NAND Flash 结构,强调降低每比特的成本,有更高的性能,并且像磁盘一样可以通过接口轻松升级。

NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中。

NOR 的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响到它的性能。

NAND的结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。

应用NAND 的困难在于Flash的管理需要特殊的系统接口。

通常读取NOR的速度比NAND稍快一些,而NAND的写入速度比NOR快很多,在设计中应该考虑这些情况。

——《ARM嵌入式Linux系统开发从入门到精通》李亚峰欧文盛等编著清华大学出版社P52 注释API Key性能比较flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。

任何flash 器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。

NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。

由于擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s,与此相反,擦除NAND器件是以8~32KB的块进行的,执行相同的操作最多只需要4ms。

STM32-FSMC-NOR FLASH

STM32-FSMC-NOR FLASH

一、基本概念(详细内容见st网站stm32应用笔记AN2784)1. FSMC配置控制一个NOR闪存存储器,需要FSMC提供下述功能:●选择合适的存储块映射NOR闪存存储器:共有4个独立的存储块可以用于与NOR闪存、SRAM和PSRAM存储器接口,每个存储块都有一个专用的片选管脚。

●使用或禁止地址/数据总线的复用功能。

●选择所用的存储器类型:NOR闪存、SRAM或PSRAM。

●定义外部存储器的数据总线宽度:8或16位。

●使用或关闭同步NOR闪存存储器的突发访问模式。

●配置等待信号的使用:开启或关闭,极性设置,时序配置。

●使用或关闭扩展模式:扩展模式用于访问那些具有不同读写操作时序的存储器。

因为NOR闪存/SRAM控制器可以支持异步和同步存储器,用户只须根据存储器的参数配置使用到的参数。

FSMC提供了一些可编程的参数,可以正确地与外部存储器接口。

依存储器类型的不同,有些参数是不需要的。

当使用一个外部异步存储器时,用户必须按照存储器的数据手册给出的时序数据,计算和设置下列参数:●ADDSET:地址建立时间●ADDHOLD:地址保持时间●DATAST:数据建立时间●ACCMOD:访问模式这个参数允许FSMC可以灵活地访问多种异步的静态存储器。

共有4种扩展模式允许以不同的时序分别读写存储器。

在扩展模式下,FSMC_BTR用于配置读操作,FSMC_BWR用于配置写操作。

(译注:如果读时序与写时序相同,只须使用FSMC_BTR即可。

)如果使用了同步的存储器,用户必须计算和设置下述参数:●CLKDIV:时钟分频系数●DATLAT:数据延时如果存储器支持的话,NOR闪存的读操作可以是同步的,而写操作仍然是异步的。

当对一个同步的NOR闪存编程时,存储器会自动地在同步与异步之间切换;因此,必须正确地设置所有的参数。

2. 时序计算如上所述,对于异步NOR闪存存储器或类似的存储,有不同的访问协议。

首先要确定对特定存储器所需要使用的操作协议,选择的依据是不同的控制信号和存储器在读或写操作中的动作。

FlashProgrammer使用说明

FlashProgrammer使用说明

Flash Programmer使用说明OCD Flash Programmer 是Macraigor 公司专门用于烧写Nor Flash 的在线编程软件可配合Macraigor 所有仿真器的使用。

有支持Windows (非常易于使用)和Linux 2种操作系统的版本。

支持CPU及Flash非常丰富具体可下载OCD Flash Programmer试用版,试用查找。

现在本使用手册以烧写SinoSys-M3 平台为例,结合Macraigor 公司的usb2Demon 仿真器,演示OCD Flash Programmer使用方法。

一、软硬件准备1、硬件SinoSys-M3 是ARM920T CPU采用Samsung S3c2440 ,Flash采用Silicon Stor age Technology的SST39VF1601;仿真器是Macraigor 公司的usb2Demon ARM20 ;PC操作系统是WindowsXp。

2、软件OCD Flash Programmer 正式版;SinoSys-M3 的bootloader.bin ;OCD Commander;二、操作步骤1、安装OCD Commander及OCD Flash Programmer,下载试用版,点击安装即可。

2、将目标板(SinoSys-M3)通过仿真器(usb2Demon)和PC连接起来,给目标板上电。

3、安装usb2Demon 驱动,系统会自动安装该驱动(驱动文件已经包含在步骤1中了),如有疑问,可参见USB2DEMON 使用说明。

4、SinoSys-M3 的bootloader.bin(需要烧写的文件)转化为S19格式。

安装完OCD Flash Programmer 后,会同时安装BinToS19 命令行程序,主要作用是将bin文件转化成S19格式文件,命令格式:即:执行BinToS19.exe bootloader.bin 0X30000000 boot.S19(我是将BinToS19.exe以及bootloader.bin拷贝到同一目录下执行的,执行后会在该目录下生成boot.S19)5、打开OCD Commander设置连接参数如图:6、点击status查看状态是否是in DEBUG:如果不是请点击halt,使其进入调试状态,关闭OCD Commander。

信源编码实验

信源编码实验

实验一信源与信宿基本通信实验一、实验目的1、学会实际中的信源与信宿的常用形式。

2、了解ARM以及ARMST2410模块的原理,以及基于ARM的Windows CE 操作系统的使用方法,并学会在该系统上进行简单的通信实验。

3、了解键盘模块的原理与使用方法。

二、实验设备1、“现代通信技术综合实验实训系统” 实验箱一台。

2、20MHZ示波器一台。

3、实验模块:ARM模块与基于ARM的液晶显示模块,或者键盘模块与基于键盘的液晶显示模块(用户可以根据不同的配置模块做不同的实验,以后情况类似不再赘述)。

三、实验原理在本实验箱的设计中,不管是ARM模块与基于ARM的液晶显示模块,还是键盘与基于键盘的液晶显示模块均采用异步串口通信模式。

RS232串口是标准的异步通信,其发送接口数据由起始位、数据位、校验位和停止位构成一帧,起始位为低电平(1BIT),用来通知接收端新帧的开始。

在不传送数据时,起始位保持高电平。

而接收接口不断检测线路的状态,若连续为高电平后又检测到一个低电平,就准备接收新的帧。

要正确实现RS232串口的通信,必须设置正确的传输速率,收发双方的波特率一定要相同,标准的波特率如表1-1所示。

表1-1 RS232串口标准的波特率序号波特率1 1102 3003 12004 24005 48006 96007 192008 384009 5760010 11520011 23040012 46080013 921600此外,RS232的标准接口9针和25针两种,其控制信号的定义见表1-2所示。

表1-2 RS232控制信号定义DB9 DB25针号功能缩写针号功能缩写1 数据载波检测RXD8 数据载波检测RXD2 接收数据TXD3 接收数据TXD3 发送数据DTR 2 发送数据DTR4 数据终端准备RXD20 数据终端准备GND5 信号地GND7 信号地DSR6 数据设备准备好DSR 6 数据准备好RTS7 请求发送RTS 4 请求发送CTS8 清除发送CTS 5 清除发送DELL9 振铃指示DELL22 振铃指示RXD在本实验箱中键盘模块采用57600bit/s的异步串口通信速率,ARM模块则可以根据具体实验要求而选择不同的信息传输速率。

JTAG烧录问题

JTAG烧录问题

解决方案:我焊接的芯片是SST39VF1601,160已经没有了,我发现程序在写入的时候总是验证0x0地址的6bit,这样验证是错误的,应该验证写入地址的6bit位。
这样就导致有时候写入成功,那是因为刚好碰上了,而多数时候是不成功的。
解决方案:在jtage的4根线上串入50或100欧姆的电阻

小邹(2010)
代码反复烧录时,会出现有时能烧录有时不能烧录问题。
解决方案:电源走线与铺地(地分割时的两地过孔连接跳线过细)问题,其引起的干扰导致晶振不起振,或起振异常。
我看JTAG_DELAY被设为空函数了,那么两次的JTAG_SET操作之间就没有时间间隔了,这样设置能保证不出错吗?还有就是我的板子烧写程序的时候有时候可以成功有时候不成功,相对来说小程序成功概率大,大一点的程序如5K几乎没有成功过,请问这是什么原因,有没有可能是Flash坏了呢?因为有时候长时间运行程序会死机,led程序有时候就不闪了?
各位大虾,请教一个古怪的问题
我自己做了一个SA1110的板子,上面有一个cpld,调试的时候,发现JTAG口不太稳定。用jflash烧程序的时候,发现ID code能够正确读出,然而读flash的属性时候,出错。怀疑是焊接问题,换了一片cpu,这次问题更严重了,读ID code又时候都不行,可是有时候又可以,烧flash的时候,还是属性不对,一次不经意间,我先把板子当作3个jtag设备来处理(当然ID都不会对了)然后再当作2个设备处理,一切正常!虽然现在这个板子基本功能都通了,可是jtag这里仍有问题
需要说明一下,jflash我自己改过了,做成gui界面,设备可选,在以前的板子上工作都没有问题,jtag口专门又作了一个调试板,主要是利用244增加jtag几根线的驱动能力和电平兼容性,这个板子我也使过,应该没有问题,还有就是,我的sa1110开封的时间比较长了,有一年了吧,不知道是不是性能下降?
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

NOR-FLASH驱动文档(SST39VF1601)2012-03-30 00:57:33NOR-FLASH是最早出现的Flash Memory,目前仍是多数供应商支持的技术架构.NOR-FLASH在擦除和编程操作较少而直接执行代码的场合,尤其是纯代码存储的应用中广泛使用,但是由于NOR-FLASH只支持块擦除,其擦除和编程速度较慢,而块尺寸又较大,导致擦除和编程操作所花费的时间很长,所以在纯数据存储和文件存储的应用中显得力不从心.NOR-FLASH的特点是:1. 程序和数据可存放在同一芯片上,FLASH芯片拥有独立的数据总线和地址总线,能快速随机读取,并且允许系统直接从Flash中读取代码执行,而无需先将代码下载至RAM中再执行;2. 可以单字节或单字读取,但不能单字节擦除,必须以部分或块为单位或对整片执行擦除操作,在执行写操作之前,必需先根据需要对部分,块或整片进行擦除,然后才能写入数据。

以SST系列NOR-FLASH芯片为例介绍FLASH的使用方法及驱动.首先,在驱动的头文件中,要根据芯片的具体情况和项目的要求作如下定义:1. 定义操作的单位,如typedef unsigned char BYTE; // BYTE is 8-bit in lengthtypedef unsigned short int WORD; // WORD is 16-bit in lengthtypedef unsigned long int Uint32; // Uint32 is 32-bit in length在这里地址多是32位的,芯片写操作的最小数据单位为WORD,定义为16位,芯片读操作的最小数据单位是BYTE,定义为8位.2. 因为芯片分为16位和32位的,所以对芯片的命令操作也分为16位操作和32位操作(命令操作在介绍具体的读写过程中将详细介绍).#ifdef GE01/*宏NorFlash_32Bit,若定义了为32位NorFlash,否则为16位NorFlash*/#define NorFlash_32Bit#endif3. 根据芯片的情况,定义部分(段)和块的大小.#define SECTOR_SIZE 2048 // Must be 2048 words for 39VF160X#define BLOCK_SIZE 32768 // Must be 32K words for 39VF160X/*其中words根据上述定义,指的是16位的数据*/其余的参数可以不用改。

下面来看具体的操作。

1.读操作NOR-FLASH可以随机读取数据,速度快,可以在FLASH的任意地址读取且读数据的最小单位控制在8位。

如下是驱动中的读操作,该段代码的作用是从Flash中偏移地址为Dst地址处读取一个长为length的数据到源地址SrcWord地址处(length的单位是字节):void NorFlash_Read(U8 *SrcWord, Uint32 Dst, int length){Uint32 DestBuf = Dst;U8 *SourceBuf = SrcWord;int Index;for(Index = 0; Index < length; Index++){ReadOneWord(SourceBuf, DestBuf);//读一个字节的函数SourceBuf++;DestBuf++;}}void ReadOneWord(U8 *SrcWord, Uint32 Dst){Uint32 DestBuf = Dst;U8 *SourceBuf = (U8 *)SrcWord;*SourceBuf = *(volatile U8*)(system_base|DestBuf); //system_base是FLASH的基址,在驱动中可以自行定义,另外读操作不需要发送命令,直接读取即可}用法:若需从FLASH的地址为0x20001000处读一段10个字节的数据至SDRAM的地址0x30001000中,代码应写成:NorFlash_Read((U8 *)0x30001000, 0x1000, 10);//FLASH 的基址是0x20000000,所以偏移地址只需写成0x1000即可。

2.擦除操作擦除操作分为3种,一是部分擦除,即擦除一个sector大小的空间,二是块擦除,三是整片擦除。

部分擦除的函数,除了读操作,其余对FLASH的操作都必须向FLASH发送相应的命令。

而具体发送什么样的命令,由FLASH芯片的型号决定,用时请查阅SST39VF1601芯片说明书int EraseOneSector(Uint32 Dst){Uint32 DestBuf = Dst;int ReturnStatus;// 39VF160X系列FLASH的命令,对照下表来写命令*sysAddress(0x5555) = 0x00AA; // write data 0x00AA to device addr 0x5555*sysAddress(0x2AAA) = 0x0055; // write data 0x0055 to device addr 0x2AAA*sysAddress(0x5555) = 0x0080; // write data 0x0080 to device addr 0x5555*sysAddress(0x5555) = 0x00AA; // write data 0x00AA to device addr 0x5555*sysAddress(0x2AAA) = 0x0055; // write data 0x0055 to device addr 0x2AAA*sysAddress(DestBuf) = 0x0030; // write data 0x0030 to device sector addrReturnStatus = CheckToggleReady(DestBuf); //检查Flash中偏移为DstBuf地址处是否正在进行写或者擦除操作。

返回1:目的地址处不在进行写和擦除操作;0:目的地址处正在进行写或擦除操作return ReturnStatus;}对应的中文擦除一个块和擦除整片的驱动代码与上述类似,但是命令有所区别,可根据上表Block-Erase和Chip-Erase的命令修改。

擦除操作具体的应用在写操作中可以看到。

3.写操作写操作的速度较慢,不要频繁使用int NorFlash_Write(WORD *Src, U32 Dst, int length)//将源地址Src地址处将一个长为length的数据写到Flash中偏移地址为Dst地址处,length的单位是字节{WORD *SourceBuf;Uint32 DestBuf;int Index, ReturnStatus;WORD tempBuf[SECTOR_SIZE];SourceBuf = Src;DestBuf = Dst;length = (length + 1) / 2; //字节数转半字数//在写数据之前,需要先擦除。

所以先要计算出要写的数据占多少块零多少个部分然后分别将其擦除Index = length / BLOCK_SIZE; //计算所占块的个数,不到一块的就不算for(Index = Index - 1; Index >= 0; Index--){//将目的地址变为偏移地址DestBuf = (DestBuf + Index * BLOCK_SIZE * 2) - system_base ;//因为该FLASH以半字为单位,所以将偏移地址DestBuf除以2。

例如一个块大小为0x8000,单位为16位的word,实际占用的存储空间为0x10000。

存储地址是以8位字节为单位的,而函数EraseOneBlock(Dest)是以word为单位的。

擦除块时D est是块的首地址的偏移地址,擦除第二块时,首地址的偏移地址为0x10000,而对于EraseOneBlock(Dest)来说,第二块的首地址应是0x8000。

所以需对偏移地址作移位处理,左移一位。

ReturnStatus = EraseOneBlock(DestBuf >> 1);if (!ReturnStatus)return ReturnStatus;}Index = (length % BLOCK_SIZE) / SECTOR_SIZE;//计算剩下未擦除的数据占用多少个部分,不足一部分的按照一部分计算DestBuf = Dst;for(Index; Index >= 0; Index--){DestBuf = (DestBuf + (length / BLOCK_SIZE) * BLOCK_SIZE * 2 + Index *SECTOR_SIZE * 2) - system_base;//将目的地址变为偏移地址ReturnStatus = EraseOneSector(DestBuf >> 1);if (!ReturnStatus)return ReturnStatus;}for (Index = 0; Index < length; Index++) //全部擦除完以后开始写数据{ReturnStatus = ProgramOneWord( SourceBuf, DestBuf);//写一个字DestBuf = DestBuf + 2;++SourceBuf;if (!ReturnStatus)return ReturnStatus;}return ReturnStatus;//若擦除和写操作其中的任意一个出错,返回的状态就为0}int ProgramOneWord (WORD *SrcWord, Uint32 Dst)//从源地址SrcWord地址处取一个WORD(16位)写到Flash中偏移地址为Dst地址处{Uint32 DestBuf = Dst;WORD *SourceBuf = SrcWord;int ReturnStatus;//写一个word的命令见上述命令表的word-program*sysAddress(0x5555) = 0xAAAA; // write data 0x00AA to device addr 0x5555*sysAddress(0x2AAA) = 0x5555; // write data 0x0055 to device addr 0x2AAA*sysAddress(0x5555) = 0xA0A0; // write data 0x00A0 to device addr 0x5555*(volatile U16*)(system_base|DestBuf) = *SourceBuf; // 把起始地址是SourceBuf的数据写到FLASH的地址(system_base|DestBuf)中ReturnStatus = CheckToggleReady(DestBuf);return ReturnStatus;}用法:若需将SDRAM的地址为0x30000000处的一段10个字节的数据写至FLASH的地址0x20001000中,代码应写成:NorFlash_Write((U8 *)0x30000000, 0x1000, 10);写操作需要注意的是:源数据地址一定是偶数,否则会出错,Flash中的目的地址也一定为偶数(否则会出现第一个字节丢失的错误)。

相关文档
最新文档