- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>//C语言标准库
- #include "flash.h"
- #define USER_FLASH_START_ADDR 0x01070000 //FLASH最后两个扇区 供用户使用
- u32tou8 u32data;//定义一个联合体
- //==================================================================================
- // 获取某个地址所在的页首地址
- // addr:FLASH地址
- // 返回:该地址所在的页 共128页(0~127)
- //==================================================================================
- unsigned int FLASH_GetFlashPage(unsigned int addr)
- {
- if (IS_FLASH_ADDRESS(addr))
- {
- return (addr&(~0xFFF));//清0低12位就是该页的起始地址
- }
- }
- //==================================================================================
- // 从FLASH中读取 一个字(32位)
- // addr:读取地址
- // 返回: 读到的字数据
- //备注: 地址为4字节对齐
- //==================================================================================
- unsigned int FLSAH_ReadWord(unsigned int addr)
- {
- return (*(unsigned int *)addr);
- }
- //==================================================================================
- //从FLASH指定地址 读取数据
- //备注: 读取数据类型为32位 读取地址为4字节对齐
- //==================================================================================
- void FLASH_Read(unsigned int ReadAddr,unsigned char *pBuffer,unsigned int NumToRead)
- {
- unsigned int i;
- u32tobyte cache;
- for(i=0; i<NumToRead; i+=4)
- {
- cache.u32data=FLSAH_ReadWord(ReadAddr+i);
- pBuffer[i]=cache.buf[0];
- pBuffer[i+1]=cache.buf[1];
- pBuffer[i+2]=cache.buf[2];
- pBuffer[i+3]=cache.buf[3];
- }
- }
- //==================================================================================
- // 向FLASH指定地址 写入大量数据
- // WriteAddr:写入首地址
- // pBuffer:数据首地址
- // NumToWrite:需要写入数据的大小
- // 返回: 4=成功 1,2,3,5=失败
- // 备注:
- //==================================================================================
- FLASH_Status FLASH_Write(unsigned int WriteAddr,unsigned char *pBuffer,unsigned int NumToWrite)
- {
- FLASH_Status status = FLASH_COMPLETE;
- u32tobyte cache;//联合体定义
- unsigned int startaddr,endaddr,pageaddr=0;
- unsigned char buffer[4096];//4K缓冲区 对应FALSH 1页
- unsigned int i;
- unsigned int index,remain;
- startaddr = WriteAddr;
- endaddr = startaddr+NumToWrite;//结束地址
-
- FLASH_Unlock();
- FCU->RO = 0;//去掉所有扇区写保护
- //==================================================================================
- // 判断写入地址是否非法 起始地址或者结束地址不在FALSH范围内则退出
- //==================================================================================
- if(!(IS_FLASH_ADDRESS(startaddr)&& IS_FLASH_ADDRESS(endaddr))) return FLASH_ERROR_PG;
-
- while(startaddr < endaddr)
- {
-
- //==================================================================================
- //1.计算起始地址在FALSH哪一页,并获取该页的首地址
- //2.计算起始地址在该页的偏移量
- //3.计算该页还剩余多少字节没写入数据
- //==================================================================================
- pageaddr = FLASH_GetFlashPage(startaddr);//获取起始地址所在页的页首地址
- index = startaddr-pageaddr;//4K缓冲区内偏移地址
- remain=4096-index;//缓存区剩余大小
- //==================================================================================
- // 将该页数据读入4K缓冲数组,后面读写都是对该缓冲数组操作
- //==================================================================================
- for(i=0;i<4096;i+=4)//读取一页到缓冲buff
- {
- cache.u32data=FLSAH_ReadWord(pageaddr+i);
- buffer[i]=cache.buf[0];
- buffer[i+1]=cache.buf[1];
- buffer[i+2]=cache.buf[2];
- buffer[i+3]=cache.buf[3];
- }
- //==================================================================================
- // 擦除FALSH对应的页,FLASH只能按页擦除,
- // 这一页数据已经被读到缓冲数组中了 之前的数据也保留下来了
- //==================================================================================
- status = FLASH_ErasePage(startaddr);
- if(status != FLASH_COMPLETE) return status;//擦除1页 4K字节
- //==================================================================================
- //1.判断要写入的数据是否大于该页剩余容量(即计算写入的数据长度是否跨多页)
- //2.将需要写入的数据转存到缓冲数据
- //==================================================================================
- if(NumToWrite > remain)//需要写入的数据量大于缓冲buf剩余字节数
- {
- for(i=index;i<4096;i++)//将需要写入FALSH的数据写入缓冲buff
- {
- buffer[i]=*(pBuffer++);
- }
- NumToWrite-=remain;//需要写入的数据长度-本次已经写入的数据长度
- startaddr+=remain;//地址向后偏移本次写入的字节数
- }
- else
- {
- for(i=index;i<NumToWrite+index;i++)//将需要写入FALSH的数据写入缓冲buff
- {
- buffer[i]=*(pBuffer++);
- }
- startaddr+=NumToWrite;//地址向后偏移本次写入的字节数
- }
- //==================================================================================
- // 将缓冲数组(4K)写入FLASH 对应的页
- // 此处必须从页首写入,因为缓冲数组正好4K,对应FALSH 1页
- //==================================================================================
- for(i=0;i<4096;i+=4)//将缓冲buffer写入 FALSH
- {
- cache.buf[0]=buffer[i];
- cache.buf[1]=buffer[i+1];
- cache.buf[2]=buffer[i+2];
- cache.buf[3]=buffer[i+3];
-
- if((status=FLASH_ProgramWord(pageaddr+i,cache.u32data))!= FLASH_COMPLETE)
- {
- FLASH_Lock();
- return status;//写入失败 FLASH上锁
- }
- }
- }
- FLASH_Lock();
- }
|