From 7a36b597be2ab7327dc3fe873372d97b57dc5471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 30 Jul 2022 15:52:47 +0200 Subject: [PATCH 01/20] Add comment to function --- stm-firmware/safety/safety-controller.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index e7dab1b..af2c762 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -364,6 +364,10 @@ static void set_overtemp_config(float over_temperature) safety_controller_overtemp_config.crc = crc_unit_get_crc(); } +/** + * @brief Check the overtemperature config structure's CRC + * @return true if check failed. false if CRC check successful + */ static bool over_temperature_config_check(void) { if (safety_controller_overtemp_config.crc_dummy_seed != 0xA4F5C7E6UL) From 6ac108e1b215bd4562033bdfd105cd961b149105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 30 Jul 2022 15:53:04 +0200 Subject: [PATCH 02/20] make LED blink if error that stop the PID are present --- stm-firmware/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/stm-firmware/main.c b/stm-firmware/main.c index dcf8145..1351e2c 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -312,7 +312,7 @@ int main(void) * it is tried to load it from SD card. */ if (systick_ticks_have_passed(quarter_sec_timestamp, 250)) { - led_set(1, 0); + led_set(1u, 0); sd_old = sd_card_mounted; sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted); @@ -325,6 +325,14 @@ int main(void) } } + /* Check if any flags are present, that disable the PID controller. Blink + * LED 0 in this case + */ + if (oven_pid_get_status() == OVEN_PID_ABORTED) + led_set(0u, led_get(0u) ? 0 : 1); + else + led_set(0u, 0); + quarter_sec_timestamp = systick_get_global_tick(); } From aaed95cc9540502a7b84eb74776ee5fc1c897c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 30 Jul 2022 16:04:46 +0200 Subject: [PATCH 03/20] Restructure safety handle function. Now returns worst flag state set. Used to blink LED --- .../reflow-controller/safety/safety-config.h | 9 +++++++ .../safety/safety-controller.h | 4 ++-- .../reflow-controller/safety/safety-memory.h | 10 +------- stm-firmware/main.c | 5 ++-- stm-firmware/safety/safety-controller.c | 24 ++++++++++++++----- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index 009ef27..21bb281 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -27,6 +27,15 @@ #ifndef __SAFETY_CONFIG_H__ #define __SAFETY_CONFIG_H__ +/** + * @brief Weights of error flags. + */ +enum config_weight { + SAFETY_FLAG_CONFIG_WEIGHT_NONE = 0, /**< @brief This flag has no global error consequence, but might be respected by certain software modules. */ + SAFETY_FLAG_CONFIG_WEIGHT_PID = 1, /**< @brief This flag will force a stop of the temperature PID controller */ + SAFETY_FLAG_CONFIG_WEIGHT_PANIC = 2, /**< @brief This flag will trigger the panic mode */ +}; + /** * @brief Enum type representing safety flags. * diff --git a/stm-firmware/include/reflow-controller/safety/safety-controller.h b/stm-firmware/include/reflow-controller/safety/safety-controller.h index 4390d73..a25a36d 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-controller.h +++ b/stm-firmware/include/reflow-controller/safety/safety-controller.h @@ -75,9 +75,9 @@ void safety_controller_init(void); /** * @brief Handle the safety controller. * @note This function must be executed periodically in order to prevent the watchdog from resetting the firmware - * @return 0 if successful + * @returns Worst flag weigth that is currently set. */ -int safety_controller_handle(void); +enum config_weight safety_controller_handle(void); /** * @brief Report one or multiple errors to the safety controller diff --git a/stm-firmware/include/reflow-controller/safety/safety-memory.h b/stm-firmware/include/reflow-controller/safety/safety-memory.h index 0d03b0f..18e6094 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-memory.h +++ b/stm-firmware/include/reflow-controller/safety/safety-memory.h @@ -24,6 +24,7 @@ #include #include #include +#include /** @addtogroup safety-memory * @{ @@ -131,15 +132,6 @@ enum config_override_entry_type { SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE = 2, }; -/** - * @brief Weights of error flags. - */ -enum config_weight { - SAFETY_FLAG_CONFIG_WEIGHT_NONE = 0, /**< @brief This flag has no global error consequence, but might be respected by certain software modules. */ - SAFETY_FLAG_CONFIG_WEIGHT_PID = 1, /**< @brief This flag will force a stop of the temperature PID controller */ - SAFETY_FLAG_CONFIG_WEIGHT_PANIC = 2, /**< @brief This flag will trigger the panic mode */ -}; - /** * @brief representation of a config override memory entry */ diff --git a/stm-firmware/main.c b/stm-firmware/main.c index 1351e2c..d485043 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -286,6 +286,7 @@ int main(void) shellmatta_handle_t shell_handle; int menu_wait_request; uint64_t quarter_sec_timestamp = 0ULL; + enum config_weight worst_safety_flag = SAFETY_FLAG_CONFIG_WEIGHT_NONE; /** - Setup all the peripherals and external componets like LCD, EEPROM etc. and the safety controller */ setup_system(); @@ -328,7 +329,7 @@ int main(void) /* Check if any flags are present, that disable the PID controller. Blink * LED 0 in this case */ - if (oven_pid_get_status() == OVEN_PID_ABORTED) + if (worst_safety_flag >= SAFETY_FLAG_CONFIG_WEIGHT_PID) led_set(0u, led_get(0u) ? 0 : 1); else led_set(0u, 0); @@ -346,7 +347,7 @@ int main(void) temp_profile_executer_handle(); /** - Handle the safety controller. This must be called! Otherwise a watchdog reset will occur */ - safety_controller_handle(); + worst_safety_flag = safety_controller_handle(); /** - If the Oven PID controller is running, we handle its sample function */ if (oven_pid_get_status() == OVEN_PID_RUNNING) diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index af2c762..c8239fd 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -1117,12 +1117,15 @@ static void safety_controller_do_systick_checking(void) * is set, the appropriate action defined by the flag weight is executed. * @note If no flag weigth is present for a given error flag, it is treated as the most critical category * (@ref SAFETY_FLAG_CONFIG_WEIGHT_PANIC) + * + * @returns Worst config weight set */ -static void safety_controller_handle_weighted_flags(void) +static enum config_weight safety_controller_handle_weighted_flags(void) { uint32_t flag_index; volatile struct error_flag *current_flag; enum config_weight flag_weigth; + enum config_weight worst = SAFETY_FLAG_CONFIG_WEIGHT_NONE; for (flag_index = 0u; flag_index < COUNT_OF(flags); flag_index++) { current_flag = &flags[flag_index]; @@ -1132,6 +1135,11 @@ static void safety_controller_handle_weighted_flags(void) continue; flag_weigth = get_flag_weight(current_flag); + + /* Override the worst flag weigt set, if it is worse than the previous ones */ + if (flag_weigth > worst) + worst = flag_weigth; + switch (flag_weigth) { case SAFETY_FLAG_CONFIG_WEIGHT_NONE: break; @@ -1147,6 +1155,8 @@ static void safety_controller_handle_weighted_flags(void) } } + + return worst; } #ifndef DEBUGBUILD @@ -1156,9 +1166,9 @@ static void external_watchdog_toggle(void) } #endif -int safety_controller_handle(void) +enum config_weight safety_controller_handle(void) { - int ret = 0; + enum config_weight worst_weight_set; #ifndef DEBUGBUILD static uint32_t watchdog_counter = 0UL; #endif @@ -1168,9 +1178,10 @@ int safety_controller_handle(void) safety_controller_handle_memory_checks(); safety_controller_do_systick_checking(); safety_controller_process_monitor_checks(); - safety_controller_handle_weighted_flags(); + worst_weight_set = safety_controller_handle_weighted_flags(); - ret |= watchdog_ack(WATCHDOG_MAGIC_KEY); + /* Ignore error here. Will trigger restart anyway */ + (void)watchdog_ack(WATCHDOG_MAGIC_KEY); #ifndef DEBUGBUILD if (get_pcb_hardware_version() != HW_REV_V1_2) { @@ -1181,7 +1192,8 @@ int safety_controller_handle(void) } } #endif - return (ret ? -1 : 0); + + return worst_weight_set; } int safety_controller_enable_timing_mon(enum timing_monitor monitor, bool enable) From f9b9a3c6858e5a132f3af51d01326d83f3599306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 30 Jul 2022 16:45:26 +0200 Subject: [PATCH 04/20] Add compile error for configuration mistake --- stm-firmware/hw-version-detect.c | 4 ++++ stm-firmware/include/reflow-controller/hw-version-detect.h | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stm-firmware/hw-version-detect.c b/stm-firmware/hw-version-detect.c index 64df7f4..d428d12 100644 --- a/stm-firmware/hw-version-detect.c +++ b/stm-firmware/hw-version-detect.c @@ -27,6 +27,10 @@ #include #include +#if HW_REV_DETECT_PIN_LOW > HW_REV_DETECT_PIN_HIGH +#error Configuration error for Hardware derection pins. Lowest position must be less than the highest pin position. +#endif + enum hw_revision get_pcb_hardware_version(void) { uint8_t current_pin; diff --git a/stm-firmware/include/reflow-controller/hw-version-detect.h b/stm-firmware/include/reflow-controller/hw-version-detect.h index ef9721a..ff41ea4 100644 --- a/stm-firmware/include/reflow-controller/hw-version-detect.h +++ b/stm-firmware/include/reflow-controller/hw-version-detect.h @@ -48,7 +48,6 @@ */ #define HW_REV_DETECT_PIN_HIGH (15U) - /** * @brief PCB/Hardware Revision Type */ From 35542f56cba246582e11700454176efc889f079a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 9 Aug 2022 00:21:57 +0200 Subject: [PATCH 05/20] Add pylintrc and fix style problems in crc patcher --- stm-firmware/crc-patcher/crc-patch-elf.py | 128 +++-- stm-firmware/crc-patcher/pylintrc | 623 ++++++++++++++++++++++ 2 files changed, 692 insertions(+), 59 deletions(-) create mode 100644 stm-firmware/crc-patcher/pylintrc diff --git a/stm-firmware/crc-patcher/crc-patch-elf.py b/stm-firmware/crc-patcher/crc-patch-elf.py index 64e3439..69f9784 100755 --- a/stm-firmware/crc-patcher/crc-patch-elf.py +++ b/stm-firmware/crc-patcher/crc-patch-elf.py @@ -9,8 +9,9 @@ For this, it searches the follwoing sections: 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. +All sections MUST be a multiple of 4 bytes long +because the CRC calculation relies on whole 32 bit words. +The sections are extracted and the CRC is calculated for each section. In the section .flashcrc, the script expects a single struct with the prototype: struct flash_crcs { @@ -22,16 +23,16 @@ struct flash_crcs { 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. +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 struct +from elftools.elf.elffile import ELFFile import crcmod import crcmod.predefined -import struct crc_calc = crcmod.predefined.mkCrcFun('crc-32-mpeg') @@ -42,6 +43,9 @@ if len(sys.argv) < 2: filename=sys.argv[1] def section_calculate_crc(section): + """ + Calculate CRC of ELF file 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 @@ -53,62 +57,68 @@ def section_calculate_crc(section): 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') +def main(): + """ + Main function. Patches CRCs into ELF file + """ + with open(filename, 'r+b') as elf_file: + elf = ELFFile(elf_file) + 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!") + 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) - 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!") + if flashcrc_sec.data_size != 6*4: + print("Error: .flashcrc section has wrong size:",flashcrc_sec.data_size) 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)) + crc_sec_data = bytearray(flashcrc_sec.data()) + magic1 = struct.unpack('?$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string='\t' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + +# Regular expression of note tags to take in consideration. +#notes-rgx= + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it work, +# install the 'python-enchant' package. +spelling-dict= + +# List of comma separated words that should be considered directives if they +# appear and the beginning of a comment and should not be checked. +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of names allowed to shadow builtins +allowed-redefined-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + +[LOGGING] + +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + +# List of decorators that change the signature of a decorated function. +signature-mutators= + + +[CLASSES] + +# Warn about protected attribute access inside special methods +check-protected-access-in-special-methods=no + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + __post_init__ + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=cls + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[IMPORTS] + +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules= + +# Output a graph (.gv or any supported image format) of external dependencies +# to the given file (report RP0402 must not be disabled). +ext-import-graph= + +# Output a graph (.gv or any supported image format) of all (i.e. internal and +# external) dependencies to the given file (report RP0402 must not be +# disabled). +import-graph= + +# Output a graph (.gv or any supported image format) of internal dependencies +# to the given file (report RP0402 must not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "BaseException, Exception". +overgeneral-exceptions=BaseException, + Exception From ab5fd6433e20cc9fb5f65df852abed093e2667ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 9 Aug 2022 00:23:23 +0200 Subject: [PATCH 06/20] Rename python file to snake case --- stm-firmware/CMakeLists.txt | 2 +- stm-firmware/crc-patcher/{crc-patch-elf.py => crc_patch_elf.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename stm-firmware/crc-patcher/{crc-patch-elf.py => crc_patch_elf.py} (100%) diff --git a/stm-firmware/CMakeLists.txt b/stm-firmware/CMakeLists.txt index 6325d1d..04f5a23 100644 --- a/stm-firmware/CMakeLists.txt +++ b/stm-firmware/CMakeLists.txt @@ -131,7 +131,7 @@ target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updat add_custom_command( TARGET ${ELFFILE} POST_BUILD - COMMAND ./python "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/crc-patch-elf.py" "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}" + COMMAND ./python "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/crc_patch_elf.py" "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}" WORKING_DIRECTORY ${VENV_BIN} COMMENT "Running Flash CRC Patcher" ) diff --git a/stm-firmware/crc-patcher/crc-patch-elf.py b/stm-firmware/crc-patcher/crc_patch_elf.py similarity index 100% rename from stm-firmware/crc-patcher/crc-patch-elf.py rename to stm-firmware/crc-patcher/crc_patch_elf.py From ad3de6e6b746434f7c8b632b5b786ca217433058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 9 Aug 2022 00:23:55 +0200 Subject: [PATCH 07/20] Improve HW version detect code. Funtionally equivalent --- stm-firmware/hw-version-detect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stm-firmware/hw-version-detect.c b/stm-firmware/hw-version-detect.c index d428d12..7dee01e 100644 --- a/stm-firmware/hw-version-detect.c +++ b/stm-firmware/hw-version-detect.c @@ -34,7 +34,8 @@ enum hw_revision get_pcb_hardware_version(void) { uint8_t current_pin; - uint16_t port_bitmask = 0U; + uint16_t port_bitmask = 0U; /* Use uint16_t because a port can have 16 IOs max. */ + const uint16_t highest_bit_mask = (1 << (HW_REV_DETECT_PIN_HIGH - HW_REV_DETECT_PIN_LOW)); static enum hw_revision revision = HW_REV_NOT_DETECTED; /* If the revision has been previously detected, @@ -57,7 +58,7 @@ enum hw_revision get_pcb_hardware_version(void) */ for (current_pin = HW_REV_DETECT_PIN_LOW; current_pin <= HW_REV_DETECT_PIN_HIGH; current_pin++) { port_bitmask >>= 1; - port_bitmask |= (HW_REV_DETECT_GPIO->IDR & (1 << current_pin)) ? 0x0 : 0x80; + port_bitmask |= (HW_REV_DETECT_GPIO->IDR & (1 << current_pin)) ? 0x0 : highest_bit_mask; } /* Resolve the read in bitmask to a hardware version */ From aeffb9df9957341e26c3652788d63e8ab59bf544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Thu, 22 Sep 2022 21:16:07 +0200 Subject: [PATCH 08/20] Update C file generator script --- stm-firmware/create-c-file-with-header.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stm-firmware/create-c-file-with-header.py b/stm-firmware/create-c-file-with-header.py index 5ad8c48..af79b01 100755 --- a/stm-firmware/create-c-file-with-header.py +++ b/stm-firmware/create-c-file-with-header.py @@ -6,7 +6,7 @@ import pathlib license_header = """/* Reflow Oven Controller * -* Copyright (C) 2020 Mario Hüttel +* Copyright (C) 2022 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * @@ -37,7 +37,7 @@ cpath = os.path.join(project_dir, sys.argv[1]+'.c') hfile = sys.argv[1]+'.h' hpath = os.path.join(module_include_dir, hfile) -h_define = '__'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'__' +h_define = '_'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'_' if os.path.exists(cpath) or os.path.exists(hpath): print("File already exists! Abort!") From 6570d217c778c7fbe034473757928f6fc6a2357d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Thu, 22 Sep 2022 21:16:41 +0200 Subject: [PATCH 09/20] Separate flash CRC checker from safety controller and implement shell command to calculate CRCs --- .../safety/flash-crc-struct.h | 37 +++++ .../reflow-controller/safety/flash-crc.h | 56 +++++++ .../safety/safety-controller.h | 7 - stm-firmware/safety/flash-crc-struct.c | 31 ++++ stm-firmware/safety/flash-crc.c | 152 ++++++++++++++++++ stm-firmware/safety/safety-controller.c | 100 +----------- stm-firmware/ui/shell.c | 58 ++++++- 7 files changed, 335 insertions(+), 106 deletions(-) create mode 100644 stm-firmware/include/reflow-controller/safety/flash-crc-struct.h create mode 100644 stm-firmware/include/reflow-controller/safety/flash-crc.h create mode 100644 stm-firmware/safety/flash-crc-struct.c create mode 100644 stm-firmware/safety/flash-crc.c diff --git a/stm-firmware/include/reflow-controller/safety/flash-crc-struct.h b/stm-firmware/include/reflow-controller/safety/flash-crc-struct.h new file mode 100644 index 0000000..7166eaf --- /dev/null +++ b/stm-firmware/include/reflow-controller/safety/flash-crc-struct.h @@ -0,0 +1,37 @@ +/* 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 . +*/ + +#ifndef _SAFETY_FLASH_CRC_STRUCT_H_ +#define _SAFETY_FLASH_CRC_STRUCT_H_ + +#include + +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; +}; + +extern const struct flash_crcs crcs_in_flash; + +#endif /* _SAFETY_FLASH_CRC_STRUCT_H_ */ diff --git a/stm-firmware/include/reflow-controller/safety/flash-crc.h b/stm-firmware/include/reflow-controller/safety/flash-crc.h new file mode 100644 index 0000000..174dc81 --- /dev/null +++ b/stm-firmware/include/reflow-controller/safety/flash-crc.h @@ -0,0 +1,56 @@ +/* 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 . +*/ + +#ifndef _SAFETY_FLASH_CRC_H_ +#define _SAFETY_FLASH_CRC_H_ + +#include + +enum flash_crc_section { + FLASH_CRC_VECTOR = 0, + FLASH_CRC_TEXT, + FLASH_CRC_DATA, + FLASH_CRC_CCMDATA, + N_FLASH_CRC, +}; + +/** + * @brief Perform a CRC check of the flash memory and set appropriate flags + * @return negative if internal error occured. Otherwise (independent from CRC check result) 0. + * @note This function requires the safety controller (and CRC unit) to be set up before calling! + */ +int flash_crc_trigger_check(void); + +/** + * @brief Calculate CRC over flash section + * @param sec Section to calculate CRC over + * @param[out] crc_result Calculated CRC + * @return negative if internal error occured. Otherwise (independent from CRC check result) 0. + */ +int flash_crc_calc_section(enum flash_crc_section sec, uint32_t *crc_result); + +/** + * @brief Get expected CRC value of a section + * @param sec Section + * @return Expected CRC + */ +uint32_t flash_crc_get_expected_crc(enum flash_crc_section sec); + +#endif /* _SAFETY_FLASH_CRC_H_ */ diff --git a/stm-firmware/include/reflow-controller/safety/safety-controller.h b/stm-firmware/include/reflow-controller/safety/safety-controller.h index a25a36d..98ed431 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-controller.h +++ b/stm-firmware/include/reflow-controller/safety/safety-controller.h @@ -267,13 +267,6 @@ int safety_controller_set_overtemp_limit(float over_temperature); */ float safety_controller_get_overtemp_limit(void); -/** - * @brief Perform a CRC check of the flash memory and set appropriate flags - * @return negative if internal error occured. Otherwise (independent from CRC check result) 0. - * @note This function requires the safety controller to be set up before! - */ -int safety_controller_trigger_flash_crc_check(void); - /** * @brief Recalculate the CRC of a given CRC Monitor. This has to be done once the supervised registers update * @param mon Monitor to recalculate diff --git a/stm-firmware/safety/flash-crc-struct.c b/stm-firmware/safety/flash-crc-struct.c new file mode 100644 index 0000000..ebe7989 --- /dev/null +++ b/stm-firmware/safety/flash-crc-struct.c @@ -0,0 +1,31 @@ +/* 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 + +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, +}; diff --git a/stm-firmware/safety/flash-crc.c b/stm-firmware/safety/flash-crc.c new file mode 100644 index 0000000..0840802 --- /dev/null +++ b/stm-firmware/safety/flash-crc.c @@ -0,0 +1,152 @@ +/* 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; +} diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index c8239fd..72f8df5 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -43,6 +43,7 @@ #include #include #include +#include #include /** @@ -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; diff --git a/stm-firmware/ui/shell.c b/stm-firmware/ui/shell.c index 6634e8b..06f9722 100644 --- a/stm-firmware/ui/shell.c +++ b/stm-firmware/ui/shell.c @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -1020,6 +1021,53 @@ shellmatta_retCode_t shell_cmd_set_baud(const shellmatta_handle_t handle, const return SHELLMATTA_OK; } +static void shell_print_crc_line(const shellmatta_handle_t handle, const char *name, + uint32_t crc, uint32_t crc_expected) +{ + shellmatta_printf(handle, "%-15s0x%08x 0x%08x [%s]\r\n", + name, + crc, + crc_expected, + crc != crc_expected ? "\e[1;31mERR\e[m" : "\e[32mOK\e[m"); +} + +shellmatta_retCode_t shell_cmd_flash_crc(const shellmatta_handle_t handle, const char *args, uint32_t len) +{ + (void)args; + (void)len; + uint32_t crc = 0; + uint32_t crc_expected = 0; + int res; + + shellmatta_printf(handle, " Calculated Expected State\r\n\r\n"); + + res = flash_crc_calc_section(FLASH_CRC_VECTOR, &crc); + crc_expected = flash_crc_get_expected_crc(FLASH_CRC_VECTOR); + if (res) + shellmatta_printf(handle, "Error during calculation!\r\n"); + shell_print_crc_line(handle, "Vector CRC:", crc, crc_expected); + + res = flash_crc_calc_section(FLASH_CRC_TEXT, &crc); + crc_expected = flash_crc_get_expected_crc(FLASH_CRC_TEXT); + if (res) + shellmatta_printf(handle, "Error during calculation!\r\n"); + shell_print_crc_line(handle, "Code CRC:", crc, crc_expected); + + res = flash_crc_calc_section(FLASH_CRC_DATA, &crc); + crc_expected = flash_crc_get_expected_crc(FLASH_CRC_DATA); + if (res) + shellmatta_printf(handle, "Error during calculation!\r\n"); + shell_print_crc_line(handle, "Data CRC:", crc, crc_expected); + + res = flash_crc_calc_section(FLASH_CRC_CCMDATA, &crc); + crc_expected = flash_crc_get_expected_crc(FLASH_CRC_CCMDATA); + if (res) + shellmatta_printf(handle, "Error during calculation!\r\n"); + shell_print_crc_line(handle, "CCM Data CRC:", crc, crc_expected); + + return SHELLMATTA_OK; +} + //typedef struct shellmatta_cmd //{ // char *cmd; /**< command name */ @@ -1029,7 +1077,7 @@ shellmatta_retCode_t shell_cmd_set_baud(const shellmatta_handle_t handle, const // shellmatta_cmdFct_t cmdFct; /**< pointer to the cmd callack function */ // struct shellmatta_cmd *next; /**< pointer to next command or NULL */ //} shellmatta_cmd_t; -static shellmatta_cmd_t cmd[25] = { +static shellmatta_cmd_t cmd[26] = { { .cmd = "version", .cmdAlias = "ver", @@ -1229,6 +1277,14 @@ static shellmatta_cmd_t cmd[25] = { .helpText = "Set a new temporary baudrate for the UART", .usageText = "baudrate ", .cmdFct = shell_cmd_set_baud, + .next = &cmd[25], + }, + { + .cmd = "flashcrc", + .cmdAlias = "fcrc", + .helpText = "Calculate the Flash CRCs", + .usageText = "flashcrc", + .cmdFct = shell_cmd_flash_crc, .next = NULL, }, From 354c26ca67e21bbee11b3495d47f3ebf7f4206d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Tue, 25 Oct 2022 21:23:02 +0200 Subject: [PATCH 10/20] Change Build step to use pathcelfcrc program instead of python script --- stm-firmware/CMakeLists.txt | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/stm-firmware/CMakeLists.txt b/stm-firmware/CMakeLists.txt index 04f5a23..2eb28a8 100644 --- a/stm-firmware/CMakeLists.txt +++ b/stm-firmware/CMakeLists.txt @@ -1,7 +1,7 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_CROSSCOMPILING 1) -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.18) set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake") @@ -43,26 +43,12 @@ else (GIT_FOUND) message("Version is set to: ${GIT_DESCRIBE}${ColorReset}") endif (GIT_FOUND) -find_program(VIRTUALENV virtualenv) -if (VIRTUALENV) - message("Python virtual environment found") - execute_process( - COMMAND ${VIRTUALENV} venv - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY - ) - set(VENV_BIN "${CMAKE_CURRENT_BINARY_DIR}/venv/bin") - execute_process( - COMMAND ./pip install -r "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/requirements.txt" - WORKING_DIRECTORY ${VENV_BIN} - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY - ) - message("${BoldGreen}python virtual environment set up!${ColorReset}") -else(VIRTUALENV) - message(FATAL_ERROR "${BoldRed}Python virtual environment not set up: virtualenv: command not found!${ColorReset}") -endif (VIRTUALENV) +find_program(PATCHELFCRC patchelfcrc) +if (PATCHELFCRC) + message("patchelfcrc found: ${PATCHELFCRC}") +else(PATCHELFCRC) + message(FATAL_ERROR "${BoldRed}Patchelfcrc not found. Cannot patch CRC checksum into ELF file: patchelfcrc: command not found! See: https://git.shimatta.de/mhu/patchelfcrc${ColorReset}") +endif (PATCHELFCRC) set(ELFFILE ${PROJECT_NAME}.elf) @@ -131,8 +117,8 @@ target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updat add_custom_command( TARGET ${ELFFILE} POST_BUILD - COMMAND ./python "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/crc_patch_elf.py" "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}" - WORKING_DIRECTORY ${VENV_BIN} + COMMAND ${PATCHELFCRC} --little-endian --verbose --granularity word --start-magic 0xa8be53f9 --end-magic 0xffa582ff -O .flashcrc -p crc-32-mpeg -S .text -S .data -S .ccmdata -S .vectors "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running Flash CRC Patcher" ) From f46044e5fce31d264c0d25c9ba155e91d9017f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 19:24:27 +0100 Subject: [PATCH 11/20] Remove mthumb-interwork from GCC command line. It is not neededfor CM4 cores --- stm-firmware/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stm-firmware/CMakeLists.txt b/stm-firmware/CMakeLists.txt index 2eb28a8..164ee2f 100644 --- a/stm-firmware/CMakeLists.txt +++ b/stm-firmware/CMakeLists.txt @@ -57,7 +57,7 @@ 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) -add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare) +add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare) set(GIT_DESCRIBE "${GIT_DESCRIBE}") @@ -110,7 +110,7 @@ add_executable(${ELFFILE} ${MAIN_SOURCES} ${CFG_PARSER_SRCS} ${UI_SRCS} add_dependencies(${ELFFILE} updater-ram-code-header-blob) target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/shellmatta/api ${CMAKE_CURRENT_SOURCE_DIR}/config-parser/include) -target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage) +target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage) target_link_libraries(${ELFFILE} base64-lib linklist-lib) target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updater/ram-code/include/") From 240b1ffc8f770bc00e294e0ca2adcb5722477a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 19:25:55 +0100 Subject: [PATCH 12/20] Update gitignore for use with vscode and clangd --- stm-firmware/.gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stm-firmware/.gitignore b/stm-firmware/.gitignore index bcb7a46..3258d04 100644 --- a/stm-firmware/.gitignore +++ b/stm-firmware/.gitignore @@ -16,3 +16,10 @@ reflow-controller.includes *.files *.user.* *.user + +# VSCODE and CLANGD sepcific excludes + +.vscode/ +build/ +.cache/ +compile_commands.json From aade3288ebec5d0266a0540a8dcc6639038f9444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 19:43:37 +0100 Subject: [PATCH 13/20] Update doxygen headers in config parser --- stm-firmware/config-parser/config-parser.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stm-firmware/config-parser/config-parser.c b/stm-firmware/config-parser/config-parser.c index 3522ddd..2ec48e4 100644 --- a/stm-firmware/config-parser/config-parser.c +++ b/stm-firmware/config-parser/config-parser.c @@ -28,7 +28,14 @@ #include #include +/** + * @brief Config parser magic value used to check sanity of passed structs + */ #define CONFIG_PARSER_MAGIC 0x464a6e2bUL + +/** + * @brief Config parser type casting macro + */ #define CONFIG_PARSER(p) ((struct config_parser *)(p)) /** From b621c66378b76da291de6934f5af18de1af4653b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 19:53:45 +0100 Subject: [PATCH 14/20] Update Flag Weights * Fix #47: Update flash and data CRCs to trigger panic mode * Update meas ADC CRC flag to stop PID * Update safety ADC CRC flag to trigger panic mode --- .../reflow-controller/safety/safety-config.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index 21bb281..4f451d7 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -168,7 +168,7 @@ enum analog_value_monitor { #define SAFETY_CRC_MON_SAFETY_ADC_PW 0xA8DF2368 /** - * @brief Default persistence of safety flags. These values are loaded into the safety tables on startup + * @brief Default persistence of safety flags. These values are loaded into the safety tables on startup. */ #define SAFETY_CONFIG_DEFAULT_PERSIST ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_OFF, false), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, false), \ @@ -192,9 +192,9 @@ enum analog_value_monitor { ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_FLASH_CRC_CODE, true), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_FLASH_CRC_DATA, true), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, true), \ - ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, true), \ + ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, true) /** - * @brief Default config weights of safety flags. These values are loaded into the safety tables on startup + * @brief Default config weights of safety flags. These values are loaded into the safety tables on startup. */ #define SAFETY_CONFIG_DEFAULT_WEIGHTS ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_OFF, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ @@ -215,9 +215,9 @@ enum analog_value_monitor { ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_OVERTEMP, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ - ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_CODE, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ - ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_DATA, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ - ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ - ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_CODE, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_DATA, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PID), \ + ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PANIC) #endif /* __SAFETY_CONFIG_H__ */ From e91b33f37917250a55a72e813420ce8890014113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 19:56:33 +0100 Subject: [PATCH 15/20] Remove old CRC patcher --- stm-firmware/crc-patcher/crc_patch_elf.py | 124 ----- stm-firmware/crc-patcher/pylintrc | 623 ---------------------- stm-firmware/crc-patcher/requirements.txt | 2 - 3 files changed, 749 deletions(-) delete mode 100755 stm-firmware/crc-patcher/crc_patch_elf.py delete mode 100644 stm-firmware/crc-patcher/pylintrc delete mode 100644 stm-firmware/crc-patcher/requirements.txt diff --git a/stm-firmware/crc-patcher/crc_patch_elf.py b/stm-firmware/crc-patcher/crc_patch_elf.py deleted file mode 100755 index 69f9784..0000000 --- a/stm-firmware/crc-patcher/crc_patch_elf.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/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 extracted 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 -""" - -import sys -import struct -from elftools.elf.elffile import ELFFile -import crcmod -import crcmod.predefined - -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): - """ - Calculate CRC of ELF file 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) - -def main(): - """ - Main function. Patches CRCs into ELF file - """ - with open(filename, 'r+b') as elf_file: - elf = ELFFile(elf_file) - 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("Error: .flashcrc section has wrong size:",flashcrc_sec.data_size) - sys.exit(-1) - - crc_sec_data = bytearray(flashcrc_sec.data()) - magic1 = struct.unpack('?$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string='\t' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module. -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO - -# Regular expression of note tags to take in consideration. -#notes-rgx= - - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes. -max-spelling-suggestions=4 - -# Spelling dictionary name. Available dictionaries: none. To make it work, -# install the 'python-enchant' package. -spelling-dict= - -# List of comma separated words that should be considered directives if they -# appear and the beginning of a comment and should not be checked. -spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains the private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to the private dictionary (see the -# --spelling-private-dict-file option) instead of raising a message. -spelling-store-unknown-words=no - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid defining new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of names allowed to shadow builtins -allowed-redefined-builtins= - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_, - _cb - -# A regular expression matching the name of dummy variables (i.e. expected to -# not be used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore. -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io - - -[LOGGING] - -# The type of string formatting that logging methods do. `old` means using % -# formatting, `new` is for `{}` formatting. -logging-format-style=old - -# Logging modules to check that the string format arguments are in logging -# function parameter format. -logging-modules=logging - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# Tells whether to warn about missing members when the owner of the attribute -# is inferred to be None. -ignore-none=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis). It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - -# List of decorators that change the signature of a decorated function. -signature-mutators= - - -[CLASSES] - -# Warn about protected attribute access inside special methods -check-protected-access-in-special-methods=no - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp, - __post_init__ - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=cls - - -[DESIGN] - -# Maximum number of arguments for function / method. -max-args=5 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in an if statement (see R0916). -max-bool-expr=5 - -# Maximum number of branch for function / method body. -max-branches=12 - -# Maximum number of locals for function / method body. -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body. -max-returns=6 - -# Maximum number of statements in function / method body. -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[IMPORTS] - -# List of modules that can be imported at any level, not just the top level -# one. -allow-any-import-level= - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma. -deprecated-modules= - -# Output a graph (.gv or any supported image format) of external dependencies -# to the given file (report RP0402 must not be disabled). -ext-import-graph= - -# Output a graph (.gv or any supported image format) of all (i.e. internal and -# external) dependencies to the given file (report RP0402 must not be -# disabled). -import-graph= - -# Output a graph (.gv or any supported image format) of internal dependencies -# to the given file (report RP0402 must not be disabled). -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - -# Couples of modules and preferred modules, separated by a comma. -preferred-modules= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "BaseException, Exception". -overgeneral-exceptions=BaseException, - Exception diff --git a/stm-firmware/crc-patcher/requirements.txt b/stm-firmware/crc-patcher/requirements.txt deleted file mode 100644 index 90599cf..0000000 --- a/stm-firmware/crc-patcher/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -crcmod==1.7 -pyelftools==0.27 From 5e00441d99b06519836562eb1358b3b4b34af275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 20:18:34 +0100 Subject: [PATCH 16/20] Add separate source file handling the mounting of the SD card. This will give proper access to the GUI to check whether an SD is mounted --- stm-firmware/include/reflow-controller/sd.h | 42 ++++++++++++++ stm-firmware/main.c | 38 +------------ stm-firmware/sd.c | 62 +++++++++++++++++++++ 3 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 stm-firmware/include/reflow-controller/sd.h create mode 100644 stm-firmware/sd.c diff --git a/stm-firmware/include/reflow-controller/sd.h b/stm-firmware/include/reflow-controller/sd.h new file mode 100644 index 0000000..5233a71 --- /dev/null +++ b/stm-firmware/include/reflow-controller/sd.h @@ -0,0 +1,42 @@ +/* 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. + * + * GDSII-Converter 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 . + */ + + #ifndef _SD_H_ + #define _SD_H_ + +#include +#include + +/** + * @brief Mount the SD card if available and not already mounted + * @param fs Filesystem to mount to. + * @return true if mounted, false if an error occured or the SD is not inserted and cannot be mounted + */ +bool mount_sd_card_if_avail(FATFS *fs); + +/** + * @brief Return whether an SD card is inserted and mounted + * + * @return true SD inserted and mounted + * @return false No SD inserted or not mounted + */ +bool sd_card_is_mounted(void); + +#endif /* _SD_H_ */ \ No newline at end of file diff --git a/stm-firmware/main.c b/stm-firmware/main.c index d485043..5573003 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -32,13 +32,13 @@ #include #include #include -#include "fatfs/shimatta_sdio_driver/shimatta_sdio.h" #include #include #include #include #include #include +#include #include #include #include @@ -88,40 +88,6 @@ static inline void uart_gpio_config(void) #endif } -/** - * @brief Mount the SD card if available and not already mounted - * @param mounted The current mounting state of the SD card - * @return true if mounted, false if an error occured or the SD is not inserted and cannot be mounted - */ -static bool mount_sd_card_if_avail(bool mounted) -{ - FRESULT res; - static uint8_t IN_SECTION(.ccm.bss) inserted_counter = 0; - - if (sdio_check_inserted() && mounted) { - memset(fs_ptr, 0, sizeof(FATFS)); - sdio_stop_clk(); - inserted_counter = 0; - return false; - } - - if (!sdio_check_inserted() && inserted_counter < 255) - inserted_counter++; - - if (!sdio_check_inserted() && !mounted && inserted_counter > 4) { - inserted_counter = 0; - res = f_mount(fs_ptr, "0:/", 1); - if (res == FR_OK) { - led_set(1, 1); - return true; - } else { - return false; - } - } - - return mounted; -} - /** * @brief Process the boot status structure in the safety (backup) RAM * Depending on the flags set there, this function will: @@ -315,7 +281,7 @@ int main(void) if (systick_ticks_have_passed(quarter_sec_timestamp, 250)) { led_set(1u, 0); sd_old = sd_card_mounted; - sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted); + sd_card_mounted = mount_sd_card_if_avail(fs_ptr); if (sd_card_mounted && !sd_old) { adc_pt1000_get_resistance_calibration(NULL, NULL, &cal_active); diff --git a/stm-firmware/sd.c b/stm-firmware/sd.c new file mode 100644 index 0000000..c061231 --- /dev/null +++ b/stm-firmware/sd.c @@ -0,0 +1,62 @@ +/* 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. + * + * GDSII-Converter 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 "fatfs/ff.h" +#include "fatfs/shimatta_sdio_driver/shimatta_sdio.h" +#include +#include +#include + +static bool sd_card_mounted_state = false; + +bool mount_sd_card_if_avail(FATFS *fs) +{ + FRESULT res; + static uint8_t IN_SECTION(.ccm.bss) inserted_counter = 0; + + if (sdio_check_inserted() && sd_card_mounted_state) { + memset(fs, 0, sizeof(FATFS)); + sdio_stop_clk(); + inserted_counter = 0; + return false; + } + + if (!sdio_check_inserted() && inserted_counter < 255) + inserted_counter++; + + if (!sdio_check_inserted() && !sd_card_mounted_state && inserted_counter > 4) { + inserted_counter = 0; + res = f_mount(fs, "0:/", 1); + if (res == FR_OK) { + led_set(1, 1); + return true; + } else { + return false; + } + } + + return sd_card_mounted_state; +} + +bool sd_card_is_mounted(void) +{ + return sd_card_mounted_state; +} \ No newline at end of file From ec2d3da4cb84a46c717f124e53476a02204833c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 20:22:08 +0100 Subject: [PATCH 17/20] Add missing header file required for memset() --- stm-firmware/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stm-firmware/sd.c b/stm-firmware/sd.c index c061231..a8f3220 100644 --- a/stm-firmware/sd.c +++ b/stm-firmware/sd.c @@ -17,11 +17,12 @@ * along with the reflow oven controller project. * If not, see . */ - + #include #include "fatfs/ff.h" #include "fatfs/shimatta_sdio_driver/shimatta_sdio.h" #include +#include #include #include From b18186423fb1359bcb5afda6eec5202ab2038287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 20:22:41 +0100 Subject: [PATCH 18/20] Fix #46: Add SD status to GUI --- stm-firmware/ui/gui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stm-firmware/ui/gui.c b/stm-firmware/ui/gui.c index 608e46a..005ec65 100644 --- a/stm-firmware/ui/gui.c +++ b/stm-firmware/ui/gui.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -789,7 +790,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr if (entry_type != MENU_ENTRY_CONTINUE) { menu_changed = true; menu_display_clear(menu); - update_display_buffer(0, "Main Menu"); + update_display_buffer(0, sd_card_is_mounted() ? "Main Menu [SD]" : "Main Menu [--]"); menu_ack_rotary_delta(menu); if (entry_type == MENU_ENTRY_FIRST_ENTER) { list.entry_names = root_entry_names; From f95ad1729ef665f7af5cc1492e12ae50927d8106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 20:29:22 +0100 Subject: [PATCH 19/20] Fix buf on sd mounting handling --- stm-firmware/sd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stm-firmware/sd.c b/stm-firmware/sd.c index a8f3220..eee16e2 100644 --- a/stm-firmware/sd.c +++ b/stm-firmware/sd.c @@ -37,7 +37,8 @@ bool mount_sd_card_if_avail(FATFS *fs) memset(fs, 0, sizeof(FATFS)); sdio_stop_clk(); inserted_counter = 0; - return false; + sd_card_mounted_state = false; + goto ret; } if (!sdio_check_inserted() && inserted_counter < 255) @@ -48,12 +49,13 @@ bool mount_sd_card_if_avail(FATFS *fs) res = f_mount(fs, "0:/", 1); if (res == FR_OK) { led_set(1, 1); - return true; + sd_card_mounted_state = true; } else { - return false; + sd_card_mounted_state = false; } } +ret: return sd_card_mounted_state; } From 5ad1d574ff17a44d17d57c53c2cb00befc972235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 31 Dec 2022 20:38:22 +0100 Subject: [PATCH 20/20] Fix #46: Fix update bug of GUI. Works now --- stm-firmware/ui/gui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stm-firmware/ui/gui.c b/stm-firmware/ui/gui.c index 005ec65..9594941 100644 --- a/stm-firmware/ui/gui.c +++ b/stm-firmware/ui/gui.c @@ -790,7 +790,6 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr if (entry_type != MENU_ENTRY_CONTINUE) { menu_changed = true; menu_display_clear(menu); - update_display_buffer(0, sd_card_is_mounted() ? "Main Menu [SD]" : "Main Menu [--]"); menu_ack_rotary_delta(menu); if (entry_type == MENU_ENTRY_FIRST_ENTER) { list.entry_names = root_entry_names; @@ -801,6 +800,8 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr } } + update_display_buffer(0, sd_card_is_mounted() ? "Main Menu [SD]" : "Main Menu [--]"); + push_button = menu_get_button_state(menu); rot_delta = menu_get_rotary_delta(menu);