IAP升级 Settings区域数据初始化
1、假如,有两个产品,A产品跟B产品,硬件都一样,要求一个软件里的board_name为N32G430C8L7_STB_A,另一个软件里的board_name为N32G430C8L7_STB_B。
那我们如何在不改boot程序跟App程序的基础上,快速的使两个软件看上去不同呢?
这里我们将setting区域的数据提前初始化,通过c语言的文件流的操作方法,创建一个setting.bin文件,然后将setting区域存储的结构体初始化后写入setting.bin文件,然后通过pyocd烧录到0x08004000地址即可。
2、根目录创建Settings目录,并创建setting_init.c Makefile文件
3、Makefile文件,编译setting_init.c的脚本文件,主要作用是用gcc编译出setting可执行文件,然后执行生成setting.bin
Makefile
CC = gcc
SRC = $(wildcard *.c)
OBJ = $(addprefix $(BUILD_DIR)/,$(notdir $(SRC:.c=.o)))
#OBJ = $(patsubst %.c, %.o, $(SRC))
TRAGET = settings
BUILD_DIR = build
ifeq ($(PRODUCT_A), y)
APPLICATION_FLAGS += \
-DUSER_PRODUCT_A
endif
ifeq ($(PRODUCT_B), y)
APPLICATION_FLAGS += \
-DUSER_PRODUCT_B
endif
C_INCLUDES += \
-I../Common/Flash \
-I../Common/Settings \
-I../Common
C_FLAG += -Wall -MD -MP -MF"$(@:%.o=%.d)"
C_FLAG += -DUSER_SETTING_IN_HOST
C_FLAG += $(APPLICATION_FLAGS)
all: $(BUILD_DIR) $(BUILD_DIR)/$(TRAGET)
$(BUILD_DIR)/$(TRAGET):$(OBJ) Makefile | $(BUILD_DIR)
$(CC) $< -o $@
$(OBJ): $(SRC) Makefile | $(BUILD_DIR)
$(CC) -c $(C_FLAG) $(C_INCLUDES) $< -o $@
$(BUILD_DIR):
@-mkdir $@
clean:
@rm -rf $(TRAGET)
@rm -rf $(OBJ)
@rm -rf $(BUILD_DIR)
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
4、setting_init.c文件
之前讲过system_info的结构体,这里只写了四个变量,当然你也可以添加更多。在setting_init.c文件里,初始化了version跟board_name 变量。
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "settings.h"
#include "flash.h"
MI_S32 get_current_times(MI_CHAR *c_time)
{
time_t timep;
struct tm *p;
time(&timep);
p = gmtime(&timep);
sprintf(c_time,"%04d%02d%02d %02d%02d%02d",p->tm_year + 1900,p->tm_mon + 1,p->tm_mday,
p->tm_hour + 8,p->tm_min,p->tm_sec);
return 0;
}
MI_S32 main(int argc,char *argv[])
{
system_info s_info;
FILE *file;
size_t w_size;
#ifdef USER_PRODUCT_A
MI_CHAR *board_name = "N32G430C8L7_STB_A";
#endif
#ifdef USER_PRODUCT_B
MI_CHAR *board_name = "N32G430C8L7_STB_B";
#endif
memset(&s_info,0,sizeof(s_info));
get_current_times(s_info.version);
memcpy(s_info.board_name,board_name,strlen(board_name));
printf(FONT_COLOR_BLUE"get current time %s\n"COLOR_NONE,s_info.version);
printf(FONT_COLOR_BLUE"get board name %s\n"COLOR_NONE,s_info.board_name);
file = fopen("./build/Settings.bin","wb");
if (file == NULL)
{
printf(FONT_COLOR_YELLOW" open settings.bin error\n"COLOR_NONE);
return -1;
}
w_size = fwrite((MI_U8 *)&s_info,1,sizeof(s_info),file);
if (w_size == sizeof(system_info))
{
printf(FONT_COLOR_YELLOW" creat settings.bin Success!\n"COLOR_NONE);
}
fclose(file);
return 0;
}
5、顶层的makefile修改
Top = ${shell pwd}
App = ${Top}/Application
BootLoader = ${Top}/Bootloader
Settings = ${Top}/Settings
#Bin = ${Top}/Bin
# A B版本的编译选项,在setting_init.c中使用
# 编译B版本setting.bin时,使用
# PRODUCT_A = n
# PRODUCT_B = y
export PRODUCT_A = y
export PRODUCT_B = n
all: gd32 setting
# 编译setting_init.c 并执行编译出来的settings
setting:
make -C ${Settings}
cd ${Settings} && ./build/settings
gd32:
make -C ${App}
make -C ${BootLoader}
# cp ${BootLoader}/build/BootLoader.bin ${Top}/BinFiles/
# cp ${App}/build/Application.bin ${Top}/BinFiles/
# amp:
# cd ${Amp} && ./ampcreater
# cd ${AllBin} && ./allinone
clean:
rm -rf ${App}/build/*
rm -rf ${BootLoader}/build/*
make clean -C ${Settings}
# rm -rf ${BinCreater}/*
gdboot:
${info "start flash boot "}
pyocd flash --erase auto --target N32G430C8L7 --base-address 0x8000000 --pack=./Nations.N32G430_DFP.1.0.0.pack ./Bootloader/build/Bootloader.bin
gdapp:
${info "start flash Application "}
pyocd flash --erase auto --target N32G430C8L7 --base-address 0x8006000 --pack=./Nations.N32G430_DFP.1.0.0.pack ./Application/build/Application.bin
# 烧录settings.bin到flash的命令
gdsetting:
${info "start flash settings "}
pyocd flash --erase auto --target N32G430C8L7 --base-address 0x8004000 --pack=./Nations.N32G430_DFP.1.0.0.pack ./Settings/build/Settings.bin
6、根目录执行make后,
A、
B、
执行make gdsetting 烧录两个setting.bin后分别验证,
结果如下:
B 、
A、
注意,编译尽量先make clean;make
7、单片机读取version board_name的代码:
#include <string.h>
#include "settings.h"
#include "flash.h"
MI_BOOL system_info_get_version(MI_CHAR *version)
{
system_info info;
memset(&info,0,sizeof(info));
n32_flash_read(SETTINGS_START_ADDRESS,(uint8_t *)&info,sizeof(info));
memcpy(version,info.version,sizeof(info.version));
return MI_TRUE;
}
MI_BOOL system_info_get_broad_name(MI_CHAR *name)
{
system_info info;
memset(&info,0,sizeof(info));
n32_flash_read(SETTINGS_START_ADDRESS,(uint8_t *)&info,sizeof(info));
memcpy(name,info.board_name,sizeof(info.board_name));
return MI_TRUE;
}
MI_BOOL system_info_get_update_flag(MI_U8 *flag)
{
system_info info;
memset(&info,0,sizeof(info));
n32_flash_read(SETTINGS_START_ADDRESS,(uint8_t *)&info,sizeof(info));
*flag = info.update_flag;
return MI_TRUE;
}
/**
* 设置升级标志位的函数
*/
MI_BOOL system_info_set_update_flag(MI_U8 flag)
{
system_info info;
memset(&info,0,sizeof(info));
n32_flash_read(SETTINGS_START_ADDRESS,(uint8_t *)&info,sizeof(info));
info.update_flag = flag;
//先清除system info 区域
n32_flash_erase(SETTINGS_START_ADDRESS,SETTINGS_END_ADDRESS);
n32_flash_write(SETTINGS_START_ADDRESS,(uint8_t *)&info,sizeof(info));
return MI_TRUE;
}
main.c
#include <string.h>
#include "main.h"
#include "bsp_led.h"
#include "bsp_delay.h"
#include "usart.h"
#include "timer.h"
#include "pwm.h"
#include "key_input.h"
#include "flash.h"
#include "settings.h"
/**
*\*\name main.
*\*\fun main function.
*\*\param none.
*\*\return none.
**/
int main(void)
{
led_init();
usart1_init();
usart2_init();
timer6_init();
tim2_pwm_init();
key_input_init();
/* Delay 1s */
SysTick_Delay_Ms(1000);
MI_CHAR name[24] = {0};
MI_CHAR version[48] = {0};
system_info_get_broad_name(name);
system_info_get_version(version);
printf(FONT_COLOR_BLUE"from settings area read name == %s\r\n"COLOR_NONE,name);
printf(FONT_COLOR_BLUE"from settings area read version == %s\r\n"COLOR_NONE,version);
while(1)
{
}
}