fixed powerchip for ctb
Build on RHEL9 docker image / build (push) Failing after 29s
Build on RHEL8 docker image / build (push) Failing after 33s

This commit is contained in:
2026-03-13 16:18:11 +01:00
parent 3b3180ef0f
commit a537de69c3
10 changed files with 67 additions and 360 deletions
@@ -572,8 +572,8 @@ void setupDetector() {
if (initError == FAIL)
return;
// power off voltage regulators
powerChip(false);
// power regulators
powerOff();
// adcs
AD9257_SetDefines(ADC_SPI_REG, ADC_SPI_SRL_CS_OTPT_MSK,
@@ -1625,6 +1625,13 @@ int getPowerRailMask(enum PWRINDEX index, uint32_t *mask, char *mess) {
return OK;
}
void powerOff() {
LOG(logINFOBLUE, ("Powering OFF all rails\n"));
// cannot call setPowerRailEnabled because of vchip dependency
uint32_t mask = POWER_ENBL_VLTG_RGLTR_MSK;
bus_w(POWER_REG, bus_r(POWER_REG) & ~(mask));
}
int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable,
char *mess) {
// get power indices for log messages and mask
@@ -151,12 +151,12 @@ int validatePower(enum DACINDEX ind, int val, char *mess);
int getPowerIndexFromDACIndex(enum DACINDEX ind, enum PWRINDEX *pwrIndex,
char *mess);
int getPowerRailMask(enum PWRINDEX ind, uint32_t *mask, char *mess);
void powerOff();
int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable,
char *mess);
int isPowerRailEnabled(enum DACINDEX ind, bool *retval, char *mess);
int verifyPowerRailDisabled(enum DACINDEX ind, char *dacName, char *mess);
void powerChip(bool enable);
int getPowerChip();
int getADC(enum ADCINDEX ind);
int getSlowADC(int ichan);
@@ -1957,7 +1957,7 @@ int acquire(int blocking, int file_des) {
}
// only set
if (Server_VerifyLock() == OK) {
#if defined(XILINX_CHIPTESTBOARDD) || defined(GOTTHARD2D)
#if defined(GOTTHARD2D)
if (!isChipConfigured()) {
ret = FAIL;
strcpy(mess, "Could not start acquisition. Chip is not configured. "
@@ -4006,8 +4006,7 @@ int power_chip(int file_des) {
LOG(logDEBUG1, ("Powering chip to %d\n", arg));
#if !defined(JUNGFRAUD) && !defined(MOENCHD) && !defined(MYTHEN3D) && \
!defined(GOTTHARD2D) && !defined(XILINX_CHIPTESTBOARDD) && \
!defined(CHIPTESTBOARDD)
!defined(GOTTHARD2D)
functionNotImplemented();
#else
// set & get
@@ -4026,8 +4025,7 @@ int power_chip(int file_des) {
}
}
#endif
#if defined(XILINX_CHIPTESTBOARDD) || defined(CHIPTESTBOARDD) || \
defined(GOTTHARD2D)
#if defined(GOTTHARD2D)
if (ret == OK) {
if (arg != -1) {
if (arg != 0 && arg != 1) {
@@ -4035,16 +4033,11 @@ int power_chip(int file_des) {
sprintf(mess, "Power chip %d should be 0 or 1\n", arg);
LOG(logERROR, (mess));
} else {
#if defined(GOTTHARD2D) || defined(XILINX_CHIPTESTBOARDD)
ret = powerChip(arg, mess);
#else
powerChip(arg);
#endif
}
}
if (ret == OK) {
retval = getPowerChip();
LOG(logDEBUG1, ("Power chip: %d\n", retval));
validate(&ret, mess, arg, retval, "power on/off chip", DEC);
}
}
@@ -10871,17 +10864,9 @@ int config_transceiver(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
#if !defined(XILINX_CHIPTESTBOARDD)
// currently not implemented anymore.
functionNotImplemented();
#else
if (Server_VerifyLock() == OK) {
LOG(logINFO, ("Configuring Transceiver\n"));
ret = configureTransceiver(mess);
if (ret == FAIL) {
LOG(logERROR, (mess));
}
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}
@@ -41,7 +41,6 @@ char initErrorMessage[MAX_STR_LENGTH];
int detPos[2] = {0, 0};
uint32_t clkFrequency[NUM_CLOCKS] = {};
int chipConfigured = 0;
int analogEnable = 0;
int digitalEnable = 0;
int transceiverEnable = 0;
@@ -379,7 +378,6 @@ void setupDetector() {
clkFrequency[ADC_CLK] = DEFAULT_ADC_CLK;
clkFrequency[SYNC_CLK] = DEFAULT_SYNC_CLK;
clkFrequency[DBIT_CLK] = DEFAULT_DBIT_CLK;
chipConfigured = 0;
analogEnable = 0;
digitalEnable = 0;
transceiverEnable = 0;
@@ -397,11 +395,11 @@ void setupDetector() {
if (initError == FAIL) {
return;
}
// power off chip
initError = powerChip(false, initErrorMessage);
if (initError == FAIL) {
// power regulators
initError = powerOff(initErrorMessage);
if (initError == FAIL)
return;
}
LTC2620_D_SetDefines(DAC_MIN_MV, DAC_MAX_MV, DAC_DRIVER_FILE_NAME, NDAC,
NPWR, DAC_POWERDOWN_DRIVER_FILE_NAME);
@@ -511,18 +509,6 @@ int waitTransceiverReset(char *mess) {
return OK;
}
#ifdef VIRTUAL
void setTransceiverAlignment(int align) {
if (align) {
bus_w(TRANSCEIVERSTATUS,
(bus_r(TRANSCEIVERSTATUS) | RXBYTEISALIGNED_MSK));
} else {
bus_w(TRANSCEIVERSTATUS,
(bus_r(TRANSCEIVERSTATUS) & ~RXBYTEISALIGNED_MSK));
}
}
#endif
int isTransceiverAligned() {
#ifdef VIRTUAL
return 1;
@@ -539,300 +525,6 @@ int isTransceiverAligned() {
return retval;
}
int waitTransceiverAligned(char *mess) {
#ifdef VIRTUAL
setTransceiverAlignment(1);
#else
// no module: transceiver will never get aligned
if (!checkModuleFlag) {
LOG(logWARNING, ("No module: Transceiver will never get aligned. "
"Ignoring alignment check.\n"));
return OK;
}
int transceiverWordAligned = isTransceiverAligned();
int times = 0;
while (transceiverWordAligned == 0) {
if (times++ > WAIT_TIME_OUT_0US_TIMES) {
sprintf(mess, "Transceiver alignment timed out. Check connection, "
"p-n inversions, LSB-MSB inversions, link error "
"counters and channel enable settings\n");
LOG(logERROR, (mess));
return FAIL;
}
usleep(0);
transceiverWordAligned = isTransceiverAligned();
}
#endif
LOG(logINFOBLUE, ("Transceiver alignment done\n"));
return OK;
}
int configureTransceiver(char *mess) {
LOG(logINFOBLUE, ("\tConfiguring transceiver\n"));
if (chipConfigured == 0) {
sprintf(mess,
"Chip not configured. Use powerchip to power on chip first.\n");
LOG(logERROR, (mess));
return FAIL;
}
return waitTransceiverAligned(mess);
}
int isChipConfigured() { return chipConfigured; }
// TODO powerchip and configurechip should be separate commands (not
// requirement) in the future
int powerChip(bool on, char *mess) {
uint32_t addr = CTRL_REG;
uint32_t mask = POWER_VIO_MSK | POWER_VCC_A_MSK | POWER_VCC_B_MSK |
POWER_VCC_C_MSK | POWER_VCC_D_MSK;
if (on) {
LOG(logINFOBLUE, ("Powering ON all\n"));
bus_w(addr, bus_r(addr) | mask);
if (configureChip(mess) == FAIL)
return FAIL;
} else {
LOG(logINFOBLUE, ("Powering OFF all\n"));
bus_w(addr, bus_r(addr) & ~mask);
chipConfigured = 0;
if (FAIL == XILINX_FMC_disable_all(mess, MAX_STR_LENGTH)) {
return FAIL;
}
#ifdef VIRTUAL
setTransceiverAlignment(0);
#endif
// transceiver alignment should be reset at power off
if (isTransceiverAligned()) {
sprintf(mess, "Transceiver alignment not reset\n");
LOG(logERROR, (mess));
// to be removed when fixed later
LOG(logWARNING,
("Bypassing this error for now. To be fixed later...\n"));
return OK;
return FAIL;
}
LOG(logINFO, ("\tTransceiver alignment has been reset\n"));
}
return OK;
}
int getPowerChip() {
uint32_t mask = POWER_VIO_MSK | POWER_VCC_A_MSK | POWER_VCC_B_MSK |
POWER_VCC_C_MSK | POWER_VCC_D_MSK;
uint32_t retval = bus_r(CTRL_REG) & mask;
if (retval == 0)
return 0;
if (retval == mask)
return 1;
LOG(logINFO, ("Power chip state is neither fully on nor fully off. Value "
"read: 0x%x\n",
retval));
return -1;
}
int configureChip(char *mess) {
LOG(logINFOBLUE, ("\tConfiguring chip\n"));
chipConfigured = 0;
if (readConfigFile(mess, CONFIG_CHIP_FILE, "chip config") == FAIL) {
return FAIL;
}
if (readConfigFile(mess, RESET_CHIP_FILE, "reset chip") == FAIL) {
return FAIL;
}
LOG(logINFOBLUE, ("Chip configured.\n"));
chipConfigured = 1;
return OK;
}
int readConfigFile(char *mess, char *fileName, char *fileType) {
const int fileNameSize = 128;
char fname[fileNameSize];
if (getAbsPath(fname, fileNameSize, fileName) == FAIL) {
sprintf(mess, "Could not get full path for %s file [%s].\n", fileType,
fname);
LOG(logERROR, (mess));
return FAIL;
}
if (access(fname, F_OK) != 0) {
sprintf(mess, "Could not find %s file [%s].\n", fileType, fname);
LOG(logERROR, (mess));
return FAIL;
}
FILE *fd = fopen(fname, "r");
if (fd == NULL) {
sprintf(mess, "Could not open on-board detector server %s file [%s].\n",
fileType, fname);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFOBLUE, ("Reading %s file %s\n", fileType, fname));
const size_t LZ = 256;
char line[LZ];
memset(line, 0, LZ);
char command[LZ];
// keep reading a line
while (fgets(line, LZ, fd)) {
// ignore comments
if (line[0] == '#') {
LOG(logDEBUG1, ("Ignoring Comment\n"));
continue;
}
// ignore empty lines
if (strlen(line) <= 1) {
LOG(logDEBUG1, ("Ignoring Empty line\n"));
continue;
}
// removing leading spaces
if (line[0] == ' ' || line[0] == '\t') {
int len = strlen(line);
// find first valid character
int i = 0;
for (i = 0; i < len; ++i) {
if (line[i] != ' ' && line[i] != '\t') {
break;
}
}
// ignore the line full of spaces (last char \n)
if (i >= len - 1) {
LOG(logDEBUG1, ("Ignoring line full of spaces\n"));
continue;
}
// copying only valid char
char temp[LZ];
memset(temp, 0, LZ);
memcpy(temp, line + i, strlen(line) - i);
memset(line, 0, LZ);
memcpy(line, temp, strlen(temp));
LOG(logDEBUG1, ("Removing leading spaces.\n"));
}
LOG(logDEBUG1, ("Command to process: (size:%d) %.*s\n", strlen(line),
strlen(line) - 1, line));
memset(command, 0, LZ);
// reg command
if (!strncmp(line, "reg", strlen("reg"))) {
uint32_t addr = 0;
uint32_t val = 0;
if (sscanf(line, "%s %x %x", command, &addr, &val) != 3) {
sprintf(mess, "Could not scan reg command. Line:[%s].\n", line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, val);
LOG(logINFOBLUE, ("Wrote 0x%x to 0x%x\n", val, addr));
}
// setbit command
else if (!strncmp(line, "setbit", strlen("setbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
if (sscanf(line, "%s %x %d", command, &addr, &bit) != 3) {
sprintf(mess, "Could not scan setbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, bus_r(addr) | (1 << bit));
LOG(logINFOBLUE, ("Set bit %d in 0x%x\n", bit, addr));
}
// clearbit command
else if (!strncmp(line, "clearbit", strlen("clearbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
if (sscanf(line, "%s %x %d", command, &addr, &bit) != 3) {
sprintf(mess, "Could not scan clearbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, bus_r(addr) & ~(1 << bit));
LOG(logINFOBLUE, ("Cleared bit %d in 0x%x\n", bit, addr));
}
// pollbit command
else if (!strncmp(line, "pollbit", strlen("pollbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
uint32_t val = 0;
if (sscanf(line, "%s %x %d %d", command, &addr, &bit, &val) != 4) {
sprintf(mess, "Could not scan pollbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
#ifndef VIRTUAL
int times = 0;
while (((bus_r(addr) >> bit) & 0x1) != val) {
if (times++ > WAIT_TIME_OUT_0US_TIMES) {
sprintf(mess, "Polling bit %d in 0x%x timed out\n", bit,
addr);
LOG(logERROR, (mess));
return FAIL;
}
usleep(0);
}
#endif
LOG(logINFOBLUE, ("Polled bit %d in 0x%x\n", bit, addr));
}
// pattern command
else if (!strncmp(line, "pattern", strlen("pattern"))) {
// take a file name and call loadPatterFile
char patternFileName[LZ];
if (sscanf(line, "%s %s", command, patternFileName) != 2) {
sprintf(mess, "Could not scan pattern command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
if (loadPatternFile(patternFileName, mess) == FAIL) {
return FAIL;
}
LOG(logINFOBLUE, ("loaded pattern [%s].\n", patternFileName));
}
// sleep command
else if (!strncmp(line, "sleep", strlen("sleep"))) {
int time = 0;
if (sscanf(line, "%s %d", command, &time) != 2) {
sprintf(mess, "Could not scan sleep command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
usleep(time * 1000 * 1000);
LOG(logINFOBLUE, ("Slept for %d s\n", time));
}
// other commands
else {
sprintf(mess,
"Could not scan command from on-board server "
"%s file. Line:[%s].\n",
fileType, line);
break;
}
memset(line, 0, LZ);
}
fclose(fd);
LOG(logINFOBLUE, ("Successfully read %s file.\n", fileType));
return OK;
}
/* set parameters - dr */
int setDynamicRange(int dr) {
@@ -1442,6 +1134,20 @@ int getPowerRailMask(enum PWRINDEX index, uint32_t *mask, char *mess) {
return OK;
}
int powerOff(char *mess) {
LOG(logINFOBLUE, ("Powering OFF all rails\n"));
enum DACINDEX indices[] = {D_PWR_D, D_PWR_C, D_PWR_B, D_PWR_A, D_PWR_IO};
int count = sizeof(indices) / sizeof(indices[0]);
int ret = setPowerRailEnabled(indices, count, false, mess);
if (ret == FAIL)
return FAIL;
if (XILINX_FMC_disable_all(mess, MAX_STR_LENGTH) == FAIL)
return FAIL;
return OK;
}
int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable,
char *mess) {
// get power indices for log messages and mask
@@ -63,18 +63,7 @@ void setupDetector();
void cleanFifos();
void resetFlow();
int waitTransceiverReset(char *mess);
#ifdef VIRTUAL
void setTransceiverAlignment(int align);
#endif
int isTransceiverAligned();
int waitTransceiverAligned(char *mess);
int configureTransceiver(char *mess);
int isChipConfigured();
int powerChip(bool on, char *mess);
int getPowerChip();
int configureChip(char *mess);
int readConfigFile(char *mess, char *fileName, char *fileType);
int resetChip(char *mess);
// parameters - dr, roi
int setDynamicRange(int dr);
@@ -138,6 +127,8 @@ int validatePower(enum DACINDEX ind, int val, char *mess);
int getPowerIndexFromDACIndex(enum DACINDEX ind, enum PWRINDEX *pwrIndex,
char *mess);
int getPowerRailMask(enum PWRINDEX ind, uint32_t *mask, char *mess);
int powerOff(char *mess);
int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable,
char *mess);
int isPowerRailEnabled(enum DACINDEX ind, bool *retval, char *mess);
+21 -5
View File
@@ -1969,8 +1969,9 @@ std::string Caller::power(int action) {
if (action == defs::HELP_ACTION) {
os << "[list of power names] [on|off]\n\t[Ctb][Xilinx Ctb] Enable or "
"disable power rails. Power name can be v_a, v_b, v_c, v_d or "
"v_io or any names set using powername. One can retrieve only "
"one at a time."
"v_io or any defines using 'powername'. If power name is set to "
"'all', the command applies to all 'powers'. Only one power can "
"be queried at a time."
<< '\n';
return os.str();
}
@@ -1993,18 +1994,33 @@ std::string Caller::power(int action) {
}
else if (action == defs::PUT_ACTION) {
bool all = false;
if (std::find(args.begin(), args.end(), "all") != args.end()) {
if (args.size() != 2)
WrongNumberOfParameters(2);
all = true;
}
if (args.size() < 1 || args.size() > 6) {
WrongNumberOfParameters(1);
}
// enable arg
std::string lastArg = args.back();
if (lastArg != "on" && lastArg != "off") {
throw RuntimeError("Last argument '" + lastArg +
"' must be on or off");
"' is enable. Options: 'on' or 'off'");
}
bool enable = StringTo(lastArg, defs::OnOff);
// power indices
std::vector<defs::dacIndex> powerIndices;
for (size_t i = 0; i < args.size() - 1; ++i) {
powerIndices.push_back(parsePowerIndex(i));
if (all) {
powerIndices = det->getPowerList();
} else {
// push back indices from command line
for (size_t i = 0; i < args.size() - 1; ++i) {
powerIndices.push_back(parsePowerIndex(i));
}
}
det->setPowerEnabled(powerIndices, enable, std::vector<int>{det_id});
+3
View File
@@ -2200,6 +2200,9 @@ Result<bool> Detector::isPowerEnabled(defs::dacIndex index,
void Detector::setPowerEnabled(const std::vector<defs::dacIndex> &indices,
bool value, Positions pos) {
if (indices.empty()) {
throw RuntimeError("No Power Index provided");
}
std::vector<defs::dacIndex> valid_indices = getPowerList();
for (const auto &index : indices) {
if (std::find(valid_indices.begin(), valid_indices.end(), index) ==
@@ -1266,8 +1266,8 @@ TEST_CASE("power", "[.detectorintegration]") {
REQUIRE(oss[6].str() == "power v_d on\n");
REQUIRE(oss[7].str() == "power v_io off\n");
}
{ // power chip
caller.call("powerchip", {"1"}, -1, PUT);
{ // power on all
caller.call("power", {"all", "on"}, -1, PUT);
std::ostringstream oss1, oss2, oss3, oss4, oss5;
caller.call("power", {"v_a"}, -1, GET, oss1);
caller.call("power", {"v_b"}, -1, GET, oss2);
@@ -1280,6 +1280,7 @@ TEST_CASE("power", "[.detectorintegration]") {
REQUIRE(oss4.str() == "power v_d on\n");
REQUIRE(oss5.str() == "power v_io on\n");
}
REQUIRE_THROWS(caller.call("power", {"all"}, -1, GET));
for (size_t iPower = 0; iPower < cmds.size(); ++iPower) {
det.setPowerEnabled(std::vector{indices[iPower]}, prev_val[iPower]);
}
@@ -1547,9 +1547,7 @@ TEST_CASE("powerchip", "[.detectorintegration]") {
auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::MOENCH ||
det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2 ||
det_type == defs::XILINX_CHIPTESTBOARD ||
det_type == defs::CHIPTESTBOARD) {
det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2) {
auto prev_val =
det.getPowerChip().tsquash("Inconsistent power chip values");
{
+3 -3
View File
@@ -305,11 +305,11 @@ def loadConfig(name, rx_hostname = 'localhost', settingsdir = None, log_file_fp
if num_interfaces == 2:
d.udp_dstip2 = 'auto'
if name == "jungfrau" or name == "moench" or name == "xilinx_ctb":
if name == "jungfrau" or name == "moench":
d.powerchip = 1
if name == "xilinx_ctb":
d.configureTransceiver()
#if name == "xilinx_ctb":
# d.configureTransceiver()
if settingsdir is not None and name in ['eiger', 'mythen3']:
d.settingspath = settingsdir + '/' + name + '/'