From 55f35a50094d3563a4dcfd98e6dd756da050d574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 25 Jan 2021 20:59:48 +0100 Subject: [PATCH] Edit doxygen headers and improve flag weight handling in safety controller --- .../reflow-controller/safety/safety-config.h | 6 +- .../reflow-controller/safety/safety-memory.h | 2 +- stm-firmware/safety/safety-controller.c | 275 +++++++++++++----- stm-firmware/safety/safety-memory.c | 4 +- 4 files changed, 215 insertions(+), 72 deletions(-) diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index be274c4..f1e3d93 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -32,6 +32,8 @@ * * The enum type is binary or'able to allow combining * multiple safety flags. + * + * @note For a more detailed explaination of the flags, check out the Sphinx documentation. */ enum safety_flag { ERR_FLAG_NO_FLAG = 0, @@ -80,11 +82,11 @@ enum analog_value_monitor { ERR_AMON_SUPPLY_VOLT = (1<<2), }; -#define ERR_FLAG_ENTRY(errflag) {.name=#errflag, .flag = (errflag), .error_state = false, .error_state_inv = true, .key = 0UL, .weight = NULL, .persistency = NULL} +#define ERR_FLAG_ENTRY(errflag) {.name=#errflag, .flag = (errflag), .error_state = false, .error_state_inv = true, .key = 0UL, .weight = NULL, .persistence = NULL} #define TIM_MON_ENTRY(mon, min, max, flag) {.name=#mon, .monitor = (mon), .associated_flag=(flag), .min_delta = (min), .max_delta = (max), .last = 0ULL, .enabled= false} #define ANA_MON_ENTRY(mon, min_value, max_value, flag) {.name=#mon, .monitor = (mon), .associated_flag=(flag), .min = (min_value), .max = (max_value), .value = 0.0f, .valid = false} #define ERR_FLAG_WEIGHT_ENTRY(_flag, _weight) {.flag = (_flag), .flag_ptr = NULL, .weight = (_weight), .start_dummy = 0x11823344, .end_dummy = 0xAABBCCFD} -#define ERR_FLAG_PERSIST_ENTRY(_flag, _persist) {.flag = (_flag), .flag_ptr = NULL, .persistency = (_persist), .start_dummy = 0xFF1100BB, .end_dummy = 0xEBB439A2} +#define ERR_FLAG_PERSIST_ENTRY(_flag, _persist) {.flag = (_flag), .flag_ptr = NULL, .persistence = (_persist), .start_dummy = 0xFF1100BB, .end_dummy = 0xEBB439A2} /** * @brief Magic key used to reset the watchdog using the @ref watchdog_ack function diff --git a/stm-firmware/include/reflow-controller/safety/safety-memory.h b/stm-firmware/include/reflow-controller/safety/safety-memory.h index ffb2f21..80dbfc0 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-memory.h +++ b/stm-firmware/include/reflow-controller/safety/safety-memory.h @@ -120,7 +120,7 @@ struct error_memory_entry { */ enum config_override_entry_type { SAFETY_MEMORY_CONFIG_OVERRIDE_WEIGHT = 1, - SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTANCE = 2, + SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE = 2, }; /** diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index 9ae8904..9455065 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -42,57 +42,111 @@ #include #include -#define check_flag_persistent(flag) ((flag)->persistency && (flag)->persistency->persistency) -#define get_flag_weight(flag) ((flag)->weight ? ((flag)->weight->weight) : SAFETY_FLAG_CONFIG_WEIGHT_NONE) +/** + * @brief Macro that checks if a given @ref error_flag is persistent + */ +#define check_flag_persistent(flag) ((flag)->persistence && (flag)->persistence->persistence) +/** + * @brief Macro that retrieves the flag weight of a given @ref error_flag + * + * If no flag weight table is present, the flag is evaluated as SAFETY_FLAG_CONFIG_WEIGHT_PANIC + */ +#define get_flag_weight(flag) ((flag)->weight ? ((flag)->weight->weight) : SAFETY_FLAG_CONFIG_WEIGHT_PANIC) + +/** + * @brief Safety controller internal structure implementing a safety flag weight. + */ struct safety_weight { - uint32_t start_dummy; - enum config_weight weight; - enum safety_flag flag; - volatile struct error_flag *flag_ptr; - uint32_t end_dummy; + /** @brief Dummy value. This seeds the CRC */ + uint32_t start_dummy; + + /** @brief The safety flag's weight */ + enum config_weight weight; + + /** @brief The enum value of the flag this weight corresponds to */ + enum safety_flag flag; + + /** @brief the flag, this weight corresponds to */ + volatile struct error_flag *flag_ptr; + + /** @brief Dummy value. This seeds the CRC */ + uint32_t end_dummy; }; -struct safety_persistency { - uint32_t start_dummy; - bool persistency; - enum safety_flag flag; - volatile struct error_flag *flag_ptr; - uint32_t end_dummy; +/** + * @brief Safety controller internal struct implementing a flag persistence entry + */ +struct safety_persistence { + /** @brief Dummy value. This seeds the CRC */ + uint32_t start_dummy; + + /** @brief Corresponding flag is persistent and cannot be cleared */ + bool persistence; + + /** @brief Corresponding safety flag's enum value */ + enum safety_flag flag; + + /** @brief Corresponding safety error flag */ + volatile struct error_flag *flag_ptr; + + /** @brief Dummy value. This seeds the CRC */ + uint32_t end_dummy; }; +/** + * @brief Safety controller internal struct implementing an error flag + */ struct error_flag { - const char *name; - enum safety_flag flag; - bool error_state; - bool error_state_inv; - volatile struct safety_persistency *persistency; - volatile struct safety_weight *weight; - uint32_t key; + /** @brief Name of the error flag */ + const char *name; + + /** @brief Enum value of this safety flag */ + enum safety_flag flag; + + /** @brief The flag's state. True is errorneous. */ + bool error_state; + + /** @brief Not the flag's state. This always has to be inverted to @ref error_flag::error_state */ + bool error_state_inv; + + /** @brief Persistence entry of this flag */ + volatile struct safety_persistence *persistence; + + /** @brief Weight entry of this flag */ + volatile struct safety_weight *weight; + + /** @brief Key needed to remove this safety flag. If key == 0, no key is set and + * the flag can be cleared by all code + */ + uint32_t key; }; struct timing_mon { - const char *name; - enum timing_monitor monitor; - enum safety_flag associated_flag; - uint64_t min_delta; - uint64_t max_delta; - uint64_t last; - uint64_t calculated_delta; - bool enabled; + const char *name; + enum timing_monitor monitor; + enum safety_flag associated_flag; + uint64_t min_delta; + uint64_t max_delta; + uint64_t last; + uint64_t calculated_delta; + bool enabled; }; struct analog_mon { - const char *name; - enum analog_value_monitor monitor; - enum safety_flag associated_flag; - float min; - float max; - float value; - bool valid; - uint64_t timestamp; + const char *name; + enum analog_value_monitor monitor; + enum safety_flag associated_flag; + float min; + float max; + float value; + bool valid; + uint64_t timestamp; }; +/** + * @brief All safety error flags. + */ static volatile struct error_flag IN_SECTION(.ccm.data) flags[] = { ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_OFF), ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG), @@ -114,6 +168,9 @@ static volatile struct error_flag IN_SECTION(.ccm.data) flags[] = { ERR_FLAG_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT), }; +/** + * @brief All timing monitors + */ static volatile struct timing_mon IN_SECTION(.ccm.data) timings[] = { TIM_MON_ENTRY(ERR_TIMING_PID, 2, 5000, ERR_FLAG_TIMING_PID), TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 0, 50, ERR_FLAG_TIMING_MEAS_ADC), @@ -121,6 +178,9 @@ static volatile struct timing_mon IN_SECTION(.ccm.data) timings[] = { TIM_MON_ENTRY(ERR_TIMING_MAIN_LOOP, 0, 1000, ERR_FLAG_TIMING_MAIN_LOOP), }; +/** + * @brief All analog value monitors + */ static volatile struct analog_mon IN_SECTION(.ccm.data) analog_mons[] = { ANA_MON_ENTRY(ERR_AMON_VREF, SAFETY_ADC_VREF_MVOLT - SAFETY_ADC_VREF_TOL_MVOLT, SAFETY_ADC_VREF_MVOLT + SAFETY_ADC_VREF_TOL_MVOLT, ERR_FLAG_AMON_VREF), @@ -131,16 +191,58 @@ static volatile struct analog_mon IN_SECTION(.ccm.data) analog_mons[] = { ERR_FLAG_AMON_SUPPLY_VOLT), }; +/** + * @brief The default flag weights, that are loaded on boot. + */ static const struct safety_weight default_flag_weights[] = { SAFETY_CONFIG_DEFAULT_WEIGHTS }; -static const struct safety_persistency default_flag_persistencies[] = {SAFETY_CONFIG_DEFAULT_PERSIST}; -static volatile struct safety_persistency IN_SECTION(.ccm.bss) flag_persistencies[COUNT_OF(default_flag_persistencies)]; +/** + * @brief The default flag persistencies, that are loaded on boot. + */ +static const struct safety_persistence default_flag_persistencies[] = {SAFETY_CONFIG_DEFAULT_PERSIST}; + +/** + * @brief The working copy of the flag persistence table. It is protected by the @ref flag_persistencies_crc + * @note This is stored in CCM RAM + */ +static volatile struct safety_persistence IN_SECTION(.ccm.bss) flag_persistencies[COUNT_OF(default_flag_persistencies)]; + +/** + * @brief The CRC of the flag weight table @ref flag_persistencies. + * + * The CRC is calculated using the internal CRC module of the STM32F407 controller. + * See the refernece manual for the polynomial. + * + * @note This is stored in CCM RAM. + */ static uint32_t IN_SECTION(.ccm.bss) flag_persistencies_crc; +/** + * @brief The working copy of the flag weight table. It is protected by the @ref flag_weight_crc. + * @note This is stored in CCM RAM + */ static volatile struct safety_weight IN_SECTION(.ccm.bss) flag_weights[COUNT_OF(default_flag_weights)]; + +/** + * @brief The CRC of the flag weight table @ref flag_weights. + * + * The CRC is calculated using the internal CRC module of the STM32F407 controller. + * See the refernece manual for the polynomial. + * + * @note This is stored in CCM RAM. + */ static uint32_t IN_SECTION(.ccm.bss) flag_weight_crc; - +/** + * @brief Convert a flag enum to the flag number. + * + * Flag numbers are used by the error memory to store flags. + * This function will fail and return 0xFF if multiple flags are ORed and + * passed as flag parameter. + * + * @param flag Flag enum + * @return Flag number or 0xFF in case of an error + */ static uint8_t flag_enum_to_flag_no(enum safety_flag flag) { uint32_t flag_mask; @@ -158,6 +260,14 @@ static uint8_t flag_enum_to_flag_no(enum safety_flag flag) return i; } +/** + * @brief Convert a safety flag's number to its enum value. + * + * Flag numbers are used by the error memory to store flags. + * + * @param no The flag number. + * @return Flag enum + */ static enum safety_flag flag_no_to_flag_enum(uint8_t no) { if (no >= COUNT_OF(flags)) @@ -166,7 +276,10 @@ static enum safety_flag flag_no_to_flag_enum(uint8_t no) return (1U << no); } - +/** + * @brief Check the CRC chacksum of the flag weight table + * @return 0 if CRC is valid, else -1; + */ static int flag_weight_table_crc_check(void) { /* Check the flag weight table */ @@ -179,6 +292,10 @@ static int flag_weight_table_crc_check(void) return 0; } +/** + * @brief Check the CRC chacksum of the flag persistence table + * @return 0 if CRC is valid, else -1. + */ static int flag_persistency_table_crc_check(void) { crc_unit_reset(); @@ -190,6 +307,15 @@ static int flag_persistency_table_crc_check(void) return 0; } +/** + * @brief Find the error flag structure for a given safety_flag enum + * + * Only one flag can be given at a time. Giving multiple flags by ORing them + * together, will not math any flag at all. + * + * @param flag Enum defining the flag. + * @return NULL in case nothing matched. Pointer otherwise. + */ static volatile struct error_flag *find_error_flag(enum safety_flag flag) { uint32_t i; @@ -227,20 +353,26 @@ static void init_safety_flag_weight_table_from_default(void) flag_weight_crc = crc_unit_get_crc(); } +/** + * @brief Initialize the default persistence settings of all safety flags. + * + * This function copies the default persistence settings of the safety flags defined in + * @ref SAFETY_CONFIG_DEFAULT_PERSIST and computes the protection CRC over the settings. + */ static void init_safety_flag_persistencies_from_default(void) { uint32_t index; - volatile struct safety_persistency *current_persistency; + volatile struct safety_persistence *current_persistence; /* Copy values */ memcpy((void *)flag_persistencies, default_flag_persistencies, sizeof(flag_persistencies)); /* Fill in flag pointers */ for (index = 0; index < COUNT_OF(flag_persistencies); index++) { - current_persistency = &flag_persistencies[index]; - current_persistency->flag_ptr = find_error_flag(current_persistency->flag); - if (current_persistency->flag_ptr) - current_persistency->flag_ptr->persistency = current_persistency; + current_persistence = &flag_persistencies[index]; + current_persistence->flag_ptr = find_error_flag(current_persistence->flag); + if (current_persistence->flag_ptr) + current_persistence->flag_ptr->persistence = current_persistence; } crc_unit_reset(); @@ -250,6 +382,12 @@ static void init_safety_flag_persistencies_from_default(void) /** * @brief Apply the config overrrides stored in the safety memory. + * + * The config overrides are read from the safety memory and applied. + * The config overrides can override the following things: + * + * 1) Safety Weights (See @ref config_weight) + * 2) Flag Persistence */ static void apply_config_overrides(void) { @@ -275,11 +413,11 @@ static void apply_config_overrides(void) flag->weight->weight = override.entry.weight_override.weight; } break; - case SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTANCE: + case SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE: flag_enum = flag_no_to_flag_enum(override.entry.persistance_override.flag); flag = find_error_flag(flag_enum); - if (flag && flag->persistency) { - flag->persistency->persistency = override.entry.persistance_override.persistance; + if (flag && flag->persistence) { + flag->persistence->persistence = override.entry.persistance_override.persistance; } break; default: @@ -756,31 +894,34 @@ static void safety_controller_do_systick_checking() /** * @brief Handle weightet flags. * - * This functions loops oer all weight entries and checks the corresponding flags. If a flag + * This functions loops over all error flags and checks the weights. If a flag * 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) */ static void safety_controller_handle_weighted_flags() { - uint32_t weight_index; - volatile struct safety_weight *current_weight; + uint32_t flag_index; + volatile struct error_flag *current_flag; + enum config_weight flag_weigth; - for (weight_index = 0; weight_index < COUNT_OF(flag_weights); weight_index++) { - current_weight = &flag_weights[weight_index]; - if (error_flag_get_status(current_weight->flag_ptr)) { - switch (current_weight->weight) { - case SAFETY_FLAG_CONFIG_WEIGHT_NONE: - break; - case SAFETY_FLAG_CONFIG_WEIGHT_PID: - oven_pid_abort(); - break; - case SAFETY_FLAG_CONFIG_WEIGHT_PANIC: - /* Expected fallthrough */ - default: - oven_pid_abort(); - panic_mode(); - break; - } + for (flag_index = 0u; flag_index < COUNT_OF(flags); flag_index++) { + current_flag = &flags[flag_index]; + flag_weigth = get_flag_weight(current_flag); + switch (flag_weigth) { + case SAFETY_FLAG_CONFIG_WEIGHT_NONE: + break; + case SAFETY_FLAG_CONFIG_WEIGHT_PID: + oven_pid_abort(); + break; + case SAFETY_FLAG_CONFIG_WEIGHT_PANIC: + /* EXPECTED FALLTHRU */ + default: + oven_pid_abort(); + panic_mode(); + break; } + } } diff --git a/stm-firmware/safety/safety-memory.c b/stm-firmware/safety/safety-memory.c index c37ba19..36fa811 100644 --- a/stm-firmware/safety/safety-memory.c +++ b/stm-firmware/safety/safety-memory.c @@ -486,7 +486,7 @@ static uint32_t convert_config_override_to_word(const struct config_override *co data |= 0xAA0000A2UL; data |= ((uint32_t)conf_override->entry.weight_override.flag) << 16; data |= ((uint32_t)conf_override->entry.weight_override.weight) << 8; - } else if (conf_override->type == SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTANCE) { + } else if (conf_override->type == SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE) { data |= 0xBB00008EUL; data |= ((uint32_t)conf_override->entry.persistance_override.flag) << 16; data |= ((uint32_t)(conf_override->entry.persistance_override.persistance ? 1UL : 0UL)) << 8; @@ -597,7 +597,7 @@ int safety_memory_get_config_override(uint32_t idx, struct config_override *conf break; case 0x8E: /* persistance override */ - config_override->type = SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTANCE; + config_override->type = SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE; config_override->entry.persistance_override.flag = (data & 0xFF0000UL) >> 16; config_override->entry.persistance_override.persistance = ((data & 0xFF00UL) >> 8) ? true : false; break;