Safety Controller

group safety-controller

This is the main module for the safety part of the firmware. It monitors analog values, error states and timeouts of timing critical sections of the firmware.

Defines

check_flag_persistent(flag) ((flag)->persistence && (flag)->persistence->persistence)

Macro that checks if a given error_flag is persistent.

get_flag_weight(flag) ((flag)->weight ? ((flag)->weight->weight) : SAFETY_FLAG_CONFIG_WEIGHT_PANIC)

Macro that retrieves the flag weight of a given error_flag.

If no flag weight table is present, the flag is evaluated as SAFETY_FLAG_CONFIG_WEIGHT_PANIC

Enums

enum analog_monitor_status

State of an analog monitor.

Values:

enumerator ANALOG_MONITOR_OK

Monitor set up and ok.

enumerator ANALOG_MONITOR_ERROR

An internal error occured.

enumerator ANALOG_MONITOR_INACTIVE

Monitor inactive. Reading is not valid.

enumerator ANALOG_MONITOR_OVER

Value too high.

enumerator ANALOG_MONITOR_UNDER

Functions

void safety_controller_init()

Initialize the safety controller.

After a call to this function the controller is iniotlaized and the watchdog is set up. You have to call safety_controller_handle If this function fails, it will hang, because errors in the safety controller are not recoverable

int safety_controller_handle()

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

int safety_controller_report_error(enum safety_flag flag)

Report one or multiple errors to the safety controller.

When passing multipe error glags, the flags have to be ORed together.

Return

0 if successful.

Parameters
  • flag: Error flag to report

int safety_controller_report_error_with_key(enum safety_flag flag, uint32_t key)

Report one or multiple error flags with a key.

When setting a key on an error flag. The error flag can only be cleared, by passing the same key value to the safety_controller_ack_flag_with_key function.

Return

0 if successful

Parameters
  • flag: Error flag to report

  • key: Key

void safety_controller_report_timing(enum timing_monitor monitor)

Report timing to a timing monitor.

Parameters
  • monitor: Monitor to report

void safety_controller_report_analog_value(enum analog_value_monitor monitor, float value)

Report an analog value to an analog value monitor.

Parameters
  • monitor: Monitor to report

  • value: Analog value

int safety_controller_enable_timing_mon(enum timing_monitor monitor, bool enable)

Enable or disable a timing monitor.

Return

0 if successful.

Parameters
  • monitor: Monitor to enable

  • enable: State to set the monitor to.

enum analog_monitor_status safety_controller_get_analog_mon_value(enum analog_value_monitor monitor, float *value)

Get the value of an analog monitor.

Return

Status of the analog monitor. value only valid, if return value does not indicate an internal error, or an inactive monitor.

Parameters
  • monitor: Monitor to get value from

  • [out] value: The analog value

int safety_controller_get_flag(enum safety_flag flag, bool *status, bool try_ack)

Get error flag state and optionally acknowledge the flag.

If the flag is persistent, it cannot be ack’ed. In this case this function does not return an error code.

Return

0 if successful.

Parameters
  • flag: Error flag

  • [out] status: state of the flag.

  • try_ack: Try to ack the flag. This might fail, if the flag is persistent.

int safety_controller_ack_flag(enum safety_flag flag)

Ack an error flag.

Return

0 if successful, -2 if flag is persistent or keyed. All other values: Errors

Parameters
  • flag: Error flag to ack

int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key)

Acknowledge error flag with a key.

Return

0 if successful, -2 if flag is persistent or key wrong. All other values: Errors

Parameters
  • flag: Error flag

  • key: Key

bool safety_controller_get_flags_by_mask(enum safety_flag mask)

Get an ored status of multiple flags.

Return

True if errors. False if no errors.

Parameters
  • mask: Flags to check

uint32_t safety_controller_get_flag_count()

Get the count of error flags.

Return

Error flag count

uint32_t safety_controller_get_analog_monitor_count()

Get the count of analog monitors.

Return

Analog monitor count

int safety_controller_get_flag_name_by_index(uint32_t index, char *buffer, size_t buffsize)

Get an error flag’s name by its index.

The name of the flag will be cropped, if the buffersize is too small. Paramter buffsize may not be zero.

Return

0 of successful

Parameters
  • index: 0 based index.

  • [out] buffer: Buffer to write the name to.

  • buffsize: Buffer size. This has to be big enough to hold the name and the \0-terminator

int safety_controller_get_flag_by_index(uint32_t index, bool *status, enum safety_flag *flag_enum)

Get the safety flag by its internal index.

Return

0 if successful; else: negative

Parameters
  • index: 0 based index.

  • [out] status: Current flag state. May be NULL.

  • [out] flag_enum: Flag enum used in SW. May be NULL.

int safety_controller_get_analog_mon_by_index(uint32_t index, struct analog_monitor_info *info)

Get an analog monitor info by the monitor’s index.

Return

0 if successful. -1001, if index out of range -1002, if info is NULL

Parameters
  • index: 0 based index

  • [out] info: Info structure.

int safety_controller_get_analog_mon_name_by_index(uint32_t index, char *buffer, size_t buffsize)

Get the name of an analog monitor by its index.

The buffer has to be large enough to hold the name plus a null terminator. If the buffer is not large enough, The name will be cropped. Parameter buffsize may not be zero.

Return

Parameters
  • index: 0 based index

  • buffer: Buffer to write name to

  • buffsize: Buffer size

int safety_controller_get_timing_mon_by_index(uint32_t index, struct timing_monitor_info *info)

Get timing monitor information by index.

Return

0 if successful

Parameters
  • index: 0 based index

  • [out] info: Info

int safety_controller_get_timing_mon_name_by_index(uint32_t index, char *buffer, size_t buffsize)

Get the name of a timing monitor by its index.

The buffer has to be large enough to hold the name plus a null terminator. If the buffer is not large enough, The name will be cropped. Parameter buffsize may not be zero.

Return

0 if successful

Parameters
  • index: 0 based index

  • buffer: Buffer to write name to.

  • buffsize: Buffer size

uint32_t safety_controller_get_timing_monitor_count(void)

Get the count of timing monitors.

Return

Timing monitor count

int safety_controller_set_overtemp_limit(float over_temperature)

Set the overtemperature limit and store it permanently in the EEPROM.

If no EEPROM is present, this will fail. The default value SAFETY_DEFAULT_OVERTEMP_LIMIT_DEGC will be used.

Return

0 if successfully saved and applied, negative if error

Parameters
  • over_temperature: Over temperature to set

float safety_controller_get_overtemp_limit(void)

Read the current overtemperature limit.

Return

Over temperature limit

void set_overtemp_config(float over_temperature)

Configure the overtemperature flag’s settings.

Parameters
  • over_temperature: Temperature to set the limit to.

bool over_temperature_config_check(void)
uint8_t flag_enum_to_flag_no(enum safety_flag flag)

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.

Return

Flag number or 0xFF in case of an error

Parameters
  • flag: Flag enum

enum safety_flag flag_no_to_flag_enum(uint8_t no)

Convert a safety flag’s number to its enum value.

Flag numbers are used by the error memory to store flags.

Return

Flag enum

Parameters
  • no: The flag number.

int flag_weight_table_crc_check(void)

Check the CRC chacksum of the flag weight table.

Return

0 if CRC is valid, else -1;

int flag_persistence_table_crc_check(void)

Check the CRC chacksum of the flag persistence table.

Return

0 if CRC is valid, else -1.

struct error_flag *find_error_flag(enum safety_flag flag)

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.

Return

NULL in case nothing matched. Pointer otherwise.

Parameters
  • flag: Enum defining the flag.

void init_safety_flag_weight_table_from_default(void)

This function copies the safety weigths from flash ro RAM and computes the CRC.

void init_safety_flag_persistencies_from_default(void)

Initialize the default persistence settings of all safety flags.

This function copies the default persistence settings of the safety flags defined in SAFETY_CONFIG_DEFAULT_PERSIST and computes the protection CRC over the settings.

void apply_config_overrides(void)

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 config_weight) 2) Flag Persistence

bool error_flag_get_status(volatile const struct error_flag *flag)

Get the error state of a flag.

This function takes inbto account that the error_flag::error_state and error_flag::error_state_inv fileds must never be the same value. In case they are, the flag is treated as errorneous.

Return

The error state

Parameters
  • flag: Flag to check

struct analog_mon *find_analog_mon(enum analog_value_monitor mon)

Find a analog value monitor structure by its enum number.

Return

NULL incase nothing is found, else pointer to structure.

Parameters
  • mon: Enum representing the analog monitor

struct timing_mon *find_timing_mon(enum timing_monitor mon)

Find a timing monitor structure by its enum number.

Return

NULL incase nothing is found, else pointer to structure.

Parameters
  • mon: Enum representing the timing monitor

void safety_controller_process_active_timing_mons()

Check the active timing monitors and set the appropriate flags in case of an error.

void safety_controller_process_monitor_checks(void)

safety_controller_process_monitor_checks Process the analog and timing monitors and set the relevant flags in case of a monitor outside its limits. Furthermore, the PT1000 resistance is checked for overtemperature

The checking of the analog monitors will only be armed after a startup delay of 1000 ms to allow the values to stabilize.

int report_error(enum safety_flag flag, uint32_t key, bool prevent_error_mem_enty)

Internal function for setting an error flag.

Multiple flags can be ored together to set them in one go. The provided key will be set on all of the flags in order to prevent them from being reset by unauthorized code. If nop key shall be used, set key to zero.

Return

0 if successful.

Parameters
  • flag: Enum of the flags to set. This can be an ORed value of multiple error flags.

  • key: The kex to set on the flag.

  • prevent_error_mem_enty: Prevent the flag from being stored in the error memory.

int get_safety_flags_from_error_mem(enum safety_flag *flags)

Return the flags, which are set in the error memory.

Return

0 if ok, != 0 if error

Parameters
  • flags: Flags read from error memory

void safety_controller_init_external_watchdog()

Initialize the GPIOs for the external hardware watchdog.

The external harware watchdog has to be periodically reset or it will reset hte controller. Because debugging is not possible, when the watchdog is active, it is only activated, if the application is compiled in release mode. Any interruption of the main programm will then trigger the internal and/or the external watchdog.

Note

When enabled, execute the external_watchdog_toggle function to reset the external watchdog.

void safety_controller_check_stack()

Check the processor’s stack.

This function checks the Stack of the application. The check consists of 2 parts:

1) Checking the remaining free space at the moment between stack pointer and top of heap. 2) Checking The CRC of the corruption detect area between heap and stack

void safety_controller_handle_safety_adc()

Handle the Safety ADC.

This function handles the safety ADC. If the safety ADC ius not executing a measurment and the time since the last measurement has passed SAFETY_CONTROLLER_ADC_DELAY_MS, the safety ADC is retriggered and will automatically perform a measurement on all of its channels. When called again, this function will retrieve the data from the safety ADC and converts it into the appropriate analog values for the analog value monitors.

The safety ADC is configured to perform multiple measurmeents of each physical channel. Therefore, this function fist calculated the mean value before converting them into the physical values.

The channels, the ssafety ADC will convert is defined in its header file using the define SAFETY_ADC_CHANNELS.

void safety_controller_handle_memory_checks(void)

Check the memory structures.

This function checks multiple memory structures.

1) The safety memory in the backup RAM is checked using safety_memory_check. In case of an error, the safety memory is reinitialized and the ERR_FLAG_SAFETY_MEM_CORRUPT flag is set. 2) The flag weight table is CRC checked. In case of an error, the ERR_FLAG_SAFETY_TAB_CORRUPT flag is set. Aditionally, the default flag weights are restored from Flash. 3) The flag persistence table is CRC checked. In case of an error, the ERR_FLAG_SAFETY_TAB_CORRUPT flag is set. Aditionally, the default values of the flag persistence is restored from Flash. 4) Check the Overtemperature flag configuration structure

void safety_controller_do_systick_checking()

Check if the systick is ticking.

If the systick stays constant for more than 1000 calls of this function, the ERR_FLAG_SYSTICK flag is set.

void safety_controller_handle_weighted_flags()

Handle weightet flags.

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 (SAFETY_FLAG_CONFIG_WEIGHT_PANIC)

void external_watchdog_toggle()

Variables

struct error_flag flags[] = {ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_OFF), ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG), ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_UNSTABLE), ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_OVERFLOW), ERR_FLAG_ENTRY(ERR_FLAG_TIMING_MEAS_ADC), ERR_FLAG_ENTRY(ERR_FLAG_TIMING_PID), ERR_FLAG_ENTRY(ERR_FLAG_AMON_UC_TEMP), ERR_FLAG_ENTRY(ERR_FLAG_AMON_VREF), ERR_FLAG_ENTRY(ERR_FLAG_STACK), ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_ADC), ERR_FLAG_ENTRY(ERR_FLAG_SYSTICK), ERR_FLAG_ENTRY(ERR_FLAG_WTCHDG_FIRED), ERR_FLAG_ENTRY(ERR_FLAG_UNCAL), ERR_FLAG_ENTRY(ERR_FLAG_DEBUG), ERR_FLAG_ENTRY(ERR_FLAG_TIMING_MAIN_LOOP), ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_MEM_CORRUPT), ERR_FLAG_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT), ERR_FLAG_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT), ERR_FLAG_ENTRY(ERR_FLAG_OVERTEMP),}

All safety error flags.

struct timing_mon 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), TIM_MON_ENTRY(ERR_TIMING_SAFETY_ADC, 10, SAFETY_CONTROLLER_ADC_DELAY_MS + 1000, ERR_FLAG_SAFETY_ADC), TIM_MON_ENTRY(ERR_TIMING_MAIN_LOOP, 0, 1000, ERR_FLAG_TIMING_MAIN_LOOP),}

All timing monitors.

struct analog_mon 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), ANA_MON_ENTRY(ERR_AMON_UC_TEMP, SAFETY_ADC_TEMP_LOW_LIM, SAFETY_ADC_TEMP_HIGH_LIM, ERR_FLAG_AMON_UC_TEMP), ANA_MON_ENTRY(ERR_AMON_SUPPLY_VOLT, SAFETY_ADC_SUPPLY_MVOLT - SAFETY_ADC_SUPPLY_TOL_MVOLT, SAFETY_ADC_SUPPLY_MVOLT + SAFETY_ADC_SUPPLY_TOL_MVOLT, ERR_FLAG_AMON_SUPPLY_VOLT),}

All analog value monitors.

const struct safety_weight default_flag_weights[] = {SAFETY_CONFIG_DEFAULT_WEIGHTS}

The default flag weights, that are loaded on boot.

const struct safety_persistence default_flag_persistencies[] = {SAFETY_CONFIG_DEFAULT_PERSIST}

The default flag persistencies, that are loaded on boot.

struct safety_persistence flag_persistencies[COUNT_OF(default_flag_persistencies)]

The working copy of the flag persistence table. It is protected by the flag_persistencies_crc.

Note

This is stored in CCM RAM

uint32_t flag_persistencies_crc

The CRC of the flag weight table 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.

struct safety_weight flag_weights[COUNT_OF(default_flag_weights)]

The working copy of the flag weight table. It is protected by the flag_weight_crc.

Note

This is stored in CCM RAM

uint32_t flag_weight_crc

The CRC of the flag weight table 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.

struct overtemp_config safety_controller_overtemp_config

Configuration struct containing the overtemperature flag configuration.

struct analog_monitor_info
#include <safety-controller.h>

Info structure describing an analog monitor.

Public Members

float value

Current analog value.

float min

Minumum value allowed.

float max

Maximum value allowed.

enum analog_monitor_status status

Current monitor status.

enum safety_flag associated_flag

Associated safety flag, that will be set, if monitor out of range.

uint64_t timestamp

ms timestamp when analog_monitor_info::value was taken.

struct timing_monitor_info
#include <safety-controller.h>

Info structure describing a timing monitor.

Public Members

uint64_t last_run

Timestamp, when the monitor was last triggered.

uint64_t min

Minimum delay between two activations in ms.

uint64_t max

Maximum delay between two activations in ms.

bool enabled

Monitor enabled.

uint64_t delta

Last delta between two activations.

struct safety_weight

Safety controller internal structure implementing a safety flag weight.

Public Members

uint32_t start_dummy

Dummy value. This seeds the CRC.

enum config_weight weight

The safety flag’s weight.

enum safety_flag flag

The enum value of the flag this weight corresponds to.

struct error_flag *flag_ptr

the flag, this weight corresponds to

uint32_t end_dummy

Dummy value. This seeds the CRC.

struct safety_persistence

Safety controller internal struct implementing a flag persistence entry.

Public Members

uint32_t start_dummy

Dummy value. This seeds the CRC.

bool persistence

Corresponding flag is persistent and cannot be cleared.

enum safety_flag flag

Corresponding safety flag’s enum value.

struct error_flag *flag_ptr

Corresponding safety error flag.

uint32_t end_dummy

Dummy value. This seeds the CRC.

struct error_flag

Safety controller internal struct implementing an error flag.

Public Members

const char *name

Name of the error flag.

enum safety_flag flag

Enum value of this safety flag.

bool error_state

The flag’s state. True is errorneous.

bool error_state_inv

Not the flag’s state. This always has to be inverted to error_flag::error_state.

struct safety_persistence *persistence

Persistence entry of this flag.

struct safety_weight *weight

Weight entry of this flag.

uint32_t key

Key needed to remove this safety flag. If key == 0, no key is set and the flag can be cleared by all code.

struct timing_mon

Public Members

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

Public Members

const char *name
enum analog_value_monitor monitor
enum safety_flag associated_flag
float min
float max
float value
bool valid
uint64_t timestamp
struct overtemp_config

Public Members

uint32_t crc_dummy_seed
float overtemp_deg_celsius
float overtemp_equiv_resistance
uint32_t crc