Further rewrite safety handling
This commit is contained in:
@@ -28,24 +28,10 @@
|
||||
#include <helper-macros/helper-macros.h>
|
||||
#include <stm-periph/clock-enable-manager.h>
|
||||
|
||||
enum safety_adc_check_result global_safety_adc_status;
|
||||
|
||||
enum safety_adc_check_result safety_adc_get_errors()
|
||||
{
|
||||
return global_safety_adc_status;
|
||||
}
|
||||
|
||||
void safety_adc_clear_errors(void)
|
||||
{
|
||||
global_safety_adc_status = SAFETY_ADC_CHECK_OK;
|
||||
}
|
||||
|
||||
void safety_adc_init()
|
||||
{
|
||||
rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(SAFETY_ADC_ADC_RCC_MASK));
|
||||
|
||||
safety_adc_clear_errors();
|
||||
|
||||
/* Enable temperature and VREFINT measurement */
|
||||
ADC->CCR |= ADC_CCR_TSVREFE;
|
||||
|
||||
@@ -65,38 +51,27 @@ void safety_adc_deinit()
|
||||
rcc_manager_enable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC2EN));
|
||||
}
|
||||
|
||||
enum safety_adc_check_result safety_adc_check_results(uint16_t vref_result, uint16_t temp_result,
|
||||
float *vref_calculated, float *temp_calculated)
|
||||
float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t analog_value)
|
||||
{
|
||||
enum safety_adc_check_result res = SAFETY_ADC_CHECK_OK;
|
||||
float vref;
|
||||
float temp;
|
||||
float converted_val;
|
||||
|
||||
|
||||
vref = (SAFETY_ADC_INT_REF_MV * 4095.0f) / (float)vref_result;
|
||||
if (vref_calculated) {
|
||||
*vref_calculated = vref;
|
||||
|
||||
switch (channel) {
|
||||
case SAFETY_ADC_MEAS_TEMP:
|
||||
converted_val = (((float)channel / 4095.0f * 2500.0f - SAFETY_ADC_TEMP_NOM_MV) /
|
||||
SAFETY_ADC_TEMP_MV_SLOPE) + SAFETY_ADC_TEMP_NOM;
|
||||
break;
|
||||
case SAFETY_ADC_MEAS_VREF:
|
||||
converted_val = (SAFETY_ADC_INT_REF_MV * 4095.0f) / (float)analog_value;
|
||||
break;
|
||||
default:
|
||||
/* Generate NaN value as default return */
|
||||
converted_val = 0.0f / 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
temp = (((float)temp_result / 4095.0f * 2500.0f -
|
||||
SAFETY_ADC_TEMP_NOM_MV) / SAFETY_ADC_TEMP_MV_SLOPE) + SAFETY_ADC_TEMP_NOM;
|
||||
if (temp_calculated) {
|
||||
*temp_calculated = temp;
|
||||
}
|
||||
|
||||
if (ABS(vref - SAFETY_ADC_VREF_MVOLT) > SAFETY_ADC_VREF_TOL_MVOLT) {
|
||||
if (vref > SAFETY_ADC_VREF_MVOLT)
|
||||
res |= SAFETY_ADC_CHECK_VREF_HIGH;
|
||||
else
|
||||
res |= SAFETY_ADC_CHECK_VREF_LOW;
|
||||
}
|
||||
|
||||
if (temp < SAFETY_ADC_TEMP_LOW_LIM)
|
||||
res |= SAFETY_ADC_CHECK_TEMP_LOW;
|
||||
else if (temp < SAFETY_ADC_CHECK_TEMP_HIGH)
|
||||
res |= SAFETY_ADC_CHECK_TEMP_HIGH;
|
||||
|
||||
return res;
|
||||
return converted_val;
|
||||
}
|
||||
|
||||
int safety_adc_poll_result(uint16_t *adc_result)
|
||||
@@ -136,60 +111,5 @@ void safety_adc_trigger_meas(enum safety_adc_meas_channel measurement)
|
||||
SAFETY_ADC_ADC_PERIPHERAL->CR2 |= ADC_CR2_SWSTART;
|
||||
}
|
||||
|
||||
static uint16_t safety_vref_meas_raw;
|
||||
static bool safety_vref_valid = false;
|
||||
static uint16_t safety_temp_meas_raw;
|
||||
static bool safety_temp_valid = false;
|
||||
static float safety_vref;
|
||||
static float safety_temp;
|
||||
|
||||
enum safety_adc_check_result handle_safety_adc()
|
||||
{
|
||||
static enum safety_adc_meas_channel safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||
enum safety_adc_check_result check_result;
|
||||
uint16_t result;
|
||||
int poll_status;
|
||||
|
||||
poll_status = safety_adc_poll_result(&result);
|
||||
|
||||
if (poll_status < 0) {
|
||||
safety_adc_trigger_meas(safety_meas_channel);
|
||||
} else if (poll_status > 0) {
|
||||
switch (safety_meas_channel) {
|
||||
case SAFETY_ADC_MEAS_TEMP:
|
||||
safety_temp_meas_raw = result;
|
||||
safety_temp_valid = true;
|
||||
safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||
break;
|
||||
case SAFETY_ADC_MEAS_VREF:
|
||||
safety_vref_meas_raw = result;
|
||||
safety_vref_valid = true;
|
||||
safety_meas_channel = SAFETY_ADC_MEAS_TEMP;
|
||||
break;
|
||||
default:
|
||||
safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||
return SAFETY_ADC_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (safety_temp_valid && safety_vref_valid) {
|
||||
check_result = safety_adc_check_results(safety_vref_meas_raw, safety_temp_meas_raw, &safety_vref, &safety_temp);
|
||||
global_safety_adc_status |= check_result;
|
||||
} else {
|
||||
check_result = SAFETY_ADC_CHECK_OK;
|
||||
}
|
||||
|
||||
return check_result;
|
||||
}
|
||||
|
||||
float safety_adc_get_temp()
|
||||
{
|
||||
return safety_temp;
|
||||
}
|
||||
|
||||
float safety_adc_get_vref()
|
||||
{
|
||||
return safety_vref;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include <reflow-controller/safety/safety-controller.h>
|
||||
#include <reflow-controller/safety/safety-config.h>
|
||||
#include <reflow-controller/safety/watchdog.h>
|
||||
#include <reflow-controller/safety/safety-adc.h>
|
||||
#include <helper-macros/helper-macros.h>
|
||||
#include <reflow-controller/systick.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
@@ -42,6 +44,7 @@ struct error_flag {
|
||||
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;
|
||||
@@ -51,6 +54,7 @@ struct timing_mon {
|
||||
struct analog_mon {
|
||||
const char *name;
|
||||
enum analog_value_monitor monitor;
|
||||
enum safety_flag associated_flag;
|
||||
float min;
|
||||
float max;
|
||||
float value;
|
||||
@@ -64,8 +68,8 @@ struct analog_mon {
|
||||
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
|
||||
#define ERR_FLAG_ENTRY(errflag, persistency) {.name=#errflag, .flag = (errflag), .error_state = false, .persistent = (persistency)}
|
||||
#define TIM_MON_ENTRY(mon, min, max) {.name=#mon, .monitor = (mon), .min_delta = (min), .max_delta = (max), .last = 0ULL, .enabled= false}
|
||||
#define ANA_MON_ENTRY(mon, min_value, max_value) {.name=#mon, .monitor = (mon), .min = (min_value), .max = (max_value), .value = 0.0f, .valid = false}
|
||||
#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}
|
||||
|
||||
static struct error_flag flags[] = {
|
||||
ERR_FLAG_ENTRY(ERR_FLAG_MEAS_ADC_OFF, false),
|
||||
@@ -80,16 +84,59 @@ static struct error_flag flags[] = {
|
||||
};
|
||||
|
||||
static struct timing_mon timings[] = {
|
||||
TIM_MON_ENTRY(ERR_TIMING_PID, 1, 800),
|
||||
TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 1, 50),
|
||||
TIM_MON_ENTRY(ERR_TIMING_SAFETY_ADC, 220, 500),
|
||||
TIM_MON_ENTRY(ERR_TIMING_PID, 1, 800, ERR_FLAG_TIMING_PID),
|
||||
TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 1, 50, ERR_FLAG_TIMING_MEAS_ADC),
|
||||
};
|
||||
|
||||
static struct analog_mon analog_mons[] = {
|
||||
ANA_MON_ENTRY(ERR_AMON_VREF, 2480.0f, 2520.0f),
|
||||
ANA_MON_ENTRY(ERR_AMON_UC_TEMP, 0.0f, 55.0f),
|
||||
ANA_MON_ENTRY(ERR_AMON_VREF, 2480.0f, 2520.0f, ERR_FLAG_AMON_VREF),
|
||||
ANA_MON_ENTRY(ERR_AMON_UC_TEMP, 0.0f, 55.0f, ERR_FLAG_AMON_UC_TEMP),
|
||||
};
|
||||
|
||||
static struct analog_mon *find_analog_mon(enum analog_value_monitor mon)
|
||||
{
|
||||
uint32_t i;
|
||||
struct analog_mon *ret = NULL;
|
||||
|
||||
for (i = 0; i < COUNT_OF(analog_mons); i++) {
|
||||
if (analog_mons[i].monitor == mon)
|
||||
ret = &analog_mons[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct timing_mon *find_timing_mon(enum timing_monitor mon)
|
||||
{
|
||||
uint32_t i;
|
||||
struct timing_mon *ret = NULL;
|
||||
|
||||
for (i = 0; i < COUNT_OF(timings); i++) {
|
||||
if (timings[i].monitor == mon)
|
||||
ret = &timings[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct error_flag *find_error_flag(enum safety_flag flag)
|
||||
{
|
||||
uint32_t i;
|
||||
struct error_flag *ret = NULL;
|
||||
|
||||
for (i = 0; i < COUNT_OF(flags); i++) {
|
||||
if (flags[i].flag == flag)
|
||||
ret = &flags[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void safety_controller_process_checks()
|
||||
{
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
int safety_controller_report_error(enum safety_flag flag)
|
||||
{
|
||||
uint32_t i;
|
||||
@@ -102,11 +149,11 @@ int safety_controller_report_error(enum safety_flag flag)
|
||||
}
|
||||
}
|
||||
|
||||
safety_controller_process_checks();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
void safety_controller_report_timing(enum timing_monitor monitor)
|
||||
{
|
||||
uint32_t i;
|
||||
@@ -115,22 +162,41 @@ void safety_controller_report_timing(enum timing_monitor monitor)
|
||||
|
||||
timestamp = systick_get_global_tick();
|
||||
|
||||
for (i = 0; i < COUNT_OF(timings); i++) {
|
||||
tim = &timings[i];
|
||||
if (tim->monitor & monitor) {
|
||||
tim->enabled = true;
|
||||
tim->last = timestamp;
|
||||
}
|
||||
tim = find_timing_mon(monitor);
|
||||
if (tim) {
|
||||
tim->last = timestamp;
|
||||
tim->enabled = true;
|
||||
}
|
||||
|
||||
safety_controller_process_checks();
|
||||
}
|
||||
|
||||
void safety_controller_report_analog_value(enum analog_value_monitor monitor, float value)
|
||||
{
|
||||
struct analog_mon *ana;
|
||||
|
||||
/* Return if not a power of two */
|
||||
if (!is_power_of_two(monitor))
|
||||
return;
|
||||
ana = find_analog_mon(monitor);
|
||||
if (ana) {
|
||||
ana->valid = true;
|
||||
ana->value = value;
|
||||
}
|
||||
|
||||
safety_controller_process_checks();
|
||||
}
|
||||
|
||||
void safety_controller_init()
|
||||
{
|
||||
safety_adc_init();
|
||||
watchdog_setup(WATCHDOG_PRESCALER);
|
||||
}
|
||||
|
||||
int safety_controller_handle()
|
||||
{
|
||||
static
|
||||
|
||||
int ret = 0;
|
||||
|
||||
/* TODO: Handle safety ADC */
|
||||
@@ -144,19 +210,49 @@ int safety_controller_handle()
|
||||
|
||||
int safety_controller_enable_timing_mon(enum timing_monitor monitor, bool enable)
|
||||
{
|
||||
uint32_t i;
|
||||
struct timing_mon *tim;
|
||||
|
||||
if (enable) {
|
||||
safety_controller_report_timing(monitor);
|
||||
} else {
|
||||
for (i = 0; i < COUNT_OF(timings); i++) {
|
||||
tim = &timings[i];
|
||||
if (tim->monitor & monitor) {
|
||||
tim->enabled = false;
|
||||
}
|
||||
}
|
||||
tim = find_timing_mon(monitor);
|
||||
if (!tim)
|
||||
return -1;
|
||||
tim->enabled = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum analog_monitor_status safety_controller_get_analog_mon_value(enum analog_value_monitor monitor, float *value)
|
||||
{
|
||||
struct analog_mon *mon;
|
||||
int ret = ANALOG_MONITOR_ERROR;
|
||||
|
||||
if (!is_power_of_two(monitor))
|
||||
goto go_out;
|
||||
|
||||
if (!value)
|
||||
goto go_out;
|
||||
|
||||
mon = find_analog_mon(monitor);
|
||||
if (mon) {
|
||||
if (!mon->valid) {
|
||||
ret = ANALOG_MONITOR_INACTIVE;
|
||||
goto go_out;
|
||||
}
|
||||
|
||||
*value = mon->value;
|
||||
if (mon->value < mon->min)
|
||||
ret = ANALOG_MONITOR_UNDER;
|
||||
else if (mon->value > mon->max)
|
||||
ret = ANALOG_MONITOR_OVER;
|
||||
else
|
||||
ret = ANALOG_MONITOR_OK;
|
||||
}
|
||||
|
||||
go_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
Reference in New Issue
Block a user