#define _IN_STAPP_C #include "stapp.h" #if (APP_SAVE_TO != APP_SAVE_NONE) #include "crc32.h" #include "cpuid.h" #include "stiap.h" #include "stflash.h" //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- // 升级程序文件管理 //------------------------------------------------------------------------------- typedef struct { char xorbuf[8]; u8 xchgbuf[8]; u32 datalen; u32 bincrc; u32 rnpucrc; u32 hddatcrc; u8 rev[1024-8-8-8-8]; }GNPUHead; GNPUHead g_gnpuHead = { #if (CUR_UPFL == GAUF_PMB1) // 绘图仪主板 { 'G', 'O', 'A', 'P', 'M', 'B', 'O', 'S', }, { 4, 6, 7, 2, 3, 5, 8, 1, }, #elif (CUR_UPFL == GAUF_EMB1) // 绣花机/布线机主板 { 'G', 'O', 'A', 'E', 'M', 'B', 'O', 'S', }, { 1, 3, 5, 2, 4, 8, 6, 7, }, #elif (CUR_UPFL == GAUF_EHA1) // 平绣机头板 { 'G', 'O', 'A', 'E', 'H', 'A', 'O', 'S', }, { 5, 1, 3, 2, 7, 4, 8, 6, }, #elif (CUR_UPFL == GAUF_EHB1) // 布线机机头板 { 'G', 'O', 'A', 'E', 'H', 'B', 'O', 'S', }, { 1, 5, 2, 4, 3, 7, 6, 8, }, #elif (CUR_UPFL == GAUF_EMCLA1) // 平绣换色板 { 'G', 'O', 'A', 'E', 'C', 'L', 'A', '1', }, { 6, 1, 7, 4, 2, 5, 3, 8, }, #elif (CUR_UPFL == GAUF_EXTIO) // 扩展IO板卡 #else { 'R', 'P', 'U', 'P', 'D', 'A', 'T', 'E', }, { 1, 2, 3, 4, 5, 6, 7, 8, }, #endif 0, 0, 0, 0, { 0, }, }; // 解码RNPU数据 int DecodeData(u8 * pBuf, int len) { int i, j, k, num1; u8 tpbuf[8], opbuf[8]; u8 temp, mod; if (pBuf == NULL || len == 0) { return -1; } for (i = 0; i < len && ((len - i) >= 8); i += 8) { // 每8个字节一组数据,如果不足8字节的数据,不做处理。 memcpy(tpbuf, &(pBuf[i]), 8); // 根据交换表交换8个字节的顺序。 memcpy(opbuf, tpbuf, 8); for (j = 0; j < 8; j++) { tpbuf[g_gnpuHead.xchgbuf[j]-1] = opbuf[j]; } // 计算数组中数据位1的个数 num1 = 0; for (j = 0; j < 8; j++) { mod = 0x01; for (k = 0; k < 8; k++) { if ((tpbuf[j] & mod) != 0) { num1++; } mod *= 2; } } // 根据个数的做循环移位操作(奇数右移,偶数左移)。 if ((num1 & 0x01) != 0) // 奇数 { // 循环右移 for (j = 0; j < num1; j++) { mod = tpbuf[7]; for (k = 0; k < 8; k++) { temp = tpbuf[k]; tpbuf[k] >>= 1; // 右移 if ((mod & 0x01) != 0) { tpbuf[k] |= 0x80; } mod = temp; } } } else // 偶数 { // 循环左移 for (j = 0; j < num1; j++) { mod = tpbuf[0]; for (k = 7; k >= 0; k--) { temp = tpbuf[k]; tpbuf[k] <<= 1; // 左移 if ((mod & 0x80) != 0) { tpbuf[k] |= 0x01; } mod = temp; } } } // 数组数据和加密字符串做异或运算 for (j = 0; j < 8; j++) { tpbuf[j] ^= g_gnpuHead.xorbuf[j]; } // 得到最终的解密数组 memcpy(&(pBuf[i]), tpbuf, 8); } return 0; } //------------------------------------------------------------------------------- typedef struct { int enFlag; int saveOffset; int isrnpufile; u32 bincrc; u32 rnpucrc; int rsvCounter; }SaveAppCtrl; SaveAppCtrl g_saveAppCtrl; void InitSaveApp(void) { g_gnpuHead.datalen = 0; g_gnpuHead.bincrc = 0; g_gnpuHead.rnpucrc = 0; g_gnpuHead.hddatcrc = 0; g_saveAppCtrl.saveOffset = 0; g_saveAppCtrl.isrnpufile = 0; g_saveAppCtrl.bincrc = CRC32_INIT; g_saveAppCtrl.rnpucrc = CRC32_INIT; g_saveAppCtrl.rsvCounter = 0; IAPCleanUpdateArea(); // 清空NORflash文件区域 } // 保存一段数据到app区域 int SaveAppData(int idx, u8 * pBuf, int len, u32 ofst) { u32 addr, wtlen; int i, thislen; //printf("SaveAppData idx=%d, len=%d, ofst=0x%x\r\n", idx, len, ofst); if (idx < 0 || pBuf == NULL || (len != SUPPORT_LEN_1 && len != SUPPORT_LEN_2) || 0 ) { printf("SaveAppData para err\r\n"); return -1; } // 文件头 if (ofst == 0 && idx == 0 && g_saveAppCtrl.saveOffset < sizeof(g_gnpuHead)) { if (ofst == 0 && idx == 0) { printf("process file head\r\n"); if (memcmp(pBuf, g_gnpuHead.xorbuf, 8) == 0 && memcmp(&(pBuf[8]), g_gnpuHead.xchgbuf, 8) == 0 && 1 ) { u32 hdcrc, hddatsize; g_saveAppCtrl.isrnpufile = 1; // 填充校验 g_saveAppCtrl.bincrc = CRC32_INIT; g_saveAppCtrl.rnpucrc = CRC32_INIT; g_gnpuHead.datalen = *((u32*)&(pBuf[16])); g_gnpuHead.bincrc = *((u32*)&(pBuf[20])); g_gnpuHead.rnpucrc = *((u32*)&(pBuf[24])); g_gnpuHead.hddatcrc = *((u32*)&(pBuf[28])); hddatsize = sizeof(g_gnpuHead) - sizeof(g_gnpuHead.rev) - 4; hdcrc = CalcCrc32((u8*)(&g_gnpuHead), hddatsize); if (hdcrc == g_gnpuHead.hddatcrc) { g_saveAppCtrl.rsvCounter = g_gnpuHead.datalen; return 0; } else { printf("file head crc error\r\n"); return -2; } } else { printf("bin file not support\r\n"); // 作为bin文件升级,不安全 return -1; } } else { printf("file not correct\r\n"); return 0; } } else { } #if (APP_SAVE_TO == APP_SAVE_NORFLASH) addr = NOR_APP_ADDR; #elif (APP_SAVE_TO == APP_SAVE_EXRAM) addr = EXRAM_APP_ADDR; #elif (APP_SAVE_TO == APP_SAVE_INFLASH) addr = APP_ADDR_BEG; #else addr = 0; #endif addr += ofst; addr += ((idx-1)*len); // 写入地址务必使用idx*len; 否则在丢包,或者处理补发数据包时地址会产生偏差 wtlen = len; g_saveAppCtrl.saveOffset += len; if (g_saveAppCtrl.isrnpufile != 0) { if (g_saveAppCtrl.rsvCounter > len) { thislen = len; g_saveAppCtrl.rsvCounter -= len; } else { thislen = g_saveAppCtrl.rsvCounter; g_saveAppCtrl.rsvCounter = 0; } for (i = 0; i < thislen; i++) { g_saveAppCtrl.rnpucrc = AddCrc32(g_saveAppCtrl.rnpucrc, pBuf[i]); } DecodeData(pBuf, thislen); // 解码 for (i = 0; i < thislen; i++) { g_saveAppCtrl.bincrc = AddCrc32(g_saveAppCtrl.bincrc, pBuf[i]); } for (i = thislen; i < len; i++) { pBuf[i] = 0xff; } } else { thislen = len; } #if (APP_SAVE_TO == APP_SAVE_NORFLASH) printf("save to norflash, addr=0x%lx, wtlen=%d\r\n", addr, wtlen); DatFlashWrData(addr, pBuf, wtlen); #elif (APP_SAVE_TO == APP_SAVE_EXRAM) printf("save to exram, addr=0x%lx, wtlen=%d\r\n", addr, wtlen); memcpy((void*)addr, (void*)pBuf, wtlen); #elif (APP_SAVE_TO == APP_SAVE_INFLASH) printf("save to in flash addr=0x%lx, wtlen=%d\r\n", addr, wtlen); STMFlashWrite(addr, (u16*)pBuf, wtlen/2, 1); #else printf("not support addr=0x%lx, wtlen=%d\r\n", addr, wtlen); #endif return thislen; } // 判断接收是否完成 // 返回接收到的数据量 int IsAppReceiveDone(void) { return (int)g_gnpuHead.datalen - (int)g_saveAppCtrl.rsvCounter; } u32 GetAppSaveDataCrc(u32 addr, u32 size) { #define RD_DAT_BUF_LEN (1024) // 字节数 // 从flash读出数据再次验证 u32 crc; #if (APP_SAVE_TO == APP_SAVE_EXRAM) u8 rdata[RD_DAT_BUF_LEN]; #else u8 volatile rdata[RD_DAT_BUF_LEN]; #endif int i, thislen, rsvlen; rsvlen = size; crc = CRC32_INIT; while(addr < APP_ADDR_BEG+size) { if (rsvlen > RD_DAT_BUF_LEN) { thislen = RD_DAT_BUF_LEN; rsvlen -= RD_DAT_BUF_LEN; } else { thislen = rsvlen; rsvlen = 0; } #if (APP_SAVE_TO == APP_SAVE_NORFLASH) DatFlashRdData(addr, rdata, RD_DAT_BUF_LEN); // 读取一个扇区 #elif (APP_SAVE_TO == APP_SAVE_EXRAM) memcpy(rdata, (void*)addr, RD_DAT_BUF_LEN); #elif (APP_SAVE_TO == APP_SAVE_INFLASH) STMFlashRead(addr, (u16*)rdata, RD_DAT_BUF_LEN/2); #else #endif for (i = 0; i < thislen; i++) { crc = AddCrc32(crc, rdata[i]); } addr += RD_DAT_BUF_LEN; // 地址增加 } return crc; } int IsSaveDataCorrect(void) { u32 crc, hddatsize; int rslt; if (g_saveAppCtrl.isrnpufile == 0) { printf("g_isrnpufile == 0\r\n"); return 0; } hddatsize = sizeof(g_gnpuHead) - sizeof(g_gnpuHead.rev) - 4; // crc = CalcCrc32((u8*)(&g_gnpuHead), hddatsize); rslt = -1; printf("check g_gnpuHead crc = 0x%lx \r\n",crc); printf("g_gnpuHead.hddatcrc = 0x%lx \r\n",g_gnpuHead.hddatcrc); printf("g_gnpuHead.bincrc = 0x%lx \r\n",g_gnpuHead.bincrc); printf("g_saveAppCtrl.bincrc = 0x%lx \r\n",g_saveAppCtrl.bincrc); printf("g_gnpuHead.rnpucrc = 0x%lx \r\n",g_gnpuHead.rnpucrc); printf("g_saveAppCtrl.rnpucrc = 0x%lx \r\n",g_saveAppCtrl.rnpucrc); printf("g_gnpuHead.datalen = 0x%lx \r\n",g_gnpuHead.datalen); printf("g_saveAppCtrl.rsvCounter = 0x%lx \r\n",g_saveAppCtrl.rsvCounter); if (g_gnpuHead.hddatcrc == crc && g_gnpuHead.bincrc == g_saveAppCtrl.bincrc && g_gnpuHead.rnpucrc == g_saveAppCtrl.rnpucrc && 1 ) { crc = GetAppSaveDataCrc(APP_ADDR_BEG, g_gnpuHead.datalen); printf("calc crc = 0x%x, g_gnpuHead.bincrc = 0x%x\r\n", crc, g_gnpuHead.bincrc); if (g_gnpuHead.bincrc == crc) { rslt = 0; } else { printf("re calc file data crc error\r\n"); } } else { printf("receive file crc error\r\n"); } return rslt; } // 启动APP升级任务 void StartAppUpdate(int reboot) { if (IsSaveDataCorrect() == 0) { u32 rdstart, wrstart, len, wtlen, check; rdstart = (APP_ADDR_BEG - APP_SAVE_BASE); wrstart = (STM32_APP_ADDR - STM32_FLASH_BASE); // 文件起始地址 len = g_gnpuHead.datalen; wtlen = (g_gnpuHead.datalen + STM32_FLASH_RW_SIZE - 1) / STM32_FLASH_RW_SIZE; wtlen *= STM32_FLASH_RW_SIZE; check = g_gnpuHead.bincrc; printf("StartAppUpdate rdstart = 0x%x, wrstart = 0x%x, len = %d, wtlen = %d, wcrc=0x%x\r\n", rdstart, wrstart, len, wtlen, check); IapWritePara(rdstart, wrstart, len, wtlen, check); #if (1) // 改为不再区分,都需要重启升级 RestartMcu(); // 重启MCU #else if (reboot != 0) { RestartMcu(); // 重启MCU } else { UpdateApp(); // 升级主控文件 JumpToApp(); // 进入APP } #endif } else { printf("IsSaveDataCorrect failed\r\n"); } } #endif