From 1e870972e3a68e0b226da1f883649f1d349e3dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 16 Jul 2021 21:17:59 +0200 Subject: [PATCH] Improve code and add a Flash CRC check --- stm-firmware/CMakeLists.txt | 2 + stm-firmware/crc-patch-elf.py | 113 ++++++++++++++++++ .../reflow-controller/safety/safety-config.h | 6 + .../safety/safety-controller.h | 7 ++ .../reflow-controller/safety/safety-memory.h | 9 +- .../reflow-controller/temp-converter.h | 2 +- stm-firmware/safety/safety-controller.c | 112 ++++++++++++++++- stm-firmware/safety/safety-memory.c | 12 +- stm-firmware/stm32f407vet6_flash.ld | 12 ++ stm-firmware/temp-converter.c | 2 +- 10 files changed, 266 insertions(+), 11 deletions(-) create mode 100755 stm-firmware/crc-patch-elf.py diff --git a/stm-firmware/CMakeLists.txt b/stm-firmware/CMakeLists.txt index 8bb0dfd..5038ad2 100644 --- a/stm-firmware/CMakeLists.txt +++ b/stm-firmware/CMakeLists.txt @@ -45,6 +45,7 @@ endif (GIT_FOUND) set(ELFFILE ${PROJECT_NAME}.elf) set(HEXFILE ${PROJECT_NAME}.hex) +set(MAPFILE ${PROJECT_NAME}.map) set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/stm32f407vet6_flash.ld) add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter) @@ -62,6 +63,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) IF(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DDEBUGBUILD) add_compile_options(-O0 -g) + add_link_options(-Wl,-Map=${MAPFILE}) ELSE() add_compile_options(-O3 -g) add_link_options(-Wl,--gc-sections) diff --git a/stm-firmware/crc-patch-elf.py b/stm-firmware/crc-patch-elf.py new file mode 100755 index 0000000..9a20386 --- /dev/null +++ b/stm-firmware/crc-patch-elf.py @@ -0,0 +1,113 @@ +#!/bin/python + +""" +This script patches the CRC checksums into an existing ELF file. + +For this, it searches the follwoing sections: + 1) .text + 2) .data + 3) .ccmdata + 4) .vectors + +All sections MUST be a multiple of 4 bytes long because the CRC calculation relies on whole 32 bit words. +The sections are excrated and the CRC is calculated for each section. + +In the section .flashcrc, the script expects a single struct with the prototype: +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; +}; + +It checks, if the start magic and end magic are set to the appropriate values and then patches in the CRC values of the sections. +The magic values checked for are: 0xA8BE53F9 and 0xFFA582FF +""" +from elftools.elf.elffile import ELFFile +from elftools.elf.segments import Segment +import elftools.elf.constants as elf_const +import sys +import crcmod +import crcmod.predefined +import struct + +crc_calc = crcmod.predefined.mkCrcFun('crc-32-mpeg') + +if len(sys.argv) < 2: + print("Usage:", sys.argv[0], ' ') + sys.exit(-1) + +filename=sys.argv[1] + +def section_calculate_crc(section): + data = bytearray(section.data()) + be_data = bytearray([0 for k in range(0, len(data))]) + # Rearrange data, because the STM controller sees it as 32 bit little endian words + for i in range(0, int(len(data)/4)): + be_data[i*4+0] = data[i*4+3] + be_data[i*4+1] = data[i*4+2] + be_data[i*4+2] = data[i*4+1] + be_data[i*4+3] = data[i*4+0] + + return crc_calc(be_data) + +with open(filename, 'r+b') as f: + elf = ELFFile(f) + sections = {} + sections['.text'] = elf.get_section_by_name('.text') + sections['.data'] = elf.get_section_by_name('.data') + sections['.ccmdata'] = elf.get_section_by_name('.ccmdata') + sections['.vectors'] = elf.get_section_by_name('.vectors') + + for key, sec in sections.items(): + if sec is None: + print("Error! Section", key, "not found in ELF file!") + sys.exit(-1) + print('Found section', key, 'Size:', + sec.data_size, 'Type:', sec['sh_type']) + if sec['sh_type'] != 'SHT_PROGBITS': + print('Error! Section must be of type SHT_PROGBITS') + sys.exit(-1) + if (sec.data_size % 4 != 0): + print("Section", key, "has wrong size. Must be a multiple of 4 bytes!") + sys.exit(-1) + + text_crc = section_calculate_crc(sections['.text']) + print('CRC of .text section:', hex(text_crc)) + data_crc = section_calculate_crc(sections['.data']) + print('CRC of .data section:', hex(data_crc)) + ccmdata_crc = section_calculate_crc(sections['.ccmdata']) + print('CRC of .ccmdata section:', hex(ccmdata_crc)) + vextors_crc = section_calculate_crc(sections['.vectors']) + print('CRC of .vectors section:', hex(vextors_crc)) + + # Check the flashcrc section + flashcrc_sec = elf.get_section_by_name('.flashcrc') + if flashcrc_sec is None: + print('Section for flash CRC missing!') + sys.exit(-1) + if flashcrc_sec.data_size != 6*4: + print("Warning!!! .flashcrc section has wrong size:",flashcrc_sec.data_size) + + crc_sec_data = bytearray(flashcrc_sec.data()) + magic1 = struct.unpack('flag_num = 0U; out->type = SAFETY_MEMORY_ERR_ENTRY_NOP; out->counter = 0U; - } else if ((entry_data & 0xFFU) == 0x51U) { + } else if ((entry_data & 0xFFU) == SAFETY_MEMORY_ERROR_ENTRY_MARKER) { out->flag_num = (uint8_t)((entry_data >> 8U) & 0xFFU); out->type = SAFETY_MEMORY_ERR_ENTRY_FLAG; out->counter = (uint16_t)((entry_data >> 16U) & 0xFFFF); @@ -57,10 +57,10 @@ static uint32_t error_memory_entry_to_word(const struct error_memory_entry *entr switch (entry->type) { case SAFETY_MEMORY_ERR_ENTRY_NOP: - word = SAFETY_MEMORY_NOP_ENTRY; + word = SAFETY_MEMORY_NOP_ENTRY_WORD; break; case SAFETY_MEMORY_ERR_ENTRY_FLAG: - word = 0x51UL | ((uint32_t)entry->flag_num << 8U) | + word = (uint32_t)SAFETY_MEMORY_ERROR_ENTRY_MARKER | ((uint32_t)entry->flag_num << 8U) | ((uint32_t)entry->counter << 16U); break; } @@ -322,9 +322,9 @@ static int safety_memory_check_error_entries() return -100; /* Valid flag entry */ - if ((data & 0xFF) == 0x51) + if ((data & 0xFF) == SAFETY_MEMORY_ERROR_ENTRY_MARKER) continue; - if (data == SAFETY_MEMORY_NOP_ENTRY) + if (data == SAFETY_MEMORY_NOP_ENTRY_WORD) continue; ret--; diff --git a/stm-firmware/stm32f407vet6_flash.ld b/stm-firmware/stm32f407vet6_flash.ld index 4b19a5b..a901124 100644 --- a/stm-firmware/stm32f407vet6_flash.ld +++ b/stm-firmware/stm32f407vet6_flash.ld @@ -44,12 +44,15 @@ SECTIONS { .vectors : ALIGN(4) { + __ld_vectors_start = .; KEEP(*(.vectors)) . = ALIGN(4); + __ld_vectors_end = .; } >FLASH =0xFF .text : ALIGN(4) { + __ld_text_start = .; *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ @@ -59,6 +62,8 @@ SECTIONS *(.eh_frame) KEEP(*(.init)) /* Constructors */ KEEP(*(.fini)) /* Destructors */ + . = ALIGN(4); + __ld_text_end = .; } >FLASH =0xFF .ARM.extab : ALIGN(4) @@ -98,6 +103,13 @@ SECTIONS /* Ensure LMA of ram data is at 32 bit word address in Flash */ . = ALIGN(4); } >FLASH =0xFF + + .flashcrc : ALIGN(4) + { + KEEP(*(.flashcrc)) + KEEP(*(.flashcrc.*)) + . = ALIGN(4); + } >FLASH =0xFF /* Initialized CCM data */ __ld_load_ccm_data = LOADADDR(.ccmdata); diff --git a/stm-firmware/temp-converter.c b/stm-firmware/temp-converter.c index 0c87c41..c76c423 100644 --- a/stm-firmware/temp-converter.c +++ b/stm-firmware/temp-converter.c @@ -75,7 +75,7 @@ return_ret_val: return ret_val; } -int temp_convertet_convert_temp_to_resistance(float temp, float *resistance_out) +int temp_converter_convert_temp_to_resistance(float temp, float *resistance_out) { int retcode = 0; unsigned int i;