GD32或STM32(GD32F103RB)读写内部FLASH,即用flash存配置信息或者版本号

对32内部的Flash进行读写主要分为两种情况:

第一种情况:对存储信息只做读取操作。这种使用可以理解为是只读的,像版本号,或因为硬件不一样做的区分信息,这些信息是只读的,不修改;attribute的方式,bin文件会很大,我没有再仔细研究了。换一种方式 #define App_Ver "AP:t001",直接定义一个宏

第二种情况:存储到flash的信息可以读取、修改,这种使用是为了让设置不至于掉电就清除了,但是设置又会根据客户需求有不一样;

这两种情况是不能同时兼容的,所谓不能同时兼容,是指在一页的地址区间内,不能有这两种情况(例如一页的范围是0到100的地址,把可以修改信息放在0-50地址,把不能修改的地址放到51-100。这种情况是不允许的)。为什么要区分好这两种情况,因为Flash的写入前必须先擦除(Flash默认是FF,只做写0操作),flash的擦除,是按照一页为单位进行操作。

#define FMC_PAGE_SIZE           ((uint16_t)0x400U)    //代码是GD32F103RB,一页是1k,0x400大小

//------------------------版本信息,属于只读信息,单独一页放置只读信息,
//------------------------

#define VersionAddr  ((uint32_t)0x0801FC00U)
const char Software_Ver[12] __attribute__((at(VersionAddr )))  = "AP:0001";


//-------------------------可读可修改的信息放在0x0801F800U页
//-------------------------

#define FMC_WRITE_START_ADDR    ((uint32_t)0x0801F800U)
#define FMC_WRITE_END_ADDR      ((uint32_t)0x0801FC00U)

typedef struct _flash_data
{
	unsigned char data_valid_flag;
	unsigned char detectMode; 
	unsigned char Otp;
	unsigned char O_E;
	ColorData baseColor1;
	unsigned short thr1;
	unsigned int tgTime;
	signed short boxID;
	ColorData baseColor2;
	unsigned char chlNum;
	unsigned short thr2;
}flash_data;//共19个字节

typedef union _flash_data_union
{
	flash_data flashParms;
	uint32_t data[6];

}flash_data_union;

flash_data g_flash_params = {0};


//----------------------------------------------------------读操作
signed char load_config_params()
{	
    unsigned char *ptr = (unsigned char *)FMC_WRITE_START_ADDR;													 
	
    if(*ptr == FLASHDataOK)
    {
		//从Flash中读取到有效的配置数据
	    memcpy(&g_flash_params, ptr, sizeof(flash_data_union));			 
		return 0;
	}
	return -1;
}

//-----------------------------------------------------------写操作
int save_config_params(flash_data *params)
{
	flash_data_union config_params_union;//联合体其实就是flash_data 
	
	if(params == NULL) return -1;
				
	memset(&config_params_union, 0, sizeof(flash_data_union));	//清空数据
	memcpy(&config_params_union.flashParms, params, sizeof(flash_data)); //拷贝数据

	//擦除FLASH
	fmc_erase_pages();
	//保存配置数据到Flash中
	fmc_program((uint32_t *)&config_params_union, sizeof(flash_data));
		
	return 0;
}

void fmc_erase_pages(void)
{
    uint32_t erase_counter;

    /* unlock the flash program/erase controller */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    
    /* erase the flash pages */
    for(erase_counter = 0; erase_counter < page_num; erase_counter++){
        fmc_page_erase(FMC_WRITE_START_ADDR + (FLASH_SECTOR_SIZE * erase_counter));
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    }

    /* lock the main FMC after the erase operation */
    fmc_lock();
}

static void fmc_program(uint32_t *data, int data_len)
{
	uint32_t address = FMC_WRITE_START_ADDR;//配置信息的地址开始写入
    /* unlock the flash program/erase controller */
    fmc_unlock();
    /* program flash */
    while(address <= FMC_WRITE_END_ADDR) 
		{
        if(data_len <= 0) break;
			
        fmc_word_program(address, *data);
        address += 4U;
				data++;
        fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR);
        data_len-=4;
    }
    /* lock the main FMC after the program operation */
    fmc_lock();
}

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值