Edit doxygen headers and improve flag weight handling in safety controller

This commit is contained in:
Mario Hüttel 2021-01-25 20:59:48 +01:00
parent 870c228e37
commit 55f35a5009
4 changed files with 215 additions and 72 deletions

View File

@ -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

View File

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

View File

@ -42,57 +42,111 @@
#include <helper-macros/helper-macros.h>
#include <stm-periph/rcc-manager.h>
#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;
}
}
}

View File

@ -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;