📄 dbs.c
字号:
/*******************************************************************
*******************************************************************/
#include "..\system.h"
//#ifdef ARM_XSCALE_CPU
// #include <string.h>
//#endif
#ifdef INTEL_X86_CPU
#include <stdio.h>
#include <io.h>
#endif
#include "..\utility.h"
#include "..\dbstru.h"
#include "..\address.h"
#include "..\hardware.h"
#include "dbs.h"
/**************************** 常量定义 *************************************/
/* 配置文件版本 */
const INT16U RELEASE_VERSION = 0x8801;
const INT16U DEBUG_VERSION = 0x7703;
/***************************** 全局变量定义 ********************************/
INT8U dbsArea[DBS_LEN]; /* 运行期数据结构区 */
INT8U ROMArea[ROM_LEN]; /* 配置文件区 */
RunDEVSTRUCT * dpDevCfg[MAXGROUP]; /* DP从站配置数组 */
DEVPARM dpPrmCfg[MAXTYPE]; /* 设备参数配置数组 */
DualPortRAM *pDPRAM; /* 双口RAM结构指针 */
/***************************** 局部变量定义 ********************************/
static INT16U deviceNum = 0; /* 已配置模块总数 */
/************************** Function Prototype ******************************/
static void InitDPRamPointer(void); /* 初始化双口RAM的指针 */
static void DbsInit(void); /* Dbs模块数据初始化 */
static INT8U* ScanToIOCfg(void); /* 扫描配置文件直到IO配置结构区 */
static INT8U CfgDbsRam(INT8U* pbegin); /* 在Dbs区中分配模块空间 */
static void CfgDPRam(void); /* 在双口RAM中分配IO模块数据区 */
static INT8U CheckDevNum(void); /* 检查已配置模块个数的合法性 */
static INT8U initIOM(RunDEVSTRUCT *, DEVSTRUCT *); /* 初始化运行期模块结构 */
/**************************** 全局函数定义 *********************************/
#if defined(ARM_XSCALE_CPU) && defined(DEBUG)
#include "..\cfgarray.h"
#endif
/* 载入IO配置文件 */
INT16U dbsFileLoad(void)
{
#ifdef ARM_XSCALE_CPU
/* read config file from Compact Flash ... */
/* if no CF, we use memory to simulate CF */
#ifdef DEBUG
memcpy(CONF_ROM_ADDRESS, configarray,
(sizeof(configarray)/sizeof(configarray[0])) );
#endif
#endif
#ifdef INTEL_X86_CPU
static char fileName[FILE_PATH_LEN] = "IOConfig.dat";
FILE *pFile = NULL;
INT16U fileLen = 0;
pFile = fopen(fileName, "rb");
if (NULL == pFile)
{
return(dbError(DBS_LOAD_FILEOPENERR));
}
fileLen = (INT16U)filelength(fileno(pFile));
if (-1 == fileLen)
{
return(dbError(DBS_LOAD_FILELENERR));
}
if (fread(CONF_ROM_ADDRESS, fileLen, 1, pFile) != 1)
{
return(dbError(DBS_LOAD_WRITEROMERR));
}
if (fclose(pFile) != 0)
{
return(dbError(DBS_LOAD_FILECLOSEERR));
}
#endif
return(SYS_NOERR);
}
/* 建立运行期数据结构 */
INT16U dbsLoad(void)
{
DEVSTRUCT *pDev; /* 设备结构指针 */
RunDEVSTRUCT *pRunDev; /* 设备运行结构指针 */
INT16U i = 0; /* 配置数组索引 */
DbsInit(); /* 模块数据初始化 */
pDev = (DEVSTRUCT *)ScanToIOCfg(); /* 指向IO配置结构 */
if (NULL == pDev)
{
return(dbError(DBS_CFGFILEVER_ERR)); /* 版本错误 */
}
pRunDev = (RunDEVSTRUCT *)(DBS_ADDRESS);
deviceNum = 0;
/* 填写DP从站配置数组 */
while (pDev->Type != PEND)
{
if (((INT8U)(pDev->GroupID) <= MAXGROUP) && ((INT8U)(pDev->GroupID) > 0))
{
i = (INT16U)((pDev->GroupID) - 1);
}
else
{
return(dbError(DBS_GROUPID_ERR)); /* GroupID错误 */
}
dpDevCfg[i] = pRunDev;
initIOM(pRunDev, pDev);
deviceNum++;
pDev++;
pRunDev++;
}
if (CfgDbsRam((INT8U*)pRunDev) != 0) /* 在Dbs区中分配模块空间 */
{
return(dbError(DBS_DEVICE_TYPE_ERR));
}
CfgDPRam(); /* 在双口RAM中分配模块空间 */
if (CheckDevNum() != 0)
{
return(dbError(DBS_DEVICE_NUM_ERR));
}
return(SYS_NOERR);
} /* End of dbsLoad */
/*
功能:使用指定的值填充内存
参数: pMem 目标内存起始地址
nMem 写入区长度
value 填充值
返回值: 无
*/
void fillmem(INT8U* pMem, INT16U nMem, INT8U value)
{
INT16U i = 0;
for (i = 0; i < nMem; i++)
{
*(INT8U*)(pMem + i) = (INT8U)value;
}
}
/*
功能 : 得到指定从站的模块类型
参数 : byIOAddr 从站地址
返回值 : 成功则返回从站类型,
失败则返回0xFF, 表示从站不存在或站地址越界
*/
INT8U getIOType(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(PEND);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->Type);
}
else
{
return(PEND);
}
}
/*
功能 : 得到指定从站的在线状态
参数 : byIOAddr 从站地址
返回值 : 1 表示从站在线
0 表示从站离线
0xFF表示从站不存在或站地址越界
*/
INT8U getIOStatus(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(PEND);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->IOM.OnLine);
}
else
{
return(PEND);
}
}
/*
功能 : 得到指定从站输入数据区起始地址
参数 : byIOAddr 从站地址
返回值 : NULL 表示从站不存在或从站无输入数据区或站地址越界,
成功则返回从站输入数据起始地址
*/
INT8U* getIOInp(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(NULL);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->pInData);
}
else
{
return(NULL);
}
}
/*
功能 : 得到指定从站输入数据区长度
参数 : byIOAddr 从站地址
返回值 : 0 表示无输入数据
0xFF表示从站不存在或站地址越界
0 ~ 255 之间表示实际数据区长度
*/
INT8U getIODataInLen(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(PEND);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->RcvDataLen);
}
else
{
return(PEND);
}
}
/*
功能 : 得到指定从站输出数据区起始地址
参数 : byIOAddr 从站地址
返回值 : NULL 表示从站不存在或从站无输出数据区或站地址越界,
成功则返回从站输出数据起始地址
*/
INT8U* getIOOutp(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(NULL);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->pOutData);
}
else
{
return(NULL);
}
}
/*
功能 : 得到指定从站输出数据区长度
参数 : byIOAddr 从站地址
返回值 : 0 表示无输出数据
0xFF表示从站不存在或站地址越界
0 ~ 255 之间表示实际数据区长度
*/
INT8U getIODataOutLen(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(PEND);
}
pRunDev = dpDevCfg[byIOAddr - 1];
if (pRunDev != (RunDEVSTRUCT *)NO_DEVICE_CONFIG)
{
return(pRunDev->SndDataLen);
}
else
{
return(PEND);
}
}
/*
功能 : 得到指定从站运行结构指针
参数 : byIOAddr 从站地址
返回值 : NULL表示站地址越界
NO_DEVICE_CONFIG 表示从站不存在
成功则返回运行期结构指针
*/
RunDEVSTRUCT* getIOStructp(INT8U byIOAddr)
{
RunDEVSTRUCT *pRunDev = NULL;
if (byIOAddr > MAXGROUP)
{
return(NULL);
}
pRunDev = dpDevCfg[byIOAddr - 1];
return(pRunDev);
}
/**************************** 局部函数定义 *********************************/
/*
功能: 在Dbs区中分配模块空间
参数: pbegin dbs区可用空间起始地址
返回值: 0 成功
1 模块类型错误
*/
INT8U CfgDbsRam(INT8U* pbegin)
{
RunDEVSTRUCT *pRunDev; /* 设备运行结构指针 */
INT8U *p; /* DbsArea区可用空间起始地址 */
INT16U i = 0;
p = pbegin; /* 保存Dbs区可用空间起始地址 */
pRunDev = (RunDEVSTRUCT *)(DBS_ADDRESS);
for (i = 0; i < deviceNum; i++)
{
if (pRunDev->RcvDataLen > 0)
{
pRunDev->pInData = p;
p += pRunDev->RcvDataLen;
fillmem(pRunDev->pInData, pRunDev->RcvDataLen, 0x00);
}
if (pRunDev->SndDataLen > 0)
{
pRunDev->pOutData = p;
p += pRunDev->SndDataLen;
fillmem(pRunDev->pOutData, pRunDev->SndDataLen, 0x00);
}
dpPrmCfg[pRunDev->Type].nTotal++;
pRunDev++; /* 指向下一个设备 */
}
/* dpPrmCfg[0].nTotal存放已配置模块总数 */
dpPrmCfg[0].nTotal = (INT8U)deviceNum;
return(0);
}
/* 在双口RAM中分配IO模块数据区 */
static void CfgDPRam(void)
{
static INT8U *pDPRamIn; /* 双口RAM输入区起始地址 */
static INT8U *pDPRamOut; /* 双口RAM输出区起始地址 */
RunDEVSTRUCT *pRunDev; /* 设备运行结构指针 */
INT8U *pDPRIn; /* 双口RAM输入区可用空间起始地址 */
INT8U *pDPROut; /* 双口RAM输出区可用空间起始地址 */
INT16U i = 0;
pDPRamIn = (INT8U*)pDPRAM->RecvPd;
pDPRamOut = (INT8U*)pDPRAM->SndPd;
pRunDev = (RunDEVSTRUCT *)(DBS_ADDRESS);
pDPRIn = pDPRamIn; /* 双口RAM输入数据区起始地址 */
pDPROut = pDPRamOut; /* 双口RAM输出数据区起始地址 */
for (i = 0; i < deviceNum; i++)
{
pRunDev->IOM.pSlavePrm = dpPrmCfg[pRunDev->Type].pdpprm; /* 从站参数 */
if (pRunDev->RcvDataLen > 0)
{ /* 输入区分配 */
pRunDev->IOM.pDPRIn = pDPRIn;
pRunDev->IOM.OffsetIn = (INT16U)((INT32U)(pRunDev->IOM.pDPRIn) -
(INT32U)pDPRamIn);
pDPRIn += pRunDev->RcvDataLen;
}
if (pRunDev->SndDataLen > 0)
{ /* 输出区分配 */
pRunDev->IOM.pDPROut = pDPROut;
pRunDev->IOM.OffsetOut = (INT16U)((INT32U)(pRunDev->IOM.pDPROut) -
(INT32U)pDPRamOut);
pDPROut += pRunDev->SndDataLen;
}
pRunDev++; /* 指向下一个设备 */
}
}
/* 初始化双口RAM的指针 */
static void InitDPRamPointer(void)
{
pDPRAM = (DualPortRAM*)getDPRBaseAddr();
}
/* Dbs模块数据初始化 */
static void DbsInit(void)
{
INT16U i = 0 ;
/* 初始化DP从站配置数组 */
for (i = 0; i < MAXGROUP; i++)
{
dpDevCfg[i] = (RunDEVSTRUCT *)NO_DEVICE_CONFIG;
}
InitDPRamPointer(); /* 初始化双口RAM的指针 */
/* 初始化设备参数配置数组 */
for (i = 0; i < MAXTYPE; i++)
{
dpPrmCfg[i].pdpprm = NULL;
dpPrmCfg[i].Type = (INT8U)i;
dpPrmCfg[i].nTotal = 0;
}
}
/*
功能: 扫描配置文件直到IO配置结构区,设置DP参数配置数组指针
参数: 无
返回值: 若版本正确则返回配置文件中IO配置结构起始地址
否则返回空指针
*/
static INT8U* ScanToIOCfg(void)
{
INT8U * pTmp = NULL;
INT16U wAllPrmLen = 0; /* 配置文件中DP参数总长度 */
INT16U wCurPrmType = 0; /* 当前参数的类型:0-总线,非0-从站 */
INT16U wCurPrmLen = 0; /* 当前DP参数长度 */
INT16U wSumPrmLen = 0; /* 实际计算DP参数总长度 */
CFGFILEVER *pCfgVer = NULL; /* 配置文件版本指针 */
pTmp = (INT8U *)CONF_ROM_ADDRESS;
pCfgVer = (CFGFILEVER *)pTmp;
pTmp += VER_LEN;
wAllPrmLen = (INT16U)*(INT16U*)pTmp;
pTmp += sizeof(INT16U);
wSumPrmLen = 2;
if (RELEASE_VERSION == pCfgVer->Ver)
{
while (wSumPrmLen < wAllPrmLen)
{
/* 读入参数类型 */
wCurPrmType = *(INT16U*)pTmp;
pTmp += sizeof(INT16U);
/* 设置参数指针 */
dpPrmCfg[wCurPrmType].pdpprm = (LPBYTE)pTmp;
wCurPrmLen = *(INT16U*)pTmp;
pTmp += wCurPrmLen;
if (wCurPrmType != 0)
{ /* 将参数Group_Ident改写为当前系ID */
*(INT8U*)(dpPrmCfg[wCurPrmType].pdpprm + 24) = getSysID();
}
wSumPrmLen += wCurPrmLen + sizeof(INT16U);
}
if (wSumPrmLen != wAllPrmLen)
{
pTmp = NULL;
}
}
else
{
pTmp = NULL;
}
return(pTmp);
}
/*
功能:检查已配置模块个数的合法性
参数: 无
返回值: 0 成功, 1 设备数错误
*/
static INT8U CheckDevNum(void)
{
INT8U i = 0, nTotalDev = 0;
for (i = 1; i < MAXTYPE; i++)
{
nTotalDev += dpPrmCfg[i].nTotal;
}
if (nTotalDev == dpPrmCfg[0].nTotal)
{
return(0);
}
else
{
return(1);
}
}
/*
功能:初始化运行期模块结构
参数: pRunDev IO运行期结构指针,
pDev IO配置结构指针
返回值: 0 成功, 1 参数为空指针
*/
static INT8U initIOM(RunDEVSTRUCT *pRunDev, DEVSTRUCT *pDev)
{
if ((NULL == pRunDev) || (NULL == pDev))
{
return(1);
}
pRunDev->GroupID = pDev->GroupID;
pRunDev->Type = pDev->Type;
pRunDev->RcvDataLen = pDev->RcvDataLen ;
pRunDev->SndDataLen = pDev->SndDataLen ;
pRunDev->pStateArea = 0;
pRunDev->pInData = 0;
pRunDev->pOutData = 0;
/* 设置模块结构 */
pRunDev->IOM.Addr = (INT8U)(pDev->GroupID); /* 2oo4系统GroupID即为站地址 */
pRunDev->IOM.OnLine = 0; /* 初始化为离线状态 */
pRunDev->IOM.OffsetIn = 0x0000;
pRunDev->IOM.OffsetOut = 0x0000;
pRunDev->IOM.pDPRIn = 0;
pRunDev->IOM.pDPROut = 0;
pRunDev->IOM.pSlavePrm = 0;
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -