From 7a0a5f8085d2469f0b5501c1969dd6ce63d5756e Mon Sep 17 00:00:00 2001 From: Grant Meyerhoff Date: Fri, 7 Aug 2026 10:02:42 -0500 Subject: [PATCH] b300: search for FPGA images if not provided --- host/lib/usrp/b300/b300_image_loader.cpp | 51 ++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/host/lib/usrp/b300/b300_image_loader.cpp b/host/lib/usrp/b300/b300_image_loader.cpp index 860030715..1208cd115 100644 --- a/host/lib/usrp/b300/b300_image_loader.cpp +++ b/host/lib/usrp/b300/b300_image_loader.cpp @@ -13,14 +13,20 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include +namespace { +constexpr const char* DEFAULT_FPGA_TYPE = "replay"; +} + namespace uhd { namespace usrp { namespace b300 { static const uint32_t READ_DATA_DATA_VALID = (1 << 31); @@ -682,10 +688,47 @@ static bool b300_image_loader(const image_loader::image_loader_args_t& image_loa if (devs.empty()) return false; + else if (devs.size() > 1) { + std::string err_msg = + "Could not resolve given args to a single B3xx-Series device.\n" + "Applicable devices:\n"; - if (not std::filesystem::exists(image_loader_args.fpga_path)) { - throw uhd::runtime_error( - "Could not find image at path " + image_loader_args.fpga_path); + for (const uhd::device_addr_t& dev : devs) { + err_msg += " * " + dev.get("product", "b3xx") + + " (resource=" + dev.get("resource") + ")\n"; + } + + err_msg += "\nSpecify one of these devices with the given args to load an image " + "onto it."; + + throw uhd::runtime_error(err_msg); + } + + std::string fpga_path_to_program = image_loader_args.fpga_path; + + if (!image_loader_args.fpga_path.empty()) { + if (not std::filesystem::exists(image_loader_args.fpga_path)) { + throw uhd::runtime_error( + "Could not find image at path " + image_loader_args.fpga_path); + } + } else { + std::string product_name = devs[0].get("product", "UNKNOWN"); + std::transform(product_name.begin(), + product_name.end(), + product_name.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + + if (product_name == "unknown") { + throw uhd::runtime_error( + "Could not determine product name for the device. " + "Please either ensure the mb eeprom is programmed correctly " + "using the usrp_burn_mb_eeprom utility, or provide the FPGA path to " + "program explicitly with the '--fpga-path' argument."); + } + + fpga_path_to_program = uhd::find_image_path( + "usrp_" + product_name + "_fpga_" + + image_loader_args.args.get("fpga", DEFAULT_FPGA_TYPE) + ".bit"); } for (size_t i = 0; i < devs.size(); ++i) { @@ -696,7 +739,7 @@ static bool b300_image_loader(const image_loader::image_loader_args_t& image_loa b300_image_loader_helper image_loader_helper( [pcie_mgr](uint32_t addr) { return pcie_mgr->peek32(addr); }, [pcie_mgr](uint32_t addr, uint32_t value) { pcie_mgr->poke32(addr, value); }); - image_loader_helper.writeBinToFlash(image_loader_args.fpga_path); + image_loader_helper.writeBinToFlash(fpga_path_to_program); } return true;