diff --git a/python/src/detector.cpp b/python/src/detector.cpp index da7a6ad91..50d81c7d8 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1520,6 +1520,9 @@ void init_det(py::module &m) { (void (Detector::*)(const std::string &, const std::string &, sls::Positions)) & Detector::copyDetectorServer, + .def("updateDetectorServer", + (void (Detector::*)(const std::string &, sls::Positions)) & + Detector::updateDetectorServer, .def("updateKernel", (void (Detector::*)(const std::string &, sls::Positions)) & Detector::updateKernel, diff --git a/slsDetectorServers/slsDetectorServer/src/programViaNios.c b/slsDetectorServers/slsDetectorServer/src/programViaNios.c index 5e4d18788..ba3b05521 100644 --- a/slsDetectorServers/slsDetectorServer/src/programViaNios.c +++ b/slsDetectorServers/slsDetectorServer/src/programViaNios.c @@ -38,10 +38,6 @@ void rebootControllerAndFPGA() { int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc, uint64_t fsize) { - if (verifyChecksumFromBuffer(mess, checksum, fpgasrc, fsize) == FAIL) { - return FAIL; - } - if (getDrive(mess) == FAIL) { return FAIL; } diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 0a5c7b696..03fec5136 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -3778,12 +3778,12 @@ void program_fpga_via_blackfin(int file_des, enum PROGRAMINDEX index, return; } - // copy to flash + // erase and copy to flash ret = copyToFlash(index, messageType, totalsize, checksum, mess); Server_SendResult(file_des, INT32, NULL, 0); } -int program_fpga_via_nios(int file_des, uint64_t filesize, char *checksum) { +void program_fpga_via_nios(int file_des, uint64_t filesize, char *checksum) { // validate file size if (filesize > NIOS_MAX_APP_IMAGE_SIZE) { ret = FAIL; @@ -3794,18 +3794,43 @@ int program_fpga_via_nios(int file_des, uint64_t filesize, char *checksum) { (long long unsigned int)NIOS_MAX_APP_IMAGE_SIZE); LOG(logERROR, (mess)); } + // memory allocation + char *src = NULL; + if (ret == OK) { + src = malloc(filesize); + if (src == NULL) { + fclose(fd); + struct sysinfo info; + sysinfo(&info); + sprintf(mess, + "Could not allocate memory to get %s. Free " + "space: %d MB\n", + messageType, (int)(info.freeram / (1024 * 1024))); + LOG(logERROR, (mess)); + ret = FAIL; + } + } Server_SendResult(file_des, INT32, NULL, 0); if (ret == FAIL) { return; } // receive program - char *src = malloc(filesize); if (receiveData(file_des, src, filesize, OTHER) < 0) { free(src); ret = printSocketReadError(); return; } + + // checksum of copied program + if (ret == OK) { + ret = verifyChecksumFromBuffer(mess, checksum, src, fsize); + } + Server_SendResult(file_des, INT32, NULL, 0); + if (ret == FAIL) { + return; + } + // erase and program ret = eraseAndWriteToFlash(mess, checksum, src, filesize); Server_SendResult(file_des, INT32, NULL, 0); diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 43866df54..eb670f387 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1744,14 +1744,21 @@ 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 + * 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 = {}); diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 9f5d554cd..eca03e314 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'; @@ -2851,9 +2855,10 @@ std::string CmdProxy::CopyDetectorServer(int action) { if (action == defs::HELP_ACTION) { 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 controller 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,12 +2876,43 @@ std::string CmdProxy::CopyDetectorServer(int action) { return os.str(); } +std::string CmdProxy::UpdateDetectorServer(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + 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() != 1) { + WrongNumberOfParameters(1); + } + 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." + 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"); diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index c52020afa..2501e2e27 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -1059,6 +1059,7 @@ class CmdProxy { {"programfpga", &CmdProxy::ProgramFpga}, {"resetfpga", &CmdProxy::resetfpga}, {"copydetectorserver", &CmdProxy::CopyDetectorServer}, + {"updatedetectorserver", &CmdProxy::UpdateDetectorServer}, {"updatekernel", &CmdProxy::UpdateKernel}, {"rebootcontroller", &CmdProxy::rebootcontroller}, {"update", &CmdProxy::UpdateFirmwareAndDetectorServer}, @@ -1184,6 +1185,7 @@ 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); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 7b5258df7..b02b0a398 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,14 +2146,25 @@ 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..."; + std::vector buffer = readBinaryFile(fname, "Update Detector Server"); + pimpl->Parallel(&Module::updateDetectorServer, pos, buffer); + if (getDetectorType().squash() != defs::EIGER) { + rebootController(pos); + } +} + void Detector::updateKernel(const std::string &fname, Positions pos) { - std::vector buffer = pimpl->readKernelFile(fname); + LOG(logINFO) << "Updating Kernel..."; + std::vector buffer = readBinaryFile(fname, "Update Kernel"); pimpl->Parallel(&Module::updateKernel, pos, buffer); rebootController(pos); } @@ -2164,6 +2177,7 @@ void Detector::updateFirmwareAndServer(const std::string &sname, const std::string &hostname, const std::string &fname, Positions pos) { + LOG(logINFO) << "Updating Firmware and Detector Server..."; pimpl->Parallel(&Module::copyDetectorServer, pos, sname, hostname); programFPGA(fname, pos); } diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index c3f123530..deb0546a3 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" @@ -1361,91 +1362,10 @@ std::vector DetectorImpl::readProgrammingFile(const std::string &fname) { } LOG(logINFOBLUE) << "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) << "Read file into memory"; - return buffer; -} - -std::vector DetectorImpl::readKernelFile(const std::string &fname) { - // validate type of file - switch (shm()->detType) { - case JUNGFRAU: - case CHIPTESTBOARD: - case MOENCH: - if (fname.find(".lzma") == std::string::npos) { - throw RuntimeError("Kernel image file must be a lzma file."); - } - break; - case MYTHEN3: - case GOTTHARD2: - if (fname.find(".bin") == std::string::npos) { - throw RuntimeError("Kernel image file must be an bin file."); - } - break; - default: - throw RuntimeError("Programming kernel image via the package is not " - "implemented for this detector"); - } - - LOG(logINFO) << "Updating Kernel..."; - LOG(logDEBUG1) << "Programming kernel image with file name:" << fname; - - // check if it exists - struct stat st; - if (stat(fname.c_str(), &st) != 0) { - throw RuntimeError("Program kernel: file does not exist"); - } - - FILE *fp = fopen(fname.c_str(), "rb"); - if (fp == nullptr) { - throw RuntimeError("Program kernel: Could not open file: " + fname); - } - - // get file size to print progress - if (fseek(fp, 0, SEEK_END) != 0) { - throw RuntimeError("Program kernel: Seek error in src file"); - } - size_t filesize = ftell(fp); - if (filesize <= 0) { - throw RuntimeError("Program kernel: Could not get length of file"); - } - rewind(fp); - - std::vector buffer(filesize, 0); - if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) { - throw RuntimeError("Program kernel: Could not read file"); - } - - if (fclose(fp) != 0) { - throw RuntimeError("Program kernel: Could not close file"); - } - - 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 c82d7a178..c51f80251 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -291,15 +291,6 @@ class DetectorImpl : public virtual slsDetectorDefs { */ std::vector readProgrammingFile(const std::string &fname); - /** - * Read file into memory - * [Jungfrau][Ctb][Moench] from lzma file - * [Mythen3][Gotthard2] from bin file - * @param fname name of file - * @returns binary of the program - */ - std::vector readKernelFile(const std::string &fname); - sls::Result getNumberofUDPInterfaces(Positions pos) const; void setNumberofUDPInterfaces(int n, Positions pos); sls::Result getDefaultDac(defs::dacIndex index, diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 93913bb85..444f24848 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -2487,14 +2487,14 @@ 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("Programming FPGA via the package is not " + throw RuntimeError("Updating Firmware via the package is not " "implemented for this detector"); } } @@ -2523,16 +2523,35 @@ void Module::copyDetectorServer(const std::string &fname, << "): detector server copied"; } +void Module::updateDetectorServer(std::vector buffer) { + switch (shm()->detType) { + case JUNGFRAU: + case CHIPTESTBOARD: + case MOENCH: + sendProgram(true, buffer, F_UPDATE_DETECTOR_SERVER, + "Update Detector Server (no tftp)"); + break; + case MYTHEN3: + case GOTTHARD2: + sendProgram(false, buffer, F_UPDATE_DETECTOR_SERVER, + "Update Detector Server (no tftp)"); + break; + default: + throw RuntimeError("Updating Kernel via the package is not implemented " + "for this detector"); + } +} + void Module::updateKernel(std::vector buffer) { switch (shm()->detType) { case JUNGFRAU: case CHIPTESTBOARD: case MOENCH: - updateKernelviaBlackfin(buffer); + sendProgram(true, buffer, F_UPDATE_KERNEL, "Update Kernel"); break; case MYTHEN3: case GOTTHARD2: - updateKernelviaNios(buffer); + sendProgram(false, buffer, F_UPDATE_KERNEL, "Update Kernel"); break; default: throw RuntimeError("Updating Kernel via the package is not implemented " @@ -3443,16 +3462,19 @@ sls_detector_module Module::readSettingsFile(const std::string &fname, return myMod; } -void Module::programFPGAviaBlackfin(std::vector buffer) { - // send program from memory to detector +void Module::sendProgram(bool blackfin, std::vector buffer, + const int functionEnum, + const std::string &functionType) { LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Sending programming binary (from pof)"; + << "): 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]; @@ -3460,39 +3482,42 @@ void Module::programFPGAviaBlackfin(std::vector buffer) { strcpy(cChecksum, checksum.c_str()); client.Send(cChecksum); - // opening file fail + // 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 - 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; + // 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 << ")" @@ -3502,50 +3527,22 @@ 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 (functionEnum == F_PROGRAM_FPGA) { + if (blackfin) { + simulatingActivityinDetector("Erasing Flash", + BLACKFIN_ERASE_FLASH_TIME); + simulatingActivityinDetector("Writing to Flash", + BLACKFIN_WRITE_TO_FLASH_TIME); + } else { + simulatingActivityinDetector("Erasing Flash", + NIOS_ERASE_FLASH_TIME); + simulatingActivityinDetector("Writing to Flash", + NIOS_WRITE_TO_FLASH_TIME); } - 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 << ")" @@ -3553,190 +3550,26 @@ void Module::programFPGAviaBlackfin(std::vector buffer) { throw DetectorError(os.str()); } LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): FPGA programmed successfully"; + << "): " << functionType << " udpated successfully"; } -void Module::programFPGAviaNios(std::vector buffer) { - LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Sending programming binary (from rbf)"; - - 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); +void Module::simulatingActivityinDetector(const std::string &functionType, + const int timeRequired) { + LOG(logINFO) << "(Simulating) " << functionType << " for module " + << moduleIndex << " (" << shm()->hostname << ")"; + 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) << "Module " << moduleIndex << " (" << shm()->hostname - << "): FPGA programmed successfully"; -} - -void Module::updateKernelviaBlackfin(std::vector buffer) { - // send program from memory to detector - LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Sending kernel image (.lzma)"; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_PROGRAM_KERNEL); - 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); - - // opening file fail - 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 - 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()); - } - filesize -= unitprogramsize; - currentPointer += unitprogramsize; - } - - // checksum - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - LOG(logINFO) << "Checksum verified for module " << moduleIndex << " (" - << shm()->hostname << ")"; - - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Kernel udpated successfully"; -} - -void Module::updateKernelviaNios(std::vector buffer) { - LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Sending kernel image (from rbf)"; - - 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); - - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname - << "): Kernel updated successfully"; + printf("\n"); } } // namespace sls diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index d81e880fc..00c4cf115 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -541,6 +541,7 @@ class Module : public virtual slsDetectorDefs { void resetFPGA(); void copyDetectorServer(const std::string &fname, const std::string &hostname); + void updateDetectorServer(std::vector buffer); void updateKernel(std::vector buffer); void rebootController(); uint32_t readRegister(uint32_t addr) const; @@ -747,13 +748,17 @@ 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 updateKernelviaBlackfin(std::vector buffer); - void updateKernelviaNios(std::vector buffer); + void sendProgram(bool blackfin, std::vector buffer, + const int functionEnum, const std::string &functionType); + 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 = 10; + static const int NIOS_WRITE_TO_FLASH_TIME = 45; }; } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/sls/file_utils.h b/slsSupportLib/include/sls/file_utils.h index cc427a88f..3e0cb3923 100644 --- a/slsSupportLib/include/sls/file_utils.h +++ b/slsSupportLib/include/sls/file_utils.h @@ -8,43 +8,34 @@ #include #include -/** (used by multi and sls) - * reads a short int raw data file - * @param infile input file stream +/** * @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); diff --git a/slsSupportLib/include/sls/sls_detector_funcs.h b/slsSupportLib/include/sls/sls_detector_funcs.h index 160669f25..8606c5f40 100755 --- a/slsSupportLib/include/sls/sls_detector_funcs.h +++ b/slsSupportLib/include/sls/sls_detector_funcs.h @@ -254,7 +254,8 @@ enum detFuncs { F_GET_READOUT_SPEED, F_SET_READOUT_SPEED, F_GET_KERNEL_VERSION, - F_PROGRAM_KERNEL, + F_UPDATE_KERNEL, + F_UPDATE_DETECTOR_SERVER, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -611,7 +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_PROGRAM_KERNEL: return "F_PROGRAM_KERNEL"; + 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/src/file_utils.cpp b/slsSupportLib/src/file_utils.cpp index 9c58c5dcf..652e0749a 100644 --- a/slsSupportLib/src/file_utils.cpp +++ b/slsSupportLib/src/file_utils.cpp @@ -53,6 +53,48 @@ 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); + } + + // get file size to print progress + if (fseek(fp, 0, SEEK_END) != 0) { + throw sls::RuntimeError(errorPrefix + + std::string(": Seek error in src file")); + } + size_t filesize = ftell(fp); + if (filesize <= 0) { + throw sls::RuntimeError(errorPrefix + + std::string(": Could not get length of file")); + } + rewind(fp); + + std::vector buffer(filesize, 0); + if (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)