diff --git a/README.md b/README.md index e9f67c97..03291142 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -#cm_mcu ![CI Status](https://github.com/apollo-lhc/cm_mcu/actions/workflows/c-cpp.yml/badge.svg) +#cm_mcu ![CI Status](https \ + : // github.com/apollo-lhc/cm_mcu/actions/workflows/c-cpp.yml/badge.svg) Microcontroller source code, initially targeting the [TI Tiva TM4C1290NCPDT](https://www.ti.com/product/TM4C1290NCPDT) on the Apollo command module. This is a Cortex-M4F 32 bit processor. ## Project diff --git a/projects/cm_mcu/LocalTasks.c b/projects/cm_mcu/LocalTasks.c index c63ebb99..caa81864 100644 --- a/projects/cm_mcu/LocalTasks.c +++ b/projects/cm_mcu/LocalTasks.c @@ -165,10 +165,11 @@ struct sm_command_t sm_command_ffldaq_f1[] = { {1, 0x00, 0x16, 2, "FF_TEMPERATURE", 0xff, "C", PM_STATUS}, {1, 0x00, 0x03, 1, "FF_LOS_ALARM", 0xff, "", PM_STATUS}, {1, 0x00, 0x05, 1, "FF_CDR_LOL_ALARM", 0xff, "", PM_STATUS}, - + {2, 0x00, 0x22, 1, "FF_OPT_POW", 0xff, "dB", PM_STATUS}, // read 4 Rx-ch registers with increasing addresses }; uint16_t ffldaq_f1_values[NSUPPLIES_FFLDAQ_F1 * NCOMMANDS_FFLDAQ_F1]; +uint16_t ffldaq_f1_opt_pow_values[NSUPPLIES_FFLDAQ_F1 * FF_DAQ_NRXCH]; struct MonitorI2CTaskArgs_t ffldaq_f1_args = { .name = "FFDAQ", @@ -179,11 +180,14 @@ struct MonitorI2CTaskArgs_t ffldaq_f1_args = { .n_commands = NCOMMANDS_FFLDAQ_F1, .n_values = NSUPPLIES_FFLDAQ_F1 * NPAGES_FFLDAQ_F1 * NCOMMANDS_FFLDAQ_F1, .n_pages = NPAGES_FFLDAQ_F1, + .selpage_reg = FF_SELPAGE_REG, .sm_values = ffldaq_f1_values, .smbus = &g_sMaster4, .smbus_status = &eStatus4, .xSem = NULL, .ffpart_bit_mask = 0U, + .n_rxchs = FF_DAQ_NRXCH, + .opt_pow_values = ffldaq_f1_opt_pow_values, .present_bit_mask = 0U, .stack_size = 4096U, }; @@ -205,7 +209,7 @@ struct sm_command_t sm_command_fflot_f1[] = { {1, 0x00, 0x16, 2, "FF_TEMPERATURE", 0xff, "C", PM_STATUS}, {2, 0x00, 0x07, 1, "FF_LOS_ALARM", 0xffff, "", PM_STATUS}, {2, 0x00, 0x14, 1, "FF_CDR_LOL_ALARM", 0xffff, "", PM_STATUS}, - + {2, 0x01, 0xe4, 1, "FF_OPT_POW", 0xff, "dB", PM_STATUS}, // read 12 Rx-ch registers with decreasing addresses }; #ifdef REV1 @@ -234,6 +238,7 @@ struct dev_moni2c_addr_t ffl12_f1_moni2c_addrs[NFIREFLIES_IT_F1] = { #endif uint16_t ffl12_f1_values[NSUPPLIES_FFL12_F1 * NCOMMANDS_FFL12_F1]; +uint16_t ffl12_f1_opt_pow_values[(NSUPPLIES_FFL12_F1 / 2) * FF_12_NRXCH]; struct MonitorI2CTaskArgs_t ffl12_f1_args = { .name = "FF12", @@ -244,11 +249,14 @@ struct MonitorI2CTaskArgs_t ffl12_f1_args = { .n_commands = NCOMMANDS_FFL12_F1, .n_values = NSUPPLIES_FFL12_F1 * NPAGES_FFL12_F1 * NCOMMANDS_FFL12_F1, .n_pages = NPAGES_FFL12_F1, + .selpage_reg = FF_SELPAGE_REG, .sm_values = ffl12_f1_values, .smbus = &g_sMaster4, .smbus_status = &eStatus4, .xSem = NULL, .ffpart_bit_mask = 0U, + .n_rxchs = FF_12_NRXCH, + .opt_pow_values = ffl12_f1_opt_pow_values, .present_bit_mask = 0U, .stack_size = 4096U, }; @@ -283,9 +291,10 @@ struct sm_command_t sm_command_ffldaq_f2[] = { {1, 0x00, 0x16, 2, "FF_TEMPERATURE", 0xff, "C", PM_STATUS}, {1, 0x00, 0x03, 1, "FF_LOS_ALARM", 0xff, "", PM_STATUS}, {1, 0x00, 0x05, 1, "FF_CDR_LOL_ALARM", 0xff, "", PM_STATUS}, - + {2, 0x00, 0x22, 1, "FF_OPT_POW", 0xff, "dB", PM_STATUS}, // read 4 Rx-ch registers with increasing addresses }; uint16_t ffldaq_f2_values[NSUPPLIES_FFLDAQ_F2 * NCOMMANDS_FFLDAQ_F2]; +uint16_t ffldaq_f2_opt_pow_values[NSUPPLIES_FFLDAQ_F2 * FF_DAQ_NRXCH]; struct MonitorI2CTaskArgs_t ffldaq_f2_args = { .name = "FFDAV", @@ -296,11 +305,14 @@ struct MonitorI2CTaskArgs_t ffldaq_f2_args = { .n_commands = NCOMMANDS_FFLDAQ_F2, .n_values = NSUPPLIES_FFLDAQ_F2 * NPAGES_FFLDAQ_F2 * NCOMMANDS_FFLDAQ_F2, .n_pages = NPAGES_FFLDAQ_F2, + .selpage_reg = FF_SELPAGE_REG, .sm_values = ffldaq_f2_values, .smbus = &g_sMaster3, .smbus_status = &eStatus3, .xSem = NULL, .ffpart_bit_mask = 0U, + .n_rxchs = FF_DAQ_NRXCH, + .opt_pow_values = ffldaq_f2_opt_pow_values, .present_bit_mask = 0U, .stack_size = 4096U, }; @@ -322,7 +334,7 @@ struct sm_command_t sm_command_fflot_f2[] = { {1, 0x00, 0x16, 2, "FF_TEMPERATURE", 0xff, "C", PM_STATUS}, {2, 0x00, 0x07, 1, "FF_LOS_ALARM", 0xffff, "", PM_STATUS}, {2, 0x00, 0x14, 1, "FF_CDR_LOL_ALARM", 0xffff, "", PM_STATUS}, - + {2, 0x01, 0xe4, 1, "FF_OPT_POW", 0xff, "dB", PM_STATUS}, // read 12 Rx-ch registers with decreasing addresses }; #ifdef REV1 @@ -346,6 +358,7 @@ struct dev_moni2c_addr_t ffl12_f2_moni2c_addrs[NFIREFLIES_IT_F2] = { #endif uint16_t ffl12_f2_values[NSUPPLIES_FFL12_F2 * NCOMMANDS_FFL12_F2]; +uint16_t ffl12_f2_opt_pow_values[NSUPPLIES_FFL12_F2 * (FF_12_NRXCH / 2)]; struct MonitorI2CTaskArgs_t ffl12_f2_args = { .name = "FF12V", @@ -356,11 +369,14 @@ struct MonitorI2CTaskArgs_t ffl12_f2_args = { .n_commands = NCOMMANDS_FFL12_F2, .n_values = NSUPPLIES_FFL12_F2 * NPAGES_FFL12_F2 * NCOMMANDS_FFL12_F2, .n_pages = NPAGES_FFL12_F2, + .selpage_reg = FF_SELPAGE_REG, .sm_values = ffl12_f2_values, .smbus = &g_sMaster3, .smbus_status = &eStatus3, .xSem = NULL, .ffpart_bit_mask = 0U, + .n_rxchs = FF_12_NRXCH, + .opt_pow_values = ffl12_f2_opt_pow_values, .present_bit_mask = 0U, .stack_size = 4096U, }; @@ -398,6 +414,7 @@ struct MonitorI2CTaskArgs_t clock_args = { .n_commands = NCOMMANDS_CLK, .n_values = NSUPPLIES_CLK * NPAGES_CLK * NCOMMANDS_CLK, .n_pages = NPAGES_CLK, + .selpage_reg = CLK_SELPAGE_REG, .sm_values = clk_values, .smbus = &g_sMaster2, .smbus_status = &eStatus2, @@ -433,6 +450,7 @@ struct MonitorI2CTaskArgs_t clockr0a_args = { .n_commands = NCOMMANDS_CLKR0A, .n_values = NSUPPLIES_CLKR0A * NPAGES_CLKR0A * NCOMMANDS_CLKR0A, .n_pages = NPAGES_CLKR0A, + .selpage_reg = CLK_SELPAGE_REG, .sm_values = clkr0a_values, .smbus = &g_sMaster2, .smbus_status = &eStatus2, @@ -724,13 +742,11 @@ void getFFpart(int which_fpga) } log_debug(LOG_SERVICE, "Bit-mask of Firefly 12-ch part (FPGA1): 0x%02x \r\n:", ffl12_f1_args.ffpart_bit_mask); -#ifdef REV2 log_debug(LOG_SERVICE, "Bit-mask of xmit_3v8_sel(FPGA1): 0x%02x \r\n:", f1_ff12xmit_4v0_sel); // Warning if 25Gbs found but is connected to 3.3V or Non-25Gbs found but is connected to 3.8V if ((f1_ff12xmit_4v0_sel ^ ffl12_f1_args.ffpart_bit_mask) != 0U) { log_warn(LOG_SERVICE, "Some 12-ch FFs have unmatched xmit_3v8_sel(0x%02x) and 12-ch ff-mask(0x%02x) \r\n", f1_ff12xmit_4v0_sel, ffl12_f1_args.ffpart_bit_mask); } -#endif // if we have a semaphore, give it if (xSemaphoreGetMutexHolder(i2c4_sem) == xTaskGetCurrentTaskHandle()) { xSemaphoreGive(i2c4_sem); @@ -807,13 +823,11 @@ void getFFpart(int which_fpga) } log_debug(LOG_SERVICE, "Bit-mask of Firefly 12-ch part (FPGA2): 0x%02x \r\n:", ffl12_f2_args.ffpart_bit_mask); -#ifdef REV2 log_debug(LOG_SERVICE, "Bit-mask of xmit_3v8_sel(FPGA2): 0x%02x \r\n:", f2_ff12xmit_4v0_sel); // Warning if 25Gbs found but is connected to 3.3V or Non-25Gbs found but is connected to 3.8V if ((f2_ff12xmit_4v0_sel ^ ffl12_f2_args.ffpart_bit_mask) != 0U) { log_warn(LOG_SERVICE, "Some 12-ch FFs have unmatched xmit_3v8_sel(0x%02x) and 12-ch ff-mask(0x%02x) \r\n", f2_ff12xmit_4v0_sel, ffl12_f2_args.ffpart_bit_mask); } -#endif // if we have a semaphore, give it if (xSemaphoreGetMutexHolder(i2c3_sem) == xTaskGetCurrentTaskHandle()) { xSemaphoreGive(i2c3_sem); @@ -1094,14 +1108,11 @@ struct MonitorTaskArgs_t dcdc_args = { .name = "PSMON", .devices = pm_addrs_dcdc, .n_devices = NSUPPLIES_PS, - .commands = - pm_command_dcdc, + .commands = pm_command_dcdc, .n_commands = NCOMMANDS_PS, - .pm_values = - dcdc_values, + .pm_values = dcdc_values, .n_values = NSUPPLIES_PS * NPAGES_PS * NCOMMANDS_PS, - .n_pages = - NPAGES_PS, + .n_pages = NPAGES_PS, .smbus = &g_sMaster1, .smbus_status = &eStatus1, .xSem = NULL, diff --git a/projects/cm_mcu/MonitorI2CTask.c b/projects/cm_mcu/MonitorI2CTask.c index d074f4c4..57fdcc24 100644 --- a/projects/cm_mcu/MonitorI2CTask.c +++ b/projects/cm_mcu/MonitorI2CTask.c @@ -184,15 +184,14 @@ void MonitorI2CTask(void *parameters) for (int c = 0; c < args->n_commands; ++c) { int index = ps * (args->n_commands * args->n_pages) + c; - log_debug(LOG_MONI2C, "%s: command page %s.\r\n", args->name, args->commands[c].name); + log_debug(LOG_MONI2C, "%s: command %s.\r\n", args->name, args->commands[c].name); uint8_t page_reg_value = args->commands[c].page; - int r = apollo_i2c_ctl_reg_w(args->i2c_dev, args->devices[ps].dev_addr, 1, 0x01, 1, page_reg_value); + int r = apollo_i2c_ctl_reg_w(args->i2c_dev, args->devices[ps].dev_addr, 1, args->selpage_reg, 1, page_reg_value); if (r != 0) { log_error(LOG_MONI2C, "%s : page fail %s\r\n", args->devices[ps].name, SMBUS_get_error(r)); break; } - log_debug(LOG_MONI2C, "%s: command %s.\r\n", args->name, args->commands[c].name); uint32_t output_raw; int res = apollo_i2c_ctl_reg_r(args->i2c_dev, args->devices[ps].dev_addr, args->commands[c].reg_size, args->commands[c].command, args->commands[c].size, &output_raw); @@ -209,6 +208,40 @@ void MonitorI2CTask(void *parameters) } } // loop over commands + +#ifdef REV2 + // get optical power information from 25Gbs FFs + if (IsFFDAQ || (IsFF12 && (args->ffpart_bit_mask & (0x1U << (int)ps / 2)) && (ps % 2 == 1))) { + uint8_t page_reg_value = args->commands[FF_OPT_POW_C].page; + int r = apollo_i2c_ctl_reg_w(args->i2c_dev, args->devices[ps].dev_addr, 1, args->selpage_reg, 1, page_reg_value); + if (r != 0) { + log_error(LOG_MONI2C, "%s : page fail %s\r\n", args->devices[ps].name, SMBUS_get_error(r)); + break; + } + for (int ch = 0; ch < args->n_rxchs; ++ch) { + uint32_t output_raw; + uint16_t opt_pw_command; + if (IsFFDAQ) { + opt_pw_command = args->commands[FF_OPT_POW_C].command + 2 * ch; + } + else { + ps = (ps - 1) / 2; + opt_pw_command = args->commands[FF_OPT_POW_C].command - 2 * ch; + } + int res = apollo_i2c_ctl_reg_r(args->i2c_dev, args->devices[ps].dev_addr, args->commands[FF_OPT_POW_C].reg_size, + opt_pw_command, args->commands[FF_OPT_POW_C].size, &output_raw); + + if (res != 0) { + log_error(LOG_MONI2C, "%s: %s read Error %s, break (ps=%d)\r\n", args->name, args->commands[FF_OPT_POW_C].name, SMBUS_get_error(res), ps); + args->opt_pow_values[ch + ps * (args->n_rxchs)] = 0xffff; + break; + } + else { + args->opt_pow_values[ch + ps * (args->n_rxchs)] = output_raw; + } + } + } +#endif // REV2 log_debug(LOG_MONI2C, "%s: end loop commands\r\n", args->name); args->updateTick = xTaskGetTickCount(); // current time in ticks diff --git a/projects/cm_mcu/MonitorI2CTask.h b/projects/cm_mcu/MonitorI2CTask.h index 4c19fac4..9e374d8d 100644 --- a/projects/cm_mcu/MonitorI2CTask.h +++ b/projects/cm_mcu/MonitorI2CTask.h @@ -35,6 +35,7 @@ struct MonitorI2CTaskArgs_t { const uint8_t n_commands; // number of commands const int n_values; // number of results const uint8_t n_pages; // number of pages to loop over + const uint16_t selpage_reg; // register for selecting page uint16_t *sm_values; tSMBus *smbus; // pointer to I2C controller volatile tSMBusStatus *smbus_status; // pointer to I2C status @@ -42,9 +43,18 @@ struct MonitorI2CTaskArgs_t { SemaphoreHandle_t xSem; // semaphore for controlling access to device uint8_t ffpart_bit_mask; // this mask is only used for detecting 12-ch 25Gbps on the REV2 board uint8_t present_bit_mask; // this mask is used for all ffs to detect if it is mounted or not + const uint8_t n_rxchs; // the number of optical receiver channels + uint16_t *opt_pow_values; // a set of optical power measurements only from FFs with 25Gbs UBaseType_t stack_size; // stack size of task }; +#define FF_SELPAGE_REG 0x7f +#define CLK_SELPAGE_REG 0x1 + +#define FF_OPT_POW_C 4 // the order of optical power command in sm_command array +#define FF_DAQ_NRXCH 4 +#define FF_12_NRXCH 12 + #ifndef REV2 #define NSUPPLIES_FFLDAQ_F1 (3) #else // REV2 diff --git a/projects/cm_mcu/README.md b/projects/cm_mcu/README.md index 400d6bb0..b6b204c0 100644 --- a/projects/cm_mcu/README.md +++ b/projects/cm_mcu/README.md @@ -1,5 +1,4 @@ -# Main project for the Apollo CM microcontroller. - +#Main project for the Apollo CM microcontroller. This project has the source code for the firmware that runs on the microcontroller to provide low-level control of the power supplies, low-level monitoring of temperatures, voltages and currents, monitoring information that is provided the to the Apollo Service Module and to the IPMC via an I2C worker, an error logger to allow basic debugging after-the-fact, and a UART-based command line interface (CLI), available either from the front panel or from the service module. @@ -40,20 +39,18 @@ Tasks are located in their own C files and are identified by names such as `XXXT void Task(void *parameters) { // do some initialization - // ... - + // ... + // initialize to the current tick time right before main task loop starts TickType_t xLastWakeTime = xTaskGetTickCount(); for (;;) { // do stuff // ... // wait here for the x msec, where x is 2nd argument below. - vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(25)); + vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(25)); } - } - ``` The `vTaskDelayUntil` sets the frequency of the tasks being called, for tasks that are not real-time critical. @@ -83,6 +80,6 @@ The vector table is defined in `startup_gcc.c`. Interrupt handlers are either in For this project you should set the environment variable FREERTOS_ROOT to point to your local FreeRTOS installation. The makefile points to a default location too but that is probably not where your FreeRTOS lives. Specifically the environment variable should point to the FreeRTOS/Source directory from the standard install. ```make -# if the environment variable is not set, this is used +#if the environment variable is not set, this is used FREERTOS_ROOT?=../../../FreeRTOSv10.2.0/FreeRTOS/Source ``` \ No newline at end of file diff --git a/projects/cm_mcu/ZynqMonTask.c b/projects/cm_mcu/ZynqMonTask.c index 8200093d..20d296ec 100644 --- a/projects/cm_mcu/ZynqMonTask.c +++ b/projects/cm_mcu/ZynqMonTask.c @@ -336,6 +336,39 @@ void zm_set_firefly_presentbit(struct zynqmon_data_t data[], int start) } } +#ifdef REV2 +void zm_set_firefly_opt_pow(struct zynqmon_data_t data[], int start) +{ + // Fireflies + // update the data for ZMON + for (int i = 0; i < ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f1_args.n_rxchs * NSUPPLIES_FFLDAQ_F1 + ffl12_f2_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F2; i++) { + data[i].sensor = i + start; // sensor id + if (!isFFStale()) { + int j; + if (i < ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2)) { + j = i; + data[i].data.us = ffl12_f1_args.opt_pow_values[j]; // sensor value and type + } + else if (ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) <= i && i < ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F1) { + j = i - (ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2)); + data[i].data.us = ffldaq_f1_args.opt_pow_values[j]; // sensor value and type + } + else if (ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F1 <= i && i < ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F1 + ffl12_f2_args.n_rxchs * (NSUPPLIES_FFL12_F2 / 2)) { + j = i - (ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F1); + data[i].data.us = ffldaq_f2_args.opt_pow_values[j]; // sensor value and type + } + else { + j = i - (ffl12_f1_args.n_rxchs * (NSUPPLIES_FFL12_F1 / 2) + ffldaq_f2_args.n_rxchs * NSUPPLIES_FFLDAQ_F1 + ffl12_f2_args.n_rxchs * (NSUPPLIES_FFL12_F2 / 2)); + data[i].data.us = ffldaq_f2_args.opt_pow_values[j]; // sensor value and type + } + } + else { + data[i].data.us = -56; // special stale value + } + } +} +#endif // REV2 + // store the zynqmon ADCMon data void zm_set_adcmon(struct zynqmon_data_t data[], int start) { @@ -512,8 +545,10 @@ void zm_fill_structs(void) zm_set_firefly_ff12part(&zynqmon_data[195], 207); // firefly present or not, size 12 zm_set_firefly_presentbit(&zynqmon_data[201], 213); + // firefly optical power of 25Gbs FFs, size 104 + zm_set_firefly_opt_pow(&zynqmon_data[213], 225); } -#define ZMON_VALID_ENTRIES 213 +#define ZMON_VALID_ENTRIES 317 #endif void zm_send_data(struct zynqmon_data_t data[])