/* Reflow Oven Controller * * Copyright (C) 2022 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * * The reflow oven controller is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * The Reflow Oven Control Firmware is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the reflow oven controller project. * If not, see . */ #include #include #include #include extern const uint32_t __ld_vectors_start; extern const uint32_t __ld_vectors_end; extern const uint32_t __ld_text_start; extern const uint32_t __ld_text_end; extern const uint32_t __ld_sdata_ccm; extern const uint32_t __ld_edata_ccm; extern const uint32_t __ld_load_ccm_data; extern const uint32_t __ld_sdata; extern const uint32_t __ld_edata; extern const uint32_t __ld_load_data; int flash_crc_trigger_check(void) { int ret = -1; int res; int any_err = 0; uint32_t crc; /* Perform CRC check over vector table */ res = flash_crc_calc_section(FLASH_CRC_VECTOR, &crc); if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_VECTOR)) safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE); any_err |= res; /* Perform CRC check over text section */ res = flash_crc_calc_section(FLASH_CRC_TEXT, &crc); if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_TEXT)) safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE); any_err |= res; /* Perform CRC check over data section */ res = flash_crc_calc_section(FLASH_CRC_DATA, &crc); if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_DATA)) safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA); any_err |= res; /* Perform CRC check over ccm data section */ res = flash_crc_calc_section(FLASH_CRC_CCMDATA, &crc); if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_CCMDATA)) safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA); any_err |= res; if (!any_err) ret = 0; return ret; } int flash_crc_calc_section(enum flash_crc_section sec, uint32_t *crc_result) { uint32_t len; const uint32_t *startptr; const uint32_t *endptr; const uint32_t *load_addr = NULL; if (!crc_result) return -1002; switch (sec) { case FLASH_CRC_VECTOR: startptr = &__ld_vectors_start; endptr = &__ld_vectors_end; break; case FLASH_CRC_TEXT: startptr = &__ld_text_start; endptr = &__ld_text_end; break; case FLASH_CRC_DATA: startptr = &__ld_sdata; endptr = &__ld_edata; load_addr = &__ld_load_data; break; case FLASH_CRC_CCMDATA: startptr = &__ld_sdata_ccm; endptr = &__ld_edata_ccm; load_addr = &__ld_load_ccm_data; break; default: return -1001; } len = (uint32_t)((void *)endptr - (void *)startptr); if (!load_addr) load_addr = startptr; /* Not a multiple of 32bit words long. Cannot calculate CRC in this case! */ if (len % 4) return -1; /* Calculate word count */ len /= 4; /* Reset CRC and calculate over data range */ crc_unit_reset(); crc_unit_input_array(load_addr, len); *crc_result = crc_unit_get_crc(); return 0; } uint32_t flash_crc_get_expected_crc(enum flash_crc_section sec) { uint32_t crc; switch (sec) { case FLASH_CRC_VECTOR: crc = crcs_in_flash.crc_section_vectors; break; case FLASH_CRC_TEXT: crc = crcs_in_flash.crc_section_text; break; case FLASH_CRC_DATA: crc = crcs_in_flash.crc_section_data; break; case FLASH_CRC_CCMDATA: crc = crcs_in_flash.crc_section_ccm_data; break; default: crc = 0xFFFFFFFFul; break; } return crc; }