Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alarm tasks for votages #171

Merged
merged 28 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
cd88a15
starting point for voltAlarm -- need to fix constants and errbuf
pkotamnives Nov 23, 2022
8cc0e14
Merge branch 'master' into dev_alarm_tasks
pkotamnives Nov 23, 2022
5174e5a
fix out of range causing infinite voltalarm call
pkotamnives Nov 23, 2022
2ac86e0
Merge branch 'dev_alarm_tasks' of github.com:apollo-lhc/cm_mcu into d…
pkotamnives Nov 23, 2022
eb124a9
Merge branch 'master' into dev_alarm_tasks
pwittich Dec 13, 2022
afdbc02
implement bitmask datafields
pkotamnives Dec 22, 2022
de89798
Update AlarmUtilities.h
pkotamnives Dec 22, 2022
f6d9f0d
fix stack msgs and external alarm cond.
pkotamnives Jan 11, 2023
f8a9af5
Merge branch 'dev_alarm_tasks' of github.com:apollo-lhc/cm_mcu into d…
pkotamnives Jan 11, 2023
15db709
double-check and alm status (volt) works + cleaning
pkotamnives Jan 31, 2023
5aa8ac1
fix bit value bugs
pkotamnives Jan 31, 2023
e7cb050
Update alarm volt with powdevice and CLI setvoltthres
pkotamnives Feb 8, 2023
c9f2894
try to fix function prototype issue
pkotamnives Feb 9, 2023
177866d
fix clang build
pkotamnives Feb 9, 2023
7edd447
Merge branch 'dev_alarm_tasks' of github.com:apollo-lhc/cm_mcu into d…
pkotamnives Feb 9, 2023
14937dc
fix codacy
pkotamnives Feb 10, 2023
1994203
PR comments + have extern xALMqueue for temp/volt
pkotamnives Feb 15, 2023
bf28c28
fix clang format
pkotamnives Feb 15, 2023
9b6bed5
fix bugs and false alarm from reboot voltages
pkotamnives Feb 22, 2023
e45667f
modify a voltage warning to be sensible
pkotamnives Feb 24, 2023
839ee09
Merge branch 'master' into dev_alarm_tasks
pkotamnives Feb 24, 2023
e553af8
minor tweaks
pwittich Mar 2, 2023
c74b6af
remove unused "setvolt"
pkotamnives Mar 3, 2023
8911837
add threshold for alarm voltage to alm status
pkotamnives Mar 8, 2023
d1a8f10
Apply clang-format changes
pkotamnives Mar 8, 2023
8805316
empty change
pkotamnives Mar 8, 2023
492e259
Apply clang-format changes
pkotamnives Mar 8, 2023
8e7ca2f
empty change
pkotamnives Mar 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions common/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,14 @@ static const char *ebuf_errstrings[] = {
"Hard fault",
"Assertion failed",
"Stack Overflow",
"Volt Normal",
"(continue)", // item 10
"Power Failure",
"Temp High (TM4C FPGA FF DCDC)",
"MARK",
"I2C error",
"Power Failure CLEAR",
"Volt High (GEN FPGA1 FPGA2)",
};
#define EBUF_N_ERRSTRINGS (sizeof(ebuf_errstrings) / sizeof(ebuf_errstrings[0]))

Expand Down Expand Up @@ -449,6 +451,14 @@ void errbuffer_temp_high(uint8_t tm4c, uint8_t fpga, uint8_t ffly, uint8_t dcdc)
return;
}

void errbuffer_volt_high(uint8_t genfpga, uint8_t fpga1, uint8_t fpga2)
{
errbuffer_put(EBUF_VOLT_HIGH, genfpga);
errbuffer_put(EBUF_CONTINUATION, fpga1);
errbuffer_put(EBUF_CONTINUATION, fpga2);
return;
}

void errbuffer_power_fail(uint16_t failmask)
{
errbuffer_put(EBUF_PWR_FAILURE, (failmask >> 8) & 0xFFU);
Expand Down
17 changes: 10 additions & 7 deletions common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,17 @@ uint64_t read_eeprom_multi(uint32_t addr);
#define EBUF_HARDFAULT 7
#define EBUF_ASSERT 8
#define EBUF_STACKOVERFLOW 9
#define EBUF_VOLT_NORMAL 10

// error codes with data
#define EBUF_WITH_DATA 10 // value used to determine which codes have data
#define EBUF_CONTINUATION 10
#define EBUF_PWR_FAILURE 11
#define EBUF_TEMP_HIGH 12
#define EBUF_MARK 13
#define EBUF_I2C 14
#define EBUF_PWR_FAILURE_CLR 15
#define EBUF_WITH_DATA 11 // value used to determine which codes have data
#define EBUF_CONTINUATION 11
#define EBUF_PWR_FAILURE 12
#define EBUF_TEMP_HIGH 13
#define EBUF_MARK 14
#define EBUF_I2C 15
#define EBUF_PWR_FAILURE_CLR 16
#define EBUF_VOLT_HIGH 17

// Restart Reasons, values of reset cause (RESC) register,
// at 0x5c offset in TM4C1290NCPDT
Expand Down Expand Up @@ -111,6 +113,7 @@ int errbuffer_get_messagestr(const uint32_t word, char *m, size_t s);

// specific error functions
void errbuffer_temp_high(uint8_t tm4c, uint8_t fpga, uint8_t ffly, uint8_t dcdc);
void errbuffer_volt_high(uint8_t genfpga, uint8_t fpga1, uint8_t fpga2);
void errbuffer_power_fail(uint16_t failmask);
void errbuffer_power_fail_clear(void);

Expand Down
213 changes: 195 additions & 18 deletions projects/cm_mcu/AlarmUtilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "MonitorTask.h"

#include "common/log.h"

#include "common/pinsel.h"

///////////////////////////////////////////////////////////
//
Expand Down Expand Up @@ -31,7 +31,7 @@ static float currentTemp[4] = {0.f, 0.f, 0.f, 0.f};
static uint32_t status_T = 0x0;

// read-only, so no need to use queue
uint32_t getAlarmStatus()
uint32_t getTempAlarmStatus(void)
{
return status_T;
}
Expand All @@ -47,18 +47,18 @@ void setAlarmTemperature(enum device theDevice, float temperature)

// check the current temperature status.
// returns +1 for warning, +2 or higher for error
int TempStatus()
int TempStatus(void)
{
int retval = 0;
status_T = 0x0U;

// microcontroller
currentTemp[TM4C] = getADCvalue(ADC_INFO_TEMP_ENTRY);
float excess_temp = currentTemp[TM4C] - getAlarmTemperature(TM4C);
if ( excess_temp > 0.f ) { // over temperature
if (excess_temp > 0.f) { // over temperature
status_T |= ALM_STAT_TM4C_OVERTEMP;
retval++;
if ( excess_temp > ALM_OVERTEMP_THRESHOLD )
if (excess_temp > ALM_OVERTEMP_THRESHOLD)
++retval;
}

Expand All @@ -70,10 +70,10 @@ int TempStatus()
currentTemp[FPGA] = fpga_args.pm_values[0];
}
excess_temp = currentTemp[FPGA] - getAlarmTemperature(FPGA);
if (excess_temp > 0.f ) {
if (excess_temp > 0.f) {
status_T |= ALM_STAT_FPGA_OVERTEMP;
retval++;
if ( excess_temp > ALM_OVERTEMP_THRESHOLD )
if (excess_temp > ALM_OVERTEMP_THRESHOLD)
++retval;
}

Expand All @@ -90,10 +90,10 @@ int TempStatus()
}
}
excess_temp = currentTemp[DCDC] - getAlarmTemperature(DCDC);
if (excess_temp > 0.f ) {
if (excess_temp > 0.f) {
status_T |= ALM_STAT_DCDC_OVERTEMP;
retval++;
if ( excess_temp > ALM_OVERTEMP_THRESHOLD )
if (excess_temp > ALM_OVERTEMP_THRESHOLD)
++retval;
}

Expand All @@ -107,35 +107,212 @@ int TempStatus()
}
currentTemp[FF] = (float)imax_ff_temp;
excess_temp = currentTemp[FF] - getAlarmTemperature(FF);
if (excess_temp > 0.f ) {
if (excess_temp > 0.f) {
status_T |= ALM_STAT_FIREFLY_OVERTEMP;
retval++;
if ( excess_temp > ALM_OVERTEMP_THRESHOLD )
if (excess_temp > ALM_OVERTEMP_THRESHOLD)
++retval;
}
return retval;
}

void TempErrorLog()
void TempErrorLog(void)
{
log_warn(LOG_ALM, "Temperature high: status: 0x%04x MCU: %d F: %d FF:%d PS:%d\r\n",
status_T, (int)currentTemp[TM4C], (int)currentTemp[FPGA],
(int)currentTemp[FF], (int)currentTemp[DCDC]);
status_T, (int)currentTemp[TM4C], (int)currentTemp[FPGA],
(int)currentTemp[FF], (int)currentTemp[DCDC]);
errbuffer_temp_high((uint8_t)currentTemp[TM4C], (uint8_t)currentTemp[FPGA],
(uint8_t)currentTemp[FF], (uint8_t)currentTemp[DCDC]);
}

void TempClearErrorLog()
void TempClearErrorLog(void)
{
log_info(LOG_ALM, "Temperature normal\r\n");
errbuffer_put(EBUF_TEMP_NORMAL, 0);
}

static QueueHandle_t const xTempAlarmQueue = 0;

struct GenericAlarmParams_t tempAlarmTask = {
.xAlmQueue = xTempAlarmQueue,
.checkStatus = &TempStatus,
.errorlog_registererror = &TempErrorLog,
.errorlog_clearerror = &TempClearErrorLog,
.stack_size = 4096,
};

///////////////////////////////////////////////////////////
//
// Voltage Alarms
//
///////////////////////////////////////////////////////////

// current value of the thresholds
#define INITIAL_ALARM_VOLT_PERCENT 0.05f // +/-5% from the ADC thresholds
static float alarmVolt = INITIAL_ALARM_VOLT_PERCENT;

float getAlarmVoltageThres(void)
{
return alarmVolt;
}
void setAlarmVoltageThres(float voltthres)
{
alarmVolt = voltthres;
}

// current status of voltages
static uint8_t currentVoltStatus[3] = {0U, 0U, 0U};

// Status flags of the voltage alarm task
static uint32_t status_V = 0x0;
// fractional value of a high voltage than an expected ADC value
static float excess_volt = 0.0f;
static int excess_volt_which_ch = 0;
// read-only, so no need to use queue
uint32_t getVoltAlarmStatus(void)
{
return status_V;
}
// check the current voltage status.
// returns +1 for warning, +2 or higher for error
int VoltStatus(void)
{
bool f1_enable = isFPGAF1_PRESENT();
bool f2_enable = isFPGAF2_PRESENT();

#ifndef REV2 // REV1
uint8_t GEN_VOLTAGE_MASK = 0x3f; // 0b111111 by default
#else // REV2
uint8_t GEN_VOLTAGE_MASK = 0x1f; // 0b11111 by default
#endif // REV 2

int retval = 0;
status_V = 0x0U;
uint8_t gen_bitmask = 0;
uint8_t fpga1_bitmask = 0;
uint8_t fpga2_bitmask = 0;
uint8_t is_alarm_volt = 0;

// microcontroller and general power

if (getPowerControlState() != POWER_ON) {
#ifndef REV2 // REV1
GEN_VOLTAGE_MASK = 0x5; // 0b000101 only allows other powers off except M3V3 and 12V
#else // REV2
GEN_VOLTAGE_MASK = 0x3; // 0b00011 only allows other powers off except M3V3 and 12V
#endif // REV 2
}

#ifdef REV2
while (getADCvalue(ADC_INFO_GEN_VCC_4V0_CH) < 0.01f) { // somehow the initial value of VCC 4V0 is 0 after reboot and can screw up the logic below
vTaskDelay(pdMS_TO_TICKS(10)); // delay 10 ms
}
#endif

for (int ch = ADC_INFO_GEN_VCC_INIT_CH; ch < ADC_INFO_GEN_VCC_FIN_CH + 1; ++ch) {

float threshold = getAlarmVoltageThres();
float now_value = getADCvalue(ch);
float excess = (now_value - getADCtargetValue(ch)) / getADCtargetValue(ch);
int tens, frac;
float_to_ints(excess * 100, &tens, &frac);
if (excess > 0.0f) {
is_alarm_volt = 1;
excess_volt = excess * 100;
excess_volt_which_ch = ch;
}

if ((excess > threshold && excess > 0.0f) || (excess * -1.0f > threshold && excess < 0.0f)) { // if this ADC voltage is greater/lower than a target value by getAlarmVoltageThres()*100%
gen_bitmask += (1 << (ch - ADC_INFO_GEN_VCC_INIT_CH)); // first to last bit corresponds to status of low to high ADC voltage channel of mcu/general
is_alarm_volt = 2;
log_debug(LOG_ALM, "alarm volt at ADC ch : %02d now %02d.%02d %% off target\r\n", ch, tens, frac); // over voltage among one of fpga power supplies by +/- getAlarmVoltageThres()*100% of its threshold
}
}

if (is_alarm_volt > 0) {
retval++;
if (is_alarm_volt == 2) {
status_V |= ALM_STAT_GEN_OVERVOLT;
++retval;
}
}

currentVoltStatus[GEN] = gen_bitmask & GEN_VOLTAGE_MASK; // applies a mask with power-off exceptions

if (retval > 0)
return retval;
else
retval = 0;

is_alarm_volt = 0;
status_V = 0x0U;

int n_fpga_half_ch = (ADC_INFO_FPGA_VCC_FIN_CH - ADC_INFO_FPGA_VCC_INIT_CH + 1) / 2;
int ADC_INFO_FPGA2_VCC_INIT_CH = n_fpga_half_ch + ADC_INFO_FPGA_VCC_INIT_CH;
for (int ch = ADC_INFO_FPGA_VCC_INIT_CH; ch < ADC_INFO_FPGA_VCC_FIN_CH + 1; ++ch) {
if ((!f1_enable) || (!f2_enable && ch > (ADC_INFO_FPGA2_VCC_INIT_CH - 1))) // check if fpga1/2 is on the board. currently fpga1 takes the first half of adc outputs in this indexing
break;
float threshold = getAlarmVoltageThres();
float now_value = getADCvalue(ch);
float excess = (now_value - getADCtargetValue(ch)) / getADCtargetValue(ch);
int tens, frac;
float_to_ints(excess * 100, &tens, &frac);
if (excess > 0.0f) {
is_alarm_volt = 1;
excess_volt = excess * 100;
excess_volt_which_ch = ch;
}
if (ch > (ADC_INFO_FPGA2_VCC_INIT_CH - 1)) {
if ((excess > threshold && excess > 0.0f) || (excess * -1.0f > threshold && excess < 0.0f)) { // if this ADC voltage is greater/lower than a target value by getAlarmVoltageThres()*100%
fpga2_bitmask += (1 << (ch - ADC_INFO_FPGA2_VCC_INIT_CH)); // first to last bit corresponds to status of low to high ADC voltage channel of fpga2
is_alarm_volt = 2;
log_debug(LOG_ALM, "alarm volt at ADC ch : %02d now +/- %02d.%02d %% off target\r\n", ch, tens, frac); // over voltage among one of fpga power supplies by +/-getAlarmVoltageThres()*100% of its threshold
}
}
else {
if ((excess > threshold && excess > 0.0f) || (excess * -1.0f > threshold && excess < 0.0f)) { // if this ADC voltage is greater/lower than a target value by getAlarmVoltageThres()*100%
fpga1_bitmask += (1 << (ch - ADC_INFO_FPGA_VCC_INIT_CH)); // first to last bit corresponds to status of low to high ADC voltage channel of fpga2
is_alarm_volt = 2;
log_debug(LOG_ALM, "alarm volt at ADC ch : %02d now +/- %02d.%02d %% off target\r\n", ch, tens, frac); // over voltage among one of fpga power supplies by +/-getAlarmVoltageThres()*100% of its threshold
}
}
}

if (is_alarm_volt > 0) {
retval++;
if (is_alarm_volt == 2) {
status_V |= ALM_STAT_FPGA_OVERVOLT;
++retval;
}
}

currentVoltStatus[FPGA1] = fpga1_bitmask;
currentVoltStatus[FPGA2] = fpga2_bitmask;

return retval;
}

void VoltErrorLog(void)
{
int tens, frac;
float_to_ints(excess_volt, &tens, &frac);
log_warn(LOG_ALM, "Voltage high: status: 0x%04x at ADC ch %02d now +%02d.%02d %% off\r\n",
status_V, excess_volt_which_ch, tens, frac);
errbuffer_volt_high((uint8_t)currentVoltStatus[GEN], (uint8_t)currentVoltStatus[FPGA1], (uint8_t)currentVoltStatus[FPGA2]); // add voltage status as a data field in eeprom rather than its value
}

void VoltClearErrorLog(void)
{
log_info(LOG_ALM, "Voltage normal\r\n");
errbuffer_put(EBUF_VOLT_NORMAL, 0);
}

struct GenericAlarmParams_t voltAlarmTask = {
.checkStatus = &VoltStatus,
.errorlog_registererror = &VoltErrorLog,
.errorlog_clearerror = &VoltClearErrorLog,
.stack_size = 4096,
};

///////////////////////////////////////////////////////////
//
// Current Alarms
//
///////////////////////////////////////////////////////////
13 changes: 11 additions & 2 deletions projects/cm_mcu/AlarmUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
#include "Tasks.h"

struct GenericAlarmParams_t {
// this queue is used to receive messages
QueueHandle_t xAlmQueue;
int (*checkStatus)(void); // return 0 for normal, 1 for warn, >1 for error
void (*errorlog_registererror)(void);
void (*errorlog_clearerror)(void);
UBaseType_t stack_size; // stack size of task
};

extern struct GenericAlarmParams_t tempAlarmTask;
extern struct GenericAlarmParams_t voltAlarmTask;
extern struct GenericAlarmParams_t currAlarmTask;

// temperature alarms
// first some commands for setting/getting the thresholds
Expand All @@ -24,5 +25,13 @@ void TempErrorLog(void);
void TempClearErrorLog(void);

// voltage alarms
// first some commands for setting/getting the thresholds
float getAlarmVoltageThres(void);
void setAlarmVoltageThres(float voltthres);
void getAlarmVoltageStatus(void);
// callback functions
int VoltStatus(void);
void VoltErrorLog(void);
void VoltClearErrorLog(void);

#endif // PROJECTS_CM_MCU_ALARMUTILITIES_H_
2 changes: 1 addition & 1 deletion projects/cm_mcu/CommandLineTask.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ struct command_t {
#define NUM_COMMANDS (sizeof(commands) / sizeof(commands[0]))
static struct command_t commands[] = {
{"adc", adc_ctl, "Displays a table showing the state of ADC inputs.\r\n", 0},
{"alm", alarm_ctl, "args: (clear|status|settemp #)\r\nGet or clear status of alarm task.\r\n",
{"alm", alarm_ctl, "args: (clear|status|settemp|setvoltthres|#)\r\nGet or clear status of alarm task.\r\n",
-1},
{"bootloader", bl_ctl, "Call the boot loader\r\n", 0},
#ifdef REV2
Expand Down
Loading