QuakeGod
2024-11-25 9aed5d7e7b3c7bf09da712e9c272ece401a7acc9
ComLib/Src/KMachine.c
@@ -11,6 +11,7 @@
#include "Globaldef.h"
#include "stm32f0xx.h"
#include "stm32f0xx_ll_flash.h"
#include "PLCFunctions.h"
//#include "stm32f0xx_hal.h"
@@ -23,19 +24,22 @@
//#define FLASH_BANK1_END       ((uint32_t)0x0800FFFFU) /*!< FLASH END address of bank1 */
#define  ApplicationAddress        0x08001000  //应用程序首地址定义
#if defined(STM32F030x8) 
#define  NewAppInfoBlockAddress 0x08008000            // 存储的新应用程序信息块的地址
#define  NewAppAddress                ((uint32_t)0x08009000U)            // 存储的新应用程序的地址
#define  NEW_APP_INFOBLOCK_ADDR 0x08008000            // 存储的新应用程序信息块的地址
#define  NEW_APP_ADDR                ((uint32_t)0x08009000U)            // 存储的新应用程序的地址
#endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */
#if defined(STM32F030xC)
#define  NewAppInfoBlockAddress 0x08020000            // 存储的新应用程序信息块的地址
#define  NewAppAddress                ((uint32_t)0x08021000U)            // 存储的新应用程序的地址
#define  NEW_APP_INFOBLOCK_ADDR 0x08020000            // 存储的新应用程序信息块的地址
#define  NEW_APP_ADDR                ((uint32_t)0x08021000U)            // 存储的新应用程序的地址
#endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */
stStoredKMSysCfg storedKMSysCfg ;
stKMem KMem;
stRunStat KMRunStat;
extern void SetErrLed(uchar bOn);
//uint8_t * pFlash1 = (uint8_t *)(STORECFGBASE);
@@ -44,34 +48,7 @@
//uint16_t FlashDatas[16];
//uint32_t * pUID = (uint32_t *)(UID_BASE);
const stKMInfoBlock KMInfoBlock =
{
//   sizeof(stKMInfoBlock),
   (BOARD_TYPE<<8) + BOARD_VER,         //nDeviceType    BOARD_VER,         //nDevieVer
   0x0109,         //ProgVer
   0x0102,         //KLinkVer
   KBUS_VER,         //KBusVer
//   0x0100,         //KNetVer
//   0x0100,         //KWLVer
   4,               //nCapacity1   ?K
   1,               //nCapacity2   ?k
   DINPUT,               //nDInput;
   DOUTPUT,            //nDOutput
   0,               //nAInput
   0,               //nAOutput
   0,               //nHInput
   0,               //nHOutput
   0,               //nExt1;
   0,               //nExt2;
   0,               //nLogSize;
   0,               //nPorts;
   0,               //nManSize;
   0,               //nAbility;
   6,               //nSwitchBits;
};
/*
const char VersionStr[] __attribute__((at(FLASH_BASE + 0X2000))) //__attribute__((at(0X8001000)))
   = "3.00";
@@ -84,19 +61,19 @@
      CFG_VER,
      0x0000,            //workmode
      0x0000,            //switchfunc
      0x0000,            //pad1;
      4,            //nCfgBlockCount;
      {            //comportparam[2]
         {
            PortType_KLink,   //PorttType
            1,                     //Station
            2304,                  //Buadrate = * 100;
            0,                     //ByteSize
            1152,                  //Buadrate = * 100;
            1,                     //ByteSize
            0,                     //Parity
            0,                     //StopBits
            0,                     //endType
            1,                     //endType
            0,                     //EofChar
            0,                     //SofChar
            0,                     //endtime
            9,                     //endtime
            0,                     //recvbuf
            0,                     //bufsize
         },
@@ -104,13 +81,13 @@
            PortType_KBus,   //PorttType
            0,                     //Station
            2304,                  //Buadrate = * 100;
            0,                     //ByteSize
            1,                     //ByteSize
            0,                     //Parity
            0,                     //StopBits
            0,                     //endType
            1,                     //endType
            0,                     //EofChar
            0,                     //SofChar
            0,                     //endtime
            1,                     //endtime
            0,                     //recvbuf
            0,                     //bufsize
         }
@@ -123,38 +100,164 @@
            0x0030,
            0x0040,
            0x0050,
            0x0060
            0x0060,
            0x0070,
            0x0080,
      },
      0x0003,         //padding s
      0x0004,
      0x0005,
      0x0006,
      0x0007,
      0x0008,
      0,0,0,0,
      {
         {0,sizeof(stKMSysCfg)},
         {1,100},
         {2,100},
         {3,32},
         {4,32},
      },
      0x0008, //padding s
      0x0009,
      0x000a,
      0x000b,
      0x000c,
   },
   0x0011,            //CRC16
   END_SIGN,
};
int nEventCount=0;
int nEventMinIndex;
int nEventMaxIndex;
unsigned int nEventMaxSeq=0;
int nEventNextSpace;
int nMaxCurTime=0;
volatile int PowerState = 0;
volatile int PowerDownFlag=0;
volatile int OldPowerDownFlag=1;
volatile int OldPowerDownEventTime=0;
int nMaxRunStatIndex=-1;
unsigned int nMaxRunStatSeq=0;
int nNextRunStatSpace=0;
int KMRegisterPort(ushort nType,stPortDef * theParam)
{
   int curPortId = KMem.nTotalPorts;
   KMem.pPorts[curPortId] = theParam;
   KMem.nTotalPorts++;
   return curPortId;
}
int KMPortReqFunc(int nPortIndex,int nReqId, int nParam1, int nParam2, void ** pData, unsigned short * nlen1)
{
   if (KMem.pPorts[nPortIndex]->ReqCommFunc)
   return KMem.pPorts[nPortIndex]->ReqCommFunc(KMem.pPorts[nPortIndex]->pInstance, nReqId, nParam1, nParam2, pData, nlen1);
   else return -1;
}
int KMRunService(int nSvrId, int nParam1, int nParam2, void **pData, unsigned short *nlen1)
{
   int res;
   switch(nSvrId)
   {
      case ReqNone:
         break;
      case ReqInit:
         break;
      case ReqReset:
            __set_PRIMASK(1);    //关闭全局中断
            NVIC_SystemReset();
         break;
      case ReqStop:
         break;
      case ReqRun:
         break;
      case ReqBlinkLED:
         break;
      case ReqStartDiag:
         break;
      case ReqStopDiag:
         break;
      case ReqUpdateFirm:
         res = WriteNewApp(nParam1,*pData,*nlen1);
         break;
      case ReqUpdateFirmInfo:
      res =   WriteNewAppInfo(nParam1,*pData,*nlen1);
         break;
      default:
         res = -1;
         break;
   }
   return res;
}
int KMachineInit(void)
{
//   ClearEventLog();
   KMem.LastScanTime=0;
   KMem.ScanTimeuS=0;
   KMem.MinScanTimeuS=99999;
   KMem.MaxScanTimeuS=0;
//      KMem.SDD[14]=(unsigned int)&KMStoreSysCfg;
//      KMem.SDD[15]=(unsigned int)&KMStoreSysCfg1;
      KMem.SDD[12]=((uint32_t *)UID_BASE)[0];
//      KMem.SDD[13]=((uint32_t *)UID_BASE)[1];
//      KMem.SDD[14]=((uint32_t *)UID_BASE)[2];
      KMem.SDD[13]=PendSvCount;
      KMem.SDD[14]=RCC->CSR;
//      KMem.SDD[15]=*(uint32_t *)FLASHSIZE_BASE;
//      KMem.SDD[16]=(unsigned int)&KMSysCfg;
   KMem.nTotalPorts = 0;
   CheckEventLog();
   LoadRunStat(&KMRunStat);
   KMem.CurTimeSec=nMaxCurTime;
   KMem.TotalRunTime=KMRunStat.UpTime;
   KMRunStat.PowerCount++;
   KMem.PwrOnCount=KMRunStat.PowerCount;
   SaveRunStat(&KMRunStat);
   KMem.SDD[15]=nMaxRunStatIndex;
   KMem.SDD[16]=nMaxRunStatSeq;
   KMem.SDD[17]=nNextRunStatSpace;
   AddEventLog(KMem.CurTimeSec,EventTypePowerUp,1,12345);
   KMem.SDD[19]=nEventCount;
   KMem.SDD[20]=nEventMinIndex;
   KMem.SDD[21]=nEventMaxIndex;
   KMem.SDD[22]=nEventMaxSeq;
   KMem.SDD[23]=nEventNextSpace;
   return 0;
}
int KMachineLoopProc(void)
{
   return 0;
}
//const stKMSysCfg KMDefaultSysCfg2[7] /*__attribute__((at(STORECFGBASE+sizeof(stKMSysCfg))))*/;
   
int ReadFlashMem(void * pBuf, void * pAddrFlash, int nByteSize)
{
//   memcpy(pBuf,pAddrFlash,nSize);
   for (int i=0;i<nByteSize/4;i++)
   {
      ((uint32_t *)pBuf)[i] = ((uint32_t *)pAddrFlash)[i];
   }
   for (int i=nByteSize/4*2;i<nByteSize/2;i++)
   {
      ((uint16_t *)pBuf)[i] = ((uint16_t *)pAddrFlash)[i];
   }
   memcpy(pBuf,pAddrFlash,nByteSize);
//   for (int i=0;i<nByteSize/4;i++)
//   {
//      ((uint32_t *)pBuf)[i] = ((uint32_t *)pAddrFlash)[i];
//   }
//   for (int i=nByteSize/4*2;i<nByteSize/2;i++)
//   {
//      ((uint16_t *)pBuf)[i] = ((uint16_t *)pAddrFlash)[i];
//   }
   return nByteSize;
}
int EraseFlashMem(void * pAddrFlash, unsigned int Pages)
{
   ErrorStatus res;
@@ -162,11 +265,13 @@
//   uint32_t ErrNo;   
   res = LL_Flash_PageErase(pAddrFlash,Pages);
   LL_FLASH_Lock(FLASH);
   return 0;
   return res;
}
int WriteToFlashMemNoErase(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
      ErrorStatus res;
      SetErrLed(1);
   res = LL_Flash_Unlock();
//   __disable_irq();   
///*   
@@ -182,9 +287,11 @@
   if (res == ERROR) return 1;
   return 0;
}
int EraseAndWriteToFlashMem(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
   
      SetErrLed(1);
   ErrorStatus res;
   res = LL_Flash_Unlock();
//   __disable_irq();
@@ -207,6 +314,61 @@
   return 0;
}
/* 烧录Flash,并自动擦除,页起始和跨页时自动擦除 页面中部分不擦除 */
int WriteToFlashAutoErase(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
   SetErrLed(1);
   ErrorStatus res;
   res = LL_Flash_Unlock();
//   __disable_irq();
   int StartPage = (int)pAddrFlash / FLASH_PAGE_SIZE;
   int EndPage = ((int)pAddrFlash + nByteSize) / FLASH_PAGE_SIZE;
   int StartOffset = (int)pAddrFlash & (FLASH_PAGE_SIZE-1);
   int NbPages = EndPage -StartPage + 1;
   if (StartOffset == 0) {   // 从最开始 , 全部擦除,然后再存储.
      res = LL_Flash_PageErase(pAddrFlash,NbPages);
      for (int i=0;i<(nByteSize+1)/2;i++)
      {
         unsigned short value = ((uint8_t *)pBuf)[i*2] + (((uint8_t *)pBuf)[i*2 +1] << 8);
         res = LL_FLASH_Program(ProgaraType_DATA16, (uint32_t)pAddrFlash + i*2, value);
         if (res == ERROR) break;
      }
   }else if (NbPages > 1){      // 跨页存储
      // 先前面的部分
      int i;
      for (i=0;i<(nByteSize+1)/2 && (((int)pAddrFlash + i*2) &(FLASH_PAGE_SIZE -1))!=0 ;i++)
      {
         unsigned short value = ((uint8_t *)pBuf)[i*2] + (((uint8_t *)pBuf)[i*2 +1] << 8);
         res = LL_FLASH_Program(ProgaraType_DATA16, (uint32_t)pAddrFlash + i*2, value);
         if (res == ERROR) break;
      }
      // 擦除后面的部分.
      res = LL_Flash_PageErase((void *)((int)pAddrFlash + i*2),NbPages - 1);
      // 继续存储
      for (    ;i<(nByteSize+1)/2;i++)
      {
         unsigned short value = ((uint8_t *)pBuf)[i*2] + (((uint8_t *)pBuf)[i*2 +1] << 8);
         res = LL_FLASH_Program(ProgaraType_DATA16, (uint32_t)pAddrFlash + i*2, value);
         if (res == ERROR) break;
      }
   }else {
      // 正常写入,不需要擦除
      for (int i=0;i<(nByteSize+1)/2;i++)
      {
         unsigned short value = ((uint8_t *)pBuf)[i*2] + (((uint8_t *)pBuf)[i*2 +1] << 8);
         res = LL_FLASH_Program(ProgaraType_DATA16, (uint32_t)pAddrFlash + i*2, value);
         if (res == ERROR) break;
      }
   }
//   __enable_irq();
   LL_FLASH_Lock(FLASH);
   if (res == ERROR) return 1;
   return 0;
}
int ReadFactoryData(void * pDatabuf, int nByteCount)
{
   memcpy(pDatabuf,(stFactoryData *)FACTORY_DATA_BASE,nByteCount);
@@ -221,42 +383,160 @@
   EraseAndWriteToFlashMem(pDataBuf, (stFactoryData *)FACTORY_DATA_BASE,nByteCount);
   return 0;
}
int ReadProgram(int nProgByteAddr, void *pBuf, int nByteSize, int nBank)
#if (ENABLE_PLC)
int ReadPLCProgram(int nBank, int nProgByteAddr, void *pBuf, int nByteSize)
{
      stStoredBinProgs * pStoredProg;
   if (nBank==0)   {
      ReadFlashMem(pBuf, (void *)(STORE_PRG_BASE+nProgByteAddr), nByteSize);
      pStoredProg = (void *)(STORE_PRG_BASE);
   }else if (nBank ==1) {
      ReadFlashMem(pBuf, (void *)(ALT_PRG_BASE+nProgByteAddr), nByteSize);
   }else if (KMRunStat.nBinProgBank==0) {
      ReadFlashMem(pBuf, (void *)(STORE_PRG_BASE+nProgByteAddr), nByteSize);
      pStoredProg = (void *)(ALT_PRG_BASE);
   }else if (storedKMSysCfg.theKMSysCfg.nProgBank==0) {
      pStoredProg = (void *)(STORE_PRG_BASE);
   } else {
      ReadFlashMem(pBuf, (void *)(ALT_PRG_BASE+nProgByteAddr), nByteSize);
      pStoredProg = (void *)(ALT_PRG_BASE);
   }      
   void * progByteAddr;
      progByteAddr   =(unsigned char *)&pStoredProg->BinInstrcns   + nProgByteAddr;
      ReadFlashMem(pBuf, (void *)(progByteAddr), nByteSize);
   return 0;
}
int WriteProgram(int nProgAddress, void * pBuf, int nByteSize, int nBank)
int StartPLCProgram(int nBank, int nByteSize, int nCRC)
{
   void * progHdrAddr;
   int nRes = 0;
   if (nBank == 0) {
      progHdrAddr=(void *)(STORE_PRG_BASE);
   }else if (nBank==1) {
      progHdrAddr=(void *)(ALT_PRG_BASE);
   } else if (storedKMSysCfg.theKMSysCfg.nProgBank==0) {
      progHdrAddr=(void *)(ALT_PRG_BASE);
   }else{
      progHdrAddr=(void *)(STORE_PRG_BASE);
   }
   stStoredHdr theHdr;
   theHdr.nBlockSign = 0xAA55;
   theHdr.nBlockType = 0;
   theHdr.nSeq = 1;
   theHdr.nSize = nByteSize;
   theHdr.nCRC2 = nCRC;
   WriteToFlashAutoErase(&theHdr,(void *)progHdrAddr,sizeof(stStoredHdr));
   return nRes;
}
int WritePLCProgram(int nBank, int nProgAddress, void * pBuf, int nByteSize)
{
         // Program Save Address;//
        // Program 2 Save Address; //
   void * progByteAddr;
   stStoredBinProgs * pStoredProg;
   if (nBank == 0) {
      progByteAddr=(void *)(STORE_PRG_BASE+nProgAddress);
      pStoredProg=(stStoredBinProgs *)(STORE_PRG_BASE);
   }else if (nBank==1) {
      progByteAddr=(void *)(ALT_PRG_BASE+nProgAddress);
   } else if (KMRunStat.nBinProgBank==0) {
      progByteAddr=(void *)(ALT_PRG_BASE+nProgAddress);
      pStoredProg=(stStoredBinProgs *)(ALT_PRG_BASE);
   } else if (storedKMSysCfg.theKMSysCfg.nProgBank==0) {
      pStoredProg=(stStoredBinProgs *)(ALT_PRG_BASE);
   }else{
      progByteAddr=(void *)(STORE_PRG_BASE+nProgAddress);
      pStoredProg=(stStoredBinProgs *)(STORE_PRG_BASE);
   }
   if ( (nProgAddress & (FLASH_PAGE_SIZE - 1)) ==0)   {
      EraseAndWriteToFlashMem(pBuf, progByteAddr, nByteSize);
   }else{
      WriteToFlashMemNoErase(pBuf, progByteAddr, nByteSize);
   }
   void * progByteAddr;
      progByteAddr   =(unsigned char *)&pStoredProg->BinInstrcns   + nProgAddress;
   WriteToFlashAutoErase(pBuf,progByteAddr,nByteSize);
   return 0;
}
int FinishiPLCProgram(int nBank, int nProgSteps,int nCRC )
{
   int nRes = 0;
      if (storedKMSysCfg.theKMSysCfg.nProgBank == 0 ) {
         storedKMSysCfg.theKMSysCfg.nProgBank = 1;
      }else {
         storedKMSysCfg.theKMSysCfg.nProgBank = 0;
      }
      storedKMSysCfg.theKMSysCfg.nProgSize = nProgSteps;
      WriteSysCfgToFlash(&storedKMSysCfg);
      KMRunStat.nBinProgSize=nProgSteps;
      KMRunStat.nBinProgBank=storedKMSysCfg.theKMSysCfg.nProgBank;
      SaveRunStat(&KMRunStat);
   return nRes;
}
int ReadPLCAnno(int nBank, int nProgByteAddr, void *pBuf, int nByteSize)
{
      stStoredBinProgs * pStoredProg;
   if (nBank==0)   {
      pStoredProg = (void *)(STORE_PRG_BASE);
   }else if (nBank ==1) {
      pStoredProg = (void *)(ALT_PRG_BASE);
   }else if (storedKMSysCfg.theKMSysCfg.nProgBank==0) {
      pStoredProg = (void *)(STORE_PRG_BASE);
   } else {
      pStoredProg = (void *)(ALT_PRG_BASE);
   }
   void * progByteAddr;
      progByteAddr   =(unsigned char *)&pStoredProg->BinInstrcns   + nProgByteAddr;
      ReadFlashMem(pBuf, (void *)(progByteAddr), nByteSize);
   return 0;
}
int StartPLCAnno(int nBank, int nByteSize, int nCRC)
{
   void * StoredAnnoHdrAddr;
   int nRes = 0;
      StoredAnnoHdrAddr=(void *)(STORE_PLC_ANNO_BASE);
   stStoredHdr theHdr;
   theHdr.nBlockSign = 0xAA55;
   theHdr.nBlockType = 3;
   theHdr.nSeq = 1;
   theHdr.nSize = nByteSize;
   theHdr.nCRC2 = nCRC;
   WriteToFlashAutoErase(&theHdr,(void *)StoredAnnoHdrAddr,sizeof(stStoredHdr));
   return nRes;
}
int WritePLCAnno(int nBank, int nByteAddress, void * pBuf, int nByteSize)
{
         // Program Save Address;//
        // Program 2 Save Address; //
   stStoredAnno * pStoredAnno;
   pStoredAnno=(stStoredAnno *)(STORE_PLC_ANNO_BASE);
   void * nByteAddr;
      nByteAddr   =pStoredAnno->Annos   + nByteAddress;
   WriteToFlashAutoErase(pBuf,nByteAddr,nByteSize);
   return 0;
}
int FinishiPLCAnno(int nBank, int nByteSize,int nCRC )
{
   int nRes = 0;
      storedKMSysCfg.theKMSysCfg.nAnnoSize = nByteSize;
      WriteSysCfgToFlash(&storedKMSysCfg);
/*
      KMRunStat.nBinProgSize=nProgSteps;
      KMRunStat.nBinProgBank=storedKMSysCfg.theKMSysCfg.nProgBank;
      SaveRunStat(&KMRunStat);
*/
   return nRes;
}
#endif  //ENABLE_PLC
int LoadDefaultSysCfg(pStoredKMSysCfg theStoredKMSysCfg)
{
   memcpy(theStoredKMSysCfg,&KMDefaultSysCfg,sizeof(stStoredKMSysCfg));
@@ -435,10 +715,6 @@
      return 0;
};
int nMaxRunStatIndex=-1;
unsigned int nMaxRunStatSeq=0;
int nNextRunStatSpace=0;
int LoadDefaultRunStat(pRunStat theRunStat)
{
   theRunStat->PowerCount=1;
@@ -447,7 +723,7 @@
//   theRunStat->WorkMode=0;
//   theRunStat->WorkMode2=0;
//   theRunStat->nBinProgBank=0;
//   theRunStat->nBinProgSize=0;
//   theRunStat->nBinInstrcnSize=0;
   return 0;
}
int LoadRunStat(pRunStat theRunStat)
@@ -516,36 +792,41 @@
   return 0;
}   
int WriteNewApp(int nProgByteAddr, void *pBuf, int nByteSize)
int WriteNewApp(int nProgByteOffset, void *pBuf, int nByteSize)
{
   int res = -1;
   if ((nProgByteAddr&(FLASH_PAGE_SIZE-1)) ==0){
   int FlashSize = *(ushort *)FLASHSIZE_BASE;
   int NewAppAddress ;
   if (FlashSize == 64) {
      NewAppAddress = 0x08009000U;
   }else if (FlashSize == 256) {
      NewAppAddress = 0x08021000U;
   }
   if ((nProgByteOffset&(FLASH_PAGE_SIZE-1)) ==0){
   //   EraseFlashMem((void *)(NewAppAddress + nProgByteAddr),1);
      res = EraseAndWriteToFlashMem(pBuf,(void *)(NewAppAddress + nProgByteAddr),nByteSize);
      res = EraseAndWriteToFlashMem(pBuf,(void *)(NewAppAddress + nProgByteOffset),nByteSize);
   }else {
//      if (nByteSize>64) return 0;
      res = WriteToFlashMemNoErase(pBuf,(void *)(NewAppAddress + nProgByteAddr),nByteSize);
      res = WriteToFlashMemNoErase(pBuf,(void *)(NewAppAddress + nProgByteOffset),nByteSize);
   }
   return res;
}
int WriteNewAppInfo(int nProgByteAddr, void *pBuf, int nByteSize)
{
   int FlashSize = *(ushort *)FLASHSIZE_BASE;
   int NewAppInfoBlockAddress ;
   if (FlashSize == 64) {
      NewAppInfoBlockAddress = 0x08008000;
   }else if (FlashSize == 256) {
      NewAppInfoBlockAddress = 0x08020000;
   }
      int res = EraseAndWriteToFlashMem(pBuf,(void *)(NewAppInfoBlockAddress + nProgByteAddr),nByteSize);
   return res;
}
int nEventCount=0;
int nEventMinIndex;
int nEventMaxIndex;
unsigned int nEventMaxSeq=0;
int nEventNextSpace;
int nMaxCurTime=0;
volatile int PowerState = 0;
volatile int PowerDownEvent=0;
volatile int OldPowerDownEvent=0;
volatile int OldPowerDownEventTime=0;
int CheckEventLog()
{
@@ -637,50 +918,26 @@
   nEventNextSpace=0;
   return 0;
}
int KMachineInit(void)
{
//   ClearEventLog();
   CheckEventLog();
   LoadRunStat(&KMRunStat);
   KMem.CurTimeSec=nMaxCurTime;
   KMem.TotalRunTime=KMRunStat.UpTime;
   KMRunStat.PowerCount++;
   KMem.PwrOnCount=KMRunStat.PowerCount;
   SaveRunStat(&KMRunStat);
   KMem.SDD[15]=nMaxRunStatIndex;
   KMem.SDD[16]=nMaxRunStatSeq;
   KMem.SDD[17]=nNextRunStatSpace;
   AddEventLog(KMem.CurTimeSec,EventTypePowerUp,1,12345);
   KMem.SDD[19]=nEventCount;
   KMem.SDD[20]=nEventMinIndex;
   KMem.SDD[21]=nEventMaxIndex;
   KMem.SDD[22]=nEventMaxSeq;
   KMem.SDD[23]=nEventNextSpace;
   return 0;
inline void SetAddrBit(unsigned short * pW, unsigned char bitPos)
{
   (*pW)|=1<<(bitPos&0xf);
}
inline void SetAddrBit(unsigned short * pW, unsigned char bitAddr)
inline void ResetBit(unsigned short * pW, unsigned char bitPos)
{
   (*pW)|=1<<(bitAddr&0xf);
   (*pW)&=~(1<<(bitPos&0xf));
}
inline void ResetBit(unsigned short * pW, unsigned char bitAddr)
static inline void SetBitValue(unsigned short * pW, unsigned char bitPos, unsigned char Value)
{
   (*pW)&=~(1<<(bitAddr&0xf));
   if (Value)   {   SetAddrBit(pW, bitPos);}
   else {ResetBit(pW, bitPos);}
}
static inline void SetBitValue(unsigned short * pW, unsigned char bitAddr, unsigned char Value)
static inline unsigned char GetBitValue(unsigned short W, unsigned char bitPos)
{
   if (Value)   {   SetAddrBit(pW, bitAddr);}
   else {ResetBit(pW, bitAddr);}
}
static inline unsigned char GetBitValue(unsigned short W, unsigned char bitAddr)
{
   if (W&(1<<(bitAddr&0xf))) return 1;
   if (W&(1<<(bitPos&0xf))) return 1;
   else return 0;
}
@@ -689,44 +946,53 @@
{
      unsigned char thisValue=0;
      unsigned short nWordAddr=(nCoilAddr&0xff0)>>4;
      unsigned char nBitAddr=nCoilAddr&0xf;
      unsigned char nBitPos=nCoilAddr&0xf;
      switch(nCoilType)
      {
      case KLCoilTypeX:
         if (nCoilAddr >= KLCoilXCount) return 0;
         thisValue = GetBitValue(KMem.WX[nWordAddr], nBitAddr);
         thisValue = GetBitValue(KMem.WX[nWordAddr], nBitPos);
         break;
      case KLCoilTypeY:
         if (nCoilAddr >= KLCoilYCount) return 0;
         thisValue = GetBitValue(KMem.WY[nWordAddr], nBitAddr);
         thisValue = GetBitValue(KMem.WY[nWordAddr], nBitPos);
         break;
      case KLCoilTypeR:
         if (nCoilAddr >= KLCoilRCount) return 0;
         thisValue = GetBitValue(KMem.WR[nWordAddr], nBitAddr);
         if (nCoilAddr < KLCoilRCount) {
            thisValue = GetBitValue(KMem.WR[nWordAddr], nBitPos);
         }else if (nCoilAddr > 9000) {
            if (nCoilAddr == 9010) thisValue = 1;
            if (nCoilAddr == 9011) thisValue = 0;
            if (nCoilAddr == 9013) thisValue = GetBitValue(KMem.WSR[nWordAddr], 13);
         }
//            return thisValue;
         break;
      case KLCoilTypeLX:
         if (nCoilAddr >= KLCoilLXCount) return 0;
          thisValue = GetBitValue(KMem.WLX[nWordAddr], nBitAddr);
          thisValue = GetBitValue(KMem.WLX[nWordAddr], nBitPos);
         break;
      case KLCoilTypeLY:
         if (nCoilAddr >= KLCoilLYCount) return 0;
         thisValue = GetBitValue(KMem.WLY[nWordAddr], nBitAddr);
         thisValue = GetBitValue(KMem.WLY[nWordAddr], nBitPos);
         break;
#if (ENABLE_PLC)
      case KLCoilTypeT:
         if (nCoilAddr >= KLCoilTCount) return 0;
         thisValue = GetBitValue(KMem.WT[nWordAddr], nBitAddr);
         thisValue = GetBitValue(PLCMem.WT[nWordAddr], nBitPos);
         break;
      case KLCoilTypeC:
         if (nCoilAddr >= KLCoilCCount) return 0;
         thisValue = GetBitValue(KMem.WC[nWordAddr], nBitAddr);
         thisValue = GetBitValue(PLCMem.WC[nWordAddr], nBitPos);
         break;
#endif
      case KLCoilTypeLR:
         if (nCoilAddr >= KLCoilLRCount) return 0;
         thisValue = GetBitValue(KMem.WLR[nWordAddr], nBitAddr);
         thisValue = GetBitValue(KMem.WLR[nWordAddr], nBitPos);
         break;
      case KLCoilTypeSR:
         if (nCoilAddr >= KLCoilSRCount) return 0;
         thisValue = GetBitValue(KMem.WSR[nWordAddr], nBitAddr);
         thisValue = GetBitValue(KMem.WSR[nWordAddr], nBitPos);
         break;
         default:
            break;
@@ -759,14 +1025,16 @@
         if (nCoilAddr >= KLCoilLYCount) return 0;
         SetBitValue(&KMem.WLY[nWordAddr], nBitAddr, nCoilValue);
         break;
#if (ENABLE_PLC)
      case KLCoilTypeT:
         if (nCoilAddr >= KLCoilTCount) return 0;
         SetBitValue(&KMem.WT[nWordAddr], nBitAddr, nCoilValue);
         SetBitValue(&PLCMem.WT[nWordAddr], nBitAddr, nCoilValue);
         break;
      case KLCoilTypeC:
         if (nCoilAddr >= KLCoilCCount) return 0;
         SetBitValue(&KMem.WC[nWordAddr], nBitAddr, nCoilValue);
         SetBitValue(&PLCMem.WC[nWordAddr], nBitAddr, nCoilValue);
         break;
#endif
      case KLCoilTypeLR:
         if (nCoilAddr >= KLCoilLRCount) return 0;
         SetBitValue(&KMem.WLR[nWordAddr], nBitAddr, nCoilValue);
@@ -824,14 +1092,16 @@
      if (nDataAddr >= KLCoilLRCount) return 0;
      thisValue = KMem.WSR[nDataAddr];
      break;
#if (ENABLE_PLC)
   case KLDataTypeSV:
      if (nDataAddr >= KLDataSVCount) return 0;
      thisValue = KMem.SV[nDataAddr];
      thisValue = PLCMem.SV[nDataAddr];
      break;
   case KLDataTypeEV:
      if (nDataAddr >= KLDataEVCount) return 0;
      thisValue = KMem.EV[nDataAddr];
      thisValue = PLCMem.EV[nDataAddr];
      break;
#endif
   case KLDataTypeLD:
      if (nDataAddr >= KLDataLDCount) return 0;
      thisValue = KMem.DT[nDataAddr];
@@ -893,14 +1163,16 @@
      if (nDataAddr >= KLCoilLRCount) return 0;
      KMem.WSR[nDataAddr] = nDataValue;
      break;
#if (ENABLE_PLC)
   case KLDataTypeSV:
      if (nDataAddr >= KLDataSVCount) return 0;
      KMem.SV[nDataAddr] = nDataValue;
      PLCMem.SV[nDataAddr] = nDataValue;
      break;
   case KLDataTypeEV:
      if (nDataAddr >= KLDataEVCount) return 0;
      KMem.EV[nDataAddr] = nDataValue;
      PLCMem.EV[nDataAddr] = nDataValue;
      break;
#endif
   case KLDataTypeLD:
      if (nDataAddr >= KLDataLDCount) return 0;
      KMem.DT[nDataAddr] = nDataValue;
@@ -937,7 +1209,8 @@
         break;
      case ReqRun:
         break;
      case ReqBlink:
      case ReqBlinkLED:
         KMRunStat.bLEDFlick=nParam;
         break;
      case ReqStartDiag:
         break;