www.pudn.com > IEC104_codeamaterial.rar > extios_l.c, change:2010-09-21,size:10339b


/*------------------------------------------------------------------------ 
 Module:		extios_l.c 
 Author:		 
 Project:		 
 Creation Date:  
 Description:	 
------------------------------------------------------------------------*/ 
 
#include <stdlib.h> 
#include <string.h> 
#include "syscfg.h" 
#include "sys.h" 
#include "extiopub.h" 
#include "extios_l.h" 
 
static DWORD SearchOneFrame(BYTE *Buf, int Len) 
{ 
	VExtIoFrmHead *pHead; 
 
	if (Len<sizeof(VExtIoFrmHead)+1)  return(PCOL_FRAME_LESS); 
		 
	pHead = (VExtIoFrmHead *)Buf; 
 
	if (pHead->byCode != EXTIO_CODE)  return(PCOL_FRAME_ERR|1); 
 
	if ((pHead->byAddr != EXTIO_BCADDR) && (pHead->byAddr != g_Sys.AddrInfo.wAddr))  return(PCOL_FRAME_ERR|1); 
 
	if (pHead->byLen > EXTIO_MAXFRM_LEN) return(PCOL_FRAME_ERR|1); 
 
	if (Len < (pHead->byLen+1)) return(PCOL_FRAME_LESS); 
	 
	if (*(Buf+pHead->byLen) != Bch(Buf,pHead->byLen)) return(PCOL_FRAME_ERR|1); 
	 
	return(PCOL_FRAME_OK|(pHead->byLen+1));	 
} 
 
static void SendFrameHead(VExtIoSL *pBus, BYTE fmType, BYTE fmFun, BYTE fmCtrl) 
{ 
	VExtIoFrmHead *pRec = (VExtIoFrmHead *)pBus->Col.RecFrm.pBuf; 
	VExtIoFrmHead *pSend = (VExtIoFrmHead *)pBus->Col.Send.pBuf; 
 
	pBus->Col.Send.wReadPtr  = 0; 
	pSend->byCode = EXTIO_CODE; 
	pSend->byAddr = (BYTE)g_Sys.AddrInfo.wAddr;	 
    if (fmCtrl & EXTIO_CTRL_MASTER)	 
		pSend->byCnt = ++pBus->byCnt; 
	else 
		pSend->byCnt = pRec->byCnt;		 
	pSend->byType = fmType; 
	pSend->byFun = fmFun; 
	pSend->byCtrl = fmCtrl; 
 
	pBus->Col.Send.wWritePtr=sizeof(VExtIoFrmHead); 
} 
 
static void SendFrameTail(VExtIoSL *pBus, BYTE fmPrio) 
{   
	VExtIoFrmHead *pSend = (VExtIoFrmHead *)pBus->Col.Send.pBuf; 
	BYTE lrcCode; 
	 
    pSend->byLen = (BYTE)pBus->Col.Send.wWritePtr; 
     
    lrcCode = Bch(pBus->Col.Send.pBuf,pBus->Col.Send.wWritePtr); 
 
    pBus->Col.Send.pBuf[pBus->Col.Send.wWritePtr++] = lrcCode; 
     
	DoSend(&pBus->Col, (pSend->byCtrl<<24)|(g_Sys.AddrInfo.wAddr<<16)|(fmPrio<<8)|0); 
}  
 
static int SendCfgSync(VExtIoSL *pBus) 
{ 
#ifdef INCLUDE_YX 
    BYTE *pnum, *pdyx; 
    int dyx; 
	VPcolCommBuf *Send = &pBus->Col.Send;	 
 
    if (TestRunFlag(RUNF_CFGSYNC_DI)) 
    { 
		SendFrameHead(pBus, EXTIO_TYPE_DICFG, EXTIO_FUN_DATA, EXTIO_CTRL_REQPOLL); 
   		pdyx = &Send->pBuf[Send->wWritePtr++];	 
		*(WORD *)(Send->pBuf+Send->wWritePtr) = (WORD)pBus->nPkgNo; 
		Send->wWritePtr += sizeof(WORD); 
   		pnum = &Send->pBuf[Send->wWritePtr++];	 
		*pnum = (BYTE)diMapRead(pBus->nPkgNo, EXTIO_MAXFRMDATA_LEN-pBus->Col.Send.wWritePtr, (VExtIoDiMap *)(pBus->Col.Send.pBuf+pBus->Col.Send.wWritePtr), &dyx); 
        *pdyx = (BYTE)dyx; 
		if (*pnum == 0) 
   		{ 
			pBus->nPkgNo = 0; 
			ClearRunFlag(RUNF_CFGSYNC_DI);			 
		} 
		else 
		{ 
			pBus->nPkgNo += (*pnum); 
			pBus->Col.Send.wWritePtr += (*pnum)*sizeof(VExtIoDiMap);	 
			SendFrameTail(pBus, FRM_PRIO_LEV7);	 
			return TRUE; 
		}	 
    }	 
#endif	     
 
    ClearRunFlag(RUNF_CFGSYNC_MASK); 
 
	evSend(BUS_CAN_ID, EV_UFLAG_DI); 
	evSend(BUS_485_ID, EV_UFLAG_DI); 
 
	return FALSE; 
} 
 
static int SendSOE(VExtIoSL *pBus, VExtIoFrmHead *pRec) 
{ 
#ifdef INCLUDE_YX 
    BYTE *pnum; 
#endif 
	VPcolCommBuf *Send = &pBus->Col.Send;	 
	 
	if ((pBus->wSoeNum) && (pBus->bySoeCnt == pRec->byCnt)) 
	{ 
#ifdef INCLUDE_YX 
		if (pBus->bySendType == EXTIO_TYPE_DISOE) 
			diSoeClear(pBus->wSoeNum); 
#endif		 
		pBus->wSoeNum = 0; 
	} 
 
#ifdef INCLUDE_YX 
	if (TestRunFlag(RUNF_DISOEF)) 
	{ 
		SendFrameHead(pBus, EXTIO_TYPE_DISOE, EXTIO_FUN_DATA, EXTIO_CTRL_REQPOLL); 
		pnum = &Send->pBuf[Send->wWritePtr++]; 
		*pnum = diSoeRead(5, (VExtIoDiSoe *)(Send->pBuf+Send->wWritePtr)); 
		if (*pnum == 0) ClearRunFlag(RUNF_DISOEF); 
		else 
		{ 
			pBus->wSoeNum = *pnum; 
			pBus->bySoeCnt = pRec->byCnt+1; 
			pBus->bySendType = EXTIO_TYPE_DISOE; 
			pBus->Col.Send.wWritePtr += (*pnum)*sizeof(VExtIoDiSoe); 
			SendFrameTail(pBus, FRM_PRIO_LEV7); 
			return TRUE; 
		}	 
	}	 
#endif 
 
	return FALSE; 
} 
 
static void SendCfgReq(VExtIoSL *pBus, BYTE id, DWORD offset) 
{ 
	VExtIoCfgFrm *pCfgFrm;  
	VPcolCommBuf *Send = &pBus->Col.Send; 
	 
	SendFrameHead(pBus, EXTIO_TYPE_CFG, EXTIO_FUN_READ, 0); 
	pCfgFrm = (VExtIoCfgFrm *)(Send->pBuf+Send->wWritePtr); 
	pCfgFrm->id = id; 
	pCfgFrm->offset = offset; 
	pBus->Col.Send.wWritePtr += sizeof(VExtIoCfgFrm); 
	SendFrameTail(pBus, FRM_PRIO_LEV7); 
} 
	 
static void SendConf(VExtIoSL *pBus, BYTE type, BYTE code) 
{ 
	SendFrameHead(pBus, type, EXTIO_FUN_CONF, 0); 
	pBus->Col.Send.pBuf[pBus->Col.Send.wWritePtr++] = code; 
	SendFrameTail(pBus, FRM_PRIO_LEV7); 
} 
 
static void ProcCfgCrcReq(VExtIoSL *pBus, VExtIoFrmHead *pRec) 
{ 
	DWORD *pbit; 
	WORD *crc; 
	 
	VPcolCommBuf *Send = &pBus->Col.Send;	 
		 
	SendFrameHead(pBus, EXTIO_TYPE_CFGCRC, EXTIO_FUN_DATA, 0); 
 
	pbit = (DWORD *)(Send->pBuf+Send->wWritePtr); 
	crc = (WORD *)(pbit+1); 
 
	*pbit = pBus->DevInfo.cfgBit; 
	*crc = pBus->DevInfo.cfgInfo[0].crc; 
	 
	Send->wWritePtr += sizeof(DWORD)+sizeof(WORD); 
	SendFrameTail(pBus, FRM_PRIO_LEV7); 
} 
 
static int WriteMyConfig(VExtIoSL *pBus) 
{ 
	struct VFileHead *pHead; 
	struct VPSysConfig *pPSysCfg; 
	struct VPFdCfg *pPFdCfg; 
	struct VPAiCfg *pPAiCfg; 
	struct VPDiCfg *pPDiCfg; 
	struct VPDoCfg *pPDoCfg; 
	//struct VPYcCfg *pPYcCfg; 
	int ret; 
 
    ret = OK; 
	 
	pHead = (struct VFileHead *)pBus->byBuf; 
	pPSysCfg=(struct VPSysConfig *)(pHead+1); 
	pPFdCfg = (struct VPFdCfg *)(pPSysCfg+1); 
	pPAiCfg = (struct VPAiCfg *)(pPFdCfg+pPSysCfg->wFDNum); 
	pPDiCfg = (struct VPDiCfg *)(pPAiCfg+pPSysCfg->wAINum); 
	pPDoCfg = (struct VPDoCfg *)(pPDiCfg+pPSysCfg->wDINum); 
	//pPYcCfg = (struct VPYcCfg *)(pPDoCfg+pPSysCfg->wDONum); 
 
#ifdef INCLUDE_YX 
	ret = SetDiCfg(0, pPSysCfg->wDINum, pPDiCfg); 
	if (ret == OK) yxChnInit(); 
#endif 
#ifdef INCLUDE_YK 
	ret = SetDoCfg(0, pPSysCfg->wDONum, pPDoCfg); 
#endif 
 
    return ret; 
} 
 
static void ProcCfgWrite(VExtIoSL *pBus, VExtIoFrmHead *pRec) 
{ 
    int ret, len; 
	struct VFileHead *pHead; 
		 
	VExtIoCfgFrm *pCfgFrm = (VExtIoCfgFrm *)(pRec+1); 
	BYTE *pData = (BYTE *)(pCfgFrm+1); 
 
	if (pCfgFrm->offset != pBus->DevInfo.cfgPtr) 
	{ 
		SendCfgReq(pBus, pBus->DevInfo.cfgId, pBus->DevInfo.cfgPtr); 
		return; 
	} 
 
	if (pRec->byCtrl & EXTIO_CTRL_SECT_1) 
	{ 
		pBus->DevInfo.cfgId = pCfgFrm->id;		 
		pHead = (struct VFileHead *)pData; 
 
		if (pHead->nLength > MAX_CFGFILE_LEN) 
		{ 
			SendConf(pBus, EXTIO_TYPE_CFG, EXTIO_RC_ERR); 
			evSend(BUS_CAN_ID, EV_KILLBUS); 
			return; 
		} 
	} 
	else if (pBus->DevInfo.cfgId != pCfgFrm->id) 
	{ 
		SendCfgReq(pBus, pBus->DevInfo.cfgId, pBus->DevInfo.cfgPtr); 
		return; 
	} 
 
    len = pRec->byLen-sizeof(VExtIoFrmHead)-sizeof(VExtIoCfgFrm); 
	memcpy(pBus->byBuf+pBus->DevInfo.cfgPtr, pData, len);	 
	pBus->DevInfo.cfgPtr += len; 
	 
	ret = OK; 
 
	if (pRec->byCtrl & EXTIO_CTRL_SECT_E) 
	{ 
		if (pBus->DevInfo.cfgId == 0) 
			ret = WriteMyConfig(pBus); 
		 
		pBus->DevInfo.cfgPtr = 0; 
	} 
 
	SendConf(pBus, EXTIO_TYPE_CFG, ret); 
	if (ret)  evSend(BUS_CAN_ID, EV_KILLBUS); 
} 
 
static void ProcCfgEnd(VExtIoSL *pBus, VExtIoFrmHead *pRec) 
{ 
	SendConf(pBus, EXTIO_TYPE_CFG, EXTIO_RC_OK); 
} 
 
static void ProcReadValue(VExtIoSL *pBus, VExtIoFrmHead *pRec) 
{	 
	if (TestRunFlag(RUNF_CFGSYNC_MASK)) 
	{ 
        if (SendCfgSync(pBus)) 
			return; 
	}	 
 
	if (TestRunFlag(RUNF_DISOEF|RUNF_YXSOEF)) 
	{ 
        if (SendSOE(pBus, pRec)) 
			return; 
	} 
 
	SendFrameHead(pBus, EXTIO_TYPE_HBEAT, EXTIO_FUN_DATA, 0); 
	SendFrameTail(pBus, FRM_PRIO_LEV7);	 
} 
 
static void ProcFrm(void *arg) 
{ 
	VExtIoSL *pBus = (VExtIoSL *)arg; 
	VExtIoFrmHead *pRec = (VExtIoFrmHead *)pBus->Col.RecFrm.pBuf; 
	 
	pBus->nNoFrm = 0; 
 
    if (TestRunFlag(RUNF_NOLOGIN)) return; 
 
    switch (pRec->byType) 
    { 
		case EXTIO_TYPE_CFGCRC: 
			ProcCfgCrcReq(pBus, pRec); 
			break; 
		case EXTIO_TYPE_CFG: 
			if (pRec->byFun == EXTIO_FUN_WRITE) 
				ProcCfgWrite(pBus, pRec); 
			else if (pRec->byFun == EXTIO_FUN_END) 
				ProcCfgEnd(pBus, pRec); 
			break; 
		case EXTIO_TYPE_VALUE: 
			ProcReadValue(pBus, pRec); 
			break; 
    }	 
} 
 
 
static void DoDiUrgency(VExtIoSL *pBus) 
{ 
	if (TestRunFlag(RUNF_CFGSYNC_MASK|RUNF_NOLOGIN)) return; 
 
#ifdef INCLUDE_YX 
	SetRunFlag(RUNF_DISOEF); 
#endif 
} 
 
static void DoTimeOut(VExtIoSL *pBus) 
{ 
    /*判断logout策略 
    与波特率有关, 115200, 时间见宏定义 
     
    1. 当低速总线(485)3秒内未收到有效报文时,要求高速总线发心跳报文; 
    2. 此时: 
       a) 高速总线异常(主机当掉或双总线均异常), 无应答平安报文,2秒后 
          判断出本装置logout 
       b) 高速总线正常,回答平安报文,之后8s内低速总线恢复正常,计数器复位 
       c) 高速总线正常,回答平安报文,但低速总线被其他设备占用(传配置、 
          传定值等), 此时计数器继续增加 
    3. 当计数器增加到8s后, 低速总线再次要求高速总线发心跳报文; 
    4. 此时: 
       a) 高速总线正常, 回答平安报文,之后的2s内低速总线恢复正常,计数器复位 
          (低速总线最大允许10秒的无访问时间, 就是10秒内低速总线必须轮询全部 
           装置一遍) 
       b  高速总线正常, 但低速总线异常(485有问题), 那么计数器继续增加, 10秒 
          后判断出本装置logout 
     
    结论: 只有双总线全部正常,通信状态才正常 
          如果双总线全部异常, 最大5秒后检出 
          如果低速总线(485)异常, 最大10秒后检出 
          如果高速总线异常, 要么初始不会登录成功, 或者10秒内由高速总线程序 
          定时平安报文检出 
    */ 
	if (TestRunFlag(RUNF_NOLOGIN)) 
    { 
		pBus->nNoFrm = 0; 
		return; 
	} 
 
	pBus->nNoFrm++; 
	if ((pBus->nNoFrm == EXTIO_REQALL_TM) || (pBus->nNoFrm == EXTIO_HBEAT_TM)) 
		evSend(BUS_CAN_ID, EV_HBEAT); 
	else if (pBus->nNoFrm >= EXTIO_LOGOUT_TM) 
	{ 
		pBus->nNoFrm = 0; 
		SetRunFlag(RUNF_NOLOGIN); 
		return; 
	} 
} 
 
void extio_low_Init(int tid) 
{ 
    VExtIoSL *pbus; 
		 
	pbus = (VExtIoSL *)malloc(sizeof(VExtIoSL)); 
	memset(pbus, 0, sizeof(VExtIoSL)); 
 
	pbus->DevInfo.cfgBit = EXTIO_CFGBIT_SYSCFG; 
	pbus->DevInfo.cfgPtr = 0; 
	pbus->DevInfo.cfgInfo[0].crc = 0; 
	 
	PcolInit(tid, &pbus->Col, ProcFrm, SearchOneFrame); 
 
    tmEvEvery(tid, SECTOTICK(1));	 
	tCreate(tid, (void  *)pbus, (ENTRYPTR)extios_low); 
} 
 
void extios_low(VExtIoSL *pBus) 
{ 
    DWORD events; 
 
    evReceive(pBus->Col.nId, EV_RX_AVAIL|EV_UFLAG_DI|EV_TM1, &events); 
 
    if (events & EV_UFLAG_DI)         
		DoDiUrgency(pBus); 
		 
    if (events & EV_RX_AVAIL)   
		DoReceive(&pBus->Col);	 
 
	if (events & EV_TM1)  
		DoTimeOut(pBus); 
}