From 9210313d2bb8c62da97e5f0eae4c340bd89ecffb Mon Sep 17 00:00:00 2001 From: Peter Wittich Date: Tue, 16 Jul 2024 10:34:20 -0500 Subject: [PATCH] Housekeeping (#230) * add power_down to reset_mcu, bootloader calls. * update to newer (higher) last stand temp thresholds * add i2c mux clearing for init tasks * workaround bug in xml_generate * add board id info printout to InitTask * fix bug in ff xmit off on F2 FF * make alarm queue per task --- common/power_ctl.c | 10 ++- common/power_ctl.h | 56 ++++++++------ projects/cm_mcu/AlarmUtilities.c | 49 +++++++----- projects/cm_mcu/AlarmUtilities.h | 2 +- projects/cm_mcu/CommandLineTask.c | 6 +- projects/cm_mcu/CommandLineTask.h | 4 +- projects/cm_mcu/FireflyUtils.c | 9 +++ projects/cm_mcu/GenericAlarmTask.c | 96 +++++++++++++++++------- projects/cm_mcu/I2CCommunication.c | 4 +- projects/cm_mcu/I2CCommunication.h | 4 +- projects/cm_mcu/InitTask.c | 6 +- projects/cm_mcu/LocalTasks.c | 20 ++++- projects/cm_mcu/MonitorTaskI2C.c | 4 + projects/cm_mcu/MonitorTaskI2C.h | 1 + projects/cm_mcu/PowerSupplyTask.c | 37 ++++----- projects/cm_mcu/Tasks.h | 33 +++++--- projects/cm_mcu/cm_mcu.c | 8 +- projects/cm_mcu/commands/BoardCommands.c | 15 ++-- projects/cm_mcu/commands/SensorControl.c | 56 +++++++------- sm_cm_config/data/PL_MEM_CM_rev2.yml | 11 +-- sm_cm_config/src/mon_generate.py | 11 ++- sm_cm_config/src/xml_generate.py | 8 +- 22 files changed, 282 insertions(+), 168 deletions(-) diff --git a/common/power_ctl.c b/common/power_ctl.c index eec474b4..833d1ff2 100644 --- a/common/power_ctl.c +++ b/common/power_ctl.c @@ -135,11 +135,13 @@ bool disable_ps(void) for (int o = 0; o < N_PS_OKS; ++o) if (states[o] != PWR_DISABLED) states[o] = PWR_OFF; - // this long delay (probably too long) allows all I2C tasks - // to finish their activity. For Rev2 of the CM (when the I2C - // pullups are from management power) this delay can be reduced or - // removed. + // this long delay (probably too long) allows all I2C tasks + // to finish their activity. For Rev2 of the CM (when the I2C + // pullups are from management power) this delay can be reduced or + // removed. +#ifdef REV1 vTaskDelay(pdMS_TO_TICKS(500)); +#endif // REV1 // disable in reverse order for (int prio = PS_NUM_PRIORITIES; prio > 0; --prio) { diff --git a/common/power_ctl.h b/common/power_ctl.h index 56dd28b7..ae77f86d 100644 --- a/common/power_ctl.h +++ b/common/power_ctl.h @@ -11,31 +11,45 @@ #include #include -// these are all LED messages -#define PS_GOOD (1) -#define PS_BAD (2) -#define PS_ON (3) -#define PS_OFF (4) -#define PS_ERROR (5) // error generated by pwr_ctl -#define PS_STATUS (6) -// alarms -#define TEMP_ALARM (7) -#define TEMP_ALARM_CLEAR (8) -#define CURRENT_ALARM (9) -#define CURRENT_ALARM_CLEAR (10) -#define PS_ANYFAIL_ALARM (11) -#define PS_ANYFAIL_ALARM_CLEAR (12) +// X-macros for Alarm messages +#define X_MACRO_QUEUE_MESSAGES \ + X(TEMP_ALARM, "Temperature Alarm") \ + X(TEMP_ALARM_CLEAR, "Temperature Alarm Clear") \ + X(CURRENT_ALARM, "Current Alarm") \ + X(CURRENT_ALARM_CLEAR, "Current Alarm Clear") \ + X(PS_ANYFAIL_ALARM, "Power Supply Any Fail Alarm") \ + X(PS_ANYFAIL_ALARM_CLEAR, "Power Supply Any Fail Alarm Clear") \ + X(PS_GOOD, "Power Supply Good") \ + X(PS_BAD, "Power Supply Bad") \ + X(PS_ON, "Power Supply On") \ + X(PS_OFF, "Power Supply Off") \ + X(PS_ERROR, "Power Supply Error") \ + X(PS_STATUS, "Power Supply Status") \ + X(HUH, "Undefined Message") -// alarms +// Generate enum and text arrays using X-macros +enum MsgQueue_Message { +#define X(name, text) name, + X_MACRO_QUEUE_MESSAGES +#undef X +}; -#define HUH (99) +extern const char *msgqueue_message_text[]; + +#define X_MACRO_PS_STATES \ + X(PWR_UNKNOWN) \ + X(PWR_ON) \ + X(PWR_OFF) \ + X(PWR_DISABLED) \ + X(PWR_FAILED) // power supply state -enum ps_state { PWR_UNKNOWN, - PWR_ON, - PWR_OFF, - PWR_DISABLED, - PWR_FAILED }; +enum ps_state { +#define X(name) name, + X_MACRO_PS_STATES +#undef X +}; + enum ps_state getPSStatus(int i); void setPSStatus(int i, enum ps_state theState); diff --git a/projects/cm_mcu/AlarmUtilities.c b/projects/cm_mcu/AlarmUtilities.c index 7cd4786d..b38a00ec 100644 --- a/projects/cm_mcu/AlarmUtilities.c +++ b/projects/cm_mcu/AlarmUtilities.c @@ -16,10 +16,10 @@ extern struct MonitorTaskArgs_t fpga_args; -#define INITIAL_ALARM_TEMP_FF 45.0f // in Celsius duh +#define INITIAL_ALARM_TEMP_FF 50.0f // in Celsius duh #define INITIAL_ALARM_TEMP_DCDC 70.0f #define INITIAL_ALARM_TEMP_TM4C 70.0f -#define INITIAL_ALARM_TEMP_FPGA 70.0f +#define INITIAL_ALARM_TEMP_FPGA 81.0f #define ALM_OVERTEMP_THRESHOLD 5.0f // if the temperature is above the threshold by OVERTEMP_THRESHOLD // a shutdown message is sent @@ -65,21 +65,6 @@ int TempStatus(void) ++retval; } - // FPGA - if (fpga_args.n_devices == 2) { - currentTemp[FPGA] = MAX(fpga_args.pm_values[0], fpga_args.pm_values[1]); - } - else { - currentTemp[FPGA] = fpga_args.pm_values[0]; - } - excess_temp = currentTemp[FPGA] - getAlarmTemperature(FPGA); - if (excess_temp > 0.f) { - status_T |= ALM_STAT_FPGA_OVERTEMP; - retval++; - if (excess_temp > ALM_OVERTEMP_THRESHOLD) - ++retval; - } - // DCDC. The first command is READ_TEMPERATURE_1. // I am assuming it stays that way!!!!!!!! currentTemp[DCDC] = -99.0f; @@ -99,9 +84,30 @@ int TempStatus(void) if (excess_temp > ALM_OVERTEMP_THRESHOLD) ++retval; } + // tests below here require the power to be on + if (getPowerControlState() != POWER_ON) { + return retval; + } + // FPGA + if (fpga_args.n_devices == 2) { + currentTemp[FPGA] = MAX(fpga_args.pm_values[0], fpga_args.pm_values[1]); + } + else { + currentTemp[FPGA] = fpga_args.pm_values[0]; + } + excess_temp = currentTemp[FPGA] - getAlarmTemperature(FPGA); + if (excess_temp > 0.f) { + status_T |= ALM_STAT_FPGA_OVERTEMP; + retval++; + if (excess_temp > ALM_OVERTEMP_THRESHOLD) + ++retval; + } // Fireflies. These are reported as ints but we are asked // to report a float. + // if stale we ignore + if (isFFStale()) + return retval; BaseType_t imax_ff_temp = -99; for (size_t i = 0; i < NFIREFLIES; ++i) { int8_t v = getFFtemp(i); @@ -130,7 +136,7 @@ void TempErrorLog(void) void TempClearErrorLog(void) { - log_info(LOG_ALM, "Temperature normal\r\n"); + log_info(LOG_ALM, "Temperature error cleared\r\n"); errbuffer_put(EBUF_TEMP_NORMAL, 0); } @@ -197,7 +203,8 @@ int VoltStatus(void) // compile-time sanity check on the flags being unique. // I need the +1 in the 11 for error void (*errorlog_registererror)(void); void (*errorlog_clearerror)(void); + QueueHandle_t xAlmQueue; 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 diff --git a/projects/cm_mcu/CommandLineTask.c b/projects/cm_mcu/CommandLineTask.c index 831cefd1..7f4a125f 100644 --- a/projects/cm_mcu/CommandLineTask.c +++ b/projects/cm_mcu/CommandLineTask.c @@ -19,8 +19,9 @@ static char m[SCRATCH_SIZE]; // this command takes no arguments and never returns. -static BaseType_t bl_ctl(int argc, char **argv, char *m) +__attribute__((noreturn)) static BaseType_t bl_ctl(int argc, char **argv, char *m) { + disable_ps(); Print("Jumping to bootloader\r\n"); ROM_SysCtlDelay(100000); // this code is copied from the JumpToBootLoader() @@ -54,8 +55,7 @@ static BaseType_t bl_ctl(int argc, char **argv, char *m) // the above points to a memory location in flash. #pragma GCC diagnostic pop - // shut up compiler warning. This will never get called - return pdFALSE; + __builtin_unreachable(); } #ifdef REV2 diff --git a/projects/cm_mcu/CommandLineTask.h b/projects/cm_mcu/CommandLineTask.h index 9a4b57c4..d767c54f 100644 --- a/projects/cm_mcu/CommandLineTask.h +++ b/projects/cm_mcu/CommandLineTask.h @@ -10,10 +10,8 @@ // includes for types #include #include -#include -#include "FreeRTOS.h" -#include "FreeRTOSConfig.h" +#include "FreeRTOS.h" // IWYU pragma: keep #include "stream_buffer.h" // Command line interface diff --git a/projects/cm_mcu/FireflyUtils.c b/projects/cm_mcu/FireflyUtils.c index 8913886a..bd31de3c 100644 --- a/projects/cm_mcu/FireflyUtils.c +++ b/projects/cm_mcu/FireflyUtils.c @@ -89,18 +89,23 @@ void readFFpresent(void) // to port 7 apollo_i2c_ctl_w(4, 0x70, 1, 0x80); apollo_i2c_ctl_reg_r(4, 0x20, 1, 0x01, 1, &present_FFL12_F1); + apollo_i2c_ctl_w(4, 0x70, 1, 0x0); // to port 6 apollo_i2c_ctl_w(4, 0x71, 1, 0x40); apollo_i2c_ctl_reg_r(4, 0x21, 1, 0x00, 1, &present_FFL4_F1); + apollo_i2c_ctl_w(4, 0x71, 1, 0x00); #elif defined(REV2) // to port 7 apollo_i2c_ctl_w(4, 0x70, 1, 0x80); apollo_i2c_ctl_reg_r(4, 0x20, 1, 0x01, 1, &present_FFL12_F1_bar); // active low + apollo_i2c_ctl_w(4, 0x70, 1, 0x8); // clear the mux + // to port 6 apollo_i2c_ctl_w(4, 0x71, 1, 0x40); apollo_i2c_ctl_reg_r(4, 0x21, 1, 0x00, 1, &present_FFL4_F1_bar); // active low apollo_i2c_ctl_reg_r(4, 0x21, 1, 0x01, 1, &f1_ff12xmit_4v0_sel); // reading FPGA1 12-ch xmit FF's power-supply physical selection (i.e either 3.3v or 4.0v) f1_ff12xmit_4v0_sel = (f1_ff12xmit_4v0_sel >> 4) & 0x7; // bits 4-6 + apollo_i2c_ctl_w(4, 0x71, 1, 0x0); // clear the mux #endif @@ -117,18 +122,22 @@ void readFFpresent(void) // to port 0 apollo_i2c_ctl_w(3, 0x72, 1, 0x01); apollo_i2c_ctl_reg_r(3, 0x20, 1, 0x01, 1, &present_0X20_F2); + apollo_i2c_ctl_w(3, 0x72, 1, 0x0); // to port 1 apollo_i2c_ctl_w(3, 0x72, 1, 0x02); apollo_i2c_ctl_reg_r(3, 0x21, 1, 0x01, 1, &present_0X21_F2); + apollo_i2c_ctl_w(3, 0x72, 1, 0x0); #elif defined(REV2) // to port 7 apollo_i2c_ctl_w(3, 0x70, 1, 0x80); apollo_i2c_ctl_reg_r(3, 0x20, 1, 0x01, 1, &present_FFL12_F2_bar); // active low + apollo_i2c_ctl_w(3, 0x70, 1, 0x0); // to port 6 apollo_i2c_ctl_w(3, 0x71, 1, 0x40); apollo_i2c_ctl_reg_r(3, 0x21, 1, 0x00, 1, &present_FFL4_F2_bar); // active low apollo_i2c_ctl_reg_r(3, 0x21, 1, 0x01, 1, &f2_ff12xmit_4v0_sel); // reading FPGA2 12-ch xmit FF's power-supply physical selection (i.e either 3.3v or 4.0v) f2_ff12xmit_4v0_sel = (f2_ff12xmit_4v0_sel >> 4) & 0x7; // bits 4-6 + apollo_i2c_ctl_w(3, 0x71, 1, 0x40); #endif // if we have a semaphore, give it diff --git a/projects/cm_mcu/GenericAlarmTask.c b/projects/cm_mcu/GenericAlarmTask.c index 10756a6f..e0f4f030 100644 --- a/projects/cm_mcu/GenericAlarmTask.c +++ b/projects/cm_mcu/GenericAlarmTask.c @@ -6,18 +6,33 @@ * * Generic alarm task that uses a callback and dispatches alarms if it deems fit. */ +#include "FreeRTOS.h" #include "Tasks.h" -#include "MonitorTask.h" -#include "common/power_ctl.h" -#include "common/utils.h" #include "common/log.h" +#include "common/power_ctl.h" #include "AlarmUtilities.h" +#include + +#define X_MACRO_ALM_STATES \ + X(ALM_INIT) \ + X(ALM_NORMAL) \ + X(ALM_WARN) \ + X(ALM_FAULT_ERRORING) \ + X(ALM_FAULT_ERROR_CLEARED) + +enum alarm_task_state { +#define X(name) name, + X_MACRO_ALM_STATES +#undef X +}; -enum alarm_task_state { ALM_INIT, - ALM_NORMAL, - ALM_WARN, - ALM_ERROR }; +// alarm state names +static const char *alarm_task_state_names[] = { +#define X(name) #name, + X_MACRO_ALM_STATES +#undef X +}; // ALARM TASK STATE MACHINE // +------+ @@ -25,35 +40,39 @@ enum alarm_task_state { ALM_INIT, // +---+--+ // | // | -// +--+--------+ +---------+ +-------+ -// | NORMAL +----->+ WARN +----->+ ERROR | -// +-----+-----+ +-+-------+ +---+---+ -// ^ | | -// +--------------+ | -// ^ | -// +---------------------------------+ +// +--+--------+ +---------+ +-------+ +-------+ +// | NORMAL +----->+ WARN +----->+ FAULT |--->| ERR_c | +// +-----+-----+ +-+-------+ +-------+ +---+---+ +// ^ | | +// +--------------+ | +// ^ | +// +------------------------------------- --------+ // once we get into the ERROR state the only way to clear an error is via a message // sent to the CLI. +// Fault_erroring means the error is active and we are in a fault state +// fault_error_cleared means the error has cleared but the fault remains. // -QueueHandle_t xAlmQueue = NULL; - void GenericAlarmTask(void *parameters) { struct GenericAlarmParams_t *params = parameters; + char *taskName = pcTaskGetTaskName(NULL); // get the name of the task + // initialize to the current tick time TickType_t xLastWakeTime = xTaskGetTickCount(); uint32_t message; // this must be in a semi-permanent scope - bool alarming; + bool external_reset = false; enum alarm_task_state currentState = ALM_INIT; for (;;) { - vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(25)); - if (xQueueReceive(xAlmQueue, &message, 0)) { + vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(50)); + if (xQueueReceive(params->xAlmQueue, &message, 0)) { + log_debug(LOG_ALM, "%s: received message %d (%s)\r\n", taskName, message, + msgqueue_message_text[message]); switch (message) { case ALM_CLEAR_ALL: // clear all alarms - alarming = false; + external_reset = true; break; default: break; @@ -74,11 +93,9 @@ void GenericAlarmTask(void *parameters) case ALM_NORMAL: { if (status) { params->errorlog_registererror(); - alarming = true; nextState = ALM_WARN; } else { - alarming = false; nextState = ALM_NORMAL; } break; @@ -88,7 +105,6 @@ void GenericAlarmTask(void *parameters) // we are back to normal params->errorlog_clearerror(); nextState = ALM_NORMAL; - alarming = false; } else if (status > 1) { // log alarm, send message to turn off power and move to error state @@ -98,33 +114,55 @@ void GenericAlarmTask(void *parameters) // this message always goes to the power queue, for all // alarms. xQueueSendToFront(xPwrQueue, &message, 100); - nextState = ALM_ERROR; + log_debug(LOG_ALM, "sent message %d (%s) to power queue\r\n", TEMP_ALARM, + msgqueue_message_text[TEMP_ALARM]); + nextState = ALM_FAULT_ERRORING; } else { nextState = ALM_WARN; } break; } - case ALM_ERROR: { - if (!alarming && !status) { - // error has cleared, log and move to normal state + case ALM_FAULT_ERRORING: { + if (!status) { + // error has cleared, log and move to fault state if (params->errorlog_clearerror) params->errorlog_clearerror(); + nextState = ALM_FAULT_ERROR_CLEARED; + } + else { + nextState = ALM_FAULT_ERRORING; + } + break; + } + case ALM_FAULT_ERROR_CLEARED: { + if (external_reset) { + external_reset = false; message = TEMP_ALARM_CLEAR; // this message always goes to the power queue, for all // alarms. xQueueSendToFront(xPwrQueue, &message, 100); + log_debug(LOG_ALM, "sent message %d (%s) to power queue\r\n", + TEMP_ALARM_CLEAR, msgqueue_message_text[TEMP_ALARM_CLEAR]); nextState = ALM_NORMAL; + // give the monitoring a moment to catch up. This is not a clean solution, + // but for now it appears to work. + vTaskDelay(pdMS_TO_TICKS(5000)); } else { - nextState = ALM_ERROR; + nextState = ALM_FAULT_ERROR_CLEARED; } break; } default: - nextState = ALM_ERROR; + nextState = ALM_FAULT_ERRORING; break; } + if (currentState != nextState) { + log_debug(LOG_ALM, "%s: change from state %s to %s\r\n", taskName, + alarm_task_state_names[currentState], alarm_task_state_names[nextState]); + } + currentState = nextState; // monitor stack usage for this task diff --git a/projects/cm_mcu/I2CCommunication.c b/projects/cm_mcu/I2CCommunication.c index 6141c1f6..442e7cfe 100644 --- a/projects/cm_mcu/I2CCommunication.c +++ b/projects/cm_mcu/I2CCommunication.c @@ -187,8 +187,8 @@ int apollo_i2c_ctl_w(uint8_t device, uint8_t address, uint8_t nbytes, unsigned i return r; } // for PMBUS commands -int apollo_pmbus_rw(tSMBus *smbus, volatile tSMBusStatus *const smbus_status, bool read, - struct dev_i2c_addr_t *add, struct pm_command_t *cmd, uint8_t *value) +tSMBusStatus apollo_pmbus_rw(tSMBus *smbus, volatile tSMBusStatus *const smbus_status, bool read, + struct dev_i2c_addr_t *add, struct pm_command_t *cmd, uint8_t *value) { // select the appropriate output for the mux uint8_t data = 0x1U << add->mux_bit; diff --git a/projects/cm_mcu/I2CCommunication.h b/projects/cm_mcu/I2CCommunication.h index 2536d1dd..83168ffb 100644 --- a/projects/cm_mcu/I2CCommunication.h +++ b/projects/cm_mcu/I2CCommunication.h @@ -28,7 +28,7 @@ int apollo_i2c_ctl_reg_w(uint8_t device, uint8_t address, uint8_t nbytes_addr, uint16_t packed_reg_address, uint8_t nbytes, uint32_t packed_data); // read/write a register using the PMBUS protocol -int apollo_pmbus_rw(tSMBus *smbus, volatile tSMBusStatus *smbus_status, bool read, - struct dev_i2c_addr_t *add, struct pm_command_t *cmd, uint8_t *value); +tSMBusStatus apollo_pmbus_rw(tSMBus *smbus, volatile tSMBusStatus *smbus_status, bool read, + struct dev_i2c_addr_t *add, struct pm_command_t *cmd, uint8_t *value); #endif /* PROJECTS_CM_MCU_I2CCOMMUNICATION_H_ */ diff --git a/projects/cm_mcu/InitTask.c b/projects/cm_mcu/InitTask.c index 647d7697..10b92d7d 100644 --- a/projects/cm_mcu/InitTask.c +++ b/projects/cm_mcu/InitTask.c @@ -22,7 +22,6 @@ void InitTask(void *parameters) { - // store the reboot into the error buffer, including the reason for the reset uint32_t r = ROM_SysCtlResetCauseGet(); uint16_t restart_reason = (uint16_t)0xFFFFUL & r; @@ -31,6 +30,11 @@ void InitTask(void *parameters) errbuffer_put(EBUF_RESTART, restart_reason); log_info(LOG_SERVICE, "REC register=0x%08x\r\n", restart_reason); + // get board information + uint32_t id, rev; + get_board_info(&rev, &id); + log_info(LOG_SERVICE, "Board ID: %d, Revision: %d\r\n", id, rev); + // wait for 3.3V power to come up. Wait indefinitely. // in Rev1 the clocks cannot be accessed before the 3.3 V is on. #ifdef REV1 diff --git a/projects/cm_mcu/LocalTasks.c b/projects/cm_mcu/LocalTasks.c index c7c43d74..f2aa43c9 100644 --- a/projects/cm_mcu/LocalTasks.c +++ b/projects/cm_mcu/LocalTasks.c @@ -393,20 +393,23 @@ void snapdump(struct dev_i2c_addr_t *add, uint8_t page, uint8_t snapshot[32], bo // page register int r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, add, &extra_cmds[0], &page); if (r) { - log_error(LOG_SERVICE, "page\r\n"); + log_error(LOG_SERVICE, "page w fail, dev 0x%x (%s)\r\n", add->dev_addr, add->name); + return; } // actual command -- snapshot control copy NVRAM for reading uint8_t cmd = 0x1; r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, add, &extra_cmds[4], &cmd); if (r) { - log_error(LOG_SERVICE, "ctrl\r\n"); + log_error(LOG_SERVICE, "ctrl w fail, dev 0x%x (%s)\r\n", add->dev_addr, add->name); + return; } // actual command -- read snapshot tSMBusStatus r2 = SMBusMasterBlockRead(&g_sMaster1, add->dev_addr, extra_cmds[3].command, &snapshot[0]); if (r2 != SMBUS_OK) { log_error(LOG_SERVICE, "block %d\r\n", r2); + return; } while ((r2 = SMBusStatusGet(&g_sMaster1)) == SMBUS_TRANSFER_IN_PROGRESS) { vTaskDelay(pdMS_TO_TICKS(10)); // wait @@ -419,7 +422,7 @@ void snapdump(struct dev_i2c_addr_t *add, uint8_t page, uint8_t snapshot[32], bo cmd = 0x3; r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, add, &extra_cmds[4], &cmd); if (r) { - log_error(LOG_SERVICE, "error reset\r\n"); + log_error(LOG_SERVICE, "error reset %s\r\n", add->name); } } @@ -835,6 +838,8 @@ int init_registers_clk(void) status += apollo_i2c_ctl_reg_w(2, 0x21, 1, 0x02, 1, 0x80); // 10000000 [P07..P00] status += apollo_i2c_ctl_reg_w(2, 0x21, 1, 0x03, 1, 0x03); // 00000011 [P17..P10] + status += apollo_i2c_ctl_w(2, 0x70, 1, 0x0); // reset the mux + // if we have a semaphore, give it if (xSemaphoreGetMutexHolder(i2c2_sem) == xTaskGetCurrentTaskHandle()) { xSemaphoreGive(i2c2_sem); @@ -1166,3 +1171,12 @@ int enable_3v8(UBaseType_t ffmask[2], bool turnOff) return result; } #endif // REV2 + +// return board information stored in on-board EEPROM +void get_board_info(uint32_t *rev, uint32_t *id) +{ + // read the board info from the EEPROM + uint32_t sn = read_eeprom_single(EEPROM_ID_SN_ADDR); + *id = sn >> 16; + *rev = sn & 0xff; +} diff --git a/projects/cm_mcu/MonitorTaskI2C.c b/projects/cm_mcu/MonitorTaskI2C.c index dda09bd3..9480d195 100644 --- a/projects/cm_mcu/MonitorTaskI2C.c +++ b/projects/cm_mcu/MonitorTaskI2C.c @@ -88,6 +88,10 @@ void MonitorTaskI2C(void *parameters) if (!good) { // ... was not good, but is now good task_watchdog_register_task(kWatchdogTaskID_MonitorI2CTask); log_info(LOG_MONI2C, "%s: PWR on. (Re)start I2Cmon.\r\n", args->name); + // clear out stale data + for (int i = 0; i < args->n_commands; ++i) { + args->commands[i].clearData(); + } good = true; } } diff --git a/projects/cm_mcu/MonitorTaskI2C.h b/projects/cm_mcu/MonitorTaskI2C.h index bb74e2af..82362e48 100644 --- a/projects/cm_mcu/MonitorTaskI2C.h +++ b/projects/cm_mcu/MonitorTaskI2C.h @@ -22,6 +22,7 @@ struct i2c_reg_command_t { uint16_t (*devicelist)(void); void (*storeData)(uint16_t data, int which); // store data in location which uint16_t (*retrieveData)(int which); // retrieve data from location which + void (*clearData)(void); // zero out the data }; // how to find an I2C device, with a mux infront of it. diff --git a/projects/cm_mcu/PowerSupplyTask.c b/projects/cm_mcu/PowerSupplyTask.c index 49d74a54..76c32731 100644 --- a/projects/cm_mcu/PowerSupplyTask.c +++ b/projects/cm_mcu/PowerSupplyTask.c @@ -24,6 +24,12 @@ #include "FreeRTOSConfig.h" #include "queue.h" +const char *msgqueue_message_text[] = { +#define X(name, text) text, + X_MACRO_QUEUE_MESSAGES +#undef X +}; + void Print(const char *); // Holds the handle of the created queue for the power supply task. @@ -73,17 +79,9 @@ void printfail(uint16_t failed_mask, uint16_t supply_ok_mask, uint16_t supply_bi } static const char *const power_system_state_names[] = { - "FAIL", - "INIT", - "DOWN", - "OFF", - "L1ON", - "L2ON", - "L3ON", - "L4ON", - "L5ON", - "L6ON", - "ON", +#define X(state) #state, + X_MACRO_PS_SYSTEM_STATES +#undef X }; const char *getPowerControlStateName(enum power_system_state s) @@ -190,6 +188,7 @@ void PowerSupplyTask(void *parameters) // non-blocking call. uint32_t message; if (xQueueReceive(xPwrQueue, &message, 0)) { // TODO: what about > 1 message + log_debug(LOG_PWRCTL, "received message 0x%x (%s)\r\n", message, msgqueue_message_text[message]); switch (message) { case PS_OFF: cli_powerdown_request = true; @@ -413,22 +412,26 @@ void PowerSupplyTask(void *parameters) if ((f1_ff12xmit_4v0_sel == pair_mask_low) && (f2_ff12xmit_4v0_sel == pair_mask_high)) { int ret = enable_3v8(ffmask, false); // enable v38 if (ret != 0) { - log_info(LOG_PWRCTL, "enable 3v8 failed with %d\r\n", ret); + log_error(LOG_PWRCTL, "enable 3v8 failed with %d\r\n", ret); + disable_ps(); // turn off power + power_supply_alarm = true; + nextState = POWER_FAILURE; } else { log_info(LOG_PWRCTL, "enable 3v8 \r\n"); + blade_power_ok(true); + nextState = POWER_ON; } - blade_power_ok(true); - nextState = POWER_ON; } else { - log_info(LOG_PWRCTL, "FF 4V0 part check failed: %x!=%x||%x!=%x\r\n", - f1_ff12xmit_4v0_sel, pair_mask_low, f2_ff12xmit_4v0_sel, pair_mask_high); + log_error(LOG_PWRCTL, "FF 4V0 part check failed: %x!=%x||%x!=%x, power off\r\n", + f1_ff12xmit_4v0_sel, pair_mask_low, f2_ff12xmit_4v0_sel, pair_mask_high); int ret = enable_3v8(ffmask, true); // disable v38 if (ret == 0) log_info(LOG_PWRCTL, "disable 3v8\r\n"); else - log_info(LOG_PWRCTL, "disable 3v8 failed with %d\r\n", ret); + log_warn(LOG_PWRCTL, "disable 3v8 failed with %d\r\n", ret); + disable_ps(); power_supply_alarm = true; nextState = POWER_FAILURE; } diff --git a/projects/cm_mcu/Tasks.h b/projects/cm_mcu/Tasks.h index 581e2a28..befb5cbb 100644 --- a/projects/cm_mcu/Tasks.h +++ b/projects/cm_mcu/Tasks.h @@ -89,19 +89,27 @@ void LedTask(void *parameters); // --- Power Supply management task void PowerSupplyTask(void *parameters); extern QueueHandle_t xPwrQueue; + +// power system state x-macros +#define X_MACRO_PS_SYSTEM_STATES \ + X(POWER_FAILURE) \ + X(POWER_INIT) \ + X(POWER_DOWN) \ + X(POWER_OFF) \ + X(POWER_L1ON) \ + X(POWER_L2ON) \ + X(POWER_L3ON) \ + X(POWER_L4ON) \ + X(POWER_L5ON) \ + X(POWER_L6ON) \ + X(POWER_ON) + enum power_system_state { - POWER_FAILURE, - POWER_INIT, - POWER_DOWN, - POWER_OFF, - POWER_L1ON, - POWER_L2ON, - POWER_L3ON, - POWER_L4ON, - POWER_L5ON, - POWER_L6ON, - POWER_ON, +#define X(state) state, + X_MACRO_PS_SYSTEM_STATES +#undef X }; + enum power_system_state getPowerControlState(void); const char *getPowerControlStateName(enum power_system_state); const bool getPowerControlExternalAlarmState(void); @@ -224,6 +232,9 @@ void I2CSlaveTask(void *parameters); // EEPROM +// get board information from on-MCU eeprom +void get_board_info(uint32_t *rev, uint32_t *id); + extern QueueHandle_t xEPRMQueue_in; extern QueueHandle_t xEPRMQueue_out; diff --git a/projects/cm_mcu/cm_mcu.c b/projects/cm_mcu/cm_mcu.c index 696374fd..f7ce435d 100644 --- a/projects/cm_mcu/cm_mcu.c +++ b/projects/cm_mcu/cm_mcu.c @@ -314,7 +314,6 @@ __attribute__((noreturn)) int main(void) // ------------------------------------------------- // Initialize all the queues // queue for the LED - xLedQueue = xQueueCreate(3, // The maximum number of items the queue can hold. sizeof(uint32_t)); // The size of each item. configASSERT(xLedQueue != NULL); @@ -327,8 +326,11 @@ __attribute__((noreturn)) int main(void) xEPRMQueue_out = xQueueCreate(5, sizeof(uint64_t)); configASSERT(xEPRMQueue_out != NULL); - xAlmQueue = xQueueCreate(10, sizeof(uint32_t)); // ALARM queue - configASSERT(xAlmQueue != NULL); + tempAlarmTask.xAlmQueue = xQueueCreate(10, sizeof(uint32_t)); // temp ALARM queue + configASSERT(tempAlarmTask.xAlmQueue != NULL); + + voltAlarmTask.xAlmQueue = xQueueCreate(10, sizeof(uint32_t)); // volt ALARM queue + configASSERT(voltAlarmTask.xAlmQueue != NULL); xZynqMonQueue = xQueueCreate(10, sizeof(uint32_t)); // Soft UART queue configASSERT(xZynqMonQueue != NULL); diff --git a/projects/cm_mcu/commands/BoardCommands.c b/projects/cm_mcu/commands/BoardCommands.c index 323ae9ab..a229d089 100644 --- a/projects/cm_mcu/commands/BoardCommands.c +++ b/projects/cm_mcu/commands/BoardCommands.c @@ -22,6 +22,7 @@ // This command takes no arguments BaseType_t restart_mcu(int argc, char **argv, char *m) { + disable_ps(); snprintf(m, SCRATCH_SIZE, "Restarting MCU\r\n"); MAP_SysCtlReset(); // This function does not return __builtin_unreachable(); @@ -82,18 +83,16 @@ BaseType_t board_id_info(int argc, char **argv, char *m) { int copied = 0; - uint32_t sn = read_eeprom_single(EEPROM_ID_SN_ADDR); - uint32_t ps = read_eeprom_single(EEPROM_ID_PS_IGNORE_MASK); - - uint32_t num = (uint32_t)sn >> 16; - uint32_t rev = ((uint32_t)sn) & 0xff; - - copied += snprintf(m + copied, SCRATCH_SIZE - copied, "ID:%08lx\r\n", sn); + uint32_t id; + uint32_t rev; + get_board_info(&rev, &id); - copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Board number: %lu\r\n", num); + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Board number: %lu\r\n", id); copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Revision: %lu\r\n", rev); copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Firefly USER config: %lx\r\n", ff_USER_mask); copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Firefly PRESENT config: %lx\r\n", ff_PRESENT_mask); + + uint32_t ps = read_eeprom_single(EEPROM_ID_PS_IGNORE_MASK); // copied += // this is here to remind you to update `copied` if you add more lines snprintf(m + copied, SCRATCH_SIZE - copied, "PS ignore mask: %lx\r\n", ps); diff --git a/projects/cm_mcu/commands/SensorControl.c b/projects/cm_mcu/commands/SensorControl.c index 966529fb..33e6bf0b 100644 --- a/projects/cm_mcu/commands/SensorControl.c +++ b/projects/cm_mcu/commands/SensorControl.c @@ -9,6 +9,7 @@ #include #include +#include "AlarmUtilities.h" #include "FireflyUtils.h" #include "I2CCommunication.h" #include "MonI2C_addresses.h" @@ -22,6 +23,7 @@ #include "Tasks.h" #include "projdefs.h" #include "MonUtils.h" +#include "common/power_ctl.h" int read_ff_register(const char *name, uint16_t packed_reg_addr, uint8_t *value, size_t size, int i2c_device) { @@ -164,8 +166,8 @@ static int disable_transmit(bool disable, int num_ff) } if (strstr(ff_moni2c_addrs[i].name, "XCVR") != NULL) { - value &= 0x000fU; // only 4 LSB matter, so mask out others - ret += write_ff_register(ff_moni2c_addrs[i].name, ECU0_25G_XVCR_TX_DISABLE_REG, value, 1, i2c_dev); + // only 4 LSB matter, so mask out others. + ret += write_ff_register(ff_moni2c_addrs[i].name, ECU0_25G_XVCR_TX_DISABLE_REG, value & 0xFU, 1, i2c_dev); } else if (strstr(ff_moni2c_addrs[i].name, "Tx") != NULL) { // same for all 12 channel parts ret += write_ff_register(ff_moni2c_addrs[i].name, ECU0_14G_TX_DISABLE_REG, value, 2, i2c_dev); @@ -323,6 +325,14 @@ BaseType_t psmon_ctl(int argc, char **argv, char *m) // send power control commands extern struct gpio_pin_t oks[N_PS_OKS]; + +// power control state names +static const char *power_control_state_names[] = { +#define X(name) #name, + X_MACRO_PS_STATES +#undef X +}; + BaseType_t power_ctl(int argc, char **argv, char *m) { int s = SCRATCH_SIZE; @@ -354,27 +364,7 @@ BaseType_t power_ctl(int argc, char **argv, char *m) } for (; i < N_PS_OKS; ++i) { enum ps_state j = getPSStatus(i); - char *c; - switch (j) { - case PWR_UNKNOWN: - c = "PWR_UNKNOWN"; - break; - case PWR_ON: - c = "PWR_ON"; - break; - case PWR_OFF: - c = "PWR_OFF"; - break; - case PWR_DISABLED: - c = "PWR_DISABLED"; - break; - case PWR_FAILED: - c = "PWR_FAILED"; - break; - default: - c = "UNKNOWN"; - break; - } + const char *c = power_control_state_names[j]; copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%16s: %s\r\n", oks[i].name, c); @@ -424,15 +414,15 @@ BaseType_t alarm_ctl(int argc, char **argv, char *m) uint32_t message; if (strncmp(argv[1], "clear", 4) == 0) { message = ALM_CLEAR_ALL; // clear all alarms - xQueueSendToBack(xAlmQueue, &message, pdMS_TO_TICKS(10)); - // xQueueSendToBack(voltAlarmTask.xAlmQueue, &message, pdMS_TO_TICKS(10)); + xQueueSendToBack(tempAlarmTask.xAlmQueue, &message, pdMS_TO_TICKS(10)); + xQueueSendToBack(voltAlarmTask.xAlmQueue, &message, pdMS_TO_TICKS(10)); m[0] = '\0'; // no output from this command return pdFALSE; } else if (strncmp(argv[1], "status", 5) == 0) { // report status to UART int copied = 0; - copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%s: ALARM status\r\n", argv[0]); + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%s: TALARM status\r\n", argv[0]); uint32_t stat = getTempAlarmStatus(); copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Raw: 0x%08lx\r\n", stat); @@ -790,9 +780,15 @@ BaseType_t ff_ch_disable_status(int argc, char **argv, char *m) } for (; whichff < NFIREFLIES; ++whichff) { - uint16_t val = get_FF_CHANNEL_DISABLE_data(whichff); - copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%17s: 0x%04x", - ff_moni2c_addrs[whichff].name, val); + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%17s: ", + ff_moni2c_addrs[whichff].name); + if (isEnabledFF(whichff)) { + uint16_t val = get_FF_CHANNEL_DISABLE_data(whichff); + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "0x%04x", val); + } + else { + copied += snprintf(m + copied, SCRATCH_SIZE - copied, " -- "); + } bool isTx = (strstr(ff_moni2c_addrs[whichff].name, "Tx") != NULL); if (isTx) copied += snprintf(m + copied, SCRATCH_SIZE - copied, "\t"); @@ -835,7 +831,7 @@ BaseType_t ff_cdr_lol_alarm(int argc, char **argv, char *m) for (; whichff < NFIREFLIES; ++whichff) { copied += snprintf(m + copied, SCRATCH_SIZE - copied, "%17s: ", ff_moni2c_addrs[whichff].name); - if (FireflyType(whichff) == DEVICE_25G12 || FireflyType(whichff) == DEVICE_25G4) { + if (isEnabledFF(whichff) && (FireflyType(whichff) == DEVICE_25G12 || FireflyType(whichff) == DEVICE_25G4)) { uint16_t val = get_FF_CDR_LOL_ALARM_data(whichff); copied += snprintf(m + copied, SCRATCH_SIZE - copied, "0x%04x", val); } diff --git a/sm_cm_config/data/PL_MEM_CM_rev2.yml b/sm_cm_config/data/PL_MEM_CM_rev2.yml index 0029b4ea..c4e08eab 100644 --- a/sm_cm_config/data/PL_MEM_CM_rev2.yml +++ b/sm_cm_config/data/PL_MEM_CM_rev2.yml @@ -1,8 +1,9 @@ -name: zynqmon configuration file -cm_hw_rev: 2B -sm_hw_rev: 1A -sm_fw_rev: 1A -revision: 1 +metadata: + - name: zynqmon configuration file + - cm_hw_rev: 2B + - sm_hw_rev: 1A + - sm_fw_rev: 1A + - revision: 1 config: diff --git a/sm_cm_config/src/mon_generate.py b/sm_cm_config/src/mon_generate.py index ae1e5f91..94a5a4ff 100755 --- a/sm_cm_config/src/mon_generate.py +++ b/sm_cm_config/src/mon_generate.py @@ -67,7 +67,8 @@ def main(): addr_template = Template("{$reg_size, $page, $reg_list, $size, \"$name\"," " $mask, \"$units\", $type, get_${prefix}_${name}_mask," - " set_${prefix}_${name}_data, get_${prefix}_${name}_data},") + " set_${prefix}_${name}_data, get_${prefix}_${name}_data," + " clear_${prefix}_${name}}, ") # output file names: header file and c source file # make sure that the output file ends with .c. Print error message and exit if it doesn't if not args.output.endswith(".c"): @@ -163,6 +164,14 @@ def main(): print(f"DEVICE_{d} | ", end="", file=fout_source) print(r"0;", file=fout_source) print(r"}", file=fout_source) + for c in config: + data_name = f"{prefix}_{c['name']}_data" + clear_fcn_name = f"clear_{prefix}_{c['name']}" + print(f"void {clear_fcn_name}(void);", file=fout_header) + print(f"void {clear_fcn_name}(void) {{", file=fout_source) + print(f" __builtin_memset({data_name}, 0, {ndev}*sizeof(uint16_t));", file=fout_source) + print(r"}", file=fout_source) + # special: for the firefly devices, generate a list of functions that # return either the data in the F1 array or the data in the F2 array, # depending on if the argument is >= than or less than NFIREFLIES_F1 diff --git a/sm_cm_config/src/xml_generate.py b/sm_cm_config/src/xml_generate.py index 75943b55..18c2d6a5 100644 --- a/sm_cm_config/src/xml_generate.py +++ b/sm_cm_config/src/xml_generate.py @@ -180,14 +180,14 @@ def yaml_file(filename): postfixes = c['postfixes'] j = 0 for p in postfixes: - addr = int((start + i)/2) - bit = i%2 + addr = int((start + i)/2) + bit = i%2 if p == 'RESERVED': i += 1 j += 1 continue -#the previous name node has odd bytes so this postfix node uses the -#previous postfix address but masks off the lower byte + # the previous name node has odd bytes so this postfix node uses the + # previous postfix address but masks off the lower byte if (bit == 1 and j == 0): pp = node = ET.SubElement(cm, 'node') pp.set('id', n)