在大多数工控应用中,由于各种复杂的环境因素,使工控设备不可避免的会面临供电突然断掉的情况。在许多应用场合,需要保存一部分现场数据,以保证工控设备在供电回复后能继续正常运行。为了保证保存数据的实时性,除了已保存的数据不受掉电影响的基本特性外,现场数据的存储频率还会非常高,因此还要求数据保存的速度应足够快,从而不影响应用程序的正常运行。本文的主要目的是分析现场数据保护的若干手段,并重点介绍英创工控主板特有的小数据高速存储方案,以支持关键现场数据的备份。
本文所指的英创工控主板包括EM9160、EM9260、EM9360以及EM9161这4个产品线的所有型号的产品。这些主板均带有大容量的NandFlash存储器,作为非易失性存储器,NandFlash主要用于存储应用程序、历史数据备份等内容。尽管NandFlash也可以作为现场数据保护的存储介质,但考虑到NandFlash介质有一定的擦写寿命限制,且数据是按扇区(512字节或2K字节)为单位写入,因此还存在写入效率较低的问题,因此基于NandFlash的文件系统存储不是作为现场数据保护的最佳方案。
对几十到几百个字节的现场数据的保存,一个比较好的办法是外扩一片NVRAM,典型的芯片可以考虑铁电存储器。有关铁电存储器的具体应用,客户可以参考《工控主板支持铁电存储器的简易方案》一文。在英创工控主板,铁电存储器的写入速度为56KB/s,即写入一个字节的时间在18us的水平。采用铁电存储器或其它NVRAM的优点是存储的数据量没有限制,但前提是需要增加一定的硬件成本,这可能成为一些大批量应用,对成本极其敏感的设备的障碍。
针对需要保存的现场数据通常很少这一特点,同时又能避免客户设备为了现场数据保存功能而增加额外的成本开销,我们通过优化工控主板的内核,为应用程序提供了最大6个字节、带掉电保护功能的高速存储空间,用于对关键现场数据的备份。由于这6个字节在系统内部,其写入速度高达1.5MB/s以上,即写入一个字节的时间在0.6us水平,6个字节的写入时间为3.6us。几微秒的存储时间可完全保证系统应用线程的正常运行。应用程序可通过3个系统调用来实现现场数据的读写,它们是:
1.检查当前存储的数据是否有效
//
// return = TRUE: data stored in NVRAM is valid
// = FALSE: data stored in NVRAM is corrupted or data is unavailable
//
BOOL NVRAMQuery()
{
BOOL bGoodData;
DWORD dwOutBufSize;
DWORD dwReturnBytes = 0;
BOOL bRet;
bGoodData = FALSE;
dwOutBufSize = sizeof(BOOL);
bRet = KernelIoControl(IOCTL_EM9X60_NVRAM_BYTE_QUERY,
NULL,
0,
(LPVOID)&bGoodData,
dwOutBufSize,
&dwReturnBytes);
if(bRet)
{
if(!bGoodData)
{
bRet = FALSE;
}
}
return bRet;
}
2. 从系统读出1-6个字节
//
// input dwMaxLength: buffer length in byte
// output pOutBuffer: output data buffer
// return >= 0: number of byte read from NVRAM <= dwmaxLength
// < 0: read failed
int NVRAMRead(LPVOID pOutBuffer, DWORD dwMaxLength)
{
DWORD dwReturnBytes = 0;
BOOL bRet;
bRet = KernelIoControl(IOCTL_EM9X60_NVRAM_BYTE_READ,
NULL,
0,
(LPVOID)pOutBuffer,
dwMaxLength,
&dwReturnBytes);
if(!bRet)
{
return -1;
}
return (int)dwReturnBytes;
}
3. 向系统写入1-6个字节
//
// input pInBuffer: input data buffer
// dwDataLength: number of byte need to write <= 6
// return >= 0: number of byte written into NVRAM
// < 0: write failed
//
int NVRAMWrite(LPVOID pInBuffer, DWORD dwDataLength)
{
DWORD dwReturnBytes = 0;
BOOL bRet;
bRet = KernelIoControl(IOCTL_EM9X60_NVRAM_BYTE_WRITE,
(LPVOID)pInBuffer,
dwDataLength,
NULL,
0,
&dwReturnBytes);
if(!bRet)
{
return -1;
}
return dwReturnBytes;
}
在后续出货的相关工控主板中,都将加上6字节掉电保护高速存储功能。对已购买英创公司的主板产品,若需要进行关键现场数据保存功能的客户,可将主板寄回英创公司进行免费更新并索取相关操作的完整源代码。