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); }