reflow-oven-control-sw/stm-firmware/safety/flash-crc.c

153 lines
3.9 KiB
C

/* 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;
}