⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbs.c

📁 ARM得编程实例。很经典。在win ce5.0环境下的编程实例
💻 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 + -