⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 写XS128的D-Flash的三个程序案例
💻 C
📖 第 1 页 / 共 2 页
字号:
//[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 + -