📄 复件 flash.c.bak
字号:
/******************文件名 upsd_flash.c**********************
*马斌 05/10/28
*修改 05/10/30
* 05/10/31 在底层函数 擦除,读写中增加清零看门狗和延时 OSTimeDly(3); // now delay 3 msec per dat sheet
*修改 05/11/11 加锁
**************说明********************
*(1) 先初始化置位Sector_Status为UNUSED,为了以后扩充flash状态定义为字节型.
*(2) 对flash的读写擦除操作都只有当Sector_Status为UNUSE时能够执行,并将置位Sector_Status为USED,
* 操作完毕置位Sector_Status为UNUSED,释放flash .(可考虑用ucos的信号量,研究中.....)
* 也就是说对flash的操作是完全占有式.
*(3) 本模块是在以下前提下编写:
* 对用户而言仅仅只有一个256k大小的flash存储器 ,可在0x0000 0000 --->0x003F FFFF 内随意读写,
* 但,读写不能同时发生.
* 从0地址开始写,当所给地址是0x8000(32k)的倍数时,说明要写下一个扇区,此时擦除改扇区后再写.
*(4) 初始化时没必要擦除flash,只要置位Sector_Status为UNUSED表示flash闲置既可.因为如果按照正规
* 的写法从0开始写,一旦发现所给地址是扇区的第一个地址会自动擦除该扇区.
**************缺点************************
*(1) 写的时候不能读:ucos采用抢占式优先,当有任务中正在采集数据,写flash的时候其它任务等待.
* 按说应该是当分配的时间片用完就要转到次优先级任务,但是当我测试一次写64k的数据时待等待了
* 近30秒,才执行下一任务.测试写入1k时,不受影响.
*(2) 擦除的时候不能读. 比如擦除0扇区的时候,不能读扇区1的内容.
**************************************************************/
#include "includes.h"
extern PSD_REGS PSD8xx_reg _at_ 0x8000;
unsigned char MemLock; //锁只加到用户API上
/***************************API**********************/
void init_flash(void)reentrant
{
MemLock = UNUSED;
}
/***************************************************************
函数名: ycc_mem_read
功能描述: 从flash存储器中的指定位置读取指定长度的字节
参数 : buf 数据缓冲区地址
len 要读取的数据数目
pos flash的相对地址
注意: 该函数面向用户,flash的内部操作通过该函数对用户透明
说明 : 成功返回1,失败返回0
**************************************************************/
unsigned char ycc_mem_read(unsigned int *buf, int len,unsigned long pos)reentrant
{
unsigned long Input_flash_addr;
unsigned int xdata * Real_Flash_Addr; //扇区绝对地址
if(pos<0||pos>=0x40000) return(0); //判断越界
Input_flash_addr = pos; //由flash状态判断
FlashLock();
//选择扇区 0~~7
switch(Input_flash_addr/0x8000)
{
case 0 :PSD8xx_reg.PAGE = SECTOR_0;
// Input_Flash_Addr -= 0 ;
break;
case 1 :PSD8xx_reg.PAGE = SECTOR_1;
Input_flash_addr -= 0x8000;
break;
case 2 :PSD8xx_reg.PAGE = SECTOR_2;
Input_flash_addr -= 0x10000;
break;
case 3 :PSD8xx_reg.PAGE = SECTOR_3;
Input_flash_addr -= 0x18000;
break;
case 4 :PSD8xx_reg.PAGE = SECTOR_4;
Input_flash_addr -= 0x20000;
break;
case 5 :PSD8xx_reg.PAGE = SECTOR_5;
Input_flash_addr -= 0x28000;
break;
case 6 :PSD8xx_reg.PAGE = SECTOR_6;
Input_flash_addr -= 0x30000;
break;
case 7 :PSD8xx_reg.PAGE = SECTOR_7;
Input_flash_addr -= 0x38000;
break;
default :
; //越界
break;
}
//获得flash存储器的绝对地址
Real_Flash_Addr = SECTOR_BASE_ADDRESS + (unsigned int)Input_flash_addr;
//检查所在扇区
Move_from_flash ( Real_Flash_Addr,buf, len); //从flash中读数据到缓冲区
FlashUnLock();
return(1);
}
/***************************************************************
函数名: ycc_mem_write
功能描述: 向flash存储器中的相对位置写入指定长度的字节
参数 : buf 数据缓冲区地址
len 要写入的数据数目
pos flash的相对地址
注意: 该函数面向用户,flash的内部操作通过该函数对用户透明
说明 : 成功返回1,失败返回0
**************************************************************/
unsigned char ycc_mem_write(unsigned char *buf, int len,unsigned long pos)reentrant
{
// unsigned long Input_Flash_Addr;
unsigned int xdata * Real_Flash_Addr; //扇区绝对地址
if(pos<0||pos>=0x40000) return(0); //判断越界
FlashLock();
switch(pos/0x8000) //选择扇区 0~~7
{
case 0 :PSD8xx_reg.PAGE = SECTOR_0;
// Input_Flash_Addr -= 0 ;
break;
case 1 :PSD8xx_reg.PAGE = SECTOR_1;
pos -= 0x8000;
break;
case 2 :PSD8xx_reg.PAGE = SECTOR_2;
pos -= 0x10000;
break;
case 3 :PSD8xx_reg.PAGE = SECTOR_3;
pos -= 0x18000;
break;
case 4 :PSD8xx_reg.PAGE = SECTOR_4;
pos -= 0x20000;
break;
case 5 :PSD8xx_reg.PAGE = SECTOR_5;
pos -= 0x28000;
break;
case 6 :PSD8xx_reg.PAGE = SECTOR_6;
pos -= 0x30000;
break;
case 7 :PSD8xx_reg.PAGE = SECTOR_7;
pos -= 0x38000;
break;
default :
; //越界
break;
}
//获得flash存储器的绝对地址
Real_Flash_Addr = SECTOR_BASE_ADDRESS + (unsigned int)pos ;
//检查所在扇区,如果绝对地址在扇区开始的位置,则先擦除扇区.
if( Real_Flash_Addr == SECTOR_BASE_ADDRESS) flash_erase_sector(Real_Flash_Addr);
Move_to_flash( buf,Real_Flash_Addr, len) ; //把缓冲区的数据编程到flash中
FlashUnLock();
}
/***********************底层函数****************************/
/***************************************************************
函数名: flash_write_with_poll
功能描述: 在flash中写入一个字节,用数据轮询方式
参数 : volatile unsigned char xdata* addr 待写入字节的位置
unsigned char dat 待写入的字节
注意: 传入的地址应该和flash存储器的分页关系无关,否则,在调用该函数前,应给PSD中页寄存器赋正确的值.
成功返回1,失败返回0.
**************************************************************/
unsigned char flash_write_with_poll(volatile unsigned char xdata* addr, unsigned char dat)reentrant
{
unsigned char done;
unsigned char error;
unsigned char err;
unsigned char poll;
done = FALSE;
err = FALSE;
EA = 0;
*(FLASH_COMMON_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(FLASH_COMMON_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(FLASH_COMMON_X555) = 0xA0; // write 0xA0 command to program
EA =1;
*(addr) = dat; // write byte to flash
dat = dat & NVM_DATA_POLL; // get bit DQ7 of original dat
do // now use dat polling method to verify successful write
{
poll = *(addr); // Read the location that was just programmed
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (dat == poll) // compare DQ7
done = TRUE; // dat byte programmed into flash OK,
// indicate successful exit criteria
else if (error == NVM_ERROR ) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while((done == FALSE) && (err == FALSE));
if (err == TRUE) // make sure timeout error and dat poll didn't
// occur simultaneously
{
poll = *(addr); // Read location in flash again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (dat == poll) // compare DQ7
done = TRUE; // dat byte programmed into flash OK at the same
// time timout error occured, indicate successful
// exit criteria
*(FLASH_COMMON_X555) = 0xF0; // reset the flash array (short reset instruction)
// OSTimeDly(3); // 不用延时似乎也没问题
}
return(done); // a successful flash write returns 1, timeout error returns 0
}
/***************************************************************
函数名: flash_erase_bulk
功能描述: 擦除整个主flash所有扇区
参数 : volatile unsigned char xdata* flash_bulk_erase_address 该地址
位于任何一个具有片选信号的flash段中
注意: 传入的地址应该和flash存储器的分页关系无关,否则,在调用该函数前,应给PSD中页寄存器赋正确的值.
**************************************************************/
unsigned char flash_erase_bulk(
volatile unsigned char xdata* flash_bulk_erase_address)reentrant
{
unsigned char done;
unsigned char poll;
unsigned char error;
unsigned char err;
WDRST = 0x00; //清零看门狗
done = FALSE;
err = FALSE;
// Note: the following constants (FLASH_COMMON_XXXX)
// are declared type volatile in the header file
// so they are not optimized away by the compiler
EA = 0;
*(FLASH_COMMON_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(FLASH_COMMON_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(FLASH_COMMON_X555) = 0x80; // write 0x80 command to erase entire chip
*(FLASH_COMMON_X555) = 0xAA; // continue unlock sequence
*(FLASH_COMMON_XAAA) = 0x55; // continue unlock sequence
*(FLASH_COMMON_X555) = 0x10; // write 0x10 command to complete erase command
EA = 1;
do // now use dat polling method to verify successful erase
{
poll = *(flash_bulk_erase_address); // read flash status from any address
// within the defined flash address space
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // look at D7
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // bulk erase OK,
// indicate successful exit criteria
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while((done == FALSE) && (err == FALSE));
if (err == TRUE) // make sure timeout error and dat poll didn't
// occur simultaneously
{
poll = *(flash_bulk_erase_address); // Read flash status again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // the flash erased OK at the same
// time timout error occured, indicate successful
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -