一. 前言
本文依据个人试验及工作经验总理而成,分享出来供大家参考,如有错误或更好的方法望与大家一起探讨。
二. 背景
作者学习Xilinx SDK的时候,发现该平台使用起来遇到各种各样的问题和bug,网上解决方法都是零零散散的或者根本找不到,有时候遇到问题就要卡上几天甚至更久,特别浪费时间。
所以在个人学习期间,就遇到的一些问题整理出来,不能说是很完整的教程,但是希望后来者少踩一些坑和少走一些弯路。
三. 主要内容
Xilinx SDK参数掉电后存储。
四. 现象
在实际应用中需要将一些配置好的参数在掉电后能存储起来,在设备五次通电后能还原上次的配置。
五. 问题起因
在编写网络程序时,时常因为设备IP地址在不同网络环境中使用不同的IP,而普通作法是将IP地址写死在程序中,当网络环境变更后需要重新更改IP并编译程序,再固化后才能使用。为了解决这个问题需要对设置的IP地址进行保存,在不同环境中只需要使用命令进行配置后便可以使用。
六. 问题分析
需要对参数进行保存必须有存储设备,而在嵌入式设备中唯一的存储设备只有FLASH或SD卡,而很多情况下我们的嵌入式程序都不会在SD卡中启动。
程序固化的存储空间一般为FLASH存储,我们可设想一下如果FLASH为16M大小,而程序只需要8M,后面未使用的小于8M的空间是否已经浪费,既然浪费我们可以利用起来作为存储参数;而嵌入式下需要存储的参数不会很大,1K或10K或128K,以至于1M的空间都能存储很多东西了。
七. 解决步骤
- 将FLASH空间划分成两部份,前部份空间用于固化程序,后一部份空间用于存储软件参数,起始地址必须以FLASH块大小的整倍数(因为在写入FLASH数据时,是以FLASH整块数据进行擦除写入),计算公式如:起始地址=FLASH大小-(参数存储空间大小+块大小-1)/块大小*块大小;
- 嵌入式系统启动时先将FLASH中的参数数据读出,并使用自定义的数据结构进行计算是否为可用数据,如果不是则复位参数;
- 对嵌入式参数进行配置时,将先将参数从FLASH中读出,运用自定义的数据结构替换要更新的参数;
- 将更新后的数据结构,计算公式将数据写回FLASH;
- 下面是读写自定义参数的源代码:
加载FLASH参数
void SYS_ConfigInfoLoad(void) { unsigned char sum = 0; unsigned char *ReadData = (unsigned char*)(DDR_SHARE_UPDATE_FLASH); unsigned long size = sizeof(SYS_CONFIG_INFO); PSYS_CONFIG_INFO pSysCfg = (PSYS_CONFIG_INFO)ReadData; unsigned long baseaddr = FLASH_Size() - 0x100000; FLASH_ReadData(baseaddr, ReadData, size); sum = VerifyByteSum(ReadData, size - 1); if ( NULL == g_sysConfigInfo ) g_sysConfigInfo = (PSYS_CONFIG_INFO)malloc(1024); // 恢复默认设置 if ( (SYS_CFG_INFO_FLAG != pSysCfg->flag) || (sum != pSysCfg->sum) ) { SYS_ConfigReset(); } else { memcpy(g_sysConfigInfo, pSysCfg, size); pSysCfg = g_sysConfigInfo; pSysCfg->sum = VerifyByteSum((unsigned char*)pSysCfg, size - 1); if ( sum != pSysCfg->sum ) { SYS_ConfigInfoSave(); } } } |
保存FLASH参数
void SYS_ConfigInfoSave() { unsigned char *WriteData = (unsigned char*)DDR_SHARE_UPDATE_FLASH; unsigned long size = sizeof(SYS_CONFIG_INFO); unsigned long baseaddr = FLASH_Size() - 0x100000; g_sysConfigInfo->flag = SYS_CFG_INFO_FLAG; g_sysConfigInfo->sum = VerifyByteSum((unsigned char*)g_sysConfigInfo, size - 1); #ifdef XPAR_PS7_QSPI_0_BASEADDR memcpy(WriteData + 4, g_sysConfigInfo, size); #elif XPAR_PS7_NAND_0_BASEADDR WriteData = (unsigned char*)g_sysConfigInfo; #endif FLASH_WriteData(baseaddr, WriteData, size); } |
八. 故障产生原因
无。
九. 结论
- 通过在FLASH最后一段空间中存储数据,可实现数据的保存和参数配置;