📄 flash.c
字号:
/****************************************Copyright (c)**************************************************
**--------------File Info-------------------------------------------------------------------------------
** File name: Flash.c
** Last modified Date: 2006-03-20
** Last Version: 1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Created by:
** Created date: 2006-03-20
** Version: 1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date: 2006-03-20
** Version:
** Descriptions:
**
********************************************************************************************************/
#include "Flash.h"
#include "string.h"
static const uint8 FlashSizeAttr[] = {FLASH_4M, FLASH_8M, FLASH_16M, FLASH_32M};
static const uint16 BlockSize[] = { 256, 512, 512, 1024,};
static const uint8 FlashDef[3][2]= { //与操作FLASH相关的变量。
MEM_TO_BUFF1, MEM_TO_BUFF2,
BUFF1_TO_MEM_WITH_ERASE, BUFF2_TO_MEM_WITH_ERASE,
BUFF_1_WRITE, BUFF_2_WRITE,};
//与写操作相关定义
static uint16 BufAddr[2]; //两个缓冲所对应的FLASH实际页地址。
/*
*函数性质:公共
*入口:无
*出口:无
*功能:刷新缓冲,将缓冲中的数据写入到FLASH中。以免断电数据丢失。
*/
void FlushFlash(void)
{
uint8 i;
for (i = 0; i < 2; i++)
{
WriteBuffToFlash(FlashDef[WRITE_FROM_BUF][i], BufAddr[i]);
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{ //等待写入完成。
CLRWATCHDOG();
}
}
}
/*
*函数性质:公共
*入口:页地址ulFlashAddr
*出口:无
*功能:将给定地址的Flash数据读入到缓冲中。
*/
void UpDateFlashBuf(uint32 FlashAddr)
{
uint8 i;
uint16 PageAddr = FlashAddr/PAGE_SIZE;
for (i = 0; i < 2; i++)
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{ //等待读入完成。
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][i], PageAddr + i);
BufAddr[i] = PageAddr + i;
}
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{ //等待读入完成。
CLRWATCHDOG();
}
}
/*
*函数性质:公共
*入口:存储器地址Addr, 数据缓冲地址Data, 数据长度Len
*出口:无
*功能:从Flash中读出给定个数的数据,并将读得的数据存放到Data中。
*/
void ReadFlashMem(uint32 Addr, uint8 *Data, uint16 Len)
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ContinueReadFlash(Addr/PAGE_SIZE, Addr%PAGE_SIZE, Data, Len);
}
/*
*函数性质:公共
*入口:存储器地址Addr,数据缓冲地址Data, 数据长度Len
*出口:无
*功能:将Data所指向的缓冲数据写入到指定的存储器地址,数据个数由Len决定。
*/
void WriteFlashMem(uint32 Addr, uint8 *Data, uint16 Len)
{
uint16 PageAddr;
uint16 j;
uint16 i;
uint8 CurBuf;
PageAddr = Addr/PAGE_SIZE;
j = Addr%PAGE_SIZE; //得出本页偏移地址。
while(Len) //写数据
{
IO1SET = DFWP;
i = PAGE_SIZE -j;
i = (i <= Len) ? i:Len; //计算出本次需要写入的数据长度。
if (BufAddr[0] ==PageAddr) //当前正使用缓冲1
{
CurBuf = 0;
if (BufAddr[1] != (PageAddr + 1) ) //判断并读入缓冲2
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][1], PageAddr + 1);
BufAddr[1] = PageAddr + 1;
}
WriteFlashBuff(FlashDef[WRITE_BUF][0], j, Data, i);//写数据入缓冲1
}
else if (BufAddr[1] == PageAddr)
{
CurBuf = 1; //当前正使用缓冲2
if (BufAddr[0] != (PageAddr + 1) ) //判断并读入缓冲1
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][0], PageAddr + 1);
BufAddr[0] = PageAddr + 1;
}
WriteFlashBuff(FlashDef[WRITE_BUF][1], j, Data, i);//写缓冲1
}
else
{ //当前的两个缓冲均不是需要写入的页,读入需要写入的页
BufAddr[0] = PageAddr;
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][0], PageAddr);
continue;
}
j += i;
// if (j >= PAGE_SIZE)
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
} //写入到Flash
WriteBuffToFlash(FlashDef[WRITE_FROM_BUF][CurBuf], BufAddr[CurBuf]);
}
Len -= i; //修改各数据指针
PageAddr += j/PAGE_SIZE;
j = j%PAGE_SIZE;
Data += i;
}
IO1CLR = DFWP;
}
/*
*函数性质:公共
*入口:无
*出口:FLASH容量,如果为4M位,则返回0
*功能:读取Flash容量。
*/
uint8 GetFlashSize(void)
{
uint8 i;
uint8 j;
i = (ReadFlashStuReg() & 0x3C);
for (j = 0; j < sizeof(FlashSizeAttr); j++)
{
if (i == FlashSizeAttr[j])
{
return j;
}
}
return 0xff; //读芯片出错,返回非法值。
}
/*
*函数性质:公共
*入口:无
*出口:无
*功能:整片擦除FLASH。
*/
void EraseAllFlash(void)
{
uint16 i;
// i = BlockSize[GetFlashSize()];
i =0x1000;
IO1SET = DFWP;
for (; i > 0; i--)
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
FlashBlockErase(i-1); //擦除块。
}
IO1CLR = DFWP;
}
/*
*函数性质:公共
*入口:无
*出口:无
*功能:初始化FLASH,将FLASH中的数据读入到缓冲中。
*/
void FlashMemIni(void)
{
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][0], 0);
while(!(ReadFlashStuReg() & FLASH_BUSY) )
{
CLRWATCHDOG();
}
ReadFlashToBuff(FlashDef[READ_TO_BUF][1], 1);
BufAddr[0] = 0;
BufAddr[1] = 1;
}
void CLRWATCHDOG(void)
{
IRQDisable();
WDFEED=0xaa;
WDFEED=0x55;
IRQEnable();
}
/********************************************************************************************************
** 函数名称:MSPI_Init()
** 函数功能:初始化SPI接口,设置为主机。
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
void SPI_Init(void)
{
PINSEL0 = (PINSEL0 & (~(0xFF << 8))) | (0x15 << 8) ;
S0PCCR = 0x16; // 设置SPI时钟分频
S0SPCR = (0 << 3) | // CPHA = 1, 数据在SCK 的第2个时钟沿采样
(1 << 4) | // CPOL = 1, SCK 为低有效
(1 << 5) | // MSTR = 1, SPI 处于主模式
(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(0 << 7); // SPIE = 0, SPI 中断被禁止
}
/********************************************************************************************************
** 函数名称:SPI_SendData()
** 函数功能:向SPI总线发送数据。
** 入口参数:data 待发送的数据
** 出口参数:返回值为读取的数据
********************************************************************************************************/
uint8 SPI_SendData(uint8 data)
{
S0PDR = data;
while( 0 == (S0SPSR & 0x80)); // 等待SPIF置位,即等待数据发送完毕
return(S0PDR);
}
/*
*函数性质:私有
*入口:待发送的数据缓冲Data,等发送的数据个数Len。
*出口:无
*功能:将缓冲中给定个数的数据移位输出到Flash
*/
void ShiftInData(uint8 *Data, uint16 Len)
{
while(Len--)
{
SPI_SendData(*Data);
Data++;
}
}
/*
*函数性质:私有
*入口:存放数据的缓冲Data, 需要读取的数据个数Len
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -