?? flash.c
字號:
//[Flash.c]Flash擦寫-------------------------------------------------------*
//本文件包含: *
// (1)Flash_Erase_Sector:擦除一個指定的扇區 *
// (2)Flash_Write_Nword:向一個指定的區域寫入若干個字 *
// (3)Flash_unsecured:使用后門機制解除Flash的安全狀態 *
// (4)Flash_SetKey:設置后門鑰匙 *
// (5)Flash_SetStatus:設置Flash的安全狀態 *
//-------------------------------------------------------------------------*
//頭文件
#include "Flash.h" //Flash擦寫頭文件
//內部調用函數聲明
void Erase_Write_Pretreat(uchar page); //擦寫子函數內部調用的函數聲明
//頁所對應的塊對照表
//兩個flash塊,每塊4頁 flash0 flash1
const uchar pagetable[2][4] = {{0x3C,0x3D,0x3E,0x3F},{0x38,0x39,0x3A,0x3B}};
//由于在Flash擦寫時會在Flash區產生高壓,造成擦寫不穩定,本工程把在高壓時執行
//的程序轉換成機器碼存放在RAM區,在執行擦寫操作時,執行RAM區0的機器碼,
//擦寫操作穩定,該機器碼存放在下面數組中,其中'0x3D'是'RTS'的機器碼
const uchar P[18] = {0x18,0x0B,0x80,0x01,0x05,0xF6,0x01,0x05,0x87,
0x87,0xC4,0x40,0x8C,0x00,0x00,0x27,0xF4,0x0A};
//FSTAT=0x80;
//while(!(FSTAT&0x80));
uchar PrgOfRam[18]; /*存放RAM區執行的的機器碼 */
void PrgToRAM(void)
{
uchar i=0x00;
for (i=0; i<18; i++)
PrgOfRam[i] = P[i];
}
//Flash_Erase_Sector:擦除指定的扇區----------------------------------------*
//功 能:對頁號為page,扇區首地址為addr的一個扇區進行擦除 *
//參 數:page--頁映射地址(0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F) *
// addr--扇區首地址(偶數) *
//返 回:無 *
//注 意:調用該函數之前,必須確定要擦除的區域可擦除 *
//-------------------------------------------------------------------------*
void Flash_Erase_Sector(uchar page,uint addr)
{
//1 判斷是否已分頻、清相關錯誤標志、根據頁號選擇相應的flash塊
//2 向要擦除的扇區首地址寫任意值(注意:經實驗證實,不可以寫0x0000)
//3 向命令寄存器寫扇區擦除命令
//4 在加高壓期間,調用RAM區的機器碼,相當于兩條語句:
// FSTAT=0x08;
// while(!(FSTAT&0x40));
Erase_Write_Pretreat(page); //擦寫子函數共同調用的內部子函數
*(uint *)addr = 0xFFFF;
FCMD = 0x40;
_asm("CALL PrgOfRam");
}
//-------------------------------------------------------------------------*
//Flash_Write_Nword:向指定的扇區寫入若干個字-------------------------------*
//功 能:將從address_source開始的len個字,寫入頁號為 page,起始地址為 *
// address_destination的扇區 *
//參 數:page--頁映射地址(0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F) *
// address_destination--目標扇區首地址(偶數) *
// address_source--源地址 *
// len--字節數 *
//返 回:無 *
//注 意:調用該函數之前,必須確定要寫入的區域可寫入 *
//-------------------------------------------------------------------------*
void Flash_Write_Nword(uchar page,uint address_destination,
uint address_source,uint len)
{
//1 判斷是否已分頻、清相關錯誤標志、根據頁號選擇相應的flash塊
//2 寫入若干個字
// (1)將源地址的一個字寫入目標地址
// (2)向命令寄存器寫字寫入命令
// (3)在加高壓期間,調用RAM區的機器碼,相當于兩條語句:
// FSTAT=0x08;
// while(!(FSTAT&0x40));
// (4)源地址和目標地址同時向后移一個字
uint m;
Erase_Write_Pretreat(page); //擦寫子函數共同調用的內部子函數
PPAGE = page; //設置頁寄存器
for (m=0; m<len; m++)
{
*(uint *)address_destination = *(uint *)address_source;
FCMD = 0x20;
asm("CALL PrgOfRam");
address_destination = address_destination+2;
address_source = address_source+2;
}
}
//-------------------------------------------------------------------------*
//Flash_Erase_Nsector:擦除多個扇區-----------------------------------------*
//功 能:以len個字為依據計算所需擦除的扇區量 *
//參 數:page--頁映射地址(0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F) *
// address_destination--目標扇區首地址(偶數) *
// len--字節數 *
//返 回:無 *
//注 意:此函數可擦除多扇區(一頁),但須保證最后一個字不 *
// 能超出指定頁,即地址不能大于0xBFFE * *
//-------------------------------------------------------------------------*
void Flash_Erase_Nsector(uchar page,uint address_destination,uint len)
{
//1 判斷是否已分頻、清相關錯誤標志、根據頁號選擇相應的flash塊
//2 計算要存儲數據所占用地址的扇區量
//3 擦除扇區
uchar Fi,Fn;
Erase_Write_Pretreat(page);
if(len%256==0)
Fn=len/256;
else
Fn=len/256+1;
if(Fn==0) return;
for(Fi=0x00;Fi<Fn;Fi++)
{
Flash_Erase_Sector(page,(address_destination+512*Fi));
}
}
//-------------------------------------------------------------------------*
//Erase_Write_Pretreat:開始擦除或寫入前的公共操作序列子函數----------------*
//功 能:判斷是否已分頻;清相關錯誤標志;根據頁號選擇相應的flash塊;如果頁號不*
// 為0,則設置PPAGE寄存器 *
//參 數:page--頁映射地址(0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F) *
//返 回:無 *
//-------------------------------------------------------------------------*
void Erase_Write_Pretreat(uchar page)
{
//1 判斷是否設置時鐘分頻,若無分頻,則先分頻
//2 清保護錯誤和訪問錯誤標志位
//3 查表、選擇塊號
uchar i,j;
if ((FCLKDIV&0x80) == 0)
FCLKDIV |= 0x4A; //設置分頻系數
FCNFG |= 0x01; //FCNFG的第0位置1,選擇BLOCK1
FSTAT |= 0x30; //清保護錯誤和訪問錯誤標志位
FCNFG &= 0xFE; //FCNFG的第0位置0,選擇BLOCK0
FSTAT |= 0x30; //清保護錯誤和訪問錯誤標志位
if (page != 0)
{
for (i = 0;i < 2;i++)
{
for (j = 0;j < 4;j++)
{
if (page == pagetable[i][j])
break;
}
if (j < 4)
break;
}
if (i == 0) FCNFG &= 0xFE; //頁號3C~3F,選擇BLOCK0
if (i == 1) FCNFG |= 0x01; //頁號38~3B,選擇BLOCK1
}
PPAGE=page;
}
//-------------------------------------------------------------------------*
//Flash_Read_Sector:讀指定Flash地址中的內容--------------------------------*
//功 能:讀取指定頁號為page,首地址為addr的連續len個字節,寫入到ch[]數組中 *
//參 數:page--頁映射地址(0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F) *
// addr--源目標首地址 *
// ch[]--目標首地址 *
// len --字節個數 *
//返 回:無 *
//注 意:FLASH存儲區的兩個字節表示一個字 *
//-------------------------------------------------------------------------*
void Flash_Read_Sector(uchar page,uint addr,uint ch[],uint len)
{
uint m;
uchar i,j;
if (page != 0)
{
for (i = 0;i < 2;i++)
{
for (j = 0;j < 4;j++)
{
if (page == pagetable[i][j])
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -