GD32F103单片机内部FLASH按字写入驱动

5 篇文章 2 订阅
这段代码提供了GD32微控制器的Flash内存管理函数,包括读取、写入和擦除操作。GDFLASH_Write_Words函数确保了数据按页写入,并在写入前检查是否需要擦除扇区。GDFLASH_Read_Words用于读取多个字的数据,而GDFLASH_ReadWord则读取单个字。这些函数对于固件更新和数据存储至关重要。
摘要由CSDN通过智能技术生成

.c部分代码

#include "gd32_flash_word.h"
static uint32_t GDFLASH_BUF_WORD [GD_SECTOR_SIZE / 4 ];//最多是2K字节

/**
  * 函数功能: 读取指定地址的字(32位数据)
  * 输入参数: faddr:读地址(此地址必须为4的倍数!!)
  * 返 回 值: 返回值:对应数据.
  * 说    明:无
  */
uint32_t GDFLASH_ReadWord (uint32_t faddr)
{
	return *(__IO uint32_t*)faddr; 
}

  
/**
  * 函数功能: FLASH写入字
  * 输入参数: WriteAddr:起始地址
  *           pBuffer:数据指针
  *           NumToWrite:字(32位)数
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Write_Word( uint32_t WriteAddr, uint32_t * pBuffer, uint16_t NumToWrite )   
{ 			 		 
	uint16_t i;	
	for(i=0;i<NumToWrite;i++)
	{
		fmc_word_program(WriteAddr,pBuffer[i]);
	  WriteAddr += 4;           //地址增加4
	}  
} 

/**
  * 函数功能: 从指定地址开始写入指定长度的数据
  * 输入参数: WriteAddr:起始地址(此地址必须为4的倍数!!)
  *           pBuffer:数据指针
  *           NumToWrite:字(32位)数(就是要写入的32位数据的个数.)
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Write_Words( uint32_t WriteAddr, uint32_t * pBuffer, uint16_t NumToWrite )	
{
	uint16_t secoff     = 0;	//扇区内偏移地址(32位字计算)
	uint16_t secremain  = 0;  //扇区内剩余地址 (32位字计算)	   
 	uint16_t i = 0;    
	uint32_t secpos = 0;	 //扇区地址
	uint32_t offaddr= 0;   //去掉0X08000000后的地址
	
	if(WriteAddr<FLASH_BASE||(WriteAddr>=(FLASH_BASE+1024*GD32_FLASH_SIZE)))
    return;//非法地址
	
	offaddr   = WriteAddr - FLASH_BASE;		    //实际偏移地址.
	secpos    = offaddr / GD_SECTOR_SIZE;			//扇区地址  0~127 for GD32F103CBT6
	secoff    = (offaddr%GD_SECTOR_SIZE)/4;	  //在扇区内的偏移(4个字节为基本单位.)
	secremain = GD_SECTOR_SIZE/4-secoff;		  //扇区剩余空间大小   
	
  if(NumToWrite <= secremain)
    secremain = NumToWrite;//不大于该扇区范围
	fmc_bank0_unlock();
	while(1) 
	{	
    //读取整个扇区数据
    GDFLASH_Read_Words(secpos*GD_SECTOR_SIZE+FLASH_BASE,GDFLASH_BUF_WORD,GD_SECTOR_SIZE/4);
		
    for(i=0;i<secremain;i++)//校验数据
		{
			if(GDFLASH_BUF_WORD[secoff+i] != 0XFFFFFFFF)
        break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
      //擦除这个扇区
      fmc_page_erase(FLASH_BASE+GD_SECTOR_SIZE*secpos);

			for(i=0;i<secremain;i++)//复制
			{
				GDFLASH_BUF_WORD[i+secoff]=pBuffer[i];	  
			}
			GDFLASH_Write_Word(secpos*GD_SECTOR_SIZE+FLASH_BASE,GDFLASH_BUF_WORD,GD_SECTOR_SIZE/4);//写入整个扇区  
		}
    else
    {
      GDFLASH_Write_Word(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
		}
    if(NumToWrite == secremain)
      break;//写入结束了
		else//写入未结束
		{
			secpos++;				//扇区地址增1
			secoff=0;				//偏移位置为0 	 
		  pBuffer    += secremain;  //指针偏移
			WriteAddr  += secremain;	//写地址偏移	   
		  NumToWrite -= secremain;	//字节(32位)数递减
			if(NumToWrite>(GD_SECTOR_SIZE/4))
        secremain = GD_SECTOR_SIZE/4;//下一个扇区还是写不完
			else 
        secremain = NumToWrite;//下一个扇区可以写完了
		}	 
	};	
	fmc_bank0_unlock();
}


/**
  * 函数功能: 从指定地址开始读出指定长度的数据
  * 输入参数: ReadAddr:起始地址
  *           pBuffer:数据指针
  *           NumToRead:字(32位)数
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Read_Words ( uint32_t ReadAddr, uint32_t *pBuffer, uint16_t NumToRead )   	
{
	uint16_t i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=GDFLASH_ReadWord(ReadAddr);//读取4个字节.
		ReadAddr += 4;                          //偏移4个字节.	
	}
}

.h部分代码

#ifndef _GD32_FLASH_WORLD_H_
#define _GD32_FLASH_WORLD_H_

#define GD32_FLASH_SIZE        256  // 所选GD32的FLASH容量大小(单位为K)
#define GD32_FLASH_WREN        1    // GD32芯片内容FLASH 写入使能(0,禁用;1,使能)

//页容量判断
#if GD32_FLASH_SIZE < 256
  #define GD_SECTOR_SIZE  1024 //字节
#else 
  #define GD_SECTOR_SIZE	 2048
#endif

uint32_t GDFLASH_ReadWord (uint32_t faddr);
void GDFLASH_Write_Word( uint32_t WriteAddr, uint32_t * pBuffer, uint16_t NumToWrite );
void GDFLASH_Write_Words( uint32_t WriteAddr, uint32_t * pBuffer, uint16_t NumToWrite);
void GDFLASH_Read_Words ( uint32_t ReadAddr, uint32_t *pBuffer, uint16_t NumToRead );

#endif //_GD32_FLASH_WORLD_H_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值