diff options
-rw-r--r-- | host/include/uhd/image_loader.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_image_loader.cpp | 192 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_prop_tree.cpp | 18 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/rpc_server.py | 5 |
4 files changed, 135 insertions, 82 deletions
diff --git a/host/include/uhd/image_loader.hpp b/host/include/uhd/image_loader.hpp index b941463cd..c451b2851 100644 --- a/host/include/uhd/image_loader.hpp +++ b/host/include/uhd/image_loader.hpp @@ -31,6 +31,8 @@ public: std::string id; std::vector<uint8_t> component; uhd::dict<std::string, std::string> metadata; + bool delay_reload = false; + bool just_reload = false; } image_loader_args_t; //! Signature of an image loading function diff --git a/host/lib/usrp/mpmd/mpmd_image_loader.cpp b/host/lib/usrp/mpmd/mpmd_image_loader.cpp index 3a285da3e..a44ca7713 100644 --- a/host/lib/usrp/mpmd/mpmd_image_loader.cpp +++ b/host/lib/usrp/mpmd/mpmd_image_loader.cpp @@ -122,91 +122,123 @@ static bool mpmd_image_loader(const image_loader::image_loader_args_t& image_loa // Generate the component files uhd::usrp::component_files_t all_component_files; - // check if a component was provided - if (not image_loader_args.id.empty() && not image_loader_args.component.empty()) { - uhd::usrp::component_file_t component = generate_component(image_loader_args.id, - image_loader_args.component, - image_loader_args.metadata); - all_component_files.push_back(component); + // Determine if we need to just reload the currently-loaded components. + // Typically called after doing delayed reload. + if (image_loader_args.just_reload) { + UHD_LOG_TRACE("MPMD IMAGE LOADER", + "Just reloading components. Creating stub components for reset operation."); + uhd::usrp::component_file_t comp_fpga_stub; + comp_fpga_stub.metadata["id"] = "fpga"; + // Set the "just_reload" field to force a MPM reset leading to + // component reload. + comp_fpga_stub.metadata["just_reload"] = "true"; + + all_component_files.push_back(comp_fpga_stub); } else { - // FPGA component struct - const auto fpga_path = [image_loader_args, dev_addr, tree]() -> std::string { - // If the user provided a path to an fpga image, use that - if (not image_loader_args.fpga_path.empty()) { - if (boost::filesystem::exists(image_loader_args.fpga_path)) { - return image_loader_args.fpga_path; - } else { - throw uhd::runtime_error( - str(boost::format("FPGA file provided does not exist: %s") - % image_loader_args.fpga_path)); - } - } - // Otherwise, we need to generate one - else { - /* - * The user can specify an FPGA type (HG, XG, AA), rather than a filename. - * If the user does not specify one, this will default to the type - * currently on the device. If this cannot be determined, then the user is - * forced to specify a filename. - */ - const auto fpga_type = [image_loader_args, tree]() -> std::string { - // If the user didn't provide a type, use the type of currently loaded - // image on the device - if (image_loader_args.args.has_key("fpga")) { - return image_loader_args.args.get("fpga"); - } else if (tree->exists("/mboards/0/components/fpga")) { - // Pull the FPGA info from the property tree - // The getter should return a vector of a single component_file_t, - // so grab the metadata from that - auto fpga_metadata = tree->access<uhd::usrp::component_files_t>( - "/mboards/0/components/fpga") - .get()[0] - .metadata; - return fpga_metadata.get("type", ""); - // TODO: Do we want to pull the type from the filename if its not - // available in the metadata directly? + // check if a component was provided + if (not image_loader_args.id.empty() && not image_loader_args.component.empty()) { + uhd::usrp::component_file_t component = + generate_component(image_loader_args.id, + image_loader_args.component, + image_loader_args.metadata); + all_component_files.push_back(component); + } else { + // Determine if we need to delay the reload of fpga/dts components. + bool delay_reload = image_loader_args.delay_reload; + UHD_LOG_TRACE( + "MPMD IMAGE LOADER", "Delay reload?: " << (delay_reload ? "Yes" : "No")); + + // FPGA component struct + const auto fpga_path = [image_loader_args, dev_addr, tree]() -> std::string { + // If the user provided a path to an fpga image, use that + if (not image_loader_args.fpga_path.empty()) { + if (boost::filesystem::exists(image_loader_args.fpga_path)) { + return image_loader_args.fpga_path; + } else { + throw uhd::runtime_error( + str(boost::format("FPGA file provided does not exist: %s") + % image_loader_args.fpga_path)); } - return ""; - }(); // generate_fpga_type lambda function - UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA type: " << fpga_type); - - if (!dev_addr.has_key("product")) { - throw uhd::runtime_error( - "Found a device but could not auto-generate an image filename."); - } else if (fpga_type == "") { - return find_image_path( - str(boost::format("usrp_%s_fpga.bit") + } + // Otherwise, we need to generate one + else { + /* + * The user can specify an FPGA type (HG, XG, AA), rather than a + * filename. If the user does not specify one, this will default to + * the type currently on the device. If this cannot be determined, + * then the user is forced to specify a filename. + */ + const auto fpga_type = [image_loader_args, tree]() -> std::string { + // If the user didn't provide a type, use the type of currently + // loaded image on the device + if (image_loader_args.args.has_key("fpga")) { + return image_loader_args.args.get("fpga"); + } else if (tree->exists("/mboards/0/components/fpga")) { + // Pull the FPGA info from the property tree + // The getter should return a vector of a single + // component_file_t, so grab the metadata from that + auto fpga_metadata = + tree->access<uhd::usrp::component_files_t>( + "/mboards/0/components/fpga") + .get()[0] + .metadata; + return fpga_metadata.get("type", ""); + // TODO: Do we want to pull the type from the filename if its + // not available in the metadata directly? + } + return ""; + }(); // generate_fpga_type lambda function + UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA type: " << fpga_type); + + if (!dev_addr.has_key("product")) { + throw uhd::runtime_error("Found a device but could not " + "auto-generate an image filename."); + } else if (fpga_type == "") { + return find_image_path(str( + boost::format("usrp_%s_fpga.bit") % (boost::algorithm::to_lower_copy(dev_addr["product"])))); - } else { - return find_image_path( - str(boost::format("usrp_%s_fpga_%s.bit") - % (boost::algorithm::to_lower_copy(dev_addr["product"])) - % fpga_type)); + } else { + return find_image_path( + str(boost::format("usrp_%s_fpga_%s.bit") + % (boost::algorithm::to_lower_copy(dev_addr["product"])) + % fpga_type)); + } } + }(); // generate_fpga_path lambda function + UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA path: " << fpga_path); + uhd::usrp::component_file_t comp_fpga = generate_component("fpga", fpga_path); + // If we want to delay the image reloading, explicitly turn off the + // component reset flag + if (delay_reload) { + comp_fpga.metadata.set("reset", "false"); + } + all_component_files.push_back(comp_fpga); + // DTS component struct + // First, we need to determine the name + const std::string base_name = + boost::filesystem::change_extension(fpga_path, "").string(); + if (base_name == fpga_path) { + const std::string err_msg( + "Can't cut extension from FPGA filename... " + fpga_path); + throw uhd::runtime_error(err_msg); + } + const std::string dts_path = base_name + ".dts"; + // Then try to generate it + try { + uhd::usrp::component_file_t comp_dts = + generate_component("dts", dts_path); + // If we want to delay the image reloading, explicitly turn off the + // component reset flag + if (delay_reload) { + comp_dts.metadata.set("reset", "false"); + } + all_component_files.push_back(comp_dts); + UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA and DTS images read from file."); + } catch (const uhd::runtime_error& ex) { + // If we can't find the DTS file, that's fine, continue without it + UHD_LOG_WARNING("MPMD IMAGE LOADER", ex.what()); + UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA images read from file."); } - }(); // generate_fpga_path lambda function - UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA path: " << fpga_path); - uhd::usrp::component_file_t comp_fpga = generate_component("fpga", fpga_path); - all_component_files.push_back(comp_fpga); - // DTS component struct - // First, we need to determine the name - const std::string base_name = - boost::filesystem::change_extension(fpga_path, "").string(); - if (base_name == fpga_path) { - const std::string err_msg( - "Can't cut extension from FPGA filename... " + fpga_path); - throw uhd::runtime_error(err_msg); - } - const std::string dts_path = base_name + ".dts"; - // Then try to generate it - try { - uhd::usrp::component_file_t comp_dts = generate_component("dts", dts_path); - all_component_files.push_back(comp_dts); - UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA and DTS images read from file."); - } catch (const uhd::runtime_error& ex) { - // If we can't find the DTS file, that's fine, continue without it - UHD_LOG_WARNING("MPMD IMAGE LOADER", ex.what()); - UHD_LOG_TRACE("MPMD IMAGE LOADER", "FPGA images read from file."); } } // Call RPC to update the component diff --git a/host/lib/usrp/mpmd/mpmd_prop_tree.cpp b/host/lib/usrp/mpmd/mpmd_prop_tree.cpp index 556e2e48d..2bd955194 100644 --- a/host/lib/usrp/mpmd/mpmd_prop_tree.cpp +++ b/host/lib/usrp/mpmd/mpmd_prop_tree.cpp @@ -13,6 +13,8 @@ #include <uhd/types/eeprom.hpp> #include <uhd/types/sensors.hpp> #include <uhd/usrp/mboard_eeprom.hpp> +#include <uhd/utils/cast.hpp> +#include <boost/algorithm/string/case_conv.hpp> using namespace uhd; using namespace uhd::mpmd; @@ -34,6 +36,7 @@ uhd::usrp::component_files_t _update_component( // Also construct a copy of just the metadata to store in the property tree uhd::usrp::component_files_t all_comps_copy; + bool just_reload = false; for (const auto& comp : comps) { // Make a map for update components args std::map<std::string, std::string> metadata; @@ -43,6 +46,12 @@ uhd::usrp::component_files_t _update_component( for (const auto& key : comp.metadata.keys()) { metadata[key] = comp.metadata[key]; comp_copy.metadata[key] = comp.metadata[key]; + if (key == "just_reload") { + just_reload = + just_reload + | uhd::cast::from_str<bool>(metadata.at("just_reload")); + //| (boost::to_lower_copy(metadata.at("just_reload")) == "true"); + } } // Copy to the update component args all_data.push_back(comp.data); @@ -51,6 +60,15 @@ uhd::usrp::component_files_t _update_component( all_comps_copy.push_back(comp_copy); } + // If reset is specified we presume that the fpga/dts + // components were updated in the last uhd::image_loader::load() + // call and just reload the fpga/dts by resetting the peripheral + // manager. + if (just_reload) { + mb->rpc->notify_with_token(MPMD_DEFAULT_INIT_TIMEOUT, "reset_timer_and_mgr"); + return all_comps_copy; + } + // Now call update component mb->rpc->notify_with_token( MPMD_DEFAULT_INIT_TIMEOUT, "update_component", all_metadata, all_data); diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py index 7fc292215..262bedb6c 100644 --- a/mpm/python/usrp_mpm/rpc_server.py +++ b/mpm/python/usrp_mpm/rpc_server.py @@ -531,8 +531,9 @@ class MPMServer(RPCServer): component_id = metadata['id'] if component_id in self.periph_manager.updateable_components: # Check if that updating that component means the PM should be reset - if self.periph_manager.updateable_components[component_id]['reset']: - reset_now = True + reset_now = (reset_now or + self.periph_manager.updateable_components[component_id]['reset']) and \ + not metadata.get('reset', "").lower() == "false" else: self.log.debug("ID {} not in updateable components ({})".format( component_id, self.periph_manager.updateable_components)) |