QuakeGod
2024-11-25 9aed5d7e7b3c7bf09da712e9c272ece401a7acc9
ComLib/Src/KMachine.c
@@ -6,18 +6,40 @@
   */
#include "KMachine.h"
#include "KBus.h"
#include "string.h"
#include "Globaldef.h"
#include "stm32f0xx_hal.h"
#include "stm32f0xx.h"
#include "stm32f0xx_ll_flash.h"
#include "PLCFunctions.h"
//#include "stm32f0xx_hal.h"
//#define OB_BASE               ((uint32_t)0x1FFFF800U)       /*!< FLASH Option Bytes base address */
//#define FLASHSIZE_BASE        ((uint32_t)0x1FFFF7CCU)       /*!< FLASH Size register base address */
//#define UID_BASE              ((uint32_t)0x1FFFF7ACU)       /*!< Unique device ID register base address */
//#define FLASH_BASE
//#define FLASH_PAGE_SIZE               0x00000400U
//#define FLASH_BANK1_END       ((uint32_t)0x0800FFFFU) /*!< FLASH END address of bank1 */
#define  ApplicationAddress        0x08001000  //应用程序首地址定义
#if defined(STM32F030x8)
#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  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);
@@ -26,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
   0x0107,         //ProgVer
   0x0100,         //KLinkVer
   0x0100,         //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";
@@ -66,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
         },
@@ -86,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
         }
@@ -105,106 +100,273 @@
            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)
{
   HAL_StatusTypeDef res;
   res = HAL_FLASH_Unlock();
   uint32_t ErrNo;
   FLASH_EraseInitTypeDef erase1;
   erase1.NbPages=Pages;
   erase1.PageAddress=(unsigned int)pAddrFlash;
   erase1.TypeErase=FLASH_TYPEERASE_PAGES;
   res = HAL_FLASHEx_Erase(&erase1,&ErrNo);
   res = HAL_FLASH_Lock();
   ErrorStatus res;
   res = LL_Flash_Unlock();
//   uint32_t ErrNo;
   res = LL_Flash_PageErase(pAddrFlash,Pages);
   LL_FLASH_Lock(FLASH);
   return res;
}
int WriteToFlashMemNoErase(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
      HAL_StatusTypeDef res;
   res = HAL_FLASH_Unlock();
/*
   for (int i=0;i<nSize/2;i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, (uint32_t)pAddrFlash + i*2, ((uint16_t *)pBuf)[i]);
   }
*/
      ErrorStatus res;
      SetErrLed(1);
   res = LL_Flash_Unlock();
//   __disable_irq();
///*   
   for (int i=0;i<nByteSize/4;i++)
   for (int i=0;i<(nByteSize+1)/2;i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)pAddrFlash + i*4, ((uint32_t *)pBuf)[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;
   }
   for (int i = nByteSize/4 * 2 ; i < nByteSize/2 ; i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, (uint32_t)pAddrFlash + i*2, ((uint16_t *)pBuf)[i]);
   }
//*/
   res = HAL_FLASH_Lock();
   return res;
// */
//   __enable_irq();
   LL_FLASH_Lock(FLASH);
   if (res == ERROR) return 1;
   return 0;
}
int EraseAndWriteToFlashMem(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
   
   HAL_StatusTypeDef res;
   res = HAL_FLASH_Unlock();
   uint32_t ErrNo;
   FLASH_EraseInitTypeDef erase1;
   erase1.NbPages=(nByteSize-1) / FLASH_PAGESIZE + 1;;
   erase1.PageAddress=(unsigned int)pAddrFlash;
   erase1.TypeErase=FLASH_TYPEERASE_PAGES;
   res = HAL_FLASHEx_Erase(&erase1,&ErrNo);
   for (int i=0;i<nByteSize/2;i++)
      SetErrLed(1);
   ErrorStatus res;
   res = LL_Flash_Unlock();
//   __disable_irq();
   int NbPages = (nByteSize-1) / FLASH_PAGE_SIZE + 1;
//   FLASH_EraseInitTypeDef erase1;
//   erase1.NbPages=(nByteSize-1) / FLASH_PAGE_SIZE + 1;;
//   erase1.PageAddress=(unsigned int)pAddrFlash;
//   erase1.TypeErase=FLASH_TYPEERASE_PAGES;
   res = LL_Flash_PageErase(pAddrFlash,NbPages);
   for (int i=0;i<(nByteSize+1)/2;i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, (uint32_t)pAddrFlash + i*2, ((uint16_t *)pBuf)[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;
   }
/*
   for (int i=0;i<nSize/4;i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)pAddrFlash + i*4, ((uint32_t *)pBuf)[i]);
   }
//   __enable_irq();
   LL_FLASH_Lock(FLASH);
   if (res == ERROR) return 1;
   return 0;
}
/* 烧录Flash,并自动擦除,页起始和跨页时自动擦除 页面中部分不擦除 */
int WriteToFlashAutoErase(void * pBuf, void * pAddrFlash, unsigned int nByteSize)
{
   SetErrLed(1);
   ErrorStatus res;
   res = LL_Flash_Unlock();
//   __disable_irq();
   
   for (int i = nSize/4 * 2 ; i < nSize/2 ; i++)
   {
      res = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, (uint32_t)pAddrFlash + i*2, ((uint16_t *)pBuf)[i]);
   }
*/
   res = HAL_FLASH_Lock();
   int StartPage = (int)pAddrFlash / FLASH_PAGE_SIZE;
   int EndPage = ((int)pAddrFlash + nByteSize) / FLASH_PAGE_SIZE;
   int StartOffset = (int)pAddrFlash & (FLASH_PAGE_SIZE-1);
   
   return res;
   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)
@@ -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 & (STORE_PRG_PAGESIZE - 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)
@@ -456,7 +732,7 @@
   pRunStat pStoreRunStats = (pRunStat)pRunStatStore;
//   int s = sizeof(stRunStat);
   
   for (int i=0;i * sizeof(stRunStat) < (STORE_RUNSTAT_PAGESIZE * STORE_RUNSTAT_PAGES) ;i++)
   for (int i=0;i * sizeof(stRunStat) < (FLASH_PAGE_SIZE * STORE_RUNSTAT_PAGES) ;i++)
   {
      if (pStoreRunStats[i].Sign1 == START_SIGN )
      {
@@ -477,7 +753,7 @@
   // find Next Space
   // if Same Page with MaxSeq Index, then not erase, skip and skip.
   // if next Page of MaxSeq Index, then earse if not empty;
   if ((nNextRunStatSpace + 1) * sizeof(stRunStat) > STORE_RUNSTAT_PAGESIZE * STORE_RUNSTAT_PAGES)   {
   if ((nNextRunStatSpace + 1) * sizeof(stRunStat) > FLASH_PAGE_SIZE * STORE_RUNSTAT_PAGES)   {
      nNextRunStatSpace=0;
   }
   return 0;
@@ -509,25 +785,48 @@
   }
   nMaxRunStatIndex=nNextRunStatSpace;
   nNextRunStatSpace++;
   if ((nNextRunStatSpace+1) * sizeof(stRunStat) > STORE_RUNSTAT_PAGESIZE * STORE_RUNSTAT_PAGES)
   if ((nNextRunStatSpace+1) * sizeof(stRunStat) > FLASH_PAGE_SIZE * STORE_RUNSTAT_PAGES)
   {
      nNextRunStatSpace=0;
   }
   return 0;
}   
int WriteNewApp(int nProgByteOffset, void *pBuf, int nByteSize)
{
   int res = -1;
   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 + nProgByteOffset),nByteSize);
   }else {
//      if (nByteSize>64) return 0;
      res = WriteToFlashMemNoErase(pBuf,(void *)(NewAppAddress + nProgByteOffset),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 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 CheckEventLog()
{
@@ -537,7 +836,7 @@
//   int s = sizeof(stEventLog);
   nEventCount=0;
   
   for (int i=0;i * sizeof(stEventLog) < (STORE_LOG_PAGESIZE * STORE_LOG_PAGES) ;i++)
   for (int i=0;i * sizeof(stEventLog) < (FLASH_PAGE_SIZE * STORE_LOG_PAGES) ;i++)
   {
      if (theEventLog[i].Sign1 == START_SIGN )
      {
@@ -559,7 +858,7 @@
   // find Next Space
   // if Same Page with MaxSeq Index, then not erase, skip and skip.
   // if next Page of MaxSeq Index, then earse if not empty;
   if ((nEventNextSpace + 1) * sizeof(stEventLog) > STORE_LOG_PAGESIZE * STORE_LOG_PAGES)   {
   if ((nEventNextSpace + 1) * sizeof(stEventLog) > FLASH_PAGE_SIZE * STORE_LOG_PAGES)   {
      nEventNextSpace=0;
   }
   
@@ -587,7 +886,7 @@
   }
   nEventMaxIndex=nEventNextSpace;
   nEventNextSpace++;
   if ((nEventNextSpace+1) * sizeof(stEventLog) > STORE_LOG_PAGESIZE * STORE_LOG_PAGES)
   if ((nEventNextSpace+1) * sizeof(stEventLog) > FLASH_PAGE_SIZE * STORE_LOG_PAGES)
   {
      nEventNextSpace=0;
   }
@@ -600,9 +899,9 @@
{
   int nEventIndex=nEventMinIndex + nIndex;
   
   if (nEventIndex * sizeof(stEventLog) >= (STORE_LOG_PAGESIZE * STORE_LOG_PAGES))
   if (nEventIndex * sizeof(stEventLog) >= (FLASH_PAGE_SIZE * STORE_LOG_PAGES))
   {
      nEventIndex -= (STORE_LOG_PAGESIZE * STORE_LOG_PAGES)/sizeof(stEventLog);
      nEventIndex -= (FLASH_PAGE_SIZE * STORE_LOG_PAGES)/sizeof(stEventLog);
   }
   unsigned char *pFlash = (unsigned char *)(STORE_LOG_BASE + nEventIndex*sizeof(stEventLog));
   
@@ -619,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;
}
@@ -671,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;
@@ -741,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);
@@ -806,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];
@@ -875,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;
@@ -904,3 +1194,62 @@
   return 0;
}
int KMachineSvFunc (int nChn, int nSvType, int nParam,void * pBuf, int nLen1)
{
   int iRet =0;
   switch (nSvType){
      case ReqNone:
         break;
      case ReqInit:
         break;
      case ReqReset:
         break;
      case ReqStop:
         break;
      case ReqRun:
         break;
      case ReqBlinkLED:
         KMRunStat.bLEDFlick=nParam;
         break;
      case ReqStartDiag:
         break;
      case ReqStopDiag:
         break;
      case ReqTransFirmware:
         break;
      case ReqTransCfg:
         break;
      case ReqTransProg:
         break;
      case ReqTransData:
         break;
      case ReqTransBlink:
         break;
      case ReqTransChild:
         break;
      case ReqTransInfo:
         break;
      case ReqTransOutBandData:
         break;
      case ReqRead1Bit:
         break;
      case ReqWrite1Bit:
         break;
      case ReqReadBits:
         break;
      case ReqWriteBits:
         break;
      case ReqReadData:
         break;
      case ReqWriteData:
         break;
      case ReqRemoteTran:
         break;
      default:
         iRet = -1;
         break;
   }
   return iRet;
}