数据存档文件,用于保存所有从节点的字典配置。
在从节点初始化时,从节点将上报boot_up报文。主节点收到boot_up报文后,将对从节点的字典和数据存档文件进行对比,如果不匹配,则需要通过sdo报文对从节点字典进行重新配置,并根据配置决定是否命令从节点将新的配置存入非易失性存储器。
主站可以为每个从站配置一个节点数据存档文件,节点数据存档文件的格式如图:
/* DCF入口 */
typedef struct
{
UNS16 Index; //索引
UNS8 Subindex; //子索引
UNS32 Size; //字节数
UNS8 *Data; //数据指针
}dcf_entry_t;
void SaveNode(CO_Data *d, UNS8 nodeId);
static UNS8 read_consise_dcf_next_entry(CO_Data *d, UNS8 nodeId);
static UNS8 write_consise_dcf_next_entry(CO_Data *d, UNS8 nodeId);
UNS8 init_consise_dcf(CO_Data *d,UNS8 nodeId);
#ifdef _MSC_VER
#define inline _inline
#endif
/* 启动节点 */
void start_node(CO_Data *d, UNS8 nodeId)
{
/* 节点开始运行 */
masterSendNMTstateChange(d, nodeId, NMT_Start_Node);
/* 节点进入运行状态 */
d->NMTable[nodeId] = Operational;
}
/* 该函数被post_SlaveBootup函数调用,检查是否要获取数据存档文件并启动节点 */
UNS8 check_and_start_node(CO_Data *d, UNS8 nodeId)
{
/* 如果该节点的数据存档文件正在初始化,则直接退出 */
if(d->dcf_status != DCF_STATUS_INIT)
return 0;
/* 初始化节点nodeId的数据存档文件,并读取该节点的数据存档文件中配置的所有条目的数据 */
if((init_consise_dcf(d, nodeId) == 0) || (read_consise_dcf_next_entry(d, nodeId) == 0))
{
/* 如果没有配置该节点数据存档文件,则直接启动该节点 */
start_node(d, nodeId);
return 1;
}
/* 开始读取该节点的数据存档文件后,将状态设置为读取检查 */
d->dcf_status = DCF_STATUS_READ_CHECK;
return 2;
}
/* 启动该节点并检查是否有节点还未进入运行态 */
void start_and_seek_node(CO_Data *d, UNS8 nodeId)
{
UNS8 node;
/* 启动该节点 */
start_node(d, nodeId);
/* 检查是否有节点还未进入运行态,如果有则检查是否要获取数据存档文件并启动节点 */
for(node = 0; node < NMT_MAX_NODE_ID; node++)
{
if(d->NMTable[node] != Initialisation)
continue;
/* 检查是否要获取数据存档文件并启动节点 */
if(check_and_start_node(d, node) == 2)
return;
}
/* 所有如果已经有从站进入运行态,则必须将主站设置为运行态 */
setState(d, Operational);
}
/* 检查数据存档文件sdo并判断下一步要做什么动作 */
static void CheckSDOAndContinue(CO_Data *d, UNS8 nodeId)
{
UNS32 abortCode = 0;
UNS8 buf[4], match = 0;
UNS32 size = 4;
/* 如果状态为读取检查,说明已经开始读取 */
if(d->dcf_status == DCF_STATUS_READ_CHECK)
{
/* 获取sdo读取到的结果 */
if(getReadResultNetworkDict(d, nodeId, buf, &size, &abortCode) != SDO_FINISHED)
goto dcferror;
/* 检查读取到的大小和本地配置的是否匹配 */
if(size == d->dcf_size)
{
match = 1;
/* 检查读取到的内容和配置的是否匹配 */
while(size--)
{
if(buf[size] != d->dcf_data[size])
match = 0;
}
}
/* 如果匹配,继续读取该节点数据存档文件中配置的下一个条目 */
if(match)
{
/* 如果已经读完该节点配置的数据存档文件中的所有条目 */
if(read_consise_dcf_next_entry(d, nodeId) == 0)
{
/* 开始并检查节点 */
start_and_seek_node(d, nodeId);
}
}
/* 如果读取的数据存档文件和配置的数据存档文件不匹配,则将配置数据存档文件写到节点字典中 */
else
{
/* 初始化节点nodeId的数据存档文件,写数据存档指针指向的条目数据并将指针偏移到下一个条目 */
if((init_consise_dcf(d, nodeId) == 0) || (write_consise_dcf_next_entry(d, nodeId) == 0))
goto dcferror;
/* 将状态配置为写 */
d->dcf_status = DCF_STATUS_WRITE;
}
}
/* 如果状态为写 */
else if(d->dcf_status == DCF_STATUS_WRITE)
{
/* 检查写字典结果是否成功 */
if(getWriteResultNetworkDict(d, nodeId, &abortCode) != SDO_FINISHED)
goto dcferror;
/* 写该节点数据存档文件中指针指向的条目的数据,并将指针偏移到该节点配置的下一个条目 */
if(write_consise_dcf_next_entry(d, nodeId) == 0)
{
#ifdef DCF_SAVE_NODE
/* 所有条目都写完,通知从站保存字典到非易失性存储器 */
SaveNode(d, nodeId);
/* 将状态设置为保存 */
d->dcf_status = DCF_STATUS_SAVED;
#else
/* 所有条目都写完,将状态设置为初始化 */
d->dcf_status = DCF_STATUS_INIT;
/* 启动该节点并检查是否有其它节点还未进入运行态,如果有则检查是否要获取数据存档文件并启动其它节点 */
start_c@RI]
N]\NB:`&.f9ke,:gg$)9fj
SJ]H
SRY
BS]S]H N
MM] N]S]XXRJRYLLK
I[\]KX[YK
NY]
HTPL
]\]S]XXRI]
NBOO
|