/** * @brief Compute the CRC of the application code to verify its integrity * @retval FAULT_CODE_NONE or FAULT_CODE_FLASH_CORRUPTION */ uint32_t flash_helper_verify_flash_memory(void) { uint32_t crc; // Look for a flag indicating that the CRC was previously computed. // If it is blank (0xFFFFFFFF), calculate and store the CRC. if(APP_CRC_WAS_CALCULATED_FLAG_ADDRESS[0] == APP_CRC_WAS_CALCULATED_FLAG) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); crc32_reset(); // compute vector table (sector 0) crc32(VECTOR_TABLE_ADDRESS, (VECTOR_TABLE_SIZE) / 4); // skip emulated EEPROM (sector 1 and 2) // compute application code crc = crc32(APP_START_ADDRESS, (APP_SIZE) / 4); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE); // A CRC over the full image should return zero. return (crc == 0) ? FAULT_CODE_NONE : FAULT_CODE_FLASH_CORRUPTION; } else { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); // Write the flag to indicate CRC has been computed. uint16_t res = FLASH_ProgramWord((uint32_t)APP_CRC_WAS_CALCULATED_FLAG_ADDRESS, APP_CRC_WAS_CALCULATED_FLAG); if (res != FLASH_COMPLETE) { FLASH_Lock(); return FAULT_CODE_FLASH_CORRUPTION; } // Compute flash crc including the new flag RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); crc32_reset(); // compute vector table (sector 0) crc32(VECTOR_TABLE_ADDRESS, (VECTOR_TABLE_SIZE) / 4); // skip emulated EEPROM (sector 1 and 2) // compute application code crc = crc32(APP_START_ADDRESS, (APP_SIZE - 4) / 4); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE); //Store CRC res = FLASH_ProgramWord((uint32_t)APP_CRC_ADDRESS, crc); if (res != FLASH_COMPLETE) { FLASH_Lock(); return FAULT_CODE_FLASH_CORRUPTION; } FLASH_Lock(); // reboot NVIC_SystemReset(); return FAULT_CODE_NONE; } }
uint32_t flash_helper_verify_flash_memory_chunk(void) { static uint32_t index = 0; uint32_t chunk_size = 1024; uint32_t res = FAULT_CODE_NONE; uint32_t crc = 0; uint32_t tot_bytes = VECTOR_TABLE_SIZE + APP_SIZE; // Make sure RCC_AHB1Periph_CRC is enabled if (index == 0) { crc32_reset(); } if ((index + chunk_size) >= tot_bytes) { chunk_size = tot_bytes - index; } if (index < VECTOR_TABLE_SIZE) { crc32(VECTOR_TABLE_ADDRESS + index / 4, chunk_size / 4); } else { crc = crc32(APP_START_ADDRESS + (index - VECTOR_TABLE_SIZE) / 4, chunk_size / 4); } index += chunk_size; if (index >= tot_bytes) { index = 0; if (crc != 0) { res = FAULT_CODE_FLASH_CORRUPTION; } } return res; }
uint8_t PackData(char *buff, char *data, uint32_t Sequence) { uint32_t _crc; char * _p; char szSeq[20]; char szCheckSum[20]; _p = data; sprintf(szSeq, "%04X", (uint16_t)Sequence); _crc = crc32_reset(); _crc = crc32_calc_block((uint8_t *)"A", 1, _crc); _crc = crc32_calc_block((uint8_t *)_p, strlen(_p), _crc); _crc = crc32_calc_block((uint8_t *)"F", 1, _crc); _crc = crc32_final(_crc); sprintf(szCheckSum, "%08X", _crc); strcpy(buff, "<"); strcat(buff, szSeq); strcat(buff, FRM0); strcat(buff, _p); strcat(buff, FRM1); strcat(buff, szCheckSum); strcat(buff, ">"); return strlen(buff); }
uint8_t UnpackData(struct Resp *Data, uint8_t InByte) { uint32_t ERR_CODE = 0; InByte = DecodeByte(InByte); if (InByte == STX) { PROTO_STATE = READ_SQ; ResetPacket(Data); LenSeq = 0; LenC = 0; LenChS = 0; LenD1 = 0; LenD2 = 0; LenD3 = 0; } else { switch(PROTO_STATE){ case READ_SQ: { if(CheckSymb(InByte)) { Data->Seq |= InByte; LenSeq++; if (LenSeq == LEN_SEQ) { PROTO_STATE = READ_FR1; } else { Data->Seq = Data->Seq << HALF_BYTE; } } else{ PROTO_STATE = WAIT_STX; ERR_CODE = BAD_SEQ; } break; } case READ_FR1: { if (InByte == FR1) { PROTO_STATE = READ_COM; } else { ResetPacket(Data); ERR_CODE = NO_FR1; PROTO_STATE = WAIT_STX; } break; } case READ_COM: { //printf("InByte Command: %02X\n", InByte); if(CheckSymb(InByte)) { Data->Command |= InByte; LenC ++; //printf("LenC Command: %d\n", LenC); if (LenC == LEN_COM) { PROTO_STATE = READ_FR2; } else { Data->Command = Data->Command << HALF_BYTE; } } else { ResetPacket(Data); PROTO_STATE = WAIT_STX; ERR_CODE = INV_COMM; } break; } case READ_FR2: { if (InByte == FR2) { PROTO_STATE = READ_DA1; } else { ResetPacket(Data); ERR_CODE = NO_FR2; PROTO_STATE = WAIT_STX; } break; } case READ_DA1: { if(CheckSymb(InByte)) { Data->Data1 |= InByte; LenD1++; if (LenD1 == LEN_DA1) { PROTO_STATE = READ_DA2; } else { Data->Data1 = Data->Data1 << HALF_BYTE; } } else{ ResetPacket(Data); ERR_CODE = INV_DA1; PROTO_STATE = WAIT_STX; } break; } case READ_DA2: { if(CheckSymb(InByte)) { Data->Data2 |= InByte; LenD2++; if (LenD2 == LEN_DA2) { PROTO_STATE = READ_DA3; } else { Data->Data2 = Data->Data2 << HALF_BYTE; } } else{ ResetPacket(Data); ERR_CODE = INV_DA2; PROTO_STATE = WAIT_STX; } break; } case READ_DA3: { if(CheckSymb(InByte)) { Data->Data3 |= InByte; LenD3++; if (LenD3 == LEN_DA3) { PROTO_STATE = READ_FR3; } else { Data->Data3 = Data->Data3 << HALF_BYTE; } } else{ ResetPacket(Data); ERR_CODE = INV_DA3; PROTO_STATE = WAIT_STX; } break; } case READ_FR3: { if (InByte == FR3) { PROTO_STATE = READ_CHS; } else { ResetPacket(Data); ERR_CODE = NO_FR3; PROTO_STATE = WAIT_STX; } break; } case READ_CHS: { if(CheckSymb(InByte)) { Data->CheckSum |= InByte; LenChS++; if (LenChS == LEN_CHS) { PROTO_STATE = READ_ETX; } else { Data->CheckSum = Data->CheckSum << HALF_BYTE; } } else { ResetPacket(Data); ERR_CODE = INV_CKECKSUM; PROTO_STATE = WAIT_STX; } break; } case READ_ETX: { if (InByte == ETX) { uint32_t _tmpcrc; char _tmpdata[40]; sprintf(_tmpdata, "%02X:%08X%08X%04X%04X", Data->Command, (uint32_t)((Data->Data1 & 0xFFFFFFFF00000000) >> 32), (uint32_t)(Data->Data1 & 0x00000000FFFFFFFF), Data->Data2, Data->Data3); _tmpcrc = crc32_reset(); _tmpcrc = crc32_calc_block((uint8_t *)"A", 1, _tmpcrc); _tmpcrc = crc32_calc_block((uint8_t *)_tmpdata, strlen(_tmpdata), _tmpcrc); _tmpcrc = crc32_calc_block((uint8_t *)"F", 1, _tmpcrc); _tmpcrc = crc32_final(_tmpcrc); if (_tmpcrc == Data->CheckSum) { Data->EndPacket = 1; ERR_CODE = PARSED_OK; } else { Data->EndPacket = 0; ERR_CODE = 10; } } else{ ERR_CODE = NO_ETX; ResetPacket(Data); } PROTO_STATE = WAIT_STX; break; } default: { ResetPacket(Data); } }