重构配置区,不做数据检验,统一头部签名,编译通过,未测试。

Flash最后一块作为配置区
This commit is contained in:
nnhy 2015-10-22 02:37:50 +00:00
parent 665323e5af
commit 91d4df401a
2 changed files with 108 additions and 116 deletions

View File

@ -1,30 +1,37 @@
#include "Config.h"
#include "Flash.h"
#include "Security\Crc.h"
Storage* ConfigBlock::Device = NULL;
uint ConfigBlock::BaseAddress = NULL;
Config* Config::Current = NULL;
bool ConfigBlock::IsGoodBlock() const
// 配置块。名称、长度、头部校验,数据部分不做校验,方便外部修改
class ConfigBlock
{
if(Signature != c_Version || HeaderCRC == 0) return false;
public:
ushort HeaderCRC;
ushort Size;
char Name[4];
bool Valid() const;
const ConfigBlock* Next() const;
const void* Data() const;
bool Init(const char* name, const ByteArray& bs);
bool Write(Storage* storage, uint addr, const ByteArray& bs);
};
bool ConfigBlock::Valid() const
{
// 计算头部 CRC。从数据CRC开始包括大小和名称
ushort crc = Crc::Hash16(&DataCRC, sizeof(*this) - offsetof(ConfigBlock, DataCRC));
ushort crc = Crc::Hash16(&Size, sizeof(*this) - offsetof(ConfigBlock, Size));
return crc == HeaderCRC;
}
bool ConfigBlock::IsGoodData() const
{
// 计算数据块CRC
ushort crc = Crc::Hash16(Data(), Size);
return crc == DataCRC;
}
const ConfigBlock* ConfigBlock::Next() const
{
if(!IsGoodBlock()) return NULL;
if(!Valid()) return NULL;
// 确保数据部分2字节对齐便于Flash操作
uint s = (Size + 1) & ~1;
@ -38,8 +45,6 @@ const void* ConfigBlock::Data() const
return (const void*)&this[1];
}
//--//
// 构造一个新的配置块
bool ConfigBlock::Init(const char* name, const ByteArray& bs)
{
@ -47,59 +52,18 @@ bool ConfigBlock::Init(const char* name, const ByteArray& bs)
uint slen = strlen(name);
if(slen > sizeof(Name)) return false;
//memset(this, 0, sizeof(*this));
Size = bs.Length();
// 数据长度为0表明是置为无效
if(bs.Length() > 0)
DataCRC = Crc::Hash16(bs.GetBuffer(), bs.Length());
else
DataCRC = 0;
/*// 只有首次允许设置名字和大小,避免后面随意扩张引起越界覆盖
if(IsGoodBlock())
{
if(bs.Length() > Size) return false;
}
else*/
{
Signature = c_Version;
Size = bs.Length();
if(slen > ArrayLength(Name)) slen = ArrayLength(Name);
memset(Name, 0, ArrayLength(Name));
memcpy(Name, name, slen);
}
if(slen > ArrayLength(Name)) slen = ArrayLength(Name);
memset(Name, 0, ArrayLength(Name));
memcpy(Name, name, slen);
// 计算头部CRC。包括数据CRC、大小、名称
HeaderCRC = Crc::Hash16(&DataCRC, sizeof(*this) - offsetof(ConfigBlock, DataCRC));
HeaderCRC = Crc::Hash16(&Size, sizeof(*this) - offsetof(ConfigBlock, Size));
return true;
}
//--//
// 循环查找配置块
const ConfigBlock* ConfigBlock::Find(const char* name, uint addr, bool fAppend)
{
const ConfigBlock* cfg = (const ConfigBlock*)addr;
uint slen = strlen(name);
assert_param2(slen <= sizeof(cfg->Name), "配置段名称最大4个字符");
// 遍历链表,找到同名块
while(cfg->IsGoodBlock())
{
if(cfg->IsGoodData() && name && memcmp(name, cfg->Name, slen) == 0)
{
return cfg;
}
cfg = cfg->Next();
}
// 如果需要添加,返回最后一个非法块的地址
return fAppend ? cfg : NULL;
}
// 更新块
bool ConfigBlock::Write(Storage* storage, uint addr, const ByteArray& bs)
{
@ -108,41 +72,71 @@ bool ConfigBlock::Write(Storage* storage, uint addr, const ByteArray& bs)
bool rs = true;
// 先写入头部,然后写入数据
uint len = sizeof(ConfigBlock) - offsetof(ConfigBlock, Signature);
rs &= storage->Write(addr, ByteArray((byte*)&Signature, len));
uint len = sizeof(ConfigBlock) - offsetof(ConfigBlock, HeaderCRC);
if(!storage->Write(addr, ByteArray(&HeaderCRC, len))) return false;
if(bs.Length() > 0)
{
uint offset = len;
len = bs.Length();
if(len > Size) len = Size;
rs &= storage->Write(addr + offset, ByteArray(bs.GetBuffer(), len));
uint len2 = bs.Length();
if(len2 > Size) len2 = Size;
if(!storage->Write(addr + len, ByteArray(bs.GetBuffer(), len2))) return false;
}
return rs;
}
// 废弃
bool ConfigBlock::Invalid(const char* name, uint addr, Storage* storage)
//--//
// 循环查找配置块
const void* Config::Find(const char* name, bool fAppend)
{
return Set(name, ByteArray(0), addr, storage);
assert_param2(name, "配置段名称不能为空");
uint addr = Address;
// 检查签名,如果不存在则写入
if(*(uint*)addr != c_Version)
{
if(!fAppend) return NULL;
Device->Write(addr, ByteArray(&c_Version, sizeof(c_Version)));
}
addr += sizeof(c_Version);
const ConfigBlock* cfg = (const ConfigBlock*)addr;
uint slen = strlen(name);
assert_param2(slen <= sizeof(cfg->Name), "配置段名称最大4个字符");
// 遍历链表,找到同名块
while(cfg->Valid())
{
if(cfg->Name[0] && memcmp(name, cfg->Name, slen) == 0) return cfg;
cfg = cfg->Next();
}
// 如果需要添加,返回最后一个非法块的地址
return fAppend ? cfg : NULL;
}
// 废弃
bool Config::Invalid(const char* name)
{
return Set(name, ByteArray(0));
}
// 根据名称更新块
const void* ConfigBlock::Set(const char* name, const ByteArray& bs, uint addr, Storage* storage)
const void* Config::Set(const char* name, const ByteArray& bs)
{
if(name == NULL) return NULL;
if(!addr) addr = BaseAddress;
if(!storage) storage = Device;
assert_param2(storage, "未指定配置段的存储设备");
assert_param2(Device, "未指定配置段的存储设备");
const ConfigBlock* cfg = Find(name, addr, true);
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, true);
if(cfg)
{
// 重新搞一个配置头,使用新的数据去重新初始化
ConfigBlock header;
header.Init(name, bs);
header.Write(storage, (uint)cfg, bs);
header.Write(Device, (uint)cfg, bs);
return cfg->Data();
}
@ -151,37 +145,44 @@ const void* ConfigBlock::Set(const char* name, const ByteArray& bs, uint addr, S
}
// 获取配置数据
bool ConfigBlock::Get(const char* name, ByteArray& bs, uint addr)
bool Config::Get(const char* name, ByteArray& bs)
{
if(name == NULL) return false;
if(!addr) addr = BaseAddress;
const ConfigBlock* cfg = Find(name, addr, false);
if(cfg)
{
if(cfg->Size <= bs.Capacity())
{
bs.Copy(cfg->Data(), 0, cfg->Size);
bs.SetLength(cfg->Size);
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, false);
if(cfg && cfg->Size <= bs.Capacity())
{
bs.Copy(cfg->Data(), 0, cfg->Size);
bs.SetLength(cfg->Size);
return true;
}
return true;
}
return false;
}
const void* ConfigBlock::Get(const char* name, uint addr)
const void* Config::Get(const char* name)
{
if(name == NULL) return NULL;
if(!addr) addr = BaseAddress;
const ConfigBlock* cfg = Find(name, addr, false);
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, false);
if(cfg) return cfg->Data();
return NULL;
}
// Flash最后一块作为配置区
Config* Config::CreateFlash()
{
// 最后一块作为配置区
static Flash flash;
static Config cfg;
cfg.Device = &flash;
cfg.Address = flash.Start + flash.Size - flash.Block;
return &cfg;
}
// 初始化
TConfig::TConfig()
{

View File

@ -5,41 +5,32 @@
#include "Stream.h"
#include "Storage\Storage.h"
class ConfigBlock
// 配置管理
// 配置区以指定签名开头,后续链式跟随各配置块
class Config
{
private:
static const uint c_Version = 0x534F5453; // STOS
public:
static Storage* Device;
static uint BaseAddress;
public:
uint Signature;
ushort HeaderCRC;
ushort DataCRC;
uint Size;
char Name[4];
bool IsGoodBlock() const;
bool IsGoodData () const;
const ConfigBlock* Next() const;
const void* Data() const;
bool Init(const char* name, const ByteArray& bs);
bool Write(Storage* storage, uint addr, const ByteArray& bs);
Storage* Device;
uint Address;
// 查找
static const ConfigBlock* Find(const char* name, uint addr = NULL, bool fAppend = false);
// 废弃
static bool Invalid(const char* name, uint addr = NULL, Storage* storage = NULL);
const void* Find(const char* name, bool fAppend = false);
// 废弃。仅清空名称,并不删除数据区
bool Invalid(const char* name);
// 设置配置数据
static const void* Set(const char* name, const ByteArray& bs, uint addr = NULL, Storage* storage = NULL);
const void* Set(const char* name, const ByteArray& bs);
// 获取配置数据
static bool Get(const char* name, ByteArray& bs, uint addr = NULL);
bool Get(const char* name, ByteArray& bs);
// 获取配置数据
static const void* Get(const char* name, uint addr = NULL);
const void* Get(const char* name);
// 当前
static Config* Current;
// Flash最后一块作为配置区
static Config* CreateFlash();
};
// 必须设定为1字节对齐否则offsetof会得到错误的位置