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

📄 flash.c

📁 基于HMS7202的波形发生器源程序
💻 C
字号:
#include "hms7202lib.h"
#include "flash.h"

/****************************************************************/
/*           constant define
***************************************************************/
#define  FLASH_CMD_ID         0x90
#define  FLASH_CMD_READ       0xFFFFFFFF
#define  FLASH_CMD_READ_STAT  0x70707070
#define  FLASH_STAT_OK        0x00800080
#define  FLASH_CMD_CLEAR_STAT 0x50505050
#define  FLASH_CMD_BLOCK_ERASE   0x20202020
#define  FLASH_CMD_CONFM         0xD0D0D0D0
#define  FLASH_CMD_WORD_PRM   0x40404040
#define  FLASH_CMD_CLBLB      0x60606060

#define  BLOCKSIZE    0x20000
#define  BANKSIZE     0x04000000
#define  BANKMASK     0xFC000000  //64MB for each bank
#define  BLOCKMASK    0xFFFE0000    //128KB for each block

/*#define  BLOCKSIZE    0x40000
#define  BANKSIZE     0x04000000
#define  BANKMASK     0xFC000000  //64MB for each bank
#define  BLOCKMASK    0xFFFC0000    //256KB for each block(2 flash chip)*/

#define  FAIL  0x0
#define  OK    0x1

/***************************************************************/
/*        获取flash的厂家ID和设备ID
          先获取flash的开始地址,然后在这地址上写读ID命令
          等待1ms后读取厂家ID(开始地址处的内容)和设备ID(开始地址+1处的内容)
*****************************************************************/
static int flash_get_ID(int addr,int *vendorID,int *devID)
{
    int chip_base;
    chip_base = addr & BANKMASK;
    
    *((char *)chip_base)=FLASH_CMD_ID;//读ID命令字
    delay(10);
    
    *vendorID = *((int *)(chip_base)) & 0xff;
    *devID = *((int *)(chip_base+0x2)) & 0xff;
    
    return OK;
}

/***********************************************************/
/* 函数功能  读取flash中的内容
   输入参数  addr:flash开始地址,des目的指针,size欲读取字节数
   返回值  若读取成功,返回OK,否则,返回FAIL      
************************************************************/
static int  flash_readarry(int addr,char *des,int size)
{
    int i=0;
    volatile unsigned int *p = (volatile unsigned int *)addr;
    char *psrc = (char *)addr;
    char *pdes = des;
    if(addr < FLASH_BASE || addr > FLASH_LIMIT)
    {
        ser_printf("\n0x%x is not a valid address",addr);
        return FAIL;//not valid address
    }
    *p = FLASH_CMD_READ;//read arry mode
    while(i<size)
    {
        *pdes++ = *psrc++;
        i++;
    }
    return OK;
}

/*************************************************************/
/*       确认当前块已解锁,若未解锁则解锁,若已解锁则返回OK
**************************************************************/
static int isunlock(int addr)
{
    int statvalue;
    volatile int *p,*pstat;
    p = (volatile int *)addr;
    pstat = (volatile int *)addr;
    
    //分析块是否已锁
    *p = FLASH_CMD_READ_STAT;//进入读状态寄存器模式
    statvalue = *p;//读取状态寄存器的值
    if(statvalue & 0x10001)//块被锁
    {
        while(*pstat & 0x00c400c4 !=0x00800080);//SR7!=1 | SR6!=0 | SR2!=0
        *p = FLASH_CMD_CLBLB;
        *p = FLASH_CMD_CONFM;//解锁
        while(*pstat & FLASH_STAT_OK !=FLASH_STAT_OK);//等待解锁完成
        if(*pstat & 0x00200020) //解锁出错
        {
            *p = FLASH_CMD_CLEAR_STAT;//清状态寄存器
            ser_printf("\nUnlock block fail. Address: 0x%x",p);
            return FAIL;
        }
        return OK;//解锁成功
    }
    return OK;//未被锁
}
/************************************************************/
/*         等待设备某操作结束
         先进入读状态寄存器模式,然后读取状态寄存器的值
          根据状态寄存器值来判断操作是否已结束
*************************************************************/
static int flash_wait()
{
    volatile int status;
    *(volatile int *)(0x00000000) = FLASH_CMD_READ_STAT;
    do 
    {
	status = *(volatile int *)(0x00000000);
    } while(status != FLASH_STAT_OK);
}

/**********************************************************/
/*             清除状态寄存器
***********************************************************/
static int flash_clr_status()
{
    *(volatile unsigned int *)(0x00000000) = FLASH_CMD_CLEAR_STAT;
}
/*********************************************************/
/*               擦除块,一次只能擦除一个块
输入参数block_base,块基地址,128K字节对齐
************************************************************/
static int flash_block_erase(int block_base)
{
    volatile int *pstat,*pblock,*p;
    pblock = (volatile int *)block_base;
    pstat = (volatile int *)block_base;
    p     = (volatile int *)block_base;
    int i;
    
    
    if(isunlock(block_base) == FAIL) return FAIL;
    
    *pblock = FLASH_CMD_BLOCK_ERASE;
    *pblock = FLASH_CMD_CONFM;
    while(*pstat & FLASH_STAT_OK != FLASH_STAT_OK);//等待块擦除结束
    i = *pstat;
    if(*pstat & 0x00200020) //说明擦除操作出错
    {
        *p = FLASH_CMD_CLEAR_STAT;//清状态寄存器
        ser_printf("\nBlock erase fail. Address: 0x%x",pblock);
        return FAIL;
    }    
    return OK;
}

/**************************************************************/
/*   片擦除
  输入参数block_base,片擦除开始地址,128K字节对齐;block_num,欲擦除的块数
***************************************************************/
int flash_chip_erase(int addr, int block_num)
{
    int i,block_base;
    block_base = addr & BLOCKMASK;
    for(i=0;i<block_num;i++)
    {
        if(flash_block_erase(block_base) == FAIL) return FAIL;
        block_base += BLOCKSIZE;
    }
    return OK;
}

/************************************************************/
/*           片字编程
输入参数  base_addr,开始地址;pData,数据指针;data_size,数据大小,以字为单位
*************************************************************/
int flash_word_pgm(int base_addr, int* pData, int data_size)
{
    int i,addr,block_num;
    volatile int *p,*pstatvalue;
    volatile int *pdes;
    addr = base_addr;
    pstatvalue = (volatile int *)base_addr;
    pdes = (int *)base_addr;
    block_num = (((base_addr+data_size*4) & BLOCKMASK)-(base_addr & BLOCKMASK))/0x20000+1;
    //先判断所用的块是否已解锁
    for(i=0;i<block_num;i++)
    {
      if(isunlock(addr) == FAIL) return FAIL;
      addr +=BLOCKSIZE;
    }
    //进行字编程
    
    for(i=0;i<data_size;i++)
    {
        p = (volatile int *)(base_addr + i);
        pstatvalue = p;
        *p = FLASH_CMD_WORD_PRM;
        *pdes++ = *pData++;
        delay(100);
        *p = FLASH_CMD_READ_STAT;
        delay(100);
        while(*pstatvalue & FLASH_STAT_OK != FLASH_STAT_OK);//等待编程操作结束
        if(*pstatvalue & 0xfffefffe != FLASH_STAT_OK)
        {
            ser_printf("\nProgram fail.  Address: 0x%x",pdes-1);
            return FAIL;
        } 
    }
    //进行字节校验
    *((volatile int *)addr) = FLASH_CMD_READ;
    
    for(i=data_size;i>0;i--)
    {
      if(*--pdes !=*--pData)
      {
          ser_printf("\nVerify error. Address: 0x%x",pdes);
          return FAIL;
      }
    }
    return OK;
    
}


/*****************************************************************/
/*                     片编程
输入参数 addr开始地址;pData数据指针;data_size数据字节数
***************************************************************/
/*int flash_pgm(int addr, char* pData, int data_size)
{
    char block_data[128*1024];//block data
    volatile int status;
    int base_addr,block_addr,length;
    int i,j,block_num;
    short *pSrc;
    short *pDest;
    base_addr = (addr & BANKMASK);//屏蔽基地址低25位,即取基地址对应的flash开始地址


	// count sector number 
	block_num = (((addr+data_size) & BLOCKMASK) - (addr & BLOCKMASK))/0x20000+1;
	
	// erase each sector 
	block_addr = addr & BLOCKMASK;
	for( i = 0 ; i < block_num ; i++ )
	{
		block_addr = block_addr + i*0x20000;
		// read data from block 
		for( j = 0 ; j < 32*1024 ; j++ )
			((long *)block_data)[j] = ((long *)block_addr)[j];//将block_data[128*1024]的基地址和块开始地址对齐
		if( i == 0 )//第0个块
		{
			// copy length 
			length = 128*1024-(addr-block_addr);
			length = (length < data_size)? length : data_size;
			// copy target data to temp data 
			
			for( j = 0 ; j < length ; j++ )
			{
				block_data[addr-block_addr+j] = pData[j];
			}
		}
		else if( i == (block_num - 1) )//最后一个块
		{
			length = (addr+data_size) - block_addr;
			for( j = 0 ; j < length ; j++ )
			{
				block_data[j] = pData[data_size-length+j];
			}
		}
		else
		{
			for( j = 0 ; j < 128*1024 ; j++ )
			{
				block_data[j] = pData[block_addr-addr+j];
			}
		}
		// erase block 
		if(flash_block_erase(block_addr)==FAIL)  return FAIL;
		// write data to sector 
		pDest = (short *)block_addr;
		pSrc = (short *)block_data;
		for( j = 0 ; j < 64*1024 ; j++ )
		{
		    *((volatile int *)(base_addr)) = FLASH_CMD_WORD_PRM;
		    pDest[j] = pSrc[j];
		    //*(volatile int *)(0x00000000) = FLASH_CMD_READ_STAT;//进入读状态模式
           do 
           {   
               status = *(volatile int *)(0x00000000);
           } while(status & FLASH_STAT_OK != FLASH_STAT_OK);//等待字编程结束
           if(status&0x08 != 0x0 ) return FAIL;

		    // check data 
		    if( pDest[j] != pSrc[j] )
		    {
		    	ser_printf("\nwrite address %x error!\n",block_addr+j*2);
		    	return FAIL;
		    }
		}
	}
	
	return OK;
}*/


/****************************************************************/
/*               flash测试函数
****************************************************************/
void flash_test()
{
    char data[256];
    int i,vendorID,devID;
    
    flash_get_ID(0x00000002,&vendorID,&devID);
    ser_printf("\nvendor ID: 0x%x  dev ID: 0x%x",vendorID,devID);
    flash_readarry(0x00000000,data,256);
    for(i=0;i<256;i++)
    data[i] = i;
    flash_chip_erase(0x00000000,1);
    delay(10000);
    
    /*for(i=0;i<4;i++)
    {
    *((volatile int *)0x000a0000) = FLASH_CMD_WORD_PRM;
    *((volatile int *)0x000a0000+i) = 0x55+i;
    //delay(100);
    }*/
    flash_word_pgm(0x00000000,(int *)data,64);
    
    
    //flash_pgm(0x00001000,data,0x256);
    
    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -