diff --git a/CMakeLists.txt b/CMakeLists.txt index a2281fb21..4db277142 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,6 @@ sls_enable_cxx_warning("-Wnull-dereference") sls_enable_cxx_warning("-Wduplicated-cond") sls_disable_cxx_warning("-Wclass-memaccess") sls_disable_c_warning("-Wstringop-truncation") -sls_disable_c_warning("-Wformat-nonliteral") if(SLS_USE_SANITIZER) diff --git a/RELEASE.txt b/RELEASE.txt index e0f1d3af7..ccb56de6c 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -20,7 +20,9 @@ This document describes the differences between vx.x.x and v6.0.0. 1. New or Changed Features ========================== - kernelversion - +- updatekernel +- updatedetectorserver +- update (without pcname) 2. Resolved Issues @@ -30,6 +32,8 @@ This document describes the differences between vx.x.x and v6.0.0. - rx id in config file was not taken into account. fixed. - programming firmware failure for blackfin, fixed but requires new kernel. - nios kernel check updated (ensuring right kernel) +- executecommand now says which module failed +- programming firmware did not delete temporary file created. fixed. 3. Known Issues =============== diff --git a/python/src/detector.cpp b/python/src/detector.cpp index c25c807de..82acb1eef 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1520,7 +1520,15 @@ void init_det(py::module &m) { (void (Detector::*)(const std::string &, const std::string &, sls::Positions)) & Detector::copyDetectorServer, - py::arg(), py::arg(), py::arg() = Positions{}) + py::arg(), py::arg(), py::arg() = Positions{}) + .def("updateDetectorServer", + (void (Detector::*)(const std::string &, sls::Positions)) & + Detector::updateDetectorServer, + py::arg(), py::arg() = Positions{}) + .def("updateKernel", + (void (Detector::*)(const std::string &, sls::Positions)) & + Detector::updateKernel, + py::arg(), py::arg() = Positions{}) .def("rebootController", (void (Detector::*)(sls::Positions)) & Detector::rebootController, py::arg() = Positions{}) @@ -1529,6 +1537,11 @@ void init_det(py::module &m) { const std::string &, sls::Positions)) & Detector::updateFirmwareAndServer, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) + .def("updateFirmwareAndServer", + (void (Detector::*)(const std::string &, const std::string &, + sls::Positions)) & + Detector::updateFirmwareAndServer, + py::arg(), py::arg(), py::arg() = Positions{}) .def("readRegister", (Result(Detector::*)(uint32_t, sls::Positions) const) & Detector::readRegister, diff --git a/slsDetectorServers/ctbDetectorServer/CMakeLists.txt b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt index 181600f44..f53bdc21d 100644 --- a/slsDetectorServers/ctbDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt @@ -17,7 +17,7 @@ add_executable(ctbDetectorServer_virtual ../slsDetectorServer/src/INA226.c ../slsDetectorServer/src/LTC2620.c ../slsDetectorServer/src/MAX1932.c - ../slsDetectorServer/src/programFpgaBlackfin.c + ../slsDetectorServer/src/programViaBlackfin.c ../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/loadPattern.c ../../slsSupportLib/src/md5.c diff --git a/slsDetectorServers/ctbDetectorServer/Makefile b/slsDetectorServers/ctbDetectorServer/Makefile index 56b3b271b..0d9229472 100755 --- a/slsDetectorServers/ctbDetectorServer/Makefile +++ b/slsDetectorServers/ctbDetectorServer/Makefile @@ -16,7 +16,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 4bc6dc6ef..bd4da43da 100755 Binary files a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer and b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer differ diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index b1f8f51bb..f062638cd 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -97,8 +97,14 @@ void basictests() { return; #else - defineGPIOpins(); - resetFPGA(); + initError = defineGPIOpins(initErrorMessage); + if (initError == FAIL) { + return; + } + initError = resetFPGA(initErrorMessage); + if (initError == FAIL) { + return; + } if (mapCSP0() == FAIL) { strcpy(initErrorMessage, "Could not map to memory. Dangerous to continue.\n"); diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 123a9cabb..5a167a967 100755 Binary files a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer and b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer differ diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h index 3f0e5a288..2711a76b5 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h @@ -3,7 +3,7 @@ #pragma once #include "sls/sls_detector_defs.h" -#define LINKED_SERVER_NAME "eigerDetectorServer" +#define LINKED_SERVER_NAME "/home/root/executables/eigerDetectorServer" #define REQUIRED_FIRMWARE_VERSION (29) // virtual ones renamed for consistency diff --git a/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt b/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt index dbe403fd3..d7b0edb31 100644 --- a/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt +++ b/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable(gotthard2DetectorServer_virtual ../slsDetectorServer/src/LTC2620_Driver.c ../slsDetectorServer/src/ALTERA_PLL_CYCLONE10.c ../slsDetectorServer/src/ASIC_Driver.c - ../slsDetectorServer/src/programFpgaNios.c + ../slsDetectorServer/src/programViaNios.c ../slsDetectorServer/src/sharedMemory.c ../../slsSupportLib/src/md5.c ) diff --git a/slsDetectorServers/gotthard2DetectorServer/Makefile b/slsDetectorServers/gotthard2DetectorServer/Makefile index 23ea50584..817babe0e 100755 --- a/slsDetectorServers/gotthard2DetectorServer/Makefile +++ b/slsDetectorServers/gotthard2DetectorServer/Makefile @@ -15,7 +15,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programViaNios.c $(main_src)/sharedMemory.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) diff --git a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer index 5b14be7d1..35b3545c0 100755 Binary files a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer and b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer differ diff --git a/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt b/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt index e2f7eac57..0ab9c9d1f 100644 --- a/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(gotthardDetectorServer_virtual ../slsDetectorServer/src/LTC2620.c ../slsDetectorServer/src/common.c ../slsDetectorServer/src/commonServerFunctions.c + ../slsDetectorServer/src/programViaBlackfin.c ../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/sharedMemory.c ../../slsSupportLib/src/md5.c diff --git a/slsDetectorServers/gotthardDetectorServer/Makefile b/slsDetectorServers/gotthardDetectorServer/Makefile index 75bed6bb9..68af42ee7 100755 --- a/slsDetectorServers/gotthardDetectorServer/Makefile +++ b/slsDetectorServers/gotthardDetectorServer/Makefile @@ -15,7 +15,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)programViaBlackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) all: clean $(PROGS) diff --git a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer index f9e9fdd34..004ff7e60 100755 Binary files a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer and b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer differ diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h index b91bb9ab2..89d38eefc 100644 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h @@ -6,6 +6,8 @@ #define LINKED_SERVER_NAME "gotthardDetectorServer" +#define CTRL_SRVR_INIT_TIME_US (300 * 1000) + /* Enums */ enum ADCINDEX { TEMP_FPGA, TEMP_ADC }; enum DACINDEX { diff --git a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt index b1cd36a13..63c3afaec 100644 --- a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable(jungfrauDetectorServer_virtual ../slsDetectorServer/src/ALTERA_PLL.c ../slsDetectorServer/src/LTC2620.c ../slsDetectorServer/src/MAX1932.c - ../slsDetectorServer/src/programFpgaBlackfin.c + ../slsDetectorServer/src/programViaBlackfin.c ../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/sharedMemory.c ../../slsSupportLib/src/md5.c diff --git a/slsDetectorServers/jungfrauDetectorServer/Makefile b/slsDetectorServers/jungfrauDetectorServer/Makefile index 0468da861..5f2e93dc4 100755 --- a/slsDetectorServers/jungfrauDetectorServer/Makefile +++ b/slsDetectorServers/jungfrauDetectorServer/Makefile @@ -15,7 +15,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)/sharedMemory.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 9d5cdadc7..0b31a5ffb 100755 Binary files a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer and b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer differ diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 9728c00ec..4f4214079 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -74,8 +74,14 @@ void basictests() { } return; #else - defineGPIOpins(); - resetFPGA(); + initError = defineGPIOpins(initErrorMessage); + if (initError == FAIL) { + return; + } + initError = resetFPGA(initErrorMessage); + if (initError == FAIL) { + return; + } if (mapCSP0() == FAIL) { strcpy(initErrorMessage, "Could not map to memory. Dangerous to continue.\n"); diff --git a/slsDetectorServers/moenchDetectorServer/CMakeLists.txt b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt index de0923b87..4d6901afc 100644 --- a/slsDetectorServers/moenchDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt @@ -14,7 +14,7 @@ add_executable(moenchDetectorServer_virtual ../slsDetectorServer/src/ALTERA_PLL.c ../slsDetectorServer/src/LTC2620.c ../slsDetectorServer/src/MAX1932.c - ../slsDetectorServer/src/programFpgaBlackfin.c + ../slsDetectorServer/src/programViaBlackfin.c ../slsDetectorServer/src/loadPattern.c ../slsDetectorServer/src/sharedMemory.c ../../slsSupportLib/src/md5.c diff --git a/slsDetectorServers/moenchDetectorServer/Makefile b/slsDetectorServers/moenchDetectorServer/Makefile index f08d178e1..e57e80a03 100755 --- a/slsDetectorServers/moenchDetectorServer/Makefile +++ b/slsDetectorServers/moenchDetectorServer/Makefile @@ -16,7 +16,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) diff --git a/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer b/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer index 52125a2a6..e936ffdbb 100755 Binary files a/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer and b/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer differ diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index 1c0c703fd..77482af77 100644 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -94,8 +94,14 @@ void basictests() { return; #else - defineGPIOpins(); - resetFPGA(); + initError = defineGPIOpins(initErrorMessage); + if (initError == FAIL) { + return; + } + initError = resetFPGA(initErrorMessage); + if (initError == FAIL) { + return; + } if (mapCSP0() == FAIL) { strcpy(initErrorMessage, "Could not map to memory. Dangerous to continue.\n"); diff --git a/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt b/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt index 9033f5200..ab1496fe6 100644 --- a/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt +++ b/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable(mythen3DetectorServer_virtual ../slsDetectorServer/src/common.c ../slsDetectorServer/src/LTC2620_Driver.c ../slsDetectorServer/src/ALTERA_PLL_CYCLONE10.c - ../slsDetectorServer/src/programFpgaNios.c + ../slsDetectorServer/src/programViaNios.c ../slsDetectorServer/src/loadPattern.c ../slsDetectorServer/src/sharedMemory.c ../../slsSupportLib/src/md5.c diff --git a/slsDetectorServers/mythen3DetectorServer/Makefile b/slsDetectorServers/mythen3DetectorServer/Makefile index 29e39f6b2..42b412f48 100755 --- a/slsDetectorServers/mythen3DetectorServer/Makefile +++ b/slsDetectorServers/mythen3DetectorServer/Makefile @@ -16,7 +16,7 @@ DESTDIR ?= bin INSTMODE = 0777 SRCS = slsDetectorFunctionList.c -SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c $(md5_dir)md5.c +SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programViaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c $(md5_dir)md5.c OBJS = $(SRCS:.c=.o) diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer index d89e6b65c..5f2bb2c8f 100755 Binary files a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer and b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer differ diff --git a/slsDetectorServers/slsDetectorServer/include/common.h b/slsDetectorServers/slsDetectorServer/include/common.h index 7cfbf007a..821e28040 100644 --- a/slsDetectorServers/slsDetectorServer/include/common.h +++ b/slsDetectorServers/slsDetectorServer/include/common.h @@ -8,7 +8,12 @@ #include #include +#define TEMP_PROG_FOLDER_NAME "/var/tmp/" +#define TEMP_PROG_FOLDER_NAME_ALL_FILES "/var/tmp/*" +#define TEMP_PROG_FILE_NAME TEMP_PROG_FOLDER_NAME "tmp.rawbin" + enum numberMode { DEC, HEX }; +enum PROGRAM_INDEX { PROGRAM_FPGA, PROGRAM_KERNEL, PROGRAM_SERVER }; /** * Convert a value from a range to a different range (eg voltage to dac or vice @@ -28,7 +33,7 @@ int getAbsPath(char *buf, size_t bufSize, char *fname); int getTimeFromString(char *buf, time_t *result); -int getKernelVersion(char* retvals); +int getKernelVersion(char *retvals); int validateKernelVersion(char *expectedVersion); @@ -38,9 +43,17 @@ void validate64(int *ret, char *mess, int64_t arg, int64_t retval, char *modename, enum numberMode nummode); int getModuleIdInFile(int *ret, char *mess, char *fileName); -int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer, - ssize_t bytes); -int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname); -int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname, - ssize_t fsize); -int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg); \ No newline at end of file +int verifyChecksumFromBuffer(char *mess, char *functionType, + char *clientChecksum, char *buffer, ssize_t bytes); +int verifyChecksumFromFile(char *mess, char *functionType, char *clientChecksum, + char *fname); +int verifyChecksumFromFlash(char *mess, char *functionType, + char *clientChecksum, char *fname, ssize_t fsize); +int verifyChecksum(char *mess, char *functionType, char *clientChecksum, + MD5_CTX *c, char *msg); +int setupDetectorServer(char *mess, char *sname); + +int writeBinaryFile(char *mess, char *fname, char *buffer, + const uint64_t filesize, char *errorPrefix); + +int moveBinaryFile(char *mess, char *dest, char *src, char *errorPrefix); diff --git a/slsDetectorServers/slsDetectorServer/include/programFpgaBlackfin.h b/slsDetectorServers/slsDetectorServer/include/programFpgaBlackfin.h deleted file mode 100644 index 23ce5e252..000000000 --- a/slsDetectorServers/slsDetectorServer/include/programFpgaBlackfin.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#pragma once - -#include -#include -#include - -#define TEMP_PROG_FILE_NAME "/var/tmp/tmp.rawbin" - -void defineGPIOpins(); -void FPGAdontTouchFlash(); -void FPGATouchFlash(); -void resetFPGA(); - -int deleteOldFile(char *mess); -/** - * deletes old file - * verify memory available to copy - * open file to copy - */ -int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess); -int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess); -int getDrive(char *mess); -/** Notify fpga not to touch flash, open src and flash drive to write */ -int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess); -int eraseFlash(char *mess); -/* write from tmp file to flash */ -int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess); -/** Notify fpga to pick up firmware from flash and wait for status confirmation - */ -int waitForFPGAtoTouchFlash(char *mess); diff --git a/slsDetectorServers/slsDetectorServer/include/programViaBlackfin.h b/slsDetectorServers/slsDetectorServer/include/programViaBlackfin.h new file mode 100644 index 000000000..9abe2e678 --- /dev/null +++ b/slsDetectorServers/slsDetectorServer/include/programViaBlackfin.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: LGPL-3.0-or-other +// Copyright (C) 2021 Contributors to the SLS Detector Package +#pragma once + +#include "common.h" + +#include +#include +#include + +int defineGPIOpins(char *mess); +int FPGAdontTouchFlash(char *mess); +int FPGATouchFlash(char *mess); +int resetFPGA(char *mess); + +int emptyTempFolder(char *mess); +/** + * deletes old file + * verify memory available to copy + * open file to copy + */ +int preparetoCopyProgram(char *mess, char *functionType, FILE **fd, + uint64_t fsize); +int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index, + char *functionType, char *clientChecksum, + ssize_t fsize); +int getDrive(char *mess, enum PROGRAM_INDEX index); +/** Notify fpga not to touch flash, open src and flash drive to write */ +int openFileForFlash(char *mess, FILE **flashfd, FILE **srcfd); +int eraseFlash(char *mess); +/* write from tmp file to flash */ +int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, FILE *srcfd); +/** Notify fpga to pick up firmware from flash and wait for status confirmation + */ +int waitForFPGAtoTouchFlash(char *mess); diff --git a/slsDetectorServers/slsDetectorServer/include/programFpgaNios.h b/slsDetectorServers/slsDetectorServer/include/programViaNios.h similarity index 58% rename from slsDetectorServers/slsDetectorServer/include/programFpgaNios.h rename to slsDetectorServers/slsDetectorServer/include/programViaNios.h index 7e9d0be7c..0b0a6bd02 100644 --- a/slsDetectorServers/slsDetectorServer/include/programFpgaNios.h +++ b/slsDetectorServers/slsDetectorServer/include/programViaNios.h @@ -2,6 +2,8 @@ // Copyright (C) 2021 Contributors to the SLS Detector Package #pragma once +#include "common.h" + #include #include @@ -13,9 +15,10 @@ void NotifyServerStartSuccess(); /** reset fpga and controller(only implemented for >= v1.1 boards) */ void rebootControllerAndFPGA(); -int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc, +int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index, + char *functionType, char *checksum, char *fpgasrc, uint64_t fsize); -int getDrive(char *mess); -int openFileForFlash(FILE **flashfd, char *mess); +int getDrive(char *mess, enum PROGRAM_INDEX index); +int openFileForFlash(char *mess, FILE **flashfd); int eraseFlash(char *mess); -int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess); \ No newline at end of file +int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, char *buffer); \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index a8854e8ca..0506650f6 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -12,9 +12,10 @@ #endif #if defined(MYTHEN3D) || defined(GOTTHARD2D) -#include "programFpgaNios.h" -#elif defined(CHIPTESTBOARDD) || defined(JUNGFRAUD) || defined(MOENCHD) -#include "programFpgaBlackfin.h" +#include "programViaNios.h" +#elif defined(CHIPTESTBOARDD) || defined(JUNGFRAUD) || defined(MOENCHD) || \ + defined(GOTTHARDD) +#include "programViaBlackfin.h" #endif #if defined(MYTHEN3D) || defined(GOTTHARD2D) @@ -60,7 +61,6 @@ typedef struct udpStruct_s { int isInitCheckDone(); int getInitResult(char **mess); void basictests(); -int getKernelVersion(char* retvals); #if defined(GOTTHARDD) || defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || \ defined(MOENCHD) || defined(MYTHEN3D) || defined(GOTTHARD2D) int checkType(); diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index a6026dd72..679ac96fa 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -277,4 +277,13 @@ int get_udp_first_dest(int); int set_udp_first_dest(int); int get_readout_speed(int); int set_readout_speed(int); -int get_kernel_version(int); \ No newline at end of file +int get_kernel_version(int); +int update_kernel(int); +int update_detector_server(int); +int receive_program(int file_des, enum PROGRAM_INDEX index); +void receive_program_via_blackfin(int file_des, enum PROGRAM_INDEX index, + char *functionType, uint64_t filesize, + char *checksum, char *serverName); +void receive_program_default(int file_des, enum PROGRAM_INDEX index, + char *functionType, uint64_t filesize, + char *checksum, char *serverName); \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/src/common.c b/slsDetectorServers/slsDetectorServer/src/common.c index 0d9d0ce74..45ebc9413 100644 --- a/slsDetectorServers/slsDetectorServer/src/common.c +++ b/slsDetectorServers/slsDetectorServer/src/common.c @@ -4,12 +4,15 @@ #include "common.h" #include "clogger.h" #include "sls/sls_detector_defs.h" +#include "slsDetectorServer_defs.h" #include // dirname #include #include // uname #include // readlink +extern int executeCommand(char *command, char *result, enum TLogLevel level); + int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin, int outputMax, int inputValue, int *outputValue) { LOG(logDEBUG1, (" Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n", @@ -92,19 +95,22 @@ int getTimeFromString(char *buf, time_t *result) { } // print time structure - LOG(logDEBUG, ("%d %d %d %d:%d:%d %d (day date month H:M:S year)\n", t.tm_wday, t.tm_mday, t.tm_mon, t.tm_year +1900, t.tm_hour, t.tm_min, t.tm_sec)); + LOG(logDEBUG, + ("%d %d %d %d:%d:%d %d (day date month H:M:S year)\n", t.tm_wday, + t.tm_mday, t.tm_mon, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec)); *result = mktime(&t); return OK; } -int getKernelVersion(char* retvals) { - struct utsname buf = {0}; +int getKernelVersion(char *retvals) { + struct utsname buf; + memset(&buf, 0, sizeof(buf)); if (uname(&buf) == -1) { strcpy(retvals, "Failed to get utsname structure from uname\n"); LOG(logERROR, (retvals)); return FAIL; - } + } strcpy(retvals, buf.version); LOG(logINFOBLUE, ("Kernel Version: %s\n", retvals)); return OK; @@ -135,7 +141,8 @@ int validateKernelVersion(char *expectedVersion) { // convert kernel date string into time time_t kernelDate; if (getTimeFromString(currentVersion, &kernelDate) == FAIL) { - LOG(logERROR, ("Could not parse retrieved kernel date, %s\n", currentVersion)); + LOG(logERROR, + ("Could not parse retrieved kernel date, %s\n", currentVersion)); return FAIL; } @@ -155,8 +162,8 @@ int validateKernelVersion(char *expectedVersion) { return FAIL; } - LOG(logINFOBLUE, ("Kernel Version Compatible: %s [min.: %s]\n", currentVersion, - expectedVersion)); + LOG(logINFOBLUE, ("Kernel Version Compatible: %s [min.: %s]\n", + currentVersion, expectedVersion)); return OK; } @@ -235,30 +242,39 @@ int getModuleIdInFile(int *ret, char *mess, char *fileName) { return retval; } -int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer, +int verifyChecksumFromBuffer(char *mess, char *functionType, + char *clientChecksum, char *buffer, ssize_t bytes) { - LOG(logINFO, ("\tVerifying Checksum...\n")); + LOG(logINFO, ("\tVerifying Checksum from memory...\n")); MD5_CTX c; if (!MD5_Init_SLS(&c)) { - strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n"); + sprintf(mess, + "Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } if (!MD5_Update_SLS(&c, buffer, bytes)) { - strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n"); + sprintf(mess, + "Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } - return verifyChecksum(mess, clientChecksum, &c, "copied program"); + return verifyChecksum(mess, functionType, clientChecksum, &c, + "copied program (buffer)"); } -int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) { - LOG(logINFO, ("\tVerifying Checksum...\n")); +int verifyChecksumFromFile(char *mess, char *functionType, char *clientChecksum, + char *fname) { + LOG(logINFO, ("\tVerifying Checksum of file...\n")); FILE *fp = fopen(fname, "r"); if (fp == NULL) { - sprintf(mess, "Unable to open %s in read mode to get checksum\n", - fname); + sprintf( + mess, + "Could not %s. Unable to open %s in read mode to get checksum\n", + functionType, fname); LOG(logERROR, (mess)); return FAIL; } @@ -266,7 +282,9 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) { MD5_CTX c; if (!MD5_Init_SLS(&c)) { fclose(fp); - strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n"); + sprintf(mess, + "Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } @@ -277,7 +295,10 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) { while (bytes > 0) { if (!MD5_Update_SLS(&c, buf, bytes)) { fclose(fp); - strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n"); + sprintf( + mess, + "Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } @@ -286,17 +307,20 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) { } LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead)); fclose(fp); - return verifyChecksum(mess, clientChecksum, &c, "copied program"); + return verifyChecksum(mess, functionType, clientChecksum, &c, + "copied program (file)"); } -int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname, - ssize_t fsize) { - LOG(logINFO, ("\tVerifying FlashChecksum...\n")); +int verifyChecksumFromFlash(char *mess, char *functionType, + char *clientChecksum, char *fname, ssize_t fsize) { + LOG(logINFO, ("\tVerifying Checksum from flash...\n")); FILE *fp = fopen(fname, "r"); if (fp == NULL) { - sprintf(mess, "Unable to open %s in read mode to get checksum\n", - fname); + sprintf( + mess, + "Could not %s. Unable to open %s in read mode to get checksum\n", + functionType, fname); LOG(logERROR, (mess)); return FAIL; } @@ -304,7 +328,9 @@ int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname, MD5_CTX c; if (!MD5_Init_SLS(&c)) { fclose(fp); - strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n"); + sprintf(mess, + "Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } @@ -324,33 +350,39 @@ int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname, if (!MD5_Update_SLS(&c, buf, bytes)) { fclose(fp); - strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n"); + sprintf( + mess, + "Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } - // read only until a particular size (drive) if (fsize != 0 && totalBytesRead >= fsize) { LOG(logINFO, ("\tReached %lu bytes. Not reading more\n", totalBytesRead)); break; } - bytes = fread(buf, 1, readUnitSize, fp); + // for less than 128 bytes + ssize_t bytesToRead = readUnitSize; + if ((readUnitSize + totalBytesRead) > fsize) { + bytesToRead = fsize - totalBytesRead; + } + bytes = fread(buf, 1, bytesToRead, fp); totalBytesRead += bytes; } LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead)); fclose(fp); - int ret = verifyChecksum(mess, clientChecksum, &c, "flash"); - if (ret == OK) { - LOG(logINFO, ("Checksum in Flash verified\n")); - } - return ret; + return verifyChecksum(mess, functionType, clientChecksum, &c, "flash"); } -int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg) { +int verifyChecksum(char *mess, char *functionType, char *clientChecksum, + MD5_CTX *c, char *msg) { unsigned char out[MD5_DIGEST_LENGTH]; if (!MD5_Final_SLS(out, c)) { - strcpy(mess, "Unable to calculate checksum (MD5_Final_SLS)\n"); + sprintf(mess, + "Could not %s. Unable to calculate checksum (MD5_Final_SLS)\n", + functionType); LOG(logERROR, (mess)); return FAIL; } @@ -370,12 +402,177 @@ int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg) { // compare checksum if (strcmp(clientChecksum, checksum)) { sprintf(mess, - "Checksum of %s does not match. Client " + "Could not %s. Checksum of %s does not match. Client " "checksum:%s, copied checksum:%s\n", - msg, clientChecksum, checksum); + functionType, msg, clientChecksum, checksum); LOG(logERROR, (mess)); return FAIL; } - LOG(logINFO, ("\tChecksum verified\n")); + LOG(logINFO, ("\tChecksum of %s verified\n", msg)); return OK; -} \ No newline at end of file +} + +int setupDetectorServer(char *mess, char *sname) { + char cmd[MAX_STR_LENGTH] = {0}; + char retvals[MAX_STR_LENGTH] = {0}; + + // give permissions + if (snprintf(cmd, MAX_STR_LENGTH, "chmod 777 %s", sname) >= + MAX_STR_LENGTH) { + strcpy(mess, "Could not copy detector server. Command to give " + "permissions to server is too long\n"); + LOG(logERROR, (mess)); + return FAIL; + } + + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (permissions). %s\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tPermissions modified\n")); + + // symbolic link + if (snprintf(cmd, MAX_STR_LENGTH, "ln -sf %s %s", sname, + LINKED_SERVER_NAME) >= MAX_STR_LENGTH) { + strcpy(mess, "Could not copy detector server. Command to " + "create symbolic link too long\n"); + LOG(logERROR, (mess)); + return FAIL; + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (symbolic link). %s\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tSymbolic link created\n")); + + // blackfin boards (respawn) (only kept for backwards compatibility) +#if defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || \ + defined(GOTTHARDD) + // delete every line with DetectorServer in /etc/inittab + strcpy(cmd, "sed -i '/DetectorServer/d' /etc/inittab"); + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (del respawning). %s\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tinittab: DetectoServer line deleted\n")); + + // add new link name to /etc/inittab + if (snprintf(cmd, MAX_STR_LENGTH, + "echo 'ttyS0::respawn:/./%s' >> /etc/inittab", + LINKED_SERVER_NAME) >= MAX_STR_LENGTH) { + strcpy(mess, "Could not copy detector server. Command " + "to add new server for spawning is too long\n"); + LOG(logERROR, (mess)); + return FAIL; + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (respawning). %s\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tinittab: updated for respawning\n")); + +#endif + + // sync + strcpy(cmd, "sync"); + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (sync). %s\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tsync\n")); + return OK; +} + +int writeBinaryFile(char *mess, char *fname, char *buffer, + const uint64_t filesize, char *errorPrefix) { + LOG(logINFO, ("\tWriting Detector Server Binary...\n")); + + FILE *fp = fopen(fname, "wb"); + if (fp == NULL) { + sprintf(mess, + "Could not %s. (opening file to write(%s). " + "Maybe it is being used? Try another name?\n", + errorPrefix, fname); + LOG(logERROR, (mess)); + return FAIL; + } + + size_t bytesWritten = 0; + size_t unitSize = 128; + int oldProgress = 0; + + while (bytesWritten < filesize) { + // print progress + int progress = (int)(((double)(bytesWritten) / filesize) * 100); + if (oldProgress != progress) { + printf("%d%%\r", progress); + fflush(stdout); + oldProgress = progress; + } + + // for less than 128 bytes + ssize_t writeSize = unitSize; + if ((unitSize + bytesWritten) > filesize) { + writeSize = filesize - bytesWritten; + } + size_t bytes = fwrite((char *)buffer + bytesWritten, 1, writeSize, fp); + + // write + if (bytes != (size_t)writeSize) { + sprintf(mess, + "Could not %s. Expected to write %lu " + "bytes, wrote %lu bytes). No space left? \n", + errorPrefix, (long unsigned int)filesize, + (long unsigned int)bytesWritten); + LOG(logERROR, (mess)); + return FAIL; + } + bytesWritten += bytes; + LOG(logDEBUG1, + ("bytesWritten:%lu filesize:%lu\n", bytesWritten, filesize)); + } + if (fclose(fp) != 0) { + sprintf(mess, "Could not %s. (closing file pointer)\n", errorPrefix); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tWritten binary to %s (%lu bytes)\n", fname, + (long unsigned int)bytesWritten)); + return OK; +} + +int moveBinaryFile(char *mess, char *dest, char *src, char *errorPrefix) { + char cmd[MAX_STR_LENGTH] = {0}; + char retvals[MAX_STR_LENGTH] = {0}; + + // one can move into the current process binary (will not interfere in + // kernel mode) + + if (snprintf(cmd, MAX_STR_LENGTH, "mv %s %s", src, dest) >= + MAX_STR_LENGTH) { + sprintf(mess, "Could not %s. Command to move binary is too long\n", + errorPrefix); + LOG(logERROR, (mess)); + return FAIL; + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, "Could not %s. (moving). %s\n", + errorPrefix, retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tMoved file from %s to %s\n", src, dest)); + return OK; +} diff --git a/slsDetectorServers/slsDetectorServer/src/programFpgaBlackfin.c b/slsDetectorServers/slsDetectorServer/src/programFpgaBlackfin.c deleted file mode 100644 index 1f14adf47..000000000 --- a/slsDetectorServers/slsDetectorServer/src/programFpgaBlackfin.c +++ /dev/null @@ -1,418 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include "programFpgaBlackfin.h" -#include "clogger.h" -#include "common.h" -#include "sls/ansi.h" -#include "slsDetectorServer_defs.h" - -#include -#include -#include // usleep - -/* global variables */ -// clang-format off -#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s -#define CMD_GET_FLASH "awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd" -#define CMD_FPGA_PICKED_STATUS "cat /sys/class/gpio/gpio7/value" -#define FLASH_BUFFER_MEMORY_SIZE (128 * 1024) // 500 KB -// clang-format on - -#define FLASH_DRIVE_NAME_SIZE 16 -char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0}; -int gpioDefined = 0; - -extern int executeCommand(char *command, char *result, enum TLogLevel level); - -int latestKernelVerified = -1; -#define KERNEL_DATE_VRSN_3GPIO "Fri Oct 29 00:00:00 2021" - -void defineGPIOpins() { -#ifdef VIRTUAL - return; -#endif - if (latestKernelVerified == -1) { - if (FAIL == validateKernelVersion(KERNEL_DATE_VRSN_3GPIO)) { - latestKernelVerified = 0; - LOG(logWARNING, - ("Kernel too old to use gpio 3 pins. Not the end " - "of the world. Continuing with current kernel.\n")); - } else { - latestKernelVerified = 1; - } - } - if (!gpioDefined) { - // define the gpio pins - system("echo 7 > /sys/class/gpio/export"); - LOG(logINFO, ("\tgpio7: defined\n")); - system("echo in > /sys/class/gpio/gpio7/direction"); - LOG(logINFO, ("\tgpio7: setting intput\n")); - system("echo 9 > /sys/class/gpio/export"); - LOG(logINFO, ("\tgpio9: defined\n")); - - if (latestKernelVerified == 1) { - // gpio 3 = not chip enable - system("echo 3 > /sys/class/gpio/export"); - LOG(logINFO, ("\tgpio3: defined\n")); - } - gpioDefined = 1; - } else - LOG(logDEBUG1, ("gpio pins already defined earlier\n")); -} - -void FPGAdontTouchFlash() { -#ifdef VIRTUAL - return; -#endif - // define as output pins - system("echo out > /sys/class/gpio/gpio9/direction"); - LOG(logINFO, ("\tgpio9: setting output\n")); - if (latestKernelVerified == 1) { - // gpio 3 = not chip enable - system("echo out > /sys/class/gpio/gpio3/direction"); - LOG(logINFO, ("\tgpio3: setting output\n")); - } - - // tell FPGA to not touch flash - system("echo 0 > /sys/class/gpio/gpio9/value"); - LOG(logINFO, ("\tgpio9: fpga dont touch flash\n")); - if (latestKernelVerified == 1) { - system("echo 1 > /sys/class/gpio/gpio3/value"); - LOG(logINFO, ("\tgpio3: fpga dont touch flash\n")); - } - // usleep(100*1000); -} - -void FPGATouchFlash() { -#ifdef VIRTUAL - return; -#endif - // tell FPGA to touch flash to program itself - system("echo in > /sys/class/gpio/gpio9/direction"); - LOG(logINFO, ("\tgpio9: setting input\n")); - if (latestKernelVerified == 1) { - system("echo in > /sys/class/gpio/gpio3/direction"); - LOG(logINFO, ("\tgpio3: setting input\n")); - } -} - -void resetFPGA() { - LOG(logINFOBLUE, ("Reseting FPGA\n")); -#ifdef VIRTUAL - return; -#endif - FPGAdontTouchFlash(); - FPGATouchFlash(); - usleep(CTRL_SRVR_INIT_TIME_US); -} - -int deleteOldFile(char *mess) { - char cmd[MAX_STR_LENGTH] = {0}; - char retvals[MAX_STR_LENGTH] = {0}; - - char *format = "rm -fr %s"; - if (snprintf(cmd, MAX_STR_LENGTH, format, TEMP_PROG_FILE_NAME) >= - MAX_STR_LENGTH) { - strcpy( - mess, - "Could not program fpga. Command to delete old file is too long\n"); - LOG(logERROR, (mess)); - return FAIL; - } - if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not delete old file: %s)\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - return FAIL; - } - LOG(logINFO, - ("\tDeleted old programming file (%s)\n", TEMP_PROG_FILE_NAME)); - return OK; -} - -int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess) { - - if (deleteOldFile(mess) == FAIL) { - return FAIL; - } - - // check available memory to copy program - { - struct sysinfo info; - sysinfo(&info); - if (fsize >= info.freeram) { - sprintf(mess, - "Could not program fpga. Not enough memory to copy " - "program. [File size:%ldMB, free RAM: %ldMB]\n", - (long int)(fsize / (1024 * 1024)), - (long int)(info.freeram / (1024 * 1024))); - LOG(logERROR, (mess)); - return FAIL; - } - } - - // open file to copy program - *fd = fopen(TEMP_PROG_FILE_NAME, "w"); - if (*fd == NULL) { - sprintf(mess, "Unable to open %s in write mode\n", TEMP_PROG_FILE_NAME); - LOG(logERROR, (mess)); - return FAIL; - } - LOG(logINFO, ("\tGoing to copy program to %s\n", TEMP_PROG_FILE_NAME)); - return OK; -} - -int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess) { - - if (getDrive(mess) == FAIL) { - return FAIL; - } - - FILE *flashfd = NULL; - FILE *srcfd = NULL; - if (openFileForFlash(&flashfd, &srcfd, mess) == FAIL) { - return FAIL; - } - - if (eraseFlash(mess) == FAIL) { - fclose(flashfd); - fclose(srcfd); - return FAIL; - } - - if (writeToFlash(fsize, flashfd, srcfd, mess) == FAIL) { - return FAIL; - } - - if (deleteOldFile(mess) == FAIL) { - return FAIL; - } - - /* ignoring this until flash fixed - if (verifyChecksumFromFlash(mess, clientChecksum, flashDriveName, fsize) == FAIL) { return FAIL; - } - */ - if (waitForFPGAtoTouchFlash(mess) == FAIL) { - return FAIL; - } - - return OK; -} - -int getDrive(char *mess) { -#ifdef VIRTUAL - strcpy(flashDriveName, "/tmp/SLS_mtd3"); - return OK; -#endif - LOG(logDEBUG1, ("Finding flash drive...\n")); - // getting the drive - // root:/> cat /proc/mtd - // dev: size erasesize name - // mtd0: 00040000 00020000 "bootloader(nor)" - // mtd1: 00100000 00020000 "linux kernel(nor)" - // mtd2: 002c0000 00020000 "file system(nor)" - // mtd3: 01000000 00010000 "bitfile(spi)" - - char cmd[MAX_STR_LENGTH] = {0}; - char retvals[MAX_STR_LENGTH] = {0}; - - strcpy(cmd, CMD_GET_FLASH); - if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not get flash drive: %s)\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - return FAIL; - } - - char *pch = strtok(retvals, ":"); - if (pch == NULL) { - strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n"); - LOG(logERROR, (mess)); - return FAIL; - } - - memset(flashDriveName, 0, sizeof(flashDriveName)); - strcpy(flashDriveName, "/dev/"); - strcat(flashDriveName, pch); - LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName)); - return OK; -} - -int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess) { - FPGAdontTouchFlash(); - - // open src file - *srcfd = fopen(TEMP_PROG_FILE_NAME, "r"); - if (*srcfd == NULL) { - sprintf(mess, - "Could not flash. Unable to open temp program file %s in read " - "mode\n", - TEMP_PROG_FILE_NAME); - LOG(logERROR, (mess)); - return FAIL; - } - LOG(logDEBUG1, ("Temp file ready for reading\n")); - - // open flash drive for writing - *flashfd = fopen(flashDriveName, "w"); - if (*flashfd == NULL) { - fclose(*srcfd); - sprintf(mess, "Unable to open flash drive %s in write mode\n", - flashDriveName); - LOG(logERROR, (mess)); - return FAIL; - } - LOG(logINFO, ("\tFlash ready for writing\n")); - return OK; -} - -int eraseFlash(char *mess) { - LOG(logINFO, ("\tErasing Flash...\n")); - -#ifdef VIRTUAL - return OK; -#endif - char cmd[MAX_STR_LENGTH] = {0}; - char retvals[MAX_STR_LENGTH] = {0}; - char *format = "flash_eraseall %s"; - if (snprintf(cmd, MAX_STR_LENGTH, format, flashDriveName) >= - MAX_STR_LENGTH) { - strcpy(mess, - "Could not program fpga. Command to erase flash is too long\n"); - LOG(logERROR, (mess)); - return FAIL; - } - if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not erase flash: %s)\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - return FAIL; - } - LOG(logINFO, ("\tFlash erased\n")); - return OK; -} - -int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess) { - LOG(logDEBUG1, ("writing to flash\n")); - - char *buffer = malloc(FLASH_BUFFER_MEMORY_SIZE); - if (buffer == NULL) { - fclose(flashfd); - fclose(srcfd); - strcpy(mess, "Could not program fpga. Memory allocation to write to " - "flash failed.\n"); - LOG(logERROR, (mess)); - return FAIL; - } - LOG(logINFO, ("\tWriting to Flash...\n")); - - int oldProgress = 0; - ssize_t totalBytes = 0; - ssize_t bytes = - fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd); - - while (bytes > 0) { - - ssize_t bytesWritten = - fwrite((void *)buffer, sizeof(char), bytes, flashfd); - totalBytes += bytesWritten; - - if (bytesWritten != bytes) { - free(buffer); - fclose(flashfd); - fclose(srcfd); - sprintf(mess, - "Could not write to flash (bytes written:%ld, expected: " - "%ld, total written:%ld)\n", - (long int)bytesWritten, (long int)bytes, - (long int)totalBytes); - LOG(logERROR, (mess)); - return FAIL; - } - - // print progress - if (fsize > 0) { - int progress = (int)(((double)(totalBytes) / fsize) * 100); - if (oldProgress != progress) { - printf("%d%%\r", progress); - fflush(stdout); - oldProgress = progress; - } - } else - printf("."); - - bytes = fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, - srcfd); - } - if (fsize <= 0) { - printf("\n"); - } - free(buffer); - fclose(flashfd); - fclose(srcfd); - LOG(logINFO, ("\tWrote %ld bytes to flash\n", totalBytes)); - - if (totalBytes != fsize) { - sprintf(mess, - "Could not program fpga. Incorrect bytes written to flash %lu " - "[expected: %lu]\n", - totalBytes, fsize); - LOG(logERROR, (mess)); - return FAIL; - } - return OK; -} - -int waitForFPGAtoTouchFlash(char *mess) { - // touch and program - FPGATouchFlash(); - -#ifdef VIRTUAL - return OK; -#endif - LOG(logINFO, ("\tWaiting for FPGA to program from flash\n")); - int timeSpent = 0; - - int result = 0; - while (result == 0) { - // time taken for fpga to pick up from flash - usleep(1000); - timeSpent += 1000; - if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) { - sprintf( - mess, - "Could not program fpga. (exceeded max time allowed: %ds)\n", - MAX_TIME_FPGA_TOUCH_FLASH_US / (1000 * 1000)); - LOG(logERROR, (mess)); - return FAIL; - } - - // read gpio status - char retvals[MAX_STR_LENGTH] = {0}; - if (FAIL == - executeCommand(CMD_FPGA_PICKED_STATUS, retvals, logDEBUG1)) { - snprintf( - mess, MAX_STR_LENGTH, - "Could not program fpga. (could not read gpio status: %s)\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - return FAIL; - } - - // convert to int - if (sscanf(retvals, "%d\n", &result) != 1) { - snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not scan int for gpio " - "status: [%s])\n", - retvals); - LOG(logERROR, (mess)); - return FAIL; - } - LOG(logDEBUG1, ("gpi07 returned %d\n", result)); - } - LOG(logINFO, ("\tFPGA has picked up the program from flash\n")); - return OK; -} diff --git a/slsDetectorServers/slsDetectorServer/src/programViaBlackfin.c b/slsDetectorServers/slsDetectorServer/src/programViaBlackfin.c new file mode 100644 index 000000000..a29215061 --- /dev/null +++ b/slsDetectorServers/slsDetectorServer/src/programViaBlackfin.c @@ -0,0 +1,574 @@ +// SPDX-License-Identifier: LGPL-3.0-or-other +// Copyright (C) 2021 Contributors to the SLS Detector Package +#include "programViaBlackfin.h" +#include "clogger.h" +#include "common.h" +#include "sls/ansi.h" +#include "slsDetectorServer_defs.h" + +#include +#include +#include // usleep + +/* global variables */ +// clang-format off +#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s + +#define CMD_GPIO7_DEFINE "echo 7 > /sys/class/gpio/export" +#define CMD_GPIO9_DEFINE "echo 9 > /sys/class/gpio/export" +#define CMD_GPIO3_DEFINE "echo 3 > /sys/class/gpio/export" + +#define CMD_GPIO7_EXIST "/sys/class/gpio/gpio7" +#define CMD_GPIO9_EXIST "/sys/class/gpio/gpio9" +#define CMD_GPIO3_EXIST "/sys/class/gpio/gpio3" + +#define CMD_GPIO9_DEFINE_OUT "echo out > /sys/class/gpio/gpio9/direction" +#define CMD_GPIO3_DEFINE_OUT "echo out > /sys/class/gpio/gpio3/direction" +#define CMD_GPIO7_DEFINE_IN "echo in > /sys/class/gpio/gpio7/direction" +#define CMD_GPIO9_DEFINE_IN "echo in > /sys/class/gpio/gpio9/direction" +#define CMD_GPIO3_DEFINE_IN "echo in > /sys/class/gpio/gpio3/direction" + +#define CMD_GPIO9_DONT_TOUCH_FLASH "echo 0 > /sys/class/gpio/gpio9/value" +#define CMD_GPIO3_DONT_TOUCH_FLASH "echo 0 > /sys/class/gpio/gpio3/value" +#define CMD_FPGA_PICKED_STATUS "cat /sys/class/gpio/gpio7/value" + +#define CMD_GET_FPGA_FLASH_DRIVE "awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd" +#define CMD_GET_KERNEL_FLASH_DRIVE "awk \'$4== \"\\\"linux\" {print $1}\' /proc/mtd" + +#define FLASH_BUFFER_MEMORY_SIZE (128 * 1024) // 500 KB +// clang-format on + +#define FLASH_DRIVE_NAME_SIZE 16 + +#ifdef VIRTUAL +char flashDriveName[FLASH_DRIVE_NAME_SIZE] = "/tmp/SLS_mtd3"; +#else +char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0}; +#endif + +char messageType[SHORT_STR_LENGTH] = {0}; + +extern int executeCommand(char *command, char *result, enum TLogLevel level); + +int latestKernelVerified = -1; +#define KERNEL_DATE_VRSN_3GPIO "Fri Oct 29 00:00:00 2021" + +int defineGPIOpins(char *mess) { +#ifdef VIRTUAL + return OK; +#endif + // only latest kernel can use gpio3 pins + if (latestKernelVerified == -1) { + if (FAIL == validateKernelVersion(KERNEL_DATE_VRSN_3GPIO)) { + latestKernelVerified = 0; + LOG(logWARNING, + ("Kernel too old to use gpio 3 pins. Update kernel to " + "guarantee error-free fpga programming. \n\tNot the end " + "of the world. Continuing with current kernel...\n")); + } else { + latestKernelVerified = 1; + } + } + + char retvals[MAX_STR_LENGTH] = {0}; + // define gpio7 + if (access(CMD_GPIO7_EXIST, F_OK) != 0) { + if (executeCommand(CMD_GPIO7_DEFINE, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not define gpio7 pins for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio7: defined\n")); + } else { + LOG(logINFO, ("\tgpio7: already defined\n")); + } + + // define gpio7 direction + if (executeCommand(CMD_GPIO7_DEFINE_IN, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio7 as input for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio7: setting intput\n")); + + // define gpio9 + if (access(CMD_GPIO9_EXIST, F_OK) != 0) { + if (executeCommand(CMD_GPIO9_DEFINE, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not define gpio9 pins for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio9: defined\n")); + } else { + LOG(logINFO, ("\tgpio9: already defined\n")); + } + + // define gpio3 (not chip enable) + if (latestKernelVerified == 1) { + if (access(CMD_GPIO3_EXIST, F_OK) != 0) { + if (executeCommand(CMD_GPIO3_DEFINE, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not define gpio3 pins for fpga (%s)\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio3: defined\n")); + } else { + LOG(logINFO, ("\tgpio3: already defined\n")); + } + } + + return OK; +} + +int FPGAdontTouchFlash(char *mess) { +#ifdef VIRTUAL + return OK; +#endif + char retvals[MAX_STR_LENGTH] = {0}; + // define gpio9 as output + if (executeCommand(CMD_GPIO9_DEFINE_OUT, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio9 as output for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio9: setting output\n")); + + // define gpio3 as output + if (latestKernelVerified == 1) { + if (executeCommand(CMD_GPIO3_DEFINE_OUT, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio3 as output for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio3: setting output\n")); + } + + // tell FPGA to not: gpio9 + if (executeCommand(CMD_GPIO9_DONT_TOUCH_FLASH, retvals, logDEBUG1) == + FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio9 to not touch flash for fpga (%s)\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio9: fpga dont touch flash\n")); + + // tell FPGA to not: gpio3 + if (latestKernelVerified == 1) { + if (executeCommand(CMD_GPIO3_DONT_TOUCH_FLASH, retvals, logDEBUG1) == + FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio3 to not touch flash for fpga (%s)\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio3: fpga dont touch flash\n")); + } + // usleep(100*1000); + return OK; +} + +int FPGATouchFlash(char *mess) { +#ifdef VIRTUAL + return OK; +#endif + char retvals[MAX_STR_LENGTH] = {0}; + // tell FPGA to touch flash to program itself + if (executeCommand(CMD_GPIO9_DEFINE_IN, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio9 as input for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio9: setting input\n")); + + if (latestKernelVerified == 1) { + if (executeCommand(CMD_GPIO3_DEFINE_IN, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not set gpio3 as input for fpga (%s)\n", retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tgpio3: setting input\n")); + } + return OK; +} + +int resetFPGA(char *mess) { + LOG(logINFOBLUE, ("Reseting FPGA\n")); +#ifdef VIRTUAL + return OK; +#endif + if (FPGAdontTouchFlash(mess) == FAIL) { + return FAIL; + } + if (FPGATouchFlash(mess) == FAIL) { + return FAIL; + } + usleep(CTRL_SRVR_INIT_TIME_US); + return OK; +} + +int emptyTempFolder(char *mess) { + char cmd[MAX_STR_LENGTH] = {0}; + char retvals[MAX_STR_LENGTH] = {0}; + + if (snprintf(cmd, MAX_STR_LENGTH, "rm -fr %s", + TEMP_PROG_FOLDER_NAME_ALL_FILES) >= MAX_STR_LENGTH) { + sprintf(mess, + "Could not update %s. Command to empty %s folder is too long\n", + messageType, TEMP_PROG_FOLDER_NAME); + LOG(logERROR, (mess)); + return FAIL; + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not update %s. (could not empty %s folder: %s)\n", + messageType, TEMP_PROG_FOLDER_NAME, retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tEmptied temp folder(%s)\n", TEMP_PROG_FOLDER_NAME)); + return OK; +} + +int preparetoCopyProgram(char *mess, char *functionType, FILE **fd, + uint64_t fsize) { + + if (emptyTempFolder(mess) == FAIL) { + return FAIL; + } + + // check available memory to copy program + { + struct sysinfo info; + sysinfo(&info); + if (fsize >= info.freeram) { + sprintf(mess, + "Could not %s. Not enough memory to copy " + "program. [File size:%ldMB, free RAM: %ldMB]\n", + functionType, (long int)(fsize / (1024 * 1024)), + (long int)(info.freeram / (1024 * 1024))); + LOG(logERROR, (mess)); + return FAIL; + } + } + + // open file to copy program + *fd = fopen(TEMP_PROG_FILE_NAME, "w"); + if (*fd == NULL) { + sprintf(mess, "Could not %s. Unable to open %s in write mode\n", + functionType, TEMP_PROG_FILE_NAME); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tGoing to copy program to %s\n", TEMP_PROG_FILE_NAME)); + return OK; +} + +int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index, + char *functionType, char *clientChecksum, + ssize_t fsize) { + + memset(messageType, 0, sizeof(messageType)); + strcpy(messageType, functionType); + + if (getDrive(mess, index) == FAIL) { + return FAIL; + } + + FILE *flashfd = NULL; + FILE *srcfd = NULL; + if (openFileForFlash(mess, &flashfd, &srcfd) == FAIL) { + return FAIL; + } + + if (index == PROGRAM_FPGA) { + if (FPGAdontTouchFlash(mess) == FAIL) { + return FAIL; + } + } + + if (eraseFlash(mess) == FAIL) { + fclose(flashfd); + fclose(srcfd); + return FAIL; + } + + if (writeToFlash(mess, fsize, flashfd, srcfd) == FAIL) { + return FAIL; + } + + if (emptyTempFolder(mess) == FAIL) { + return FAIL; + } + + /* remove condition when flash fpga fixed */ + if (index == PROGRAM_KERNEL) { + if (verifyChecksumFromFlash(mess, messageType, clientChecksum, + flashDriveName, fsize) == FAIL) { + return FAIL; + } + } + + if (index == PROGRAM_FPGA) { + if (waitForFPGAtoTouchFlash(mess) == FAIL) { + return FAIL; + } + } + + // kernel + else { + char retvals[MAX_STR_LENGTH] = {0}; + if (executeCommand("sync", retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not update %s. (could not sync)\n", messageType); + LOG(logERROR, (mess)); + return FAIL; + } + } + + return OK; +} + +int getDrive(char *mess, enum PROGRAM_INDEX index) { +#ifdef VIRTUAL + return OK; +#endif + LOG(logDEBUG1, ("Finding flash drive...\n")); + // getting the drive + // root:/> cat /proc/mtd + // dev: size erasesize name + // mtd0: 00040000 00020000 "bootloader(nor)" + // mtd1: 00100000 00020000 "linux kernel(nor)" + // mtd2: 002c0000 00020000 "file system(nor)" + // mtd3: 01000000 00010000 "bitfile(spi)" + + char cmd[MAX_STR_LENGTH] = {0}; + char retvals[MAX_STR_LENGTH] = {0}; + + if (index == PROGRAM_FPGA) { + strcpy(cmd, CMD_GET_FPGA_FLASH_DRIVE); + } else { + strcpy(cmd, CMD_GET_KERNEL_FLASH_DRIVE); + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not %s. (could not get flash drive: %s)\n", messageType, + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + + if (strlen(retvals) == 0) { + LOG(logERROR, ("Could not %s. Could not get mtd drive, script returned " + "empty string\n", + messageType)); + return FAIL; + } + + char *pch = strtok(retvals, ":"); + if (pch == NULL) { + sprintf(mess, + "Could not %s. Could not get mtd drive to flash (strtok " + "fail).\n", + messageType); + LOG(logERROR, (mess)); + return FAIL; + } + + memset(flashDriveName, 0, sizeof(flashDriveName)); + sprintf(flashDriveName, "/dev/%s", pch); + LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName)); + return OK; +} + +int openFileForFlash(char *mess, FILE **flashfd, FILE **srcfd) { + // open src file + *srcfd = fopen(TEMP_PROG_FILE_NAME, "r"); + if (*srcfd == NULL) { + sprintf(mess, + "Could not %s. Unable to open temp program file %s in read " + "mode\n", + messageType, TEMP_PROG_FILE_NAME); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logDEBUG1, ("Temp file ready for reading\n")); + + // open flash drive for writing + *flashfd = fopen(flashDriveName, "w"); + if (*flashfd == NULL) { + fclose(*srcfd); + sprintf(mess, + "Could not %s. Unable to open flash drive %s in write " + "mode\n", + messageType, flashDriveName); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tFlash ready for writing\n")); + return OK; +} + +int eraseFlash(char *mess) { + LOG(logINFO, ("\tErasing Flash...\n")); + +#ifdef VIRTUAL + return OK; +#endif + char cmd[MAX_STR_LENGTH] = {0}; + char retvals[MAX_STR_LENGTH] = {0}; + if (snprintf(cmd, MAX_STR_LENGTH, "flash_eraseall %s", flashDriveName) >= + MAX_STR_LENGTH) { + sprintf(mess, "Could not %s. Command to erase flash is too long\n", + messageType); + LOG(logERROR, (mess)); + return FAIL; + } + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not update %s. (could not erase flash: %s)\n", + messageType, retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tFlash erased\n")); + return OK; +} + +int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, FILE *srcfd) { + LOG(logDEBUG1, ("writing to flash\n")); + + char *buffer = malloc(FLASH_BUFFER_MEMORY_SIZE); + if (buffer == NULL) { + fclose(flashfd); + fclose(srcfd); + sprintf(mess, + "Could not %s. Memory allocation to write to " + "flash failed.\n", + messageType); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logINFO, ("\tWriting to Flash...\n")); + + int oldProgress = 0; + ssize_t totalBytes = 0; + ssize_t bytes = + fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd); + + while (bytes > 0) { + + ssize_t bytesWritten = + fwrite((void *)buffer, sizeof(char), bytes, flashfd); + totalBytes += bytesWritten; + + if (bytesWritten != bytes) { + free(buffer); + fclose(flashfd); + fclose(srcfd); + sprintf(mess, + "Could not %s. Could not write to flash (bytes " + "written:%ld, expected: " + "%ld, total written:%ld)\n", + messageType, (long int)bytesWritten, (long int)bytes, + (long int)totalBytes); + LOG(logERROR, (mess)); + return FAIL; + } + + // print progress + if (fsize > 0) { + int progress = (int)(((double)(totalBytes) / fsize) * 100); + if (oldProgress != progress) { + printf("%d%%\r", progress); + fflush(stdout); + oldProgress = progress; + } + } else + printf("."); + + bytes = fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, + srcfd); + } + if (fsize <= 0) { + printf("\n"); + } + free(buffer); + fclose(flashfd); + fclose(srcfd); + LOG(logINFO, ("\tWrote %ld bytes to flash\n", totalBytes)); + + if (totalBytes != fsize) { + sprintf(mess, + "Could not %s. Incorrect bytes written to flash %lu " + "[expected: %lu]\n", + messageType, totalBytes, fsize); + LOG(logERROR, (mess)); + return FAIL; + } + return OK; +} + +int waitForFPGAtoTouchFlash(char *mess) { + // touch and program + if (FPGATouchFlash(mess) == FAIL) { + return FAIL; + } + +#ifdef VIRTUAL + return OK; +#endif + LOG(logINFO, ("\tWaiting for FPGA to program from flash\n")); + int timeSpent = 0; + + int result = 0; + while (result == 0) { + // time taken for fpga to pick up from flash + usleep(1000); + timeSpent += 1000; + if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) { + sprintf( + mess, + "Could not program fpga. (exceeded max time allowed: %ds)\n", + MAX_TIME_FPGA_TOUCH_FLASH_US / (1000 * 1000)); + LOG(logERROR, (mess)); + return FAIL; + } + + // read gpio status + char retvals[MAX_STR_LENGTH] = {0}; + if (FAIL == + executeCommand(CMD_FPGA_PICKED_STATUS, retvals, logDEBUG1)) { + snprintf( + mess, MAX_STR_LENGTH, + "Could not program fpga. (could not read gpio status: %s)\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + return FAIL; + } + + // convert to int + if (sscanf(retvals, "%d\n", &result) != 1) { + snprintf(mess, MAX_STR_LENGTH, + "Could not program fpga. (could not scan int for gpio " + "status: [%s])\n", + retvals); + LOG(logERROR, (mess)); + return FAIL; + } + LOG(logDEBUG1, ("gpi07 returned %d\n", result)); + } + LOG(logINFO, ("\tFPGA has picked up the program from flash\n")); + return OK; +} diff --git a/slsDetectorServers/slsDetectorServer/src/programFpgaNios.c b/slsDetectorServers/slsDetectorServer/src/programViaNios.c similarity index 54% rename from slsDetectorServers/slsDetectorServer/src/programFpgaNios.c rename to slsDetectorServers/slsDetectorServer/src/programViaNios.c index c82685224..c81598650 100644 --- a/slsDetectorServers/slsDetectorServer/src/programFpgaNios.c +++ b/slsDetectorServers/slsDetectorServer/src/programViaNios.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-other // Copyright (C) 2021 Contributors to the SLS Detector Package -#include "programFpgaNios.h" +#include "programViaNios.h" #include "clogger.h" #include "common.h" #include "sls/ansi.h" @@ -11,10 +11,19 @@ /* global variables */ -#define CMD_GET_FLASH "awk \'$5== \"Application\" {print $1}\' /proc/mtd" - +#define CMD_GET_FPGA_FLASH_DRIVE \ + "awk \'$5== \"Application\" {print $1}\' /proc/mtd" +#define CMD_GET_KERNEL_FLASH_DRIVE \ + "awk \'$5== \"Linux\" && $9 != \"Backup\\\"\" {print $1}\' /proc/mtd" #define FLASH_DRIVE_NAME_SIZE 16 + +#ifdef VIRTUAL +char flashDriveName[FLASH_DRIVE_NAME_SIZE] = "/tmp/SLS_mtd3"; +#else char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0}; +#endif + +char messageType[SHORT_STR_LENGTH] = {0}; #define MICROCONTROLLER_FILE "/dev/ttyAL0" extern int executeCommand(char *command, char *result, enum TLogLevel level); @@ -35,19 +44,19 @@ void rebootControllerAndFPGA() { system(command); } -int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc, +int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index, + char *functionType, char *checksum, char *fpgasrc, uint64_t fsize) { - if (verifyChecksumFromBuffer(mess, checksum, fpgasrc, fsize) == FAIL) { - return FAIL; - } + memset(messageType, 0, sizeof(messageType)); + strcpy(messageType, functionType); - if (getDrive(mess) == FAIL) { + if (getDrive(mess, index) == FAIL) { return FAIL; } FILE *flashfd = NULL; - if (openFileForFlash(&flashfd, mess) == FAIL) { + if (openFileForFlash(mess, &flashfd) == FAIL) { return FAIL; } @@ -56,21 +65,33 @@ int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc, return FAIL; } - if (writeToFlash(fsize, flashfd, fpgasrc, mess) == FAIL) { + if (writeToFlash(mess, fsize, flashfd, fpgasrc) == FAIL) { return FAIL; } - /* ignoring this until a consistent way to read from nios flash - if (verifyChecksumFromFlash(mess, checksum, flashDriveName, fsize) == - FAIL) { - return FAIL; + + /* remove condition when flash fpga fixed */ + if (index == PROGRAM_KERNEL) { + if (verifyChecksumFromFlash(mess, messageType, checksum, flashDriveName, + fsize) == FAIL) { + return FAIL; + } } - */ + + if (index == PROGRAM_KERNEL) { + char retvals[MAX_STR_LENGTH] = {0}; + if (executeCommand("sync", retvals, logDEBUG1) == FAIL) { + snprintf(mess, MAX_STR_LENGTH, + "Could not update %s. (could not sync)\n", messageType); + // LOG(logERROR, (mess)); already printed in executecommand + return FAIL; + } + } + return OK; } -int getDrive(char *mess) { +int getDrive(char *mess, enum PROGRAM_INDEX index) { #ifdef VIRTUAL - strcpy(flashDriveName, "/tmp/SLS_mtd3"); return OK; #endif LOG(logDEBUG1, ("Finding flash drive...\n")); @@ -86,18 +107,33 @@ int getDrive(char *mess) { char cmd[MAX_STR_LENGTH] = {0}; char retvals[MAX_STR_LENGTH] = {0}; - strcpy(cmd, CMD_GET_FLASH); + + if (index == PROGRAM_FPGA) { + strcpy(cmd, CMD_GET_FPGA_FLASH_DRIVE); + } else { + strcpy(cmd, CMD_GET_KERNEL_FLASH_DRIVE); + } if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not get flash drive: %s)\n", + "Could not %s. (could not get flash drive: %s)\n", messageType, retvals); // LOG(logERROR, (mess)); already printed in executecommand return FAIL; } + if (strlen(retvals) == 0) { + LOG(logERROR, ("Could not %s. Could not get mtd drive, script returned " + "empty string\n", + messageType)); + return FAIL; + } + char *pch = strtok(retvals, ":"); if (pch == NULL) { - strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n"); + sprintf( + mess, + "Could not %s. Could not get mtd drive to flash (strtok fail).\n", + messageType); LOG(logERROR, (mess)); return FAIL; } @@ -109,11 +145,12 @@ int getDrive(char *mess) { return OK; } -int openFileForFlash(FILE **flashfd, char *mess) { +int openFileForFlash(char *mess, FILE **flashfd) { *flashfd = fopen(flashDriveName, "w"); if (*flashfd == NULL) { - sprintf(mess, "Unable to open flash drive %s in write mode\n", - flashDriveName); + sprintf(mess, + "Could not %s. Unable to open flash drive %s in write mode\n", + messageType, flashDriveName); LOG(logERROR, (mess)); return FAIL; } @@ -130,17 +167,16 @@ int eraseFlash(char *mess) { char cmd[MAX_STR_LENGTH] = {0}; char retvals[MAX_STR_LENGTH] = {0}; - char *format = "flash_erase %s 0 0"; - if (snprintf(cmd, MAX_STR_LENGTH, format, flashDriveName) >= + if (snprintf(cmd, MAX_STR_LENGTH, "flash_erase %s 0 0", flashDriveName) >= MAX_STR_LENGTH) { - strcpy(mess, - "Could not program fpga. Command to erase flash is too long\n"); + sprintf(mess, "Could not %s. Command to erase flash is too long\n", + messageType); LOG(logERROR, (mess)); return FAIL; } if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { snprintf(mess, MAX_STR_LENGTH, - "Could not program fpga. (could not erase flash: %s)\n", + "Could not %s. (could not erase flash: %s)\n", messageType, retvals); // LOG(logERROR, (mess)); already printed in executecommand return FAIL; @@ -150,19 +186,20 @@ int eraseFlash(char *mess) { return OK; } -int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess) { +int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, char *buffer) { LOG(logINFO, ("\tWriting to Flash...\n")); ssize_t bytesWritten = fwrite((void *)buffer, sizeof(char), fsize, flashfd); if (bytesWritten != fsize) { fclose(flashfd); sprintf(mess, - "Could not program fpga. Incorrect bytes written to flash %lu " + "Could not %s. Incorrect bytes written to flash %lu " "[expected: %lu]\n", - (long int)bytesWritten, (long int)fsize); + messageType, (long int)bytesWritten, (long int)fsize); LOG(logERROR, (mess)); return FAIL; } - LOG(logINFO, ("\tWritten to Flash\n")); + fclose(flashfd); + LOG(logINFO, ("\tWrote %ld bytes to flash\n", bytesWritten)); return OK; } diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 086e6380e..5a2976a8a 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -92,14 +92,13 @@ void init_detector() { #ifdef EIGERD udpDetails[0].dstport2 = DEFAULT_UDP_DST_PORTNO + 1; #endif - + lockStatus = 0; if (isControlServer) { basictests(); initControlServer(); - } else + } else { initStopServer(); - strcpy(mess, "dummy message"); - lockStatus = 0; + } } int decode_function(int file_des) { @@ -415,6 +414,8 @@ void function_table() { flist[F_GET_READOUT_SPEED] = &get_readout_speed; flist[F_SET_READOUT_SPEED] = &set_readout_speed; flist[F_GET_KERNEL_VERSION] = &get_kernel_version; + flist[F_UPDATE_KERNEL] = &update_kernel; + flist[F_UPDATE_DETECTOR_SERVER] = &update_detector_server; // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { @@ -472,7 +473,7 @@ int executeCommand(char *command, char *result, enum TLogLevel level) { if (strlen(result)) { if (success) { success = FAIL; - LOG(logERROR, ("%s\n", result)); + LOG(logERROR, ("Executing cmd[%s]:%s\n", cmd, result)); } else { LOG(level, ("Result:\n[%s]\n", result)); } @@ -486,11 +487,6 @@ int M_nofunc(int file_des) { ret = FAIL; memset(mess, 0, sizeof(mess)); - // to receive any arguments - int n = 1; - while (n > 0) - n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER); - sprintf(mess, "Unrecognized Function enum %d. Please do not proceed.\n", fnum); LOG(logERROR, (mess)); @@ -1561,15 +1557,8 @@ int set_module(int file_des) { } } - // receive all arguments - if (ret == FAIL) { - int n = 1; - while (n > 0) - n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER); - } - // only set - else if (Server_VerifyLock() == OK) { + if (ret == OK && Server_VerifyLock() == OK) { // check index // setsettings @@ -3641,149 +3630,10 @@ int program_fpga(int file_des) { memset(mess, 0, sizeof(mess)); #if defined(EIGERD) || defined(GOTTHARDD) - // to receive any arguments - int n = 1; - while (n > 0) - n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER); functionNotImplemented(); + return Server_SendResult(file_des, INT32, NULL, 0); #else - // only set - if (Server_VerifyLock() == OK) { - - LOG(logINFOBLUE, ("Programming FPGA...\n")); - - // filesize - uint64_t filesize = 0; - if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0) - return printSocketReadError(); - LOG(logDEBUG1, ("Program size is: %lld\n", (long long int)filesize)); - - // checksum - char checksum[MAX_STR_LENGTH]; - memset(checksum, 0, MAX_STR_LENGTH); - if (receiveData(file_des, checksum, MAX_STR_LENGTH, OTHER) < 0) - return printSocketReadError(); - LOG(logDEBUG1, ("checksum is: %s\n\n", checksum)); - -#if defined(MYTHEN3D) || defined(GOTTHARD2D) - if (filesize > NIOS_MAX_APP_IMAGE_SIZE) { - ret = FAIL; - sprintf(mess, - "Could not start programming FPGA. File size 0x%llx " - "exceeds max size 0x%llx. Forgot Compression?\n", - (long long unsigned int)filesize, - (long long unsigned int)NIOS_MAX_APP_IMAGE_SIZE); - LOG(logERROR, (mess)); - } - Server_SendResult(file_des, INT32, NULL, 0); - - // receive program - if (ret == OK) { - char *fpgasrc = malloc(filesize); - if (receiveData(file_des, fpgasrc, filesize, OTHER) < 0) { - free(fpgasrc); - return printSocketReadError(); - } - ret = eraseAndWriteToFlash(mess, checksum, fpgasrc, filesize); - Server_SendResult(file_des, INT32, NULL, 0); - free(fpgasrc); - } - if (ret == FAIL) { - LOG(logERROR, ("Program FPGA FAIL!\n")); - return FAIL; - } - -#else // jungfrau, ctb, moench - - // open file and allocate memory for part program - FILE *fd = NULL; - ret = preparetoCopyFPGAProgram(&fd, filesize, mess); - char *src = NULL; - if (ret == OK) { - src = malloc(MAX_FPGAPROGRAMSIZE); - if (src == NULL) { - fclose(fd); - struct sysinfo info; - sysinfo(&info); - sprintf(mess, - "Could not allocate memory to get fpga program. Free " - "space: %d MB\n", - (int)(info.freeram / (1024 * 1024))); - LOG(logERROR, (mess)); - ret = FAIL; - } - } - Server_SendResult(file_des, INT32, NULL, 0); - if (ret == FAIL) { - LOG(logERROR, ("Program FPGA FAIL1!\n")); - return FAIL; - } - - // copying program part by part - uint64_t totalsize = filesize; - while (ret == OK && filesize) { - uint64_t unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb - if (unitprogramsize > filesize) // less than 2mb - unitprogramsize = filesize; - LOG(logDEBUG1, ("unit size to receive is:%lld [filesize:%lld]\n", - (long long unsigned int)unitprogramsize, - (long long unsigned int)filesize)); - - // receive part of program - if (receiveData(file_des, src, unitprogramsize, OTHER) < 0) { - printSocketReadError(); - break; - } - - if (unitprogramsize - filesize == 0) { - // src[unitprogramsize] = '\0'; - filesize -= unitprogramsize; - // unitprogramsize++; - } else - filesize -= unitprogramsize; - - // copy program - if (fwrite((void *)src, sizeof(char), unitprogramsize, fd) != - unitprogramsize) { - ret = FAIL; - sprintf(mess, "Could not copy program to /var/tmp (size:%ld)\n", - (long int)unitprogramsize); - LOG(logERROR, (mess)); - } - Server_SendResult(file_des, INT32, NULL, 0); - if (ret == FAIL) { - break; - } - // print progress - LOG(logINFO, - ("\t%d%%\r", - (int)(((double)(totalsize - filesize) / totalsize) * 100))); - fflush(stdout); - } - free(src); - fclose(fd); - - // checksum of copied program - if (ret == OK) { - ret = verifyChecksumFromFile(mess, checksum, TEMP_PROG_FILE_NAME); - } - Server_SendResult(file_des, INT32, NULL, 0); - if (ret == FAIL) { - LOG(logERROR, ("Program FPGA FAIL!\n")); - return FAIL; - } - - // copy to flash - ret = copyToFlash(totalsize, checksum, mess); - Server_SendResult(file_des, INT32, NULL, 0); - if (ret == FAIL) { - LOG(logERROR, ("Program FPGA FAIL!\n")); - return FAIL; - } - -#endif // end of Blackfin programming - LOG(logINFOGREEN, ("Programming FPGA completed successfully\n")); - } + receive_program(file_des, PROGRAM_FPGA); #endif return ret; } @@ -3801,9 +3651,25 @@ int reset_fpga(int file_des) { if (Server_VerifyLock() == OK) { if (isControlServer) { basictests(); // mapping of control server at least - initControlServer(); - } else + char *message = NULL; + if (getInitResult(&message) == FAIL) { + ret = FAIL; + strcpy(mess, message); + LOG(logERROR, (mess)); + } else { + initControlServer(); + } + } else { initStopServer(); // remapping of stop server + } + if (ret == OK) { + char *message = NULL; + if (getInitResult(&message) == FAIL) { + ret = FAIL; + strcpy(mess, message); + LOG(logERROR, (mess)); + } + } } #endif return Server_SendResult(file_des, INT32, NULL, 0); @@ -4228,9 +4094,8 @@ int copy_detector_server(int file_des) { char cmd[MAX_STR_LENGTH] = {0}; // tftp server - char *format = "tftp %s -r %s -g"; - if (snprintf(cmd, MAX_STR_LENGTH, format, hostname, sname) >= - MAX_STR_LENGTH) { + if (snprintf(cmd, MAX_STR_LENGTH, "tftp %s -r %s -g", hostname, + sname) >= MAX_STR_LENGTH) { ret = FAIL; strcpy(mess, "Could not copy detector server. Command to copy " "server too long\n"); @@ -4244,95 +4109,8 @@ int copy_detector_server(int file_des) { LOG(logINFO, ("\tServer copied\n")); } - // give permissions if (ret == OK) { - if (snprintf(cmd, MAX_STR_LENGTH, "chmod 777 %s", sname) >= - MAX_STR_LENGTH) { - ret = FAIL; - strcpy(mess, "Could not copy detector server. Command to give " - "permissions to server is too long\n"); - LOG(logERROR, (mess)); - } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - ret = FAIL; - snprintf(mess, MAX_STR_LENGTH, - "Could not copy detector server (permissions). %s\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - } else { - LOG(logINFO, ("\tPermissions modified\n")); - } - } - - // symbolic link - if (ret == OK) { - if (snprintf(cmd, MAX_STR_LENGTH, "ln -sf %s %s", sname, - LINKED_SERVER_NAME) >= MAX_STR_LENGTH) { - ret = FAIL; - strcpy(mess, "Could not copy detector server. Command to " - "create symbolic link too long\n"); - LOG(logERROR, (mess)); - } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - ret = FAIL; - snprintf(mess, MAX_STR_LENGTH, - "Could not copy detector server (symbolic link). %s\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - } else { - LOG(logINFO, ("\tSymbolic link created\n")); - } - } - - // blackfin boards (respawn) (only kept for backwards compatibility) -#if defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || \ - defined(GOTTHARDD) - // delete every line with DetectorServer in /etc/inittab - if (ret == OK) { - strcpy(cmd, "sed -i '/DetectorServer/d' /etc/inittab"); - if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - ret = FAIL; - snprintf( - mess, MAX_STR_LENGTH, - "Could not copy detector server (del respawning). %s\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - } else { - LOG(logINFO, ("\tinittab: DetectoServer line deleted\n")); - } - } - - // add new link name to /etc/inittab - if (ret == OK) { - format = "echo 'ttyS0::respawn:/./%s' >> /etc/inittab"; - if (snprintf(cmd, MAX_STR_LENGTH, format, LINKED_SERVER_NAME) >= - MAX_STR_LENGTH) { - ret = FAIL; - strcpy(mess, "Could not copy detector server. Command " - "to add new server for spawning is too long\n"); - LOG(logERROR, (mess)); - } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - ret = FAIL; - snprintf(mess, MAX_STR_LENGTH, - "Could not copy detector server (respawning). %s\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - } else { - LOG(logINFO, ("\tinittab: updated for respawning\n")); - } - } -#endif - - // sync - if (ret == OK) { - strcpy(cmd, "sync"); - if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { - ret = FAIL; - snprintf(mess, MAX_STR_LENGTH, - "Could not copy detector server (sync). %s\n", - retvals); - // LOG(logERROR, (mess)); already printed in executecommand - } else { - LOG(logINFO, ("\tsync\n")); - } + ret = setupDetectorServer(mess, sname); } } #endif @@ -9426,11 +9204,302 @@ int get_kernel_version(int file_des) { // get only ret = getKernelVersion(retvals); if (ret == FAIL) { - snprintf(mess, MAX_STR_LENGTH, - "Could not get kernel version. %s\n", retvals); + if (snprintf(mess, MAX_STR_LENGTH, "Could not get kernel version. %s\n", + retvals) >= MAX_STR_LENGTH) { + ret = FAIL; + strcpy(mess, "Could not get kernel version. Reason too long to copy\n"); + } LOG(logERROR, (mess)); } else { LOG(logDEBUG1, ("kernel version: [%s]\n", retvals)); } return Server_SendResult(file_des, OTHER, retvals, sizeof(retvals)); } + +int update_kernel(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); +#ifdef EIGERD + functionNotImplemented(); + return Server_SendResult(file_des, INT32, NULL, 0); +#else + receive_program(file_des, PROGRAM_KERNEL); +#endif + return ret; +} + +int update_detector_server(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + return receive_program(file_des, PROGRAM_SERVER); +} + +int receive_program(int file_des, enum PROGRAM_INDEX index) { + // only set + if (Server_VerifyLock() == OK) { + char functionType[SHORT_STR_LENGTH] = {0}; + switch (index) { + case PROGRAM_FPGA: + strcpy(functionType, "Update Firmware"); + break; + case PROGRAM_KERNEL: + strcpy(functionType, "Update Kernel"); + break; + case PROGRAM_SERVER: + strcpy(functionType, "Update Server"); + break; + } + LOG(logINFOBLUE, ("%s ...\n", functionType)); + + // filesize + uint64_t filesize = 0; + if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0) + return printSocketReadError(); + LOG(logINFO, ("\tProgram size: %lld\n", (long long int)filesize)); + + // client checksum + char checksum[MAX_STR_LENGTH] = {0}; + if (receiveData(file_des, checksum, MAX_STR_LENGTH, OTHER) < 0) + return printSocketReadError(); + LOG(logINFO, ("\tChecksum: %s\n", checksum)); + + // server name + char serverName[MAX_STR_LENGTH] = {0}; + if (index == PROGRAM_SERVER) { + if (receiveData(file_des, serverName, MAX_STR_LENGTH, OTHER) < 0) + return printSocketReadError(); + LOG(logINFO, ("\tServer Name: %s\n", serverName)); + } + +#if defined(GOTTHARD2D) || defined(MYTHEN3D) || defined(EIGERD) + receive_program_default(file_des, index, functionType, filesize, + checksum, serverName); +#else + receive_program_via_blackfin(file_des, index, functionType, filesize, + checksum, serverName); +#endif + + if (ret == OK) { + LOG(logINFOGREEN, ("%s completed successfully\n", functionType)); + } else { + LOG(logERROR, ("%s FAIL!\n", functionType)); + } + } + + return ret; +} + +void receive_program_via_blackfin(int file_des, enum PROGRAM_INDEX index, + char *functionType, uint64_t filesize, + char *checksum, char *serverName) { + +#if !defined(JUNGFRAUD) && !defined(CHIPTESTBOARDD) && !defined(MOENCHD) && \ + !defined(GOTTHARDD) + ret = FAIL; + sprintf(mess, + "Could not %s. program via blackfin not implmented for this " + "detector.\n", + functionType); + LOG(logERROR, (mess)); +#else + // open file and allocate memory for part program + FILE *fd = NULL; + ret = preparetoCopyProgram(mess, functionType, &fd, filesize); + char *src = NULL; + if (ret == OK) { + src = malloc(MAX_BLACKFIN_PROGRAM_SIZE); + if (src == NULL) { + fclose(fd); + struct sysinfo info; + sysinfo(&info); + sprintf(mess, + "Could not %s. Memory allocation failure. Free " + "space: %d MB\n", + functionType, (int)(info.freeram / (1024 * 1024))); + LOG(logERROR, (mess)); + ret = FAIL; + } + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + return; + } + + // copying program part by part + uint64_t totalsize = filesize; + while (ret == OK && filesize) { + uint64_t unitprogramsize = MAX_BLACKFIN_PROGRAM_SIZE; + if (unitprogramsize > filesize) + unitprogramsize = filesize; + LOG(logDEBUG1, ("unit size to receive is:%lld [filesize:%lld]\n", + (long long unsigned int)unitprogramsize, + (long long unsigned int)filesize)); + + // receive part of program + if (receiveData(file_des, src, unitprogramsize, OTHER) < 0) { + printSocketReadError(); + break; + } + filesize -= unitprogramsize; + + // copy program + if (fwrite((void *)src, sizeof(char), unitprogramsize, fd) != + unitprogramsize) { + ret = FAIL; + sprintf( + mess, + "Could not %s. Could not copy program to /var/tmp (size:%ld)\n", + functionType, (long int)unitprogramsize); + LOG(logERROR, (mess)); + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + break; + } + // print progress + LOG(logINFO, + ("\t%d%%\r", + (int)(((double)(totalsize - filesize) / totalsize) * 100))); + fflush(stdout); + } + free(src); + fclose(fd); + + // checksum of copied program + if (ret == OK) { + ret = verifyChecksumFromFile(mess, functionType, checksum, + TEMP_PROG_FILE_NAME); + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + return; + } + + // appropriate functions + switch (index) { + case PROGRAM_FPGA: + case PROGRAM_KERNEL: + ret = eraseAndWriteToFlash(mess, index, functionType, checksum, + totalsize); + break; + case PROGRAM_SERVER: + ret = moveBinaryFile(mess, serverName, TEMP_PROG_FILE_NAME, + "update detector server"); + if (ret == OK) { + ret = setupDetectorServer(mess, serverName); + } + break; + default: + modeNotImplemented("Program index", (int)index); + break; + } + + // erase and copy to flash + Server_SendResult(file_des, INT32, NULL, 0); +#endif +} + +void receive_program_default(int file_des, enum PROGRAM_INDEX index, + char *functionType, uint64_t filesize, + char *checksum, char *serverName) { +#if !defined(GOTTHARD2D) && !defined(MYTHEN3D) && !defined(EIGERD) + ret = FAIL; + sprintf(mess, + "Could not %s. program via blackfin not implmented for this " + "detector.\n", + functionType); + LOG(logERROR, (mess)) +#else +#if defined(GOTTHARD2D) || defined(MYTHEN3D) + // validate file size + if (filesize > NIOS_MAX_APP_IMAGE_SIZE) { + ret = FAIL; + sprintf(mess, + "Could not %s. File size 0x%llx " + "exceeds max size 0x%llx. Forgot Compression?\n", + functionType, (long long unsigned int)filesize, + (long long unsigned int)NIOS_MAX_APP_IMAGE_SIZE); + LOG(logERROR, (mess)); + } +#endif + + // memory allocation + char *src = NULL; + if (ret == OK) { + src = malloc(filesize); + if (src == NULL) { + struct sysinfo info; + sysinfo(&info); + sprintf(mess, + "Could not %s. Memory allocation failure. Free " + "space: %d MB\n", + functionType, (int)(info.freeram / (1024 * 1024))); + LOG(logERROR, (mess)); + ret = FAIL; + } + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + return; + } + + // receive program + if (receiveData(file_des, src, filesize, OTHER) < 0) { + free(src); + ret = printSocketReadError(); + return; + } + + // checksum of copied program + if (ret == OK) { + ret = verifyChecksumFromBuffer(mess, functionType, checksum, src, + filesize); + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + return; + } + + // appropriate functions + switch (index) { +#if defined(GOTTHARD2D) || defined(MYTHEN3D) + case PROGRAM_FPGA: + case PROGRAM_KERNEL: + ret = eraseAndWriteToFlash(mess, index, functionType, checksum, src, + filesize); + break; +#endif +#if defined(GOTTHARD2D) || defined(MYTHEN3D) || defined(EIGERD) + case PROGRAM_SERVER: + ret = writeBinaryFile(mess, TEMP_PROG_FILE_NAME, src, filesize, + "update detector server"); + // extra step to write to temp and move to real file as + // fopen will give text busy if opening same name as process name + char dest[MAX_STR_LENGTH] = {0}; + sprintf(dest, "%s%s", + (myDetectorType == EIGER ? "/home/root/executables/" : ""), + serverName); + + if (ret == OK) { + ret = moveBinaryFile(mess, dest, TEMP_PROG_FILE_NAME, + "update detector server"); + } + if (ret == OK) { + ret = verifyChecksumFromFile(mess, functionType, checksum, dest); + } + if (ret == OK) { + ret = setupDetectorServer(mess, dest); + } + break; +#endif + default: + modeNotImplemented("Program index", (int)index); + break; + } + // send result + Server_SendResult(file_des, INT32, NULL, 0); + + // free resources + free(src); +#endif +} \ No newline at end of file diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 451038412..389fec128 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1733,7 +1733,8 @@ class Detector { /** [Jungfrau][CTB][Moench] Advanced user Function! */ void resetFPGA(Positions pos = {}); - /** [Jungfrau][Eiger][Gotthard][CTB][Moench][Mythen3][Gotthard2] + /** [[deprecated ("Replaced by updateDetectorServer, which does not require tftp")]] + * [Jungfrau][Eiger][Gotthard][CTB][Moench][Mythen3][Gotthard2] * Advanced user Function! \n * Copy detector server fname from tftp folder of hostname to detector. Also * creates a symbolic link to a shorter name (without vx.x.x). Then the @@ -1744,11 +1745,26 @@ class Detector { void copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos = {}); + /** [Jungfrau][Eiger][Ctb][Moench][Mythen3][Gotthard2] Copies detector + * server via TCP (without tftp).\nMakes a symbolic link with a shorter + * name (without vx.x.x).\nThen, detector controller reboots (except + * Eiger).\n[Jungfrau][Ctb][Moench]Also changes respawn server to the + * link, which is effective after a reboot. + */ + void updateDetectorServer(const std::string &fname, Positions pos = {}); + + /** [Jungfrau][Ctb][Moench][Mythen3][Gotthard2] \n + * Advanced Command!! You could damage the detector. Please use with + * caution.\nUpdates the kernel image. Then, detector controller reboots + * with new kernel + */ + void updateKernel(const std::string &fname, Positions pos = {}); + /** [Jungfrau][Gotthard][CTB][Moench][Mythen3][Gotthard2] Advanced user * Function! */ void rebootController(Positions pos = {}); - /** + /** [[deprecated ("Replaced by overloaded updateDetectorServer, which does not require tftp and has one less argument")]] * Advanced user Function!\n [Jungfrau][Gotthard][CTB][Moench] Updates the * firmware, detector server, make a soft link and then reboots detector * controller. \n [Mythen3][Gotthard2] Will require a script to start up the @@ -1760,6 +1776,16 @@ class Detector { const std::string &hostname, const std::string &fname, Positions pos = {}); + /** + * Advanced user Function!\n [Jungfrau][Gotthard][CTB][Moench] Updates the + * firmware, detector server, make a soft link and then reboots detector + * controller. \n [Mythen3][Gotthard2] Will require a script to start up the + * shorter named server link at start up \n sname is full path name of detector + * server \n fname is programming file name with full path to it + */ + void updateFirmwareAndServer(const std::string &sname, + const std::string &fname, Positions pos = {}); + /** Advanced user Function! \n * Goes to stop server. Hence, can be called while calling blocking * acquire(). \n [Eiger] Address is +0x100 for only left, +0x200 for only diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 5ecf8f281..84f485bee 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -285,12 +285,14 @@ std::string CmdProxy::Versions(int action) { os << "\nFirmware Version: " << OutStringHex(t); } os << "\nDetector Server Version: " - << OutStringHex(det->getDetectorServerVersion(std::vector{det_id})); + << OutStringHex( + det->getDetectorServerVersion(std::vector{det_id})); os << "\nDetector Server Version: " << OutString(det->getKernelVersion({std::vector{det_id}})); if (det->getUseReceiverFlag().squash(true)) { os << "\nReceiver Version: " - << OutStringHex(det->getReceiverVersion(std::vector{det_id})); + << OutStringHex( + det->getReceiverVersion(std::vector{det_id})); } os << std::dec << '\n'; } else if (action == defs::PUT_ACTION) { @@ -1432,7 +1434,9 @@ std::string CmdProxy::UDPDestinationList(int action) { throw sls::RuntimeError("udp_dstlist must be at module level."); } if (rx_id < 0 || rx_id >= MAX_UDP_DESTINATION) { - throw sls::RuntimeError(std::string("Invalid receiver index ") + std::to_string(rx_id) + std::string(" to set round robin entry.")); + throw sls::RuntimeError(std::string("Invalid receiver index ") + + std::to_string(rx_id) + + std::string(" to set round robin entry.")); } auto t = det->getDestinationUDPList(rx_id, std::vector{det_id}); os << OutString(t) << '\n'; @@ -2849,11 +2853,13 @@ std::string CmdProxy::CopyDetectorServer(int action) { std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { + LOG(logWARNING) << "Deprecated! Replaced by updatedetectorserver that requires no tftp.\n"; os << "[server_name (in tftp folder)] " "[pc_host_name]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3][" - "Gotthard2] Copies detector server via tftp from pc. Ensure that " + "Gotthard2] Copies detector server via TFTP from pc. Ensure that " "server is in the pc's tftp folder. Makes a symbolic link with a " - "shorter name (without vx.x.x). Then, detector reboots (except " + "shorter name (without vx.x.x). Then, detector controller " + "reboots (except " "Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server " "to the link, which is effective after a reboot." << '\n'; @@ -2871,30 +2877,93 @@ std::string CmdProxy::CopyDetectorServer(int action) { return os.str(); } -std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) { +std::string CmdProxy::UpdateDetectorServer(int action) { std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { - os << "[server_name (in tftp folder)] [pc_host_name] [fname.pof (incl " - "full path)]\n\t[Jungfrau][Gotthard][CTB][Moench] Updates the " - "firmware, detector server, creates the symbolic link and then " - "reboots detector controller. \n\t[Mythen3][Gotthard2] will " - "require a script to start up the shorter named server link at " - "start up. \n\tsname is name of detector server binary found on " - "tftp folder of host pc \n\thostname is name of pc to tftp from " - "\n\tfname is programming file name" + os << "[server_name with full " + "path]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3][" + "Gotthard2] Copies detector server via TCP (without tftp). Makes " + "a symbolic link with a shorter name (without vx.x.x). Then, " + "detector controller reboots (except " + "Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server " + "to the link, which is effective after a reboot." << '\n'; } else if (action == defs::GET_ACTION) { throw sls::RuntimeError("Cannot get"); } else if (action == defs::PUT_ACTION) { - if (args.size() != 3) { - WrongNumberOfParameters(3); + if (args.size() != 1) { + WrongNumberOfParameters(1); } - if (args[2].find(".pof") == std::string::npos) { - throw sls::RuntimeError("Programming file must be a pof file."); + det->updateDetectorServer(args[0], std::vector{det_id}); + os << "successful\n"; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + +std::string CmdProxy::UpdateKernel(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[kernel_name with full " + "path]\n\t[Jungfrau][Ctb][Moench][Mythen3][" + "Gotthard2] Advanced Command!! You could damage the detector. " + "Please use" + "with caution.\n\tUpdates the kernel image. Then, detector " + "controller " + "reboots with new kernel." + << '\n'; + } else if (action == defs::GET_ACTION) { + throw sls::RuntimeError("Cannot get"); + } else if (action == defs::PUT_ACTION) { + if (args.size() != 1) { + WrongNumberOfParameters(1); } - det->updateFirmwareAndServer(args[0], args[1], args[2], + det->updateKernel(args[0], std::vector{det_id}); + os << "successful\n"; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + +std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "\n\tDeprecated!! Replaced without using tftp (as shown next)[server_name" + " (in tftp folder)] [pc_host_name] [fname.pof (incl full path)]"; + os << "\n\t[server_name (incl fullpath)] [fname.pof (incl full path)] " + "This does not use tftp." + "\n\t\t[Jungfrau][Gotthard][CTB][Moench] Updates the " + "firmware, detector server, creates the symbolic link and then " + "reboots detector controller. \n\t[Mythen3][Gotthard2] will " + "require a script to start up the shorter named server link at " + "start up. \n\t\tsname is full path name of detector server binary" + "\n\t\tfname is full path of programming file" + << '\n'; + } else if (action == defs::GET_ACTION) { + throw sls::RuntimeError("Cannot get"); + } else if (action == defs::PUT_ACTION) { + if (args.size() != 3 && args.size() != 2) { + WrongNumberOfParameters(2); + } + + int fpos = args.size() - 1; + if (args[fpos].find(".pof") == std::string::npos && args[fpos].find(".rbf") == std::string::npos) { + throw sls::RuntimeError("Programming file must be a pof/rbf file."); + } + + if (args.size() == 3) { + LOG(logWARNING) << "Deprecated! Recommend to use same command without tftp (no pc name) and using full path to the server binary"; + det->updateFirmwareAndServer(args[0], args[1], args[2], + std::vector{det_id}); + } else { + det->updateFirmwareAndServer(args[0], args[1], std::vector{det_id}); + } os << "successful\n"; } else { throw sls::RuntimeError("Unknown action"); diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 0e9fdfa5d..2501e2e27 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -1059,6 +1059,8 @@ class CmdProxy { {"programfpga", &CmdProxy::ProgramFpga}, {"resetfpga", &CmdProxy::resetfpga}, {"copydetectorserver", &CmdProxy::CopyDetectorServer}, + {"updatedetectorserver", &CmdProxy::UpdateDetectorServer}, + {"updatekernel", &CmdProxy::UpdateKernel}, {"rebootcontroller", &CmdProxy::rebootcontroller}, {"update", &CmdProxy::UpdateFirmwareAndDetectorServer}, {"reg", &CmdProxy::Register}, @@ -1183,6 +1185,8 @@ class CmdProxy { /* Advanced */ std::string ProgramFpga(int action); std::string CopyDetectorServer(int action); + std::string UpdateDetectorServer(int action); + std::string UpdateKernel(int action); std::string UpdateFirmwareAndDetectorServer(int action); std::string Register(int action); std::string AdcRegister(int action); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index bfa62f1f6..a8f999713 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -9,6 +9,7 @@ #include "Module.h" #include "sls/Pattern.h" #include "sls/container_utils.h" +#include "sls/file_utils.h" #include "sls/logger.h" #include "sls/sls_detector_defs.h" #include "sls/versionAPI.h" @@ -2133,6 +2134,7 @@ void Detector::setAdditionalJsonParameter(const std::string &key, // Advanced void Detector::programFPGA(const std::string &fname, Positions pos) { + LOG(logINFO) << "Updating Firmware..."; std::vector buffer = pimpl->readProgrammingFile(fname); pimpl->Parallel(&Module::programFPGA, pos, buffer); rebootController(pos); @@ -2144,12 +2146,30 @@ void Detector::resetFPGA(Positions pos) { void Detector::copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos) { + LOG(logINFO) << "Updating Detector Server (via tftp)..."; pimpl->Parallel(&Module::copyDetectorServer, pos, fname, hostname); if (getDetectorType().squash() != defs::EIGER) { rebootController(pos); } } +void Detector::updateDetectorServer(const std::string &fname, Positions pos) { + LOG(logINFO) << "Updating Detector Server (no tftp)..."; + std::vector buffer = readBinaryFile(fname, "Update Detector Server"); + std::string filename = sls::getFileNameFromFilePath(fname); + pimpl->Parallel(&Module::updateDetectorServer, pos, buffer, filename); + if (getDetectorType().squash() != defs::EIGER) { + rebootController(pos); + } +} + +void Detector::updateKernel(const std::string &fname, Positions pos) { + LOG(logINFO) << "Updating Kernel..."; + std::vector buffer = sls::readBinaryFile(fname, "Update Kernel"); + pimpl->Parallel(&Module::updateKernel, pos, buffer); + rebootController(pos); +} + void Detector::rebootController(Positions pos) { pimpl->Parallel(&Module::rebootController, pos); } @@ -2158,10 +2178,23 @@ void Detector::updateFirmwareAndServer(const std::string &sname, const std::string &hostname, const std::string &fname, Positions pos) { + LOG(logINFO) << "Updating Firmware and Detector Server (with tftp)..."; + LOG(logINFO) << "Updating Detector Server (via tftp)..."; pimpl->Parallel(&Module::copyDetectorServer, pos, sname, hostname); programFPGA(fname, pos); } +void Detector::updateFirmwareAndServer(const std::string &sname, + const std::string &fname, + Positions pos) { + LOG(logINFO) << "Updating Firmware and Detector Server (no tftp)..."; + LOG(logINFO) << "Updating Detector Server (no tftp)..."; + std::vector buffer = readBinaryFile(fname, "Update Detector Server"); + std::string filename = sls::getFileNameFromFilePath(sname); + pimpl->Parallel(&Module::updateDetectorServer, pos, buffer, filename); + programFPGA(fname, pos); +} + Result Detector::readRegister(uint32_t addr, Positions pos) const { return pimpl->Parallel(&Module::readRegister, pos, addr); } @@ -2240,7 +2273,7 @@ Result Detector::getLastClientIP(Positions pos) const { Result Detector::executeCommand(const std::string &value, Positions pos) { - return pimpl->Parallel(&Module::execCommand, pos, value); + return pimpl->Parallel(&Module::executeCommand, pos, value); } Result Detector::getNumberOfFramesFromStart(Positions pos) const { diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index f9aa1a1ab..2d51e7b58 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -12,6 +12,7 @@ #include "sls/ToString.h" #include "sls/container_utils.h" +#include "sls/file_utils.h" #include "sls/network_utils.h" #include "sls/string_utils.h" @@ -1261,8 +1262,7 @@ std::vector DetectorImpl::readProgrammingFile(const std::string &fname) { throw RuntimeError("programfpga not implemented for this detector"); } - LOG(logINFO) - << "Updating Firmware. This can take awhile. Please be patient..."; + LOG(logINFO) << "This can take awhile. Please be patient."; LOG(logDEBUG1) << "Programming FPGA with file name:" << fname; // check if it exists @@ -1280,14 +1280,7 @@ std::vector DetectorImpl::readProgrammingFile(const std::string &fname) { } // get srcSize to print progress - if (fseek(src, 0, SEEK_END) != 0) { - throw RuntimeError("Program FPGA: Seek error in src file"); - } - size_t srcSize = ftell(src); - if (srcSize <= 0) { - throw RuntimeError("Program FPGA: Could not get length of source file"); - } - rewind(src); + ssize_t srcSize = sls::getFileSize(src, "Program FPGA"); // create temp destination file char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX"; @@ -1359,36 +1352,12 @@ std::vector DetectorImpl::readProgrammingFile(const std::string &fname) { if (close(dst) != 0) { throw RuntimeError("Program FPGA: Could not close destination file"); } - LOG(logINFOBLUE) << "File has been converted to " << destfname; + LOG(logINFO) << "File has been converted to " << destfname; - // loading dst file to memory - // FILE *fp = fopen("/tmp/SLS_DET_MCB.tzgmUT", "r"); - FILE *fp = fopen(destfname, "r"); - if (fp == nullptr) { - throw RuntimeError("Program FPGA: Could not open rawbin file"); - } - if (fseek(fp, 0, SEEK_END) != 0) { - throw RuntimeError("Program FPGA: Seek error in rawbin file"); - } - size_t filesize = ftell(fp); - if (filesize <= 0) { - throw RuntimeError("Program FPGA: Could not get length of rawbin file"); - } - rewind(fp); - - std::vector buffer(filesize, 0); - if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) { - throw RuntimeError("Program FPGA: Could not read rawbin file"); - } - - if (fclose(fp) != 0) { - throw RuntimeError( - "Program FPGA: Could not close destination file after converting"); - } - - // unlink(destfname); // delete temporary file - LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory"; - LOG(logDEBUG1) << "Read file into memory"; + // load converted file to memory + std::vector buffer = readBinaryFile(destfname, "Program FPGA"); + // delete temporary + unlink(destfname); return buffer; } diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index 37d57d7bf..c51f80251 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -284,7 +284,7 @@ class DetectorImpl : public virtual slsDetectorDefs { /** * Convert raw file - * [Jungfrau][Ctb] from pof file + * [Jungfrau][Ctb][Moench] from pof file * [Mythen3][Gotthard2] from rbf file * @param fname name of pof/rbf file * @returns binary of the program diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index dfbc4e001..de0559d37 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -836,8 +836,9 @@ std::vector Module::getNumMissingPackets() const { auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); client.Send(F_GET_NUM_MISSING_PACKETS); if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + throw ReceiverError( + "Receiver " + std::to_string(moduleIndex) + + " returned error: " + client.readErrorMessage()); } else { auto nports = client.Receive(); std::vector retval(nports); @@ -1172,7 +1173,8 @@ void Module::setReceiverHostname(const std::string &receiverIP) { LOG(logDEBUG1) << "Setting up Receiver hostname with " << receiverIP; if (getRunStatus() == RUNNING) { - throw RuntimeError("Cannot set receiver hostname. Acquisition already running. Stop it first."); + throw RuntimeError("Cannot set receiver hostname. Acquisition already " + "running. Stop it first."); } if (receiverIP == "none") { @@ -1529,7 +1531,7 @@ void Module::sendReceiverRateCorrections(const std::vector &t) { receiver.Send(t); if (receiver.Receive() == FAIL) { throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + receiver.readErrorMessage()); + " returned error: " + receiver.readErrorMessage()); } } @@ -1785,7 +1787,7 @@ void Module::sendVetoPhoton(const int chipIndex, client.Send(values); if (client.Receive() == FAIL) { throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } } @@ -1797,14 +1799,14 @@ void Module::getVetoPhoton(const int chipIndex, client.Send(chipIndex); if (client.Receive() == FAIL) { throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } auto nch = client.Receive(); if (nch != shm()->nChan.x) { throw DetectorError("Could not get veto photon. Expected " + - std::to_string(shm()->nChan.x) + " channels, got " + - std::to_string(nch)); + std::to_string(shm()->nChan.x) + " channels, got " + + std::to_string(nch)); } std::vector gainIndices(nch); std::vector values(nch); @@ -2032,7 +2034,7 @@ void Module::getBadChannels(const std::string &fname) const { client.Send(F_GET_BAD_CHANNELS); if (client.Receive() == FAIL) { throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } // receive badchannels auto nch = client.Receive(); @@ -2089,7 +2091,7 @@ void Module::setBadChannels(const std::string &fname) { } if (client.Receive() == FAIL) { throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } } @@ -2403,7 +2405,7 @@ std::map Module::getAdditionalJsonHeader() const { client.Send(F_GET_ADDITIONAL_JSON_HEADER); if (client.Receive() == FAIL) { throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } else { auto size = client.Receive(); std::string buff(size, '\0'); @@ -2452,7 +2454,7 @@ void Module::setAdditionalJsonHeader( if (client.Receive() == FAIL) { throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } } @@ -2485,14 +2487,15 @@ void Module::programFPGA(std::vector buffer) { case JUNGFRAU: case CHIPTESTBOARD: case MOENCH: - programFPGAviaBlackfin(buffer); + sendProgram(true, buffer, F_PROGRAM_FPGA, "Update Firmware"); break; case MYTHEN3: case GOTTHARD2: - programFPGAviaNios(buffer); + sendProgram(false, buffer, F_PROGRAM_FPGA, "Update Firmware"); break; default: - throw RuntimeError("Program FPGA is not implemented for this detector"); + throw RuntimeError("Updating Firmware via the package is not " + "implemented for this detector"); } } @@ -2503,7 +2506,8 @@ void Module::copyDetectorServer(const std::string &fname, char args[2][MAX_STR_LENGTH]{}; sls::strcpy_safe(args[0], fname.c_str()); sls::strcpy_safe(args[1], hostname.c_str()); - LOG(logINFO) << "Sending detector server " << args[0] << " from host " + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending detector server " << args[0] << " from host " << args[1]; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(F_COPY_DET_SERVER); @@ -2516,12 +2520,51 @@ void Module::copyDetectorServer(const std::string &fname, throw DetectorError(os.str()); } LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): detector server copied"; + << "): Detector server copied"; +} + +void Module::updateDetectorServer(std::vector buffer, + const std::string &serverName) { + switch (shm()->detType) { + case JUNGFRAU: + case CHIPTESTBOARD: + case MOENCH: + sendProgram(true, buffer, F_UPDATE_DETECTOR_SERVER, + "Update Detector Server (no tftp)", serverName); + break; + case MYTHEN3: + case GOTTHARD2: + case EIGER: + sendProgram(false, buffer, F_UPDATE_DETECTOR_SERVER, + "Update Detector Server (no tftp)", serverName); + break; + default: + throw RuntimeError("Updating DetectorServer via the package is not implemented " + "for this detector"); + } +} + +void Module::updateKernel(std::vector buffer) { + switch (shm()->detType) { + case JUNGFRAU: + case CHIPTESTBOARD: + case MOENCH: + sendProgram(true, buffer, F_UPDATE_KERNEL, "Update Kernel"); + break; + case MYTHEN3: + case GOTTHARD2: + sendProgram(false, buffer, F_UPDATE_KERNEL, "Update Kernel"); + break; + default: + throw RuntimeError("Updating Kernel via the package is not implemented " + "for this detector"); + } } void Module::rebootController() { sendToDetector(F_REBOOT_CONTROLLER); - LOG(logINFO) << "Controller rebooted successfully!"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Controller rebooted successfully!"; } uint32_t Module::readRegister(uint32_t addr) const { @@ -2599,11 +2642,25 @@ sls::IpAddr Module::getLastClientIP() const { return sendToDetector(F_GET_LAST_CLIENT_IP); } -std::string Module::execCommand(const std::string &cmd) { +std::string Module::executeCommand(const std::string &cmd) { char arg[MAX_STR_LENGTH]{}; char retval[MAX_STR_LENGTH]{}; sls::strcpy_safe(arg, cmd.c_str()); - sendToDetector(F_EXEC_COMMAND, arg, retval); + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending command " << cmd; + auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + client.Send(F_EXEC_COMMAND); + client.Send(arg); + if (client.Receive() == FAIL) { + std::cout << '\n'; + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + client.Receive(retval); + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): command executed"; return retval; } @@ -3161,7 +3218,7 @@ void Module::setModule(sls_detector_module &module, bool trimbits) { sendModule(&module, client); if (client.Receive() == FAIL) { throw DetectorError("Module " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + " returned error: " + client.readErrorMessage()); } } @@ -3407,56 +3464,69 @@ sls_detector_module Module::readSettingsFile(const std::string &fname, return myMod; } -void Module::programFPGAviaBlackfin(std::vector buffer) { - // send program from memory to detector - LOG(logINFO) << "Sending programming binary (from pof) to module " - << moduleIndex << " (" << shm()->hostname << ")"; +void Module::sendProgram(bool blackfin, std::vector buffer, + const int functionEnum, + const std::string &functionType, + const std::string serverName) { + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending " << functionType; + + // send fnum and filesize auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_PROGRAM_FPGA); + client.Send(functionEnum); uint64_t filesize = buffer.size(); client.Send(filesize); - // checksum + // send checksum std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize); LOG(logDEBUG1) << "Checksum:" << checksum; - char cChecksum[MAX_STR_LENGTH]; - memset(cChecksum, 0, MAX_STR_LENGTH); + char cChecksum[MAX_STR_LENGTH] = {0}; strcpy(cChecksum, checksum.c_str()); client.Send(cChecksum); - // opening file fail + // send server name + if (functionEnum == F_UPDATE_DETECTOR_SERVER) { + char sname[MAX_STR_LENGTH] = {0}; + strcpy(sname, serverName.c_str()); + client.Send(sname); + } + + // validate memory allocation etc in detector if (client.Receive() == FAIL) { - std::cout << '\n'; std::ostringstream os; os << "Module " << moduleIndex << " (" << shm()->hostname << ")" << " returned error: " << client.readErrorMessage(); throw DetectorError(os.str()); } - // sending program in parts of 2mb each - uint64_t unitprogramsize = 0; - int currentPointer = 0; - while (filesize > 0) { - unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb - if (unitprogramsize > filesize) { // less than 2mb - unitprogramsize = filesize; - } - LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize - << "\t filesize:" << filesize; + // send program + if (blackfin) { + uint64_t unitprogramsize = 0; + int currentPointer = 0; + while (filesize > 0) { + unitprogramsize = MAX_BLACKFIN_PROGRAM_SIZE; + if (unitprogramsize > filesize) { + unitprogramsize = filesize; + } + LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize + << "\t filesize:" << filesize; - client.Send(&buffer[currentPointer], unitprogramsize); - if (client.Receive() == FAIL) { - std::cout << '\n'; - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); + client.Send(&buffer[currentPointer], unitprogramsize); + if (client.Receive() == FAIL) { + std::cout << '\n'; + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + filesize -= unitprogramsize; + currentPointer += unitprogramsize; } - filesize -= unitprogramsize; - currentPointer += unitprogramsize; + } else { + client.Send(buffer); } - // checksum + // tmp checksum verified in detector if (client.Receive() == FAIL) { std::ostringstream os; os << "Module " << moduleIndex << " (" << shm()->hostname << ")" @@ -3466,134 +3536,56 @@ void Module::programFPGAviaBlackfin(std::vector buffer) { LOG(logINFO) << "Checksum verified for module " << moduleIndex << " (" << shm()->hostname << ")"; - // simulating erasing flash - { - LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex - << " (" << shm()->hostname << ")"; - printf("%d%%\r", 0); - std::cout << std::flush; - // erasing takes 65 seconds, printing here (otherwise need threads - // in server-unnecessary) - const int ERASE_TIME = 65; - int count = ERASE_TIME + 1; - while (count > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - --count; - printf("%d%%\r", - static_cast( - (static_cast(ERASE_TIME - count) / ERASE_TIME) * - 100)); - std::cout << std::flush; + // simulating erasing and writing to + if (blackfin) { + if (functionEnum == F_PROGRAM_FPGA) { + simulatingActivityinDetector("Erasing Flash", + BLACKFIN_ERASE_FLASH_TIME); + simulatingActivityinDetector("Writing to Flash", + BLACKFIN_WRITE_TO_FLASH_TIME); + } + } else { + if (functionEnum == F_PROGRAM_FPGA) { + simulatingActivityinDetector("Erasing Flash", + NIOS_ERASE_FLASH_TIME_FPGA); + simulatingActivityinDetector("Writing to Flash", + NIOS_WRITE_TO_FLASH_TIME_FPGA); + } else if (functionEnum == F_UPDATE_KERNEL) { + simulatingActivityinDetector("Erasing Flash", + NIOS_ERASE_FLASH_TIME_KERNEL); + simulatingActivityinDetector("Writing to Flash", + NIOS_WRITE_TO_FLASH_TIME_KERNEL); } - printf("\n"); - } - - // simulating writing to flash - { - LOG(logINFO) << "(Simulating) Writing to Flash for module " - << moduleIndex << " (" << shm()->hostname << ")"; - printf("%d%%\r", 0); - std::cout << std::flush; - // writing takes 30 seconds, printing here (otherwise need threads - // in server-unnecessary) - const int ERASE_TIME = 30; - int count = ERASE_TIME + 1; - while (count > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - --count; - printf("%d%%\r", - static_cast( - (static_cast(ERASE_TIME - count) / ERASE_TIME) * - 100)); - std::cout << std::flush; - } - printf("\n"); } + // update verified if (client.Receive() == FAIL) { std::ostringstream os; os << "Module " << moduleIndex << " (" << shm()->hostname << ")" << " returned error: " << client.readErrorMessage(); throw DetectorError(os.str()); } - LOG(logINFO) << "FPGA programmed successfully"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): " << functionType << " udpated successfully"; } -void Module::programFPGAviaNios(std::vector buffer) { - LOG(logINFO) << "Sending programming binary (from rbf) to Module " +void Module::simulatingActivityinDetector(const std::string &functionType, + const int timeRequired) { + LOG(logINFO) << "(Simulating) " << functionType << " for module " << moduleIndex << " (" << shm()->hostname << ")"; - - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_PROGRAM_FPGA); - uint64_t filesize = buffer.size(); - client.Send(filesize); - - // checksum - std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize); - LOG(logDEBUG1) << "Checksum:" << checksum; - char cChecksum[MAX_STR_LENGTH]; - memset(cChecksum, 0, MAX_STR_LENGTH); - strcpy(cChecksum, checksum.c_str()); - client.Send(cChecksum); - - // validate file size before sending program - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - client.Send(buffer); - - // simulating erasing flash - { - LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex - << " (" << shm()->hostname << ")"; - printf("%d%%\r", 0); + printf("%d%%\r", 0); + std::cout << std::flush; + const int ERASE_TIME = timeRequired; + int count = ERASE_TIME + 1; + while (count > 0) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + --count; + printf( + "%d%%\r", + static_cast( + (static_cast(ERASE_TIME - count) / ERASE_TIME) * 100)); std::cout << std::flush; - // erasing takes 10 seconds, printing here (otherwise need threads - // in server-unnecessary) - const int ERASE_TIME = 10; - int count = ERASE_TIME + 1; - while (count > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - --count; - printf("%d%%\r", - static_cast( - (static_cast(ERASE_TIME - count) / ERASE_TIME) * - 100)); - std::cout << std::flush; - } - printf("\n"); } - - // simulating writing to flash - { - LOG(logINFO) << "(Simulating) Writing to Flash for module " - << moduleIndex << " (" << shm()->hostname << ")"; - printf("%d%%\r", 0); - std::cout << std::flush; - // writing takes 45 seconds, printing here (otherwise need threads - // in server-unnecessary) - const int ERASE_TIME = 45; - int count = ERASE_TIME + 1; - while (count > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - --count; - printf("%d%%\r", - static_cast( - (static_cast(ERASE_TIME - count) / ERASE_TIME) * - 100)); - std::cout << std::flush; - } - printf("\n"); - } - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - LOG(logINFO) << "FPGA programmed successfully"; + printf("\n"); } } // namespace sls diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 6bb10a9d3..0750fb941 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -541,6 +541,9 @@ class Module : public virtual slsDetectorDefs { void resetFPGA(); void copyDetectorServer(const std::string &fname, const std::string &hostname); + void updateDetectorServer(std::vector buffer, + const std::string &serverName); + void updateKernel(std::vector buffer); void rebootController(); uint32_t readRegister(uint32_t addr) const; uint32_t writeRegister(uint32_t addr, uint32_t val); @@ -565,7 +568,7 @@ class Module : public virtual slsDetectorDefs { bool getLockDetector() const; void setLockDetector(bool lock); sls::IpAddr getLastClientIP() const; - std::string execCommand(const std::string &cmd); + std::string executeCommand(const std::string &cmd); int64_t getNumberOfFramesFromStart() const; int64_t getActualTime() const; int64_t getMeasurementTime() const; @@ -746,11 +749,20 @@ class Module : public virtual slsDetectorDefs { std::string getTrimbitFilename(detectorSettings settings, int e_eV); sls_detector_module readSettingsFile(const std::string &fname, bool trimbits = true); - void programFPGAviaBlackfin(std::vector buffer); - void programFPGAviaNios(std::vector buffer); + void sendProgram(bool blackfin, std::vector buffer, + const int functionEnum, const std::string &functionType, + const std::string serverName = ""); + void simulatingActivityinDetector(const std::string &functionType, + const int timeRequired); const int moduleIndex; mutable sls::SharedMemory shm{0, 0}; + static const int BLACKFIN_ERASE_FLASH_TIME = 65; + static const int BLACKFIN_WRITE_TO_FLASH_TIME = 30; + static const int NIOS_ERASE_FLASH_TIME_FPGA = 10; + static const int NIOS_WRITE_TO_FLASH_TIME_FPGA = 45; + static const int NIOS_ERASE_FLASH_TIME_KERNEL = 9; + static const int NIOS_WRITE_TO_FLASH_TIME_KERNEL = 40; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index e6e3851fe..a08db3a4c 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -2708,6 +2708,25 @@ TEST_CASE("copydetectorserver", "[.cmd]") { } } +TEST_CASE("updatekernel", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::JUNGFRAU || det_type == defs::CHIPTESTBOARD || + det_type == defs::MOENCH || det_type == defs::MYTHEN3 || + det_type == defs::GOTTHARD2) { + // TODO: send real server? + // std::ostringstream oss; + // proxy.Call("updatekernel",{"juImage_detector.lzma", + // "pc13784"}, -1, PUT, oss); + // REQUIRE(oss.str() == "updatekernel successful\n"); + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET)); + } else { + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, PUT)); + } +} + TEST_CASE("rebootcontroller", "[.cmd]") { Detector det; CmdProxy proxy(&det); diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index 75d820c7f..371dc5b30 100644 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -355,7 +355,7 @@ std::string Implementation::getFilePath() const { return filePath; } void Implementation::setFilePath(const std::string &c) { if (!c.empty()) { - mkdir_p(c); // throws if it can't create + sls::mkdir_p(c); // throws if it can't create filePath = c; } LOG(logINFO) << "File path: " << filePath; diff --git a/slsSupportLib/include/sls/file_utils.h b/slsSupportLib/include/sls/file_utils.h index cc427a88f..0959154d8 100644 --- a/slsSupportLib/include/sls/file_utils.h +++ b/slsSupportLib/include/sls/file_utils.h @@ -8,49 +8,46 @@ #include #include -/** (used by multi and sls) - * reads a short int raw data file - * @param infile input file stream +namespace sls { + + +/** * @param data array of data values * @param nch number of channels * @param offset start channel value - * @returns OK or FAIL if it could not read the file or data=NULL */ int readDataFile(std::ifstream &infile, short int *data, int nch, int offset = 0); -/** (used by multi and sls) - * reads a short int rawdata file - * @param fname name of the file to be read +/** * @param data array of data value * @param nch number of channels - * @returns OK or FAIL if it could not read the file or data=NULL */ int readDataFile(std::string fname, short int *data, int nch); -/** (used by multi and sls) - * writes a short int raw data file - * @param outfile output file stream + +std::vector readBinaryFile(const std::string &fname, + const std::string &errorPrefix); + +/** * @param nch number of channels * @param data array of data values * @param offset start channel number - * @returns OK or FAIL if it could not write the file or data=NULL */ int writeDataFile(std::ofstream &outfile, int nch, short int *data, int offset = 0); -/** (used by multi and sls) - * writes a short int raw data file - * @param fname of the file to be written +/** * @param nch number of channels * @param data array of data values - * @returns OK or FAIL if it could not write the file or data=NULL */ int writeDataFile(std::string fname, int nch, short int *data); // mkdir -p path implemented by recursive calls void mkdir_p(const std::string &path, std::string dir = ""); -namespace sls { int getFileSize(std::ifstream &ifs); +ssize_t getFileSize(FILE* fd, const std::string &prependErrorString); + +std::string getFileNameFromFilePath(const std::string &fpath); } diff --git a/slsSupportLib/include/sls/sls_detector_defs.h b/slsSupportLib/include/sls/sls_detector_defs.h index 0f65441b7..6feb18c23 100644 --- a/slsSupportLib/include/sls/sls_detector_defs.h +++ b/slsSupportLib/include/sls/sls_detector_defs.h @@ -55,9 +55,8 @@ /** maximum trim en */ #define MAX_TRIMEN 100 -/** maximum unit size of program sent to detector */ -//#define MAX_FPGAPROGRAMSIZE (2 * 1024 * 1024) -#define MAX_FPGAPROGRAMSIZE (128 * 1024) +/** maximum unit size of program sent to blackfin */ +#define MAX_BLACKFIN_PROGRAM_SIZE (128 * 1024) #define GET_FLAG -1 diff --git a/slsSupportLib/include/sls/sls_detector_funcs.h b/slsSupportLib/include/sls/sls_detector_funcs.h index 62b232513..8606c5f40 100755 --- a/slsSupportLib/include/sls/sls_detector_funcs.h +++ b/slsSupportLib/include/sls/sls_detector_funcs.h @@ -254,6 +254,8 @@ enum detFuncs { F_GET_READOUT_SPEED, F_SET_READOUT_SPEED, F_GET_KERNEL_VERSION, + F_UPDATE_KERNEL, + F_UPDATE_DETECTOR_SERVER, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -610,6 +612,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_READOUT_SPEED: return "F_GET_READOUT_SPEED"; case F_SET_READOUT_SPEED: return "F_SET_READOUT_SPEED"; case F_GET_KERNEL_VERSION: return "F_GET_KERNEL_VERSION"; + case F_UPDATE_DETECTOR_SERVER: return "F_UPDATE_DETECTOR_SERVER"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h index 3b29c55f2..681ddae93 100644 --- a/slsSupportLib/include/sls/versionAPI.h +++ b/slsSupportLib/include/sls/versionAPI.h @@ -6,10 +6,10 @@ #define APILIB 0x211027 #define APIRECEIVER 0x211020 #define APIGUI 0x211021 -#define APICTB 0x211103 -#define APIGOTTHARD 0x211103 -#define APIGOTTHARD2 0x211103 -#define APIJUNGFRAU 0x211103 -#define APIMYTHEN3 0x211103 -#define APIMOENCH 0x211103 -#define APIEIGER 0x211103 +#define APICTB 0x211117 +#define APIGOTTHARD 0x211117 +#define APIGOTTHARD2 0x211117 +#define APIJUNGFRAU 0x211117 +#define APIMYTHEN3 0x211117 +#define APIMOENCH 0x211111 +#define APIEIGER 0x211117 diff --git a/slsSupportLib/src/file_utils.cpp b/slsSupportLib/src/file_utils.cpp index 9c58c5dcf..ee6c9e15f 100644 --- a/slsSupportLib/src/file_utils.cpp +++ b/slsSupportLib/src/file_utils.cpp @@ -11,6 +11,8 @@ #include #include +namespace sls { + int readDataFile(std::ifstream &infile, short int *data, int nch, int offset) { int ichan, iline = 0; short int idata; @@ -53,6 +55,39 @@ int readDataFile(std::string fname, short int *data, int nch) { return iline; } +std::vector readBinaryFile(const std::string &fname, + const std::string &errorPrefix) { + // check if it exists + struct stat st; + if (stat(fname.c_str(), &st) != 0) { + throw sls::RuntimeError(errorPrefix + + std::string(" (file does not exist)")); + } + + FILE *fp = fopen(fname.c_str(), "rb"); + if (fp == nullptr) { + throw sls::RuntimeError(errorPrefix + + std::string(" (Could not open file: ") + fname + std::string(")")); + } + + // get file size to print progress + ssize_t filesize = sls::getFileSize(fp, errorPrefix); + + std::vector buffer(filesize, 0); + if ((ssize_t)fread(buffer.data(), sizeof(char), filesize, fp) != filesize) { + throw sls::RuntimeError(errorPrefix + + std::string(" (Could not read file)")); + } + + if (fclose(fp) != 0) { + throw sls::RuntimeError(errorPrefix + + std::string(" (Could not close file)")); + } + + LOG(logDEBUG1) << "Read file into memory"; + return buffer; +} + int writeDataFile(std::ofstream &outfile, int nch, short int *data, int offset) { if (data == nullptr) @@ -96,7 +131,6 @@ void mkdir_p(const std::string &path, std::string dir) { mkdir_p(path.substr(i + 1), dir); } -namespace sls { int getFileSize(std::ifstream &ifs) { auto current_pos = ifs.tellg(); ifs.seekg(0, std::ios::end); @@ -104,4 +138,27 @@ int getFileSize(std::ifstream &ifs) { ifs.seekg(current_pos); return file_size; } + +std::string getFileNameFromFilePath(const std::string &fpath) { + std::string fname(fpath); + std::size_t slashPos = fpath.rfind('/'); + if (slashPos != std::string::npos) { + fname = fpath.substr(slashPos + 1, fpath.size() - 1); + } + return fname; +} + +ssize_t getFileSize(FILE* fd, const std::string &prependErrorString) { + if (fseek(fd, 0, SEEK_END) != 0) { + throw RuntimeError(prependErrorString + std::string(" (Seek error in src file)")); + } + size_t fileSize = ftell(fd); + if (fileSize <= 0) { + throw RuntimeError(prependErrorString + std::string(" (Could not get length of source file)")); + } + rewind(fd); + return fileSize; +} + + } // namespace sls