Separate flash CRC checker from safety controller and implement shell command to calculate CRCs

This commit is contained in:
2022-09-22 21:16:41 +02:00
parent aeffb9df99
commit 6570d217c7
7 changed files with 335 additions and 106 deletions

View File

@@ -0,0 +1,31 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/flash-crc-struct.h>
#include <helper-macros/helper-macros.h>
const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash = {
.start_magic = 0xA8BE53F9UL,
.crc_section_ccm_data = 0UL,
.crc_section_text = 0UL,
.crc_section_data = 0UL,
.crc_section_vectors = 0UL,
.end_magic = 0xFFA582FFUL,
};

View File

@@ -0,0 +1,152 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/flash-crc.h>
#include <reflow-controller/safety/flash-crc-struct.h>
#include <reflow-controller/safety/safety-controller.h>
#include <stm-periph/crc-unit.h>
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;
}

View File

@@ -43,6 +43,7 @@
#include <stm-periph/rcc-manager.h>
#include <reflow-controller/temp-converter.h>
#include <reflow-controller/adc-meas.h>
#include <reflow-controller/safety/flash-crc.h>
#include <reflow-controller/periph-config/safety-adc-hwcfg.h>
/**
@@ -154,15 +155,6 @@ struct overtemp_config {
uint32_t crc;
};
struct flash_crcs {
uint32_t start_magic;
uint32_t crc_section_text;
uint32_t crc_section_data;
uint32_t crc_section_ccm_data;
uint32_t crc_section_vectors;
uint32_t end_magic;
};
struct crc_monitor_register {
const volatile void *reg_addr;
uint32_t mask;
@@ -914,7 +906,7 @@ void safety_controller_init(void)
/* This is usually done by the safety memory already. But, since this module also uses the CRC... */
crc_unit_init();
safety_controller_trigger_flash_crc_check();
flash_crc_trigger_check();
stack_check_init_corruption_detect_area();
hw_rev = get_pcb_hardware_version();
@@ -1454,94 +1446,6 @@ float safety_controller_get_overtemp_limit(void)
return safety_controller_overtemp_config.overtemp_deg_celsius;
}
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 safety_controller_trigger_flash_crc_check(void)
{
/* This structs needs to be volatile!!
* This prevents the compiler form optimizing out the reads to the crcs which will be patched in later by
* a separate python script!
*/
static volatile const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash = {
.start_magic = 0xA8BE53F9UL,
.crc_section_ccm_data = 0UL,
.crc_section_text = 0UL,
.crc_section_data = 0UL,
.crc_section_vectors = 0UL,
.end_magic = 0xFFA582FFUL,
};
int ret = -1;
uint32_t len;
uint32_t crc;
/* Perform CRC check over vector table */
len = (uint32_t)((void *)&__ld_vectors_end - (void *)&__ld_vectors_start);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_vectors_start, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_vectors)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
/* Perform CRC check over text section */
len = (uint32_t)((void *)&__ld_text_end - (void *)&__ld_text_start);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_text_start, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_text)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
/* Perform CRC check over data section */
len = (uint32_t)((void *)&__ld_edata - (void *)&__ld_sdata);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_load_data, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_data)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
/* Perform CRC check over ccm data section */
len = (uint32_t)((void *)&__ld_edata_ccm - (void *)&__ld_sdata_ccm);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_load_ccm_data, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_ccm_data)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
ret = 0;
return ret;
}
int safety_controller_set_crc_monitor(enum crc_monitor mon, uint32_t password)
{
uint32_t i;