第十二章 FLASH 模拟 EEPROM 试验 W7500EVB本身没有自带 EEPROM,但是W7500具有 IAP(在应用编程)功能,所以可以把它的 FLASH 当成 EEPROM 来使用。本章将利用W7500内部的 FLASH 来储存数据,将数据直接存放在W7500内部,而不是存放在EEPROM。
本章分为如下几个部分:
12.1 W7500 FLASH 简介
12.2 硬件设计
12.3 软件设计
12.4 下载验证
12.1 W7500 FLASH 简介Flash 存储器由长度为32位的存储单元构成,可以用于存储代码或数据。块和扇区提供读/写保护,如图12.1.1所示:
图12.1.1 W7500EVB FLASH内存分配图 W7500 嵌入式 Flash 存储器可以使用在电路编程或在应用编程。在电路编程(ICP)方法用于更新 Flash 存储器的全部内容,使用 SWD 协议或引导加载程序(boot loader)来下载用户应用到单片机。 ICP 提供快速和高效的可迭代式设计,从而避免了设备不必要的插拔处理。相比 ICP 方法,在应用编程(IAP)可以使用单片机支持的任何通信接口 (I / Os、 UART、 I2C、 SPI等等)编程下载数据到内存中。 IAP 允许当应用程序正在运行时用户对存储器重新编程。然而,在应用编程(IAP)的部分应用需要使用在电路编程(ICP)提前编译到 Flash 存储器中。 他们可以通过以下7个 Flash 寄存器来进行管理: u Flash 访问控制寄存器(FACCR) u Flash 地址寄存器(FADDR) u Flash 数据寄存器(FDATAR) u Flash 控制寄存器(FCTRLR) u Flash 状态寄存器 (FSTATR) u Flash 锁存器 (FLOCKR0/R1) u Flash 密钥寄存器(FKEYR0/R1) 解锁 Flash 访问控制寄存器(FACCR) 重置后, Flash 存储器将受到保护以防止不必要的写或擦除操作。 FACCR 寄存器在烧写模式时拒绝访问。想要访问 FACCR 寄存器需要向 Flash 密钥寄存器(FKEYR0/R1)中写入一个解锁流程。
这个流程包含两个写操作: u Write KEY0 (FKEYR0) = 0x52537175 u Write KEY1 (FKEYR1) = 0xA91875FC 任意错误的流程将会锁住 FACCR 寄存器。
FACCR 寄存器在完成 Flash 控制操作后可以再次被锁住。 读操作 嵌入式 Flash 模组可以作为一个通用存储空间来进行直接寻址。任何访问 Flash 模块中内容的数据读操作,均需通过指定读取流程才能获取所需要数据。取指令和数据访问都是通过相同的 AHB 总线。通过 Flash 控制寄存器(FCTRLR)管理的以下选项,读操作才能生效。
使用 FCTRLR 寄存器读 Flash 顺序是如下,如图12.1.2所示:
1. 通过检查在 FSTATR 寄存器中的 RDY 位,检查有没有主 Flash 存储器操作正在进行。
2. 为了设置 FACCR 寄存器,先要设置 FKEYR0/R 中的密钥(KEY)。
3. 设置 FACCR 寄存器中的 FEN 和 CTRL 位。
4. 写主 Flash 存储器地址或数据块地址到 FADDR 寄存器。
5. 在 FACTRLR 寄存器中设置 RDI 或者 RD 位为 1。如果用 RDI 位,不需要再设置
FADDR 因为在 FACCR 寄存器中的 SZ 位会自动增加。
6. 从 FDATAR 寄存器读数据。
7. 等待直到 FATATR 寄存器中的 RDY 位为 1(当程序编译成功,该位将会被设置) 。
8. 设置 FKEYR0/R1 的 KEY 以清除 FACCR 寄存器。
9. 清除 FACCR 寄存器中的 FEN 和 CTRL 位 图12.1.2 W7500EVB FLASH读操作 Flash 擦除操作 扇区擦除
通过下面的过程来擦除扇区,如图12.1.3所示:
1. 通过检查在 FSTATR 寄存器中的 RDY 位,检查没有主 Flash 存储器操作正在进行。
2. 为了设置 FACCR 寄存器,先要设置 FKEYR0/R 中的密钥(KEY)。
3. 设置 FACCR 寄存器中的 FEN 和 CTRL 位。
4. 写主 Flash 存储器地址到 FADDR 寄存器以供擦除。
5. 设置 FACRLR 的 SER 位为 1。
6. 等待直到 FSTATR 寄存器中的 RDY 位为 1。
7. 设置 FKEYR0/R1 的密钥(KEY)以清除 FACCR 寄存器。
8. 在 FACCR 寄存器中清 FEN 和 CTRL 位 图12.1.3 W7500EVB Flash 擦除操作 块擦除 想要擦除一个块,可以设置 FACTRLR 寄存器的 BER 位。其他所有的进程和扇区擦除的顺序相同。 芯片擦除 ( 擦除所有 Flash 存储器) 想要擦除芯片(主 Flash 存储器),可以设置 FACTRLR 寄存器的 SER 位。 其他所有的进程和扇区擦除的顺序相同。 集体擦除 ( 所有的主 Flash 存储器擦除+数据块擦除) 想要集体擦除(主 Flash 存储器+数据块),可以设置 FACTRLR 的 MER 位。 其他所有的进程和扇区擦除的顺序相同。 函数库提供了 FLASH 写函数。 void DO_IAP( uint32_t id, uint32_t dst_addr, char* src_addr, uint32_t size);也提供了FLASH读函数。 void ReadBuf(char* Readbuff,char* pBuffer1,uint16_t nSize);12.2 硬件设计本章实验功能简介: 将数据写入FLASH中在读取出来存到一个数组里,然后通过串口2打印显示出来。所要用到的硬件资源如下: 1) UART2 2) W7500内部FLASH 12.3 软件设计在W7500EVB FLASH工程里,可以看到main.c文件里有两个函数一个是写FLASH一个是读FLASH。 #define IAP_ENTRY 0x1FFF1001 // Because Thum code#define IAP_ERAS 0x010#define IAP_ERAS_DAT0 (IAP_ERAS + 0) #define IAP_ERAS_DAT1 (IAP_ERAS + 1) #define IAP_ERAS_SECT (IAP_ERAS + 2) #define IAP_ERAS_BLCK (IAP_ERAS + 3) #define IAP_ERAS_CHIP (IAP_ERAS + 4) #define IAP_ERAS_MASS (IAP_ERAS + 5) #define IAP_PROG 0x022#define DAT0_START_ADDR 0x0003FE00#define DAT1_START_ADDR 0x0003FF00#define CODE_TEST_ADDR 0x0001F000#define BLOCK_SIZE 4096#define SECT_SIZE 256char save_buff[100],read_buff[100]; void DO_IAP( uint32_t id, uint32_t dst_addr, char* src_addr, uint32_t size); void ReadBuf(char* Readbuff,char* pBuffer1,uint16_t nSize); //============================================================int main(){/* 炜世科技—WIZnet W7500官方代理商,全程技术支持,价格绝对优势! */ CRG_PLL_InputFrequencySelect(CRG_OCLK); SystemInit(); SysTick_Config((GetSystemClock()/1000)); S_UART_Init(115200); strcpy(save_buff,"深圳炜世科技"); DO_IAP(IAP_ERAS_DAT0,0,0,0); DO_IAP(IAP_PGRO,DAT0_START_ADDR,save_buff,12); ReadBuf(read_buff,((char*)(DAT0_START_ADDR)),12); printf("%s\r\n",read_buff); while(1); }//---------------------------------FLASH写------------------------------------------------------void DO_IAP( uint32_t id, uint32_t dst_addr, char* src_addr, uint32_t size) { __disable_irq(); // Call IAP Function ((void(*)(uint32_t,uint32_t,uint8_t*,uint32_t))IAP_ENTRY)( id,dst_addr,(uint8_t*)src_addr,size); __enable_irq();}//---------------------------------FLASH读------------------------------------------------------void ReadBuf(char* Readbuff,char* pBuffer1,uint16_t nSize) { uint16_t i; for(i=0;i<nSize;i++) { Readbuff = *pBuffer1; pBuffer1++; }}主函数部分代码非常简单,首先将数据写进FLASH,然后再读取FLASH里的数据存到一个变量中。 12.4 下载验证在代码编译成功之后,下载代码到 W7500EVB上,可以看到串口打印一串数据出来,如图12.4.1所示这就是我们写进FLASH中的数据。 图12.4.1 W7500EVB FLASH试验结果
|