diff --git a/doc/examples/README.md b/doc/examples/README.md index b334593edf33499d95a82ecbd84b2363c35b8806..9b68178e50767b5a66b1db1fa610dc95cc1c8a90 100644 --- a/doc/examples/README.md +++ b/doc/examples/README.md @@ -22,8 +22,8 @@ The full sequence starting from compilation, assuming that the build system is c cd </path/to/cmsgemos/> cd gemrpc DESTDIR=_install cmake3 --build _build --target install -rsync -v -a --delete --include='/bin/***' --include='/lib/' --include='/lib/rpcmodules/***' --exclude='*' _build/_install/mnt/persistent/gempro/ gempro@gem-shelf01-amc02: -ssh gempro@gem-shelf01-amc02 'bash -l -c "/bin/clockinit /mnt/persistent/gemdaq/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0; v7load /mnt/persistent/gemdaq/fw/gem_ctp7.bit; source /mnt/persistent/gemdaq/gemloader/gemloader_configure.sh; killall -9 gemrpc; LD_LIBRARY_PATH=/mnt/persistent/gempro/lib/rpcmodules:/mnt/persistent/gempro/lib GEM_PATH=/mnt/persistent/gemdaq bin/gemrpc"' +rsync -v -a --delete --include='/bin/***' --include='/lib/' --include='/lib/gem/***' --exclude='*' _build/_install/mnt/persistent/gempro/ gempro@gem-shelf01-amc02: +ssh gempro@gem-shelf01-amc02 'bash -l -c "killall -9 gemrpc; bin/gemrpc; bin/gem-recover"' ``` The GBT configurations examples can be found under `gemrpc/doc/gbt/<gem type>/`, but the files used for the configuration of the chamber are stored on the AMC folder `/mnt/persistent/gempro/etc/gem/gbt`. diff --git a/extern/rpcsvc/server/interface/ModuleManager.h b/extern/rpcsvc/server/interface/ModuleManager.h index 11d8cf48eb14bbfdbb7d53f48a6cf86e60fdf450..21f8f8049f33e40b394d5235679207ffa09f57ae 100644 --- a/extern/rpcsvc/server/interface/ModuleManager.h +++ b/extern/rpcsvc/server/interface/ModuleManager.h @@ -26,8 +26,7 @@ protected: public: ModuleManager() {}; - int load_modules_dir(std::string dir); - bool load_module(std::string dir, std::string mod_name, std::string version_key); + bool load_module(std::string module_name); void register_method(std::string service, std::string module, rpc_method_t func); void invoke_method(std::string method, RPCMsg* request, RPCMsg* response); }; diff --git a/extern/rpcsvc/server/src/ModuleManager.cpp b/extern/rpcsvc/server/src/ModuleManager.cpp index d4b7108ab712f0e6171c93943a6ea2fc62a1c1a0..0b7aa4c444e03d9b0e889fcb437b27f158d972d1 100644 --- a/extern/rpcsvc/server/src/ModuleManager.cpp +++ b/extern/rpcsvc/server/src/ModuleManager.cpp @@ -5,104 +5,34 @@ #include "ModuleManager.h" -int ModuleManager::load_modules_dir(std::string dir) +bool ModuleManager::load_module(std::string module_name) { - DIR* dh = opendir(dir.c_str()); - if (!dh) - return -1; - errno = 0; LogManager::ScopeService scopesvc(LOGGER, "ModuleManager"); - while (struct dirent* ent = readdir(dh)) { - if (std::string(".") == ent->d_name || std::string("..") == ent->d_name) - continue; - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Loading module %s/%s", dir.c_str(), ent->d_name)); - - void* mod = dlopen((dir + "/" + ent->d_name).c_str(), RTLD_NOW | RTLD_LOCAL); - if (!mod) { - LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s/%s: %s", dir.c_str(), ent->d_name, dlerror())); - continue; - } - - void* initfunc = dlsym(mod, "module_init"); - if (!initfunc) { - LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s/%s: %s", dir.c_str(), ent->d_name, dlerror())); - continue; - } - - void* module_activity_color = dlsym(mod, "module_activity_color"); - if (module_activity_color) - this->modload_activity_color = *static_cast<int*>(module_activity_color); - - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s/%s", dir.c_str(), ent->d_name)); - LOGGER->push_active_service(ent->d_name); - reinterpret_cast<void (*)(ModuleManager*)>(initfunc)(this); - LOGGER->pop_active_service(ent->d_name); - this->modulestate[dir + "/" + ent->d_name] = 1; - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s/%s", dir.c_str(), ent->d_name)); - - this->modload_activity_color = 0; - errno = 0; // for next readdir(); - } - if (errno) { - closedir(dh); - return -1; - } - closedir(dh); - return 0; -} - -bool ModuleManager::load_module(std::string dir, std::string mod_name, std::string version_key) -{ - LogManager::ScopeService scopesvc(LOGGER, "ModuleManager"); - - if (mod_name.find("/") != std::string::npos) { - LOGGER->log_message(LogManager::CRITICAL, stdsprintf("Security violation. Module name \"%s\" contains a '/'!", mod_name.c_str())); - return false; - } - - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Loading module %s/%s.so", dir.c_str(), mod_name.c_str())); - void* mod = dlopen((dir + "/" + mod_name + ".so").c_str(), RTLD_NOW | RTLD_LOCAL); + void* mod = dlopen(module_name.data(), RTLD_NOW | RTLD_LOCAL); if (!mod) { - LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror())); + LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to dlopen %s: %s", module_name.data(), dlerror())); return false; } - void* module_version_key_sym = dlsym(mod, "module_version_key"); - if (!module_version_key_sym) { - LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate version key in %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror())); - return false; - } - - const char* module_version_key = reinterpret_cast<const char*>(*reinterpret_cast<void**>(module_version_key_sym)); - if (version_key != module_version_key) { - LOGGER->log_message(LogManager::WARNING, stdsprintf("Bad version key for %s/%s.so: \"%s\"!=\"%s\"", dir.c_str(), mod_name.c_str(), version_key.c_str(), module_version_key)); - return false; - } - - if (this->modulestate[dir + "/" + mod_name + ".so"] == 1) { - LOGGER->log_message(LogManager::INFO, stdsprintf("Module %s/%s.so is already loaded", dir.c_str(), mod_name.c_str())); + if (this->modulestate[module_name] == 1) { + LOGGER->log_message(LogManager::INFO, stdsprintf("Module %s is already loaded", module_name.data())); return true; } void* initfunc = dlsym(mod, "module_init"); if (!initfunc) { - LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s/%s.so: %s", dir.c_str(), mod_name.c_str(), dlerror())); + LOGGER->log_message(LogManager::ERROR, stdsprintf("Unable to locate initialization function in %s: %s", module_name.data(), dlerror())); return false; } - void* module_activity_color = dlsym(mod, "module_activity_color"); - if (module_activity_color) - this->modload_activity_color = *static_cast<int*>(module_activity_color); - - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s/%s.so", dir.c_str(), mod_name.c_str())); - LOGGER->push_active_service(mod_name); + LOGGER->log_message(LogManager::DEBUG, stdsprintf("Initializing loaded module %s", module_name.data())); + LOGGER->push_active_service(module_name); reinterpret_cast<void (*)(ModuleManager*)>(initfunc)(this); - LOGGER->pop_active_service(mod_name); - this->modulestate[dir + "/" + mod_name + ".so"] = 1; - LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s/%s.so", dir.c_str(), mod_name.c_str())); + LOGGER->pop_active_service(module_name); + this->modulestate[module_name] = 1; + LOGGER->log_message(LogManager::DEBUG, stdsprintf("Completed module initialization for %s", module_name.c_str())); - this->modload_activity_color = 0; return true; } diff --git a/extern/rpcsvc/server/src/run_client.cpp b/extern/rpcsvc/server/src/run_client.cpp index e27175c2b109ad2ed52568d709abcd8af89d90eb..c4e1567e034bbbe82e9d90b7c69d33684dfefa96 100644 --- a/extern/rpcsvc/server/src/run_client.cpp +++ b/extern/rpcsvc/server/src/run_client.cpp @@ -1,6 +1,6 @@ #define PROTOVER 3 #define MIN_PROTOVER 3 -#define MODULES_DIR "/mnt/persistent/gempro/lib/rpcmodules" +#define MODULE_NAME "libgemhardwarerpc.so" #define LOG_PATH_FORMAT "syslog" // #define LOG_PATH_FORMAT "/var/log/rpcsvc/rpcsvc.%s.%u.log" #define LOG_OUTPUT_LEVEL LogManager::INFO @@ -101,10 +101,8 @@ int run_client(int clientfd) LOGGER->log_message(LogManager::NOTICE, stdsprintf("Client connected from %s", get_ip4_string(clientfd).c_str())); ModuleManager modmgr; -#ifdef LOAD_ALL_MODULES - if (modmgr.load_modules_dir(MODULES_DIR) < 0) - ERROR_DIE("Unable to load modules"); -#endif + if (!modmgr.load_module(MODULE_NAME)) + ERROR_DIE("Unable to load the RPC module"); uint32_t protover = htonl(PROTOVER); if (write(clientfd, &protover, 4) != 4) @@ -156,13 +154,7 @@ int run_client(int clientfd) RPCMsg rpcrsp(rpcreq.get_method()); try { - if (rpcreq.get_method() == "module.load") { - // This special case will be handled here. - - if (!modmgr.load_module(MODULES_DIR, rpcreq.get_string("module"), rpcreq.get_string("module_version_key"))) - rpcrsp.set_string("rpcerror", "Unable to load the requested module."); - } else - modmgr.invoke_method(rpcreq.get_method(), &rpcreq, &rpcrsp); + modmgr.invoke_method(rpcreq.get_method(), &rpcreq, &rpcrsp); } catch (RPCMsg::TypeException& e) { rpcrsp.set_string("rpcerror", std::string("RPCMsg::TypeException Occurred")); } catch (RPCMsg::BadKeyException& e) { @@ -171,23 +163,6 @@ int run_client(int clientfd) std::string rsp = rpcrsp.serialize(); uint32_t rsplen = rsp.size(); - -#if 0 - // -------- DEBUG BEGIN -------- - dprintf("Debug Message Seralize: [rsplen=%u]\n", rsplen); - for (uint32_t i = 0; i < rsplen; i++) { - if (rsp.c_str()[i] >= 32 && rsp.c_str()[i] <= 127) - dprintf("%3c", rsp.c_str()[i]); - else - dprintf(" "); - } - dprintf("\n"); - for (uint32_t i = 0; i < rsplen; i++) - dprintf(" %02x", rsp.c_str()[i]); - dprintf("\n"); - // -------- DEBUG END -------- -#endif - uint32_t rspcrc = crc32(0, reinterpret_cast<const unsigned char*>(rsp.data()), rsplen); rsplen = htonl(rsplen); diff --git a/extern/xhal/client/interface/XHALInterface.h b/extern/xhal/client/interface/XHALInterface.h index 83678469f78ecba6f0d1182067a7e409fd5bd0f2..5856ce29370570bb233b4aea4432a6ca361281c1 100644 --- a/extern/xhal/client/interface/XHALInterface.h +++ b/extern/xhal/client/interface/XHALInterface.h @@ -81,9 +81,6 @@ namespace client { /// @brief Initialize interface and establish RPC service connection with CTP7 void disconnect(); - /// @brief load remote module - void loadModule(const std::string& module_name, const std::string& module_version); - /// @brief Call a remote RPC method /// /// The remote method called is defined by the template parameter diff --git a/extern/xhal/client/src/XHALInterface.cpp b/extern/xhal/client/src/XHALInterface.cpp index 697eca56736bf52ca902da701b035fbfda687083..92893b9dab39068668d5f214fb03b1ea75303822 100644 --- a/extern/xhal/client/src/XHALInterface.cpp +++ b/extern/xhal/client/src/XHALInterface.cpp @@ -88,14 +88,6 @@ void xhal::client::XHALInterface::disconnect() } } -void xhal::client::XHALInterface::loadModule(const std::string& module_name, const std::string& module_version) -{ - try { - ASSERT(rpc.load_module(module_name, module_version)); - } - STANDARD_CATCH; -} - void xhal::client::XHALInterface::setLogLevel(int loglevel) { switch (loglevel) { diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp index e87149004de34d9add280e1fb1a029fcb075019d..4919af6b36d21154ef5d1d8f17dfd32b942f15de 100644 --- a/gemhardware/managers/src/AMCManager.cpp +++ b/gemhardware/managers/src/AMCManager.cpp @@ -91,10 +91,10 @@ void gem::hardware::AMCManager::initializeAction() // Establish the communication with the backend board const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_); m_connection = std::make_shared<xhal::client::XHALInterface>(deviceName); - m_connection->loadModule("gem_rpc", ""); // == AMC == - m_connection->call<::amc::recoverAMC>(); + CMSGEMOS_INFO("AMCManager::initializeAction: reset AMC"); + m_connection->call<::amc::resetAMC>(); // == OptoHybrids == diff --git a/gemmonitor/src/AMCMonitor.cpp b/gemmonitor/src/AMCMonitor.cpp index e921a66ca066cfc8d34daac988598aa8d5b234c3..163eb89156106f03987ce2ddf8d763263b9fd8a1 100644 --- a/gemmonitor/src/AMCMonitor.cpp +++ b/gemmonitor/src/AMCMonitor.cpp @@ -40,7 +40,7 @@ void gem::monitor::AMCMonitor::actionPerformed(xdata::Event& event) CMSGEMOS_DEBUG("AMCMonitor::actionPerformed() setDefaultValues"); const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_); m_amc = std::make_shared<xhal::client::XHALInterface>(deviceName); - m_amc->loadModule("gem_rpc", ""); + m_ohMask = m_amc->call<::daqmon::getmonOHMask>(); const std::string class_name = this->getApplicationDescriptor()->getClassName(); diff --git a/gemrpc/CMakeLists.txt b/gemrpc/CMakeLists.txt index 742851c6d30b64d85a3292e7bc46873640605595..9c1df35603aa2361482ef1356489028a5dc911ae 100644 --- a/gemrpc/CMakeLists.txt +++ b/gemrpc/CMakeLists.txt @@ -65,33 +65,16 @@ else() include_directories("${CMAKE_CURRENT_BINARY_DIR}/_interface") # - # memhub is a regular library + # memhub library # add_library(memhub SHARED src/memhub.cpp) target_link_libraries(memhub PUBLIC memsvc) - install(TARGETS memhub LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/rpcmodules") + install(TARGETS memhub LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem") # - # RPC modules + # GEM hardware library # - function(gemrpc_add_module NAME) - cmake_parse_arguments(ARGS "" "" "SOURCES;DEPS" ${ARGN}) - - add_library(${NAME} SHARED ${ARGS_SOURCES}) - target_link_libraries(${NAME} PRIVATE ${ARGS_DEPS}) - target_link_libraries(${NAME} PRIVATE memhub) - target_link_libraries(${NAME} PUBLIC xhal::common) - target_link_libraries(${NAME} PRIVATE xhal::server) - target_link_libraries(${NAME} PRIVATE log4cplus) - - # Remove the `lib` prefix - set_target_properties(${NAME} PROPERTIES PREFIX "") - - install(TARGETS ${NAME} LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/rpcmodules") - endfunction() - - gemrpc_add_module(gem_rpc - SOURCES + add_library(gemhardware SHARED src/amc.cpp src/amc/blaster_ram.cpp src/amc/daq.cpp @@ -101,13 +84,43 @@ else() src/daq_monitor.cpp src/expert_tools.cpp src/gbt.cpp - src/gem_rpc.cpp + # src/optical.cpp src/optohybrid.cpp src/vfat3.cpp src/utils.cpp src/XHALXMLParser.cpp - DEPS - lmdb xerces-c reedmuller-c) - target_include_directories(gem_rpc PUBLIC extern) + ) + + target_link_libraries(gemhardware PUBLIC memhub) + target_link_libraries(gemhardware PUBLIC xhal::common) + + target_link_libraries(gemhardware PRIVATE lmdb) + target_link_libraries(gemhardware PRIVATE log4cplus) + target_link_libraries(gemhardware PRIVATE reedmuller-c) + target_link_libraries(gemhardware PRIVATE xerces-c) + + target_include_directories(gemhardware PUBLIC extern) + + install(TARGETS gemhardware LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem") + + # + # RPC module + # + add_library(gemhardwarerpc SHARED src/gemhardwarerpc.cpp) + + target_link_libraries(gemhardwarerpc PRIVATE gemhardware) + target_link_libraries(gemhardwarerpc PRIVATE xhal::server) + + install(TARGETS gemhardwarerpc LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gem") + + # + # Standalone executables + # + add_executable(gem-recover src/recover.cpp) + target_link_libraries(gem-recover PRIVATE gemhardware) + install(TARGETS gem-recover RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") + add_executable(gem-update-address-table src/update_address_table.cpp) + target_link_libraries(gem-update-address-table PRIVATE gemhardware) + install(TARGETS gem-update-address-table RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") endif() diff --git a/gemrpc/interface/amc.h b/gemrpc/interface/amc.h index 79eb910c3ee2e8a9d040f28987eb7617bba49d31..41a18e1401a3c4f164bfc39f90dafd34c9a151b4 100644 --- a/gemrpc/interface/amc.h +++ b/gemrpc/interface/amc.h @@ -93,25 +93,31 @@ struct repeatedRegRead : public xhal::common::Method { /// @brief Recovers the AMC /// /// * Enable the optical TX lasers -/// * Reset the FPGA registers -/// * Configure the GTH transceivers +/// * Reset the external PLL (Si5324) +/// * Load the Virtex-7 firmware +/// * Load the OptoHybrid firmware into RAM /// -/// @throws @c std::runtime::error if -/// * fails to enable the optical TX lasers. +/// @throws @c std::runtime::error if any of the operation fails. struct recoverAMC : public xhal::common::Method { void operator()() const; }; -/// @brief Resets all the AMC clocks +/// @brief Resets the AMC +/// +/// * Reset the FPGA registers +/// * Configure the MGT +struct resetAMC : public xhal::common::Method { + void operator()() const; +}; + +/// @brief Resets the AMC clocks /// -/// * Reset the external PLL (Si5324) [currently disabled] /// * Reset the internal PLL /// * Reset the FPGA logic after clock changes /// * Align the clock phase to the TTC backplane clock -/// * Reset the GTH transceivers +/// * Reset the MGT /// /// @throws @c std::runtime::error if -/// * fails to reset the external PLL; /// * fails to reset the internal PLL. struct resetClocks : public xhal::common::Method { void operator()() const; diff --git a/gemrpc/interface/daq_monitor.h b/gemrpc/interface/daq_monitor.h index 7e408c54101aa9d38f274f2138b12d728897e0a5..8371041ef54987468240c74618c420f978604288 100644 --- a/gemrpc/interface/daq_monitor.h +++ b/gemrpc/interface/daq_monitor.h @@ -122,13 +122,13 @@ struct getmonVFATLink : xhal::common::Method { std::map<std::string, uint32_t> operator()(const bool& doReset = false) const; }; -/// @brief Creates a dump of the required registers, specified by a file expected in <blah>/registers.txt +/// @brief Creates a dump of the required registers, specified in the file passed as argument /// /// @throws @c std::runtime_error if it is not possible to open @c fname /// /// @returns @c std::map struct getmonCTP7dump : xhal::common::Method { - std::map<std::string, uint32_t> operator()(const std::string& fname = "/mnt/persistent/gemdaq/mon_registers.txt") const; + std::map<std::string, uint32_t> operator()(const std::string& fname) const; }; /// @brief Tests the register "GEM_AMC.SLOW_CONTROL.SCA.STATUS.READY" to derive the OH mask that should be used diff --git a/gemrpc/interface/utils.h b/gemrpc/interface/utils.h index 53b55087a006a1269b178771d4e23017d62f5985..bddf943f20be5994c37263e2c58ea5f500106c73 100644 --- a/gemrpc/interface/utils.h +++ b/gemrpc/interface/utils.h @@ -39,11 +39,9 @@ struct RegInfo { } }; -/// @brief Updates the LMDB object -/// -/// @param @c at_xml is the name of the XML address table to use to populate the LMDB +/// @brief Updates the LMDB address table struct update_address_table : public xhal::common::Method { - void operator()(const std::string& at_xml) const; + void operator()() const; }; /// @brief Read register information from LMDB diff --git a/gemrpc/interface/vfat3.h b/gemrpc/interface/vfat3.h index 1396ffc3523de85b610687e48d019d2af8cba435..b0f3b1d6f87b4042dcf7e155b41a1b5dbddf9c05 100644 --- a/gemrpc/interface/vfat3.h +++ b/gemrpc/interface/vfat3.h @@ -39,7 +39,7 @@ struct configureVFAT3DACMonitor : public xhal::common::Method { /// @brief Configures VFAT3 chips /// -/// VFAT configurations are stored in files under \c /mnt/persistent/gemdaq/vfat3/config_OHX_VFATY.cfg. +/// VFAT configurations are stored in files under \c $HOME/etc/gem/vfat/config_OHx_VFATy.cfg. /// Each non-empty line contains one register name followed by its value. /// The comment character is #. /// diff --git a/gemrpc/src/amc.cpp b/gemrpc/src/amc.cpp index e3076f73f938b38edf7248963eef768b694772ae..aca70345c08c0bb00101700b952ecd8638d2dcd2 100644 --- a/gemrpc/src/amc.cpp +++ b/gemrpc/src/amc.cpp @@ -18,6 +18,7 @@ #include <gem/rpc/utils.h> #include <chrono> +#include <fstream> #include <thread> #include <time.h> @@ -158,14 +159,49 @@ std::vector<uint32_t> amc::sbitReadOut::operator()(const uint32_t& ohN, const ui void amc::recoverAMC::operator()() const { - // Step 1: Enable the optical TX lasers + const std::string home_path = std::getenv("HOME"); + + // == Enable the optical TX lasers == LOG4CPLUS_INFO(logger, "Enable the optical TX lasers"); utils::execute_command("/bin/txpower enable"); - // Step 2: Reset the FPGA registers + // == Reset the external PLL == + LOG4CPLUS_INFO(logger, "Reset the external PLL"); + const std::string ctp7_cfg_filename = home_path + "/etc/gem/gem_ctp7.cfg"; + std::ifstream ctp7_cfg_file { ctp7_cfg_filename }; + std::string ctp7_cfg; + std::getline(ctp7_cfg_file, ctp7_cfg); + utils::execute_command(std::string { "/bin/clockinit " } + ctp7_cfg); + + // Wait for the PLL to lock + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // == Load the Virtex-7 firmware == + LOG4CPLUS_INFO(logger, "Load the Virtex-7 firmware"); + const std::string ctp7_fw_filename = home_path + "/etc/gem/gem_ctp7.bit"; + utils::execute_command(std::string { "/bin/v7load " } + ctp7_fw_filename); + + // == Load the OptoHybrid firmware into RAM == + LOG4CPLUS_INFO(logger, "Load the OptoHybrid firmware into RAM"); + + const std::string optohybrid_fw_filename = home_path + "/etc/gem/gem_optohybrid.bit"; + utils::execute_command(std::string { "/bin/gemloader load " } + optohybrid_fw_filename); + + // Write the firmware size (rounded-up to a multiple of 4 bytes) + std::ifstream optohybrid_fw(optohybrid_fw_filename, std::ifstream::ate | std::ifstream::binary); + const uint32_t optohybrid_fw_size = ((static_cast<uint32_t>(optohybrid_fw.tellg()) + 3) / 4) * 4; + utils::writeRawAddress(0x6a000004, optohybrid_fw_size); + + // Enable the GEM loader IP core + utils::writeRawAddress(0x6a000000, 1); +} + +void amc::resetAMC::operator()() const +{ + // == Reset the FPGA registers == utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.IPBUS_RESET", 1); - // Step 3: Configure the GTH transceivers + // == Configure the GTH transceivers == // // Regular GTH config/control value: // Bit 0: TX_POWERDOWN: Transmitter powered down @@ -192,14 +228,7 @@ void amc::recoverAMC::operator()() const void amc::resetClocks::operator()() const { - // Step 1: Reset the external PLL - /* LOG4CPLUS_INFO(logger, "Reset the external PLL"); */ - /* utils::execute_command("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0"); */ - - /* // Wait for the PLL to lock */ - /* std::this_thread::sleep_for(std::chrono::milliseconds(1000)); */ - - // Step 2: Reset the internal PLL + // == Reset the internal PLL == LOG4CPLUS_INFO(logger, "Reset the internal PLL"); utils::writeReg("GEM_AMC.TTC.CTRL.MMCM_RESET", 1); for (size_t i = 0; i < 10; ++i) { @@ -212,11 +241,11 @@ void amc::resetClocks::operator()() const std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - // Step 3: Reset the FPGA logic after clock changes + // == Reset the FPGA logic after clock changes == utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.GLOBAL_RESET", 1); std::this_thread::sleep_for(std::chrono::milliseconds(50)); - // Step 4: Align the clock phase to the TTC backplane clock + // == Align the clock phase to the TTC backplane clock == LOG4CPLUS_INFO(logger, "Align the clock phase to the TTC backplane clock"); // Write the target phase @@ -231,14 +260,14 @@ void amc::resetClocks::operator()() const } while ((utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") > targetPhase + tollerancePhase) || (utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") < targetPhase - tollerancePhase)); utils::writeReg("GEM_AMC.TTC.CTRL.CNT_RESET", 1); - // Step 5: Reset the GTH transceivers - LOG4CPLUS_INFO(logger, "Reset the GTH transceivers"); + // == Reset the MGT == + LOG4CPLUS_INFO(logger, "Reset the MGT"); for (uint32_t i = 0; i < 64; i++) { const auto tmp = std::string { "GEM_AMC.OPTICAL_LINKS.MGT_CHANNEL_" } + std::to_string(i) + ".RESET"; utils::writeReg(tmp, 0x7); } - // Check the GTH status + // Check the MGT status LOG4CPLUS_INFO(logger, "GTHs status"); LOG4CPLUS_INFO(logger, " Ch # | GTH Status | GTH Ctrl "); LOG4CPLUS_INFO(logger, "------------------------------------"); diff --git a/gemrpc/src/gbt.cpp b/gemrpc/src/gbt.cpp index 5eca83e92311c75699aad53f11237403bce66d0c..3830aeec708f81c21c0f72b478fde769a873e730 100644 --- a/gemrpc/src/gbt.cpp +++ b/gemrpc/src/gbt.cpp @@ -176,7 +176,8 @@ void gbt::writeGBTReg(const uint32_t ohN, const uint32_t gbtN, const uint16_t ad void gbt::configureGBTs::operator()(const uint32_t& ohN) const { for (unsigned int j = 0; j < GBTS_PER_OH; j++) { - const std::string gbtConfigFileName = "/mnt/persistent/gempro/etc/gem/gbt/config_OH" + std::to_string(ohN) + "_GBT" + std::to_string(j) + ".cfg"; + const std::string home_path = std::getenv("HOME"); + const std::string gbtConfigFileName = home_path + "/etc/gem/gbt/config_OH" + std::to_string(ohN) + "_GBT" + std::to_string(j) + ".cfg"; std::ifstream gbtConfigFile; gbtConfigFile.exceptions(std::ifstream::badbit); gbtConfigFile.open(gbtConfigFileName); diff --git a/gemrpc/src/gem_rpc.cpp b/gemrpc/src/gemhardwarerpc.cpp similarity index 98% rename from gemrpc/src/gem_rpc.cpp rename to gemrpc/src/gemhardwarerpc.cpp index 9dfeab383c08540331840fd8ead8c0a51fdbd1ed..fe4a2a8852d2cb0e10fe164b30e8fd2d412c7109 100644 --- a/gemrpc/src/gem_rpc.cpp +++ b/gemrpc/src/gemhardwarerpc.cpp @@ -1,4 +1,4 @@ -/// @file gem_rpc.cpp +/// @file gemhardwarerpc.cpp /// @brief the registration of all the RPC methods done inside the module_init function for the different RPC modules are combined into this /// @author Monika Mittal <monika.mittal@cern.ch> /// @author Laurent Pétré <laurent.petre@cern.ch> @@ -48,6 +48,7 @@ void module_init(ModuleManager* modmgr) xhal::server::registerMethod<amc::getOHVFATMaskMultiLink>(modmgr); xhal::server::registerMethod<amc::recoverAMC>(modmgr); xhal::server::registerMethod<amc::repeatedRegRead>(modmgr); + xhal::server::registerMethod<amc::resetAMC>(modmgr); xhal::server::registerMethod<amc::resetClocks>(modmgr); xhal::server::registerMethod<amc::sbitReadOut>(modmgr); diff --git a/gemrpc/src/recover.cpp b/gemrpc/src/recover.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aee91ac0a889f670c40fb55909170977f86419ef --- /dev/null +++ b/gemrpc/src/recover.cpp @@ -0,0 +1,12 @@ +#include "utils.h" +#include <gem/rpc/amc.h> + +int main(int argc, const char* argv[]) +{ + ::utils::init_lmdb(); + memhub_open(&memsvc); + + ::amc::recoverAMC {}(); + + return 0; +} diff --git a/gemrpc/src/update_address_table.cpp b/gemrpc/src/update_address_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ea9a6bad64636f5c9698945a529cdf3fdcbcd83 --- /dev/null +++ b/gemrpc/src/update_address_table.cpp @@ -0,0 +1,8 @@ +#include <gem/rpc/utils.h> + +int main(int argc, const char* argv[]) +{ + ::utils::update_address_table {}(); + + return 0; +} diff --git a/gemrpc/src/utils.cpp b/gemrpc/src/utils.cpp index 1889ecc04e44e696f238f45a07761977a4df2278..b43405cff4c9fa4d8f7792b7f1a712a56c1d829a 100644 --- a/gemrpc/src/utils.cpp +++ b/gemrpc/src/utils.cpp @@ -95,19 +95,18 @@ void utils::execute_command(const std::string& command) } } -void utils::update_address_table::operator()(const std::string& at_xml) const +void utils::update_address_table::operator()() const { auto logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("logger")); LOG4CPLUS_INFO(logger, "START UPDATE ADDRESS TABLE"); - const char* const gem_path = std::getenv("GEM_PATH"); - if (gem_path == nullptr) - throw std::runtime_error("The GEM_PATH environment variable must be defined."); - const auto lmdb_data_file = std::string { gem_path } + "/address_table.mdb/data.mdb"; - const auto lmdb_lock_file = std::string { gem_path } + "/address_table.mdb/lock.mdb"; - const auto lmdb_area_file = std::string { gem_path } + "/address_table.mdb"; + const std::string home_path = std::getenv("HOME"); + const std::string xml_address_table = home_path + "/etc/gem/gem_ctp7.xml"; + const std::string lmdb_data_file = home_path + "/var/gem/address_tables.mdb/data.mdb"; + const std::string lmdb_lock_file = home_path + "/var/gem/address_tables.mdb/lock.mdb"; + const std::string lmdb_area_file = home_path + "/var/gem/address_tables.mdb"; - auto parser = std::make_unique<xhal::common::utils::XHALXMLParser>(at_xml.data()); + auto parser = std::make_unique<xhal::common::utils::XHALXMLParser>(xml_address_table.data()); try { parser->setLogLevel(0); parser->parseXML(); @@ -180,10 +179,8 @@ void utils::init_lmdb() if (lmdb_handles) return; - const char* const gem_path = std::getenv("GEM_PATH"); - if (gem_path == nullptr) - throw std::runtime_error("The GEM_PATH environment variable must be defined."); - const auto lmdb_data_file = std::string { gem_path } + "/address_table.mdb"; + const std::string home_path = std::getenv("HOME"); + const std::string lmdb_data_file = home_path + "/var/gem/address_tables.mdb"; auto env = lmdb::env::create(); env.set_mapsize(utils::LMDB_SIZE); diff --git a/gemrpc/src/vfat3.cpp b/gemrpc/src/vfat3.cpp index 3c44342517ea3aa4b1032d9ad690321b69168b13..61b448ddea03dd95daf6973f90d6841e836c3c3d 100644 --- a/gemrpc/src/vfat3.cpp +++ b/gemrpc/src/vfat3.cpp @@ -175,7 +175,8 @@ void vfat3::configureVFAT3s::operator()(const uint16_t& ohN, const uint32_t& vfa LOG4CPLUS_INFO(logger, "Loading configuration settings"); for (size_t vfatN = 0; vfatN < oh::VFATS_PER_OH; ++vfatN) { if ((notmask >> vfatN) & 0x1) { - const std::string configFile = "/mnt/persistent/gempro/etc/gem/vfat/config_OH" + std::to_string(ohN) + "_VFAT" + std::to_string(vfatN) + ".cfg"; + const std::string home_path = std::getenv("HOME"); + const std::string configFile = home_path + "/etc/gem/vfat/config_OH" + std::to_string(ohN) + "_VFAT" + std::to_string(vfatN) + ".cfg"; std::ifstream infile(configFile); if (!infile.is_open()) { std::stringstream errmsg;