GD25Q32C FLASH DRV

/*******************************************************************************
* GD25Q32C  32 M-Bit 4M Byte 
* 
* 256 Byte One Page
* 
*******************************************************************************/
#include "DataType.h"
#include "McuSpiMem.h"
#include "mcuDrv.h"


#define CMD_RESET (INT8U)(0x99)
#define CMD_RESETEN (INT8U)(0x66)
#define  WREN_CMD                      (INT8U)(0x06)     //写使能命令 使WEL 位置1;
#define  ERASE_ALL_CMD                 (INT8U)(0xc7)     //擦除整片
#define  ERASE_SECTOR_CMD              (INT8U)(0x20)     //擦除一个扇区
#define  PAGE_WR_CMD                   (INT8U)(0x02)     //页写


#define  READ_ID_CMD                   (INT8U)(0x90)     //读manu id and device id




#define  FLASH_RD_CMD                  (INT8U)(0x03)
#define  STAREG_WT_CMD                 (INT8U)(0x01)     //写状态寄存器 
#define  STAREG_RD_CMD                 (INT8U)(0x05)     //读状态寄存器 
#define  STAREG_WREN_CMD                 (INT8U)(0x50)     //状态寄存器写使能
#define  ADDRESS_MAX                            0x3fffff
#define  READ_ID                        0x15




#define  OFFSET_64K                             1024 * 64 //64K偏移量,用于解锁
#define  START_ADDR                             0x00000000
#define  SECTOR_SIZE                            4096     //扇区大小
#define  PAGE_SIZE                              256      //页大小




void MEM_FlashInit(void);
void MEM_FlashChipErase(void);
void MEM_FlashRead(INT32U Addr,INT8U* pBuff,INT16U tNum);
void MEM_FlashWrite(INT32U Addr,INT8U* pBuff, INT16U tNum);
static void MEM_UnProtect(void);


static void Flash_WriteEn(void);
INT8U FLASH_ReadStatusRegister(void);
BOOL FLASH_WriteStatusRegister(INT8U cSta);




static INT8U Flash_Buff[SECTOR_SIZE]@0x20002000;
void MEM_FLASH_Test(void)
{
INT8U cConstBuf[16] = {
0x21,0x24,0x26,0x78,0x90,
                      0x22,0x34,0x56,0x78,0x90,
0x22,0x34,0x56,0x78,0x90,
0x11};

INT8U cBuff[16];
//MEM_FlashInit();


//MEM_FlashChipErase();
//MEM_UnProtect();

MEM_FlashRead(0x000000,cBuff,16);
MEM_FlashWrite(0x000000,cConstBuf,16);
MEM_FlashRead(0x000000,cBuff,16);


}




void MEM_FlashInit(void)
{
//Flash_4ByteModeSet();
//MEM_UnProtect();
INT8U staReg;
staReg = FLASH_ReadStatusRegister();
FLASH_WriteStatusRegister(0);
staReg = FLASH_ReadStatusRegister();


MEM_Check();




}
void Flash_SndCmd(INT8U cCmd)
{
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(&cCmd,1);
MCU_MemSPI_CS(IOHILO_HI);
}


/***********************************************************************
  函数名称:Flash_WriteEn
  函数功能:SPI写使能
  入口参数:无
  出口参数:无
 ************************************************************************/
static void Flash_WriteEn(void)
{
INT8U Cmd;

MCU_MemSPI_CS(IOHILO_LO);
Cmd = WREN_CMD;
MCU_MemSPI_Snd(&Cmd,1);
MCU_MemSPI_CS(IOHILO_HI);
}    


/**************************************************************************
  函数名称:FLASH_WaitForWriteEnd
  函数功能:读Flash芯片状态寄存器的值并且循环读取标志位直到写周期结束
  入口参数:无
  出口参数:无
 *************************************************************************/
static void FLASH_WaitForWriteEnd(void)
{
INT8U cBuff[4];
cBuff[0] = STAREG_RD_CMD;


MCU_MemSPI_CS(IOHILO_LO);


MCU_MemSPI_Snd(cBuff,1); //读取Flash 状态寄存器1


do
{
MCU_MemSPI_Rcv(cBuff,1); //读状态寄存器的数据;
}while ((cBuff[0] & 0x01) == 0x01); //若没有写完则一直等待,保持CS=0


MCU_MemSPI_CS(IOHILO_HI);


}


/*********************************************************************
  函数名称:Flash_ChipErase
  函数功能:整片擦除                  
 *********************************************************************/         
void MEM_FlashChipErase(void)
{
INT8U cCmdBuff[4];

Flash_WriteEn();


cCmdBuff[0] = ERASE_ALL_CMD;
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cCmdBuff,1);
MCU_MemSPI_CS(IOHILO_HI);


//等待擦除完成
FLASH_WaitForWriteEnd();
}




/************************************************************************
  函数名称:Flash_Sector_Erase
  函数功能:Flash的扇区擦除
  入口参数:@Sector_Num: 将要擦除的扇区号
 *************************************************************************/
void MEM_FlashEraseSector(INT16U Sector_Num)
{
INT8U  cSendCmd[8];
INT32U tWriteAddr;


tWriteAddr = Sector_Num * SECTOR_SIZE;


Flash_WriteEn();
 
cSendCmd[0] = ERASE_SECTOR_CMD;
cSendCmd[1] = (tWriteAddr & 0xff0000) >> 16;
cSendCmd[2] = (tWriteAddr & 0xff00) >> 8;
cSendCmd[3] = tWriteAddr & 0xff;


MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cSendCmd,4);
MCU_MemSPI_CS(IOHILO_HI);
 
FLASH_WaitForWriteEnd(); //等待擦除完成
}


/************************************************************************
  函数名称:Flash_PageWrite
  函数功能:Flash  页写
  入口参数:
  tBuf---------->待发数据指针
  tWriteAddr---->发送至Flash的地址(字节对齐)(4字节地址最大0X3FFFFF(即4M个字节))
  tNum---------->发送数据个数(最大256个)
 *************************************************************************/
static void Flash_PageWrite(INT8U* tBuf,INT32U tWriteAddr,INT16U tNum)
{
INT8U cSendCmd[8];

if (tWriteAddr > ADDRESS_MAX)
return ;


Flash_WriteEn();


cSendCmd[0] = PAGE_WR_CMD;


cSendCmd[1] = (tWriteAddr & 0xff0000) >> 16;
cSendCmd[2] = (tWriteAddr & 0xff00) >> 8;
cSendCmd[3] = tWriteAddr & 0xff;


MCU_MemSPI_CS(IOHILO_LO);


MCU_MemSPI_Snd(cSendCmd,4);
MCU_MemSPI_Snd(tBuf,tNum);


MCU_MemSPI_CS(IOHILO_HI);


FLASH_WaitForWriteEnd();   
}


/************************************************************************
  函数名称:Flash_Write_NoCheck
  函数功能:在指定地址开始写入指定长度的数据,但是要确保地址不越界! 具有自动换页功能 
  注意:在写之前先擦除将要写入的地址


  入口参数:
  tBuf---------->待发数据指针
  tWriteAddr---->发送至Flash的地址(4字节地址最大3FFFFF(即4M个字节))
  tNum---------->发送数据个数(65536)
  返回值:
 *************************************************************************/
static void Flash_Write_NoCheck(INT8U* pBuffer, INT32U WriteAddr, INT32U NumByteToWrite)   
{
INT16U Page_Remain;


Page_Remain = PAGE_SIZE - WriteAddr % PAGE_SIZE;   //计算当前页剩余字节数;
if (NumByteToWrite <= Page_Remain)
{
   Page_Remain = NumByteToWrite;  
}


while (1)
{
   Flash_PageWrite(pBuffer, WriteAddr, Page_Remain);  

   if (NumByteToWrite == Page_Remain)
   {
       break;   /*表示当前数据已经写完*/
   }
   else
   {
       pBuffer += Page_Remain;                   
       WriteAddr += Page_Remain; 
       NumByteToWrite -= Page_Remain; 
       if (NumByteToWrite > PAGE_SIZE)
       {
           Page_Remain = PAGE_SIZE;             //将写入数据大于256个
       }
       else
       {
           Page_Remain = NumByteToWrite;       //将写数据不足256个
       }
   }
}
}


/************************************************************************
  函数名称:Flash_Write
  函数功能:在指定地址开始写入指定长度的数据(该函数带擦除操作!);
  入口参数:
  pBuffer---------->数据缓冲区指针
  WriteAddr---->任意Flash地址,不用担心该地址处是否已经擦除
  NumByteToWrite---------->将写入到数据个数(最大65535即一个Block大小)
 *************************************************************************/


void MEM_FlashWrite(INT32U WriteAddr, INT8U *pBuffer, INT16U NumByteToWrite)   
{
    INT32U i;
    INT32U Sector_Addr;
    INT32U Sector_Num;   
    INT32U Sector_Offest;
    INT32U Sector_Remain;


    /*calculate the beginning address of the current sector*/
    Sector_Addr = (WriteAddr / SECTOR_SIZE) * SECTOR_SIZE;   
    /*calculate the Sector number according to the WriteAddr*/
    Sector_Num = WriteAddr / SECTOR_SIZE;
    /*calculate the offest number of the sector*/
    Sector_Offest = WriteAddr % SECTOR_SIZE;
    /*calculate the remain of the sector*/
    Sector_Remain = SECTOR_SIZE - Sector_Offest;


    if (NumByteToWrite <= Sector_Remain)  
        Sector_Remain = NumByteToWrite;
    while (1)
    {
        /*copy the data writen previously into the sector to Flash_Buff*/
        MEM_FlashRead(Sector_Addr, Flash_Buff, SECTOR_SIZE);
        for(i = 0; i < Sector_Remain; i++) 
        {
            if (Flash_Buff[Sector_Offest + i] != 0xFF) break;   //表明需要擦除 
        
        }
        if(i < Sector_Remain) 
        {
            /*erase the Sector_Num*/
            MEM_FlashEraseSector(Sector_Num);  
           
            for(i = 0; i < Sector_Remain; i++)
                Flash_Buff[Sector_Offest + i] = pBuffer[i];
            /*write the data including previous data and the portion of new input data into the whole sector*/
            Flash_Write_NoCheck(Flash_Buff, Sector_Addr, SECTOR_SIZE);
        }
        else 
        {
            Flash_Write_NoCheck(pBuffer, WriteAddr, Sector_Remain);
        }


        if (NumByteToWrite == Sector_Remain)
            break; 
        else
        {
            Sector_Addr += SECTOR_SIZE;
            Sector_Num++;       //下一个扇区号
            Sector_Offest = 0; 
            pBuffer += Sector_Remain;
            NumByteToWrite -=Sector_Remain; 
            Sector_Remain = SECTOR_SIZE;  //默认写入4096个字节
            if (NumByteToWrite < SECTOR_SIZE) Sector_Remain = NumByteToWrite;  //当此次写入的数据不足一个扇区大小时。
        }


    }


}


/************************************************************************
  函数名称:Flash_Read
  函数功能:在整个Flash 范围内读取任意指定的地址开始处的数据
  入口参数:
  pBuf---------->接收数据缓冲区指针
  tWriteAddr---->读取的Flash地址
  tNum---------->读取数据个数
 *************************************************************************/
void MEM_FlashRead(INT32U tReadAddr, INT8U* pBuf, INT16U tNum)
{
INT8U   cSend[8];


cSend[0] = FLASH_RD_CMD;


cSend[1] = (tReadAddr & 0xff0000) >> 16;
cSend[2] = (tReadAddr & 0xff00) >> 8;
cSend[3] = tReadAddr & 0xff;


MCU_MemSPI_CS(IOHILO_LO);


MCU_MemSPI_Snd(cSend,4);


MCU_MemSPI_Rcv(pBuf, tNum);


MCU_MemSPI_CS(IOHILO_HI);


}




int MEM_Check(void)
{
INT8U  cBuff[8];
INT32U cError=0;


cError = 0;
cBuff[0] = READ_ID_CMD;
cBuff[1] = 0;
cBuff[2] = 0;
cBuff[3] = 0;


MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 4);
MCU_MemSPI_Rcv(cBuff,2);
MCU_MemSPI_CS(IOHILO_HI);


if(0xc8 !=cBuff[0])
{
cError = 1;
}
else
{
if(READ_ID!=cBuff[1])
{
cError = 2;
}
}
    return cError;
}




/*关闭写独立扇区/块保护*/
static void MEM_UnProtect(void)
{
INT8U cBuff[4];
INT8U  status;


do {
cBuff[0] = STAREG_RD_CMD;
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 1);
MCU_MemSPI_Rcv(&status,1);
MCU_MemSPI_CS(IOHILO_HI);


if ((status & (0x18))  == (0x18))
{
return ;
}


Flash_WriteEn();     


cBuff[0] = STAREG_WT_CMD;
cBuff[1] = (status|0x18);


MCU_MemSPI_CS(IOHILO_LO); 
MCU_MemSPI_Snd(cBuff,2);
MCU_MemSPI_CS(IOHILO_HI);
   }while (1);
}












INT8U FLASH_ReadStatusRegister(void)
{
INT8U  cBuff[4];


cBuff[0] = STAREG_RD_CMD;


MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 1);
MCU_MemSPI_Rcv(cBuff,1);
MCU_MemSPI_CS(IOHILO_HI);


return cBuff[0];
}


BOOL FLASH_WriteStatusRegister(INT8U cSta)
{
INT8U  cBuff[4];


cBuff[0] = STAREG_WREN_CMD;
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 1);
MCU_MemSPI_CS(IOHILO_HI);


    Flash_WriteEn();


cBuff[0] = STAREG_WT_CMD;
cBuff[1] = cSta;
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 2);
MCU_MemSPI_CS(IOHILO_HI);
return TRUE;


}


INT8U FLASH_IsBusy(void)
{
INT8U cBuff[4];
INT8U timeOutCnt = 0;




cBuff[0] = STAREG_RD_CMD;


MCU_MemSPI_CS(IOHILO_LO);


MCU_MemSPI_Snd(cBuff,1); //读取Flash 状态寄存器1


do
{
MCU_MemSPI_Rcv(cBuff,1); //读状态寄存器的数据;
if(++timeOutCnt >= 8)
{
break;
}
}while ((cBuff[0] & 0x01) == 0x01); //若没有写完则一直等待,保持CS=0


MCU_MemSPI_CS(IOHILO_HI);
if(timeOutCnt >= 8)
{
return 1;
}
return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
gd32c10x_dfp是GigaDevice公司开发的一款支持GD32C1系列微控制器的设备支持包。GD32C1系列微控制器是基于ARM Cortex-M3内核设计的,集成多种外设功能,适用于各种应用领域。 gd32c10x_dfp提供了一系列的软件库和驱动程序,方便开发人员在GD32C1系列微控制器上进行快速开发。它包括了各种外设的驱动程序、中间件和各种实用工具,可以简化开发人员在这些芯片上的开发过程。 gd32c10x_dfp的特点包括: 1. 集成了丰富的外设驱动程序,如UART、SPI、I2C、ADC、DAC等,可以轻松配置和使用这些外设功能。 2. 提供了自动生成的硬件抽象层(HAL),简化了底层驱动程序的开发过程,提高了代码的可移植性。 3. 提供了实用的中间件库,如文件系统、USB来离线下载/在线升级等,方便开发各种应用。 4. 支持多种集成开发环境(IDE),如Keil、IAR和GCC等,开发人员可以选择适合自己的开发环境。 5. 提供了丰富的例程和示例代码,方便开发人员学习和参考。 6. 兼容标准的Cortex-M3体系结构,可以与其他Cortex-M3兼容的设备进行互操作。 总之,gd32c10x_dfp是一个集成了丰富的软件库和驱动程序的设备支持包,可以帮助开发人员快速开发基于GD32C1系列微控制器的应用。它具有易于使用、可移植性好、功能丰富等优点,在嵌入式系统开发中具有很高的实用性和价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缥缈孤鸿_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值