一步一步實現STM32-FOTA系列教程之FLASH靜態區讀寫

一步一步實現STM32-FOTA系列教程之FLASH靜態區讀寫

文章系列鏈接

《一步一步實現STM32-FOTA系列教程之bin文件生成》

《一步一步實現STM32-FOTA系列教程之STM32-FLASH分區說明》
《一步一步實現STM32-FOTA系列教程之Bootloader編寫》

前言

在上一篇文章《一步一步實現STM32-FOTA系列教程之STM32-FLASH分區說明》中,對STM32的FLASH進行了人爲了分區,分成了 Bootloader分區、主分區、備份分區和靜態區四個區域。其中靜態區是用來存放系統一些參數信息的,該分區的內容可以通過編程進行讀寫,如果不人爲的破壞該分區,分區裏面的信息會一直保存,掉電不丟失,也就是所謂的FLASH模擬EEPROM的功能。
這篇文章就來說說如何在程序中進行FLASH靜態區的讀寫操作,以方便後續的使用。

FLASH靜態區使用

我們在FLASH中給靜態區分配了32KB大小的空間,即從0x0803 8000 ~ 0x0804 0000 一共 32 * 1024 字節。

對於單片機而言,能夠擁有這麼大靜態區存儲空間已經非常大了,當然我們也不能浪費了。但從Bootloder的分區啓動選擇而言,利用一個字節的空間用來存儲啓動分區標誌位就已經足夠了。考慮到在應用程序中還要公用這一塊FLASH靜態區,我們還是將這塊區域進行結構化定義,才能更爲方便的使用。

這裏,我們就根據自己的項目實際需求,定義一個靜態區變量存儲的結構體,用於進行參數讀寫。

#pragma pack(1)

//靜態區參數 配置信息
typedef struct STM32_STATIC_FLASH_SAVE
{
	char firmware_info[64];   //固件信息
	char hardwareversion[32]; //硬件版本
	char softwareversion[64]; //軟件版本
	char device_sn[20];   //設備SN
	char device_imei[20]; //設備IMEI
	char updateflag;  //flash信息更新標誌
	unsigned int  runcounts;  //運行次數
	char bootinfo[32];//系統啓動相關參數信息
}STM32_SFS;

#pragma pack()

定義完成FLASH 靜態區參數結構體後,每一次進行的 FLASH 靜態區操作,都利用該結構體進行編解碼,即可對我們代碼中的參數進行實時的讀取寫入,非常方便。

該結構體中定義的 updateflag 即爲系統啓動分區標誌位,Bootloader 啓動之後,讀取完靜態區FLASH信息,就會判斷該標誌位的值,如果該標誌位爲1,則會從主分區啓動程序,如果爲2,則會從備份分區啓動程序,如果爲0,則代表主分區和備份分區還沒有燒寫軟件,需要先進行燒寫。

STM32-FLASH的編程接口

有關 STM32 中 FLASH 的編程接口,在STM32的庫函數中,已經爲我們提供了 stm32f10x_flash.c 和 stm32f10x_flash.h 兩個 FLASH 操作的庫文件,如果要在程序中對FLASH進行操作,需要在工程中引入這兩個庫文件。

除此之外,原子大哥也將 STM32 FLASH 的讀寫操作流程編寫出來一份C文件,我們在使用的時候,可以直接移植到自己的工程中來 即stmflash.c 和 stmflash.h 兩個文件。
爲了更爲快速的實現Bootloader功能,這裏就直接使用這幾份 FLASH 操作的函數庫來對FLASH進行操作。

FLASH 靜態區參數讀寫實現

首先定義一個 FLASH 靜態區參數的全局結構體。

// FLASH 靜態區參數信息
STM32_SFS nbdevice_sfs;

然後編寫一個獲取FLASH靜態區參數的函數。

//得到設備信息
void GetDeviceInfo(void)
{
	u8 i=0;
	STM32_SFS *nbsfs = &nbdevice_sfs; 
	
	memset(&nbdevice_sfs,0,sizeof(STM32_SFS));

	printf("Static Params Address :0x%08X\r\n",CONFIG_PARAM_START_ADDR);
	//STMFLASH_Read(CONFIG_PARAM_ADDR, &buf, 1);
	STMFLASH_Read(CONFIG_PARAM_START_ADDR, (u16*)&nbdevice_sfs, sizeof(STM32_SFS));
	//靜態區沒有初始化
	if(NULL==strstr(nbdevice_sfs.firmware_info,"NBIOT_SMART_STREET_V2.0"))
	{
		printf("static flash not init\r\n");
		printf("start to init flash\r\n");
		memset(&nbdevice_sfs,0,sizeof(STM32_SFS));
		STMFLASH_Write(CONFIG_PARAM_START_ADDR,(u16*)&nbdevice_sfs,sizeof(STM32_SFS));
		
	}
	memset(&nbdevice_sfs,0,sizeof(STM32_SFS));
	STMFLASH_Read(CONFIG_PARAM_START_ADDR, (u16*)&nbdevice_sfs, sizeof(STM32_SFS));
	if(nbdevice_sfs.updateflag ==0)
	{
		sprintf(nbsfs->firmware_info,"%s","NBIOT_SMART_STREET_V2.0");
		nbdevice_sfs.updateflag = 1;
		printf("please upload firmware to stm32\r\n");
		STMFLASH_Write(CONFIG_PARAM_START_ADDR, (u16*)&nbdevice_sfs, sizeof(STM32_SFS));
	}
	else if(nbdevice_sfs.updateflag ==1)
	{
		bootflag=nbdevice_sfs.updateflag;
		printf("start to boot firmware one\r\n");
		printf("Testing...\r\n");
		printf("set updateflag 2\r\n");
		nbdevice_sfs.updateflag = 2;
		STMFLASH_Write(CONFIG_PARAM_START_ADDR, (u16*)&nbdevice_sfs, sizeof(STM32_SFS));
	}
	else if(nbdevice_sfs.updateflag ==2)
	{
		bootflag=nbdevice_sfs.updateflag;
		printf("start to boot firmware two\r\n");
		
		
		printf("Testing...\r\n");
		printf("set updateflag 1\r\n");
		nbdevice_sfs.updateflag = 1;
		STMFLASH_Write(CONFIG_PARAM_START_ADDR, (u16*)&nbdevice_sfs, sizeof(STM32_SFS));
	}	

}

該函數實現非常簡單,就是讀取FLASH靜態區信息,然後判斷程序啓動分區標誌位,如果啓動分區標誌位爲1,則將其改寫爲2,如果爲2,怎將其改寫爲1,如果爲0,則打印出下載固件的提示信息,如此以來,該函數能夠實現兩個分區的程序交替運行。

主函數實現

int main()
{
	
	ledInit();
	uart1_init(9600);

	delay_init();
	printf("-----------------------------------\r\n");
	printf("------------Bootloader-------------\r\n");
	printf("-----------------------------------\r\n");
	LOG_COMPILE();
	printf("Version: V1.0\r\n");
	LED0_Blink(100);
	GetDeviceInfo();

}

日誌打印

這裏我重啓了3次,分別打印出來3次 bootloader 的打印信息,請參考。

-----------------------------------
------------Bootloader-------------
-----------------------------------
Compile Time: Nov 13 2018,11:37:15
Version: V1.0
Static Params Address :0x08038000
static flash not init
start to init flash
please upload firmware to stm32
-----------------------------------
------------Bootloader-------------
-----------------------------------
Compile Time: Nov 13 2018,11:37:15
Version: V1.0
Static Params Address :0x08038000
start to boot firmware one
Testing...
set updateflag 2
-----------------------------------
------------Bootloader-------------
-----------------------------------
Compile Time: Nov 13 2018,11:37:15
Version: V1.0
Static Params Address :0x08038000
start to boot firmware two
Testing...
set updateflag 1

源碼

編寫教程不易,還請到CSDN下載區下載源碼。
源碼下載鏈接

參考文檔

正點原子 STM32 系列開發板FLASH模擬EEPROM實驗

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章