aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp')
-rw-r--r--host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp327
1 files changed, 177 insertions, 150 deletions
diff --git a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
index e030e6106..02a243b70 100644
--- a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
+++ b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
@@ -5,9 +5,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include "octoclock_impl.hpp"
#include "common.h"
-
+#include "octoclock_impl.hpp"
#include <uhd/device.hpp>
#include <uhd/image_loader.hpp>
#include <uhd/transport/udp_simple.hpp>
@@ -17,61 +16,63 @@
#include <uhd/utils/paths.hpp>
#include <uhd/utils/static.hpp>
#include <uhdlib/utils/ihex.hpp>
-
+#include <stdint.h>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
-
#include <algorithm>
-#include <iterator>
+#include <chrono>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
+#include <iterator>
#include <string>
-#include <chrono>
#include <thread>
-#include <stdint.h>
namespace fs = boost::filesystem;
using namespace uhd;
using namespace uhd::usrp_clock;
using namespace uhd::transport;
-#define OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES (1024*120) // Last 8 MB are for bootloader
-#define OCTOCLOCK_BLOCK_SIZE 256
+#define OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES (1024 * 120) // Last 8 MB are for bootloader
+#define OCTOCLOCK_BLOCK_SIZE 256
/*
* OctoClock burn session
*/
-typedef struct {
- bool found;
- uhd::device_addr_t dev_addr;
- std::string image_filepath;
- uint16_t crc;
- uint16_t num_blocks;
- uint32_t sequence;
- udp_simple::sptr ctrl_xport;
- udp_simple::sptr fw_xport;
- uint8_t data_in[udp_simple::mtu];
- uint32_t starting_firmware_version;
+typedef struct
+{
+ bool found;
+ uhd::device_addr_t dev_addr;
+ std::string image_filepath;
+ uint16_t crc;
+ uint16_t num_blocks;
+ uint32_t sequence;
+ udp_simple::sptr ctrl_xport;
+ udp_simple::sptr fw_xport;
+ uint8_t data_in[udp_simple::mtu];
+ uint32_t starting_firmware_version;
std::vector<uint8_t> image;
} octoclock_session_t;
-static void octoclock_calculate_crc(octoclock_session_t &session){
+static void octoclock_calculate_crc(octoclock_session_t& session)
+{
session.crc = 0xFFFF;
- for(size_t i = 0; i < session.image.size(); i++)
- {
+ for (size_t i = 0; i < session.image.size(); i++) {
session.crc ^= session.image[i];
- for(uint8_t j = 0; j < 8; ++j){
- if(session.crc & 1) session.crc = (session.crc >> 1) ^ 0xA001;
- else session.crc = (session.crc >> 1);
+ for (uint8_t j = 0; j < 8; ++j) {
+ if (session.crc & 1)
+ session.crc = (session.crc >> 1) ^ 0xA001;
+ else
+ session.crc = (session.crc >> 1);
}
}
}
-static void octoclock_read_bin(octoclock_session_t &session)
+static void octoclock_read_bin(octoclock_session_t& session)
{
- std::ifstream bin_file(session.image_filepath.c_str(), std::ios::in | std::ios::binary);
+ std::ifstream bin_file(
+ session.image_filepath.c_str(), std::ios::in | std::ios::binary);
if (not bin_file.is_open()) {
throw uhd::io_error("Could not read image file.");
}
@@ -80,183 +81,197 @@ static void octoclock_read_bin(octoclock_session_t &session)
session.image.clear();
session.image.resize(filesize);
bin_file.read((char*)&session.image[0], filesize);
- if(size_t(bin_file.gcount()) != filesize) {
+ if (size_t(bin_file.gcount()) != filesize) {
throw uhd::io_error("Failed to read firmware image.");
}
bin_file.close();
}
-static void octoclock_validate_firmware_image(octoclock_session_t &session){
- if(not fs::exists(session.image_filepath)){
+static void octoclock_validate_firmware_image(octoclock_session_t& session)
+{
+ if (not fs::exists(session.image_filepath)) {
throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\"")
% session.image_filepath));
}
std::string extension = fs::extension(session.image_filepath);
- if(extension == ".bin"){
+ if (extension == ".bin") {
octoclock_read_bin(session);
- }
- else if(extension == ".hex"){
+ } else if (extension == ".hex") {
ihex_reader hex_reader(session.image_filepath);
session.image = hex_reader.to_vector(OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES);
- }
- else throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin.")
- % extension));
-
- if(session.image.size() > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES){
- throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d")
- % session.image.size() % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES));
+ } else
+ throw uhd::runtime_error(
+ str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin.")
+ % extension));
+
+ if (session.image.size() > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES) {
+ throw uhd::runtime_error(
+ str(boost::format("The specified firmware image is too large: %d vs. %d")
+ % session.image.size() % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES));
}
session.num_blocks = (session.image.size() % OCTOCLOCK_BLOCK_SIZE)
- ? ((session.image.size() / OCTOCLOCK_BLOCK_SIZE) + 1)
- : (session.image.size() / OCTOCLOCK_BLOCK_SIZE);
+ ? ((session.image.size() / OCTOCLOCK_BLOCK_SIZE) + 1)
+ : (session.image.size() / OCTOCLOCK_BLOCK_SIZE);
octoclock_calculate_crc(session);
}
-static void octoclock_setup_session(octoclock_session_t &session,
- const uhd::device_addr_t &args,
- const std::string &filepath){
-
+static void octoclock_setup_session(octoclock_session_t& session,
+ const uhd::device_addr_t& args,
+ const std::string& filepath)
+{
// See if we can find an OctoClock with the given args
device_addrs_t devs = octoclock_find(args);
- if(devs.size() == 0){
+ if (devs.size() == 0) {
session.found = false;
return;
- }
- else if(devs.size() > 1){
- std::string err_msg = "Could not resolve given args to a single OctoClock device.\n"
- "Applicable devices:\n";
-
- for(const uhd::device_addr_t &dev: devs){
- std::string name = (dev["type"] == "octoclock") ? str(boost::format("OctoClock r%d")
- % dev.get("revision","4"))
- : "OctoClock Bootloader";
- err_msg += str(boost::format(" * %s (addr=%s)\n")
- % name
- % dev.get("addr"));
+ } else if (devs.size() > 1) {
+ std::string err_msg =
+ "Could not resolve given args to a single OctoClock device.\n"
+ "Applicable devices:\n";
+
+ for (const uhd::device_addr_t& dev : devs) {
+ std::string name =
+ (dev["type"] == "octoclock")
+ ? str(boost::format("OctoClock r%d") % dev.get("revision", "4"))
+ : "OctoClock Bootloader";
+ err_msg += str(boost::format(" * %s (addr=%s)\n") % name % dev.get("addr"));
}
- err_msg += "\nSpecify one of these devices with the given args to load an image onto it.";
+ err_msg += "\nSpecify one of these devices with the given args to load an image "
+ "onto it.";
throw uhd::runtime_error(err_msg);
}
session.dev_addr = devs[0];
- session.found = true;
+ session.found = true;
// If no filepath is given, use the default
- if(filepath == ""){
- session.image_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex")
- % session.dev_addr.get("revision","4")
- ));
- }
- else session.image_filepath = filepath;
+ if (filepath == "") {
+ session.image_filepath =
+ find_image_path(str(boost::format("octoclock_r%s_fw.hex")
+ % session.dev_addr.get("revision", "4")));
+ } else
+ session.image_filepath = filepath;
octoclock_validate_firmware_image(session);
- session.ctrl_xport = udp_simple::make_connected(session.dev_addr["addr"],
- BOOST_STRINGIZE(OCTOCLOCK_UDP_CTRL_PORT));
- session.fw_xport = udp_simple::make_connected(session.dev_addr["addr"],
- BOOST_STRINGIZE(OCTOCLOCK_UDP_FW_PORT));
+ session.ctrl_xport = udp_simple::make_connected(
+ session.dev_addr["addr"], BOOST_STRINGIZE(OCTOCLOCK_UDP_CTRL_PORT));
+ session.fw_xport = udp_simple::make_connected(
+ session.dev_addr["addr"], BOOST_STRINGIZE(OCTOCLOCK_UDP_FW_PORT));
// To avoid replicating sequence numbers between sessions
- session.sequence = uint32_t(std::rand());
+ session.sequence = uint32_t(std::rand());
// Query OctoClock again to get compat number
octoclock_packet_t pkt_out;
- const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
+ const octoclock_packet_t* pkt_in =
+ reinterpret_cast<const octoclock_packet_t*>(session.data_in);
size_t len = 0;
- UHD_OCTOCLOCK_SEND_AND_RECV(session.ctrl_xport, OCTOCLOCK_FW_COMPAT_NUM, OCTOCLOCK_QUERY_CMD, pkt_out, len, session.data_in);
- if(UHD_OCTOCLOCK_PACKET_MATCHES(OCTOCLOCK_QUERY_ACK, pkt_out, pkt_in, len)){
+ UHD_OCTOCLOCK_SEND_AND_RECV(session.ctrl_xport,
+ OCTOCLOCK_FW_COMPAT_NUM,
+ OCTOCLOCK_QUERY_CMD,
+ pkt_out,
+ len,
+ session.data_in);
+ if (UHD_OCTOCLOCK_PACKET_MATCHES(OCTOCLOCK_QUERY_ACK, pkt_out, pkt_in, len)) {
session.starting_firmware_version = uhd::htonx<uint32_t>(pkt_in->proto_ver);
} else {
throw uhd::runtime_error("Failed to communicate with OctoClock.");
}
}
-static void octoclock_reset_into_bootloader(octoclock_session_t &session){
-
+static void octoclock_reset_into_bootloader(octoclock_session_t& session)
+{
// Already in bootloader
- if(session.dev_addr["type"] == "octoclock-bootloader")
+ if (session.dev_addr["type"] == "octoclock-bootloader")
return;
// Force compat num to device's current, works around old firmware bug
octoclock_packet_t pkt_out;
- pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
+ pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
pkt_out.proto_ver = uhd::htonx<uint32_t>(session.starting_firmware_version);
- pkt_out.code = RESET_CMD;
+ pkt_out.code = RESET_CMD;
std::cout << " -- Resetting into bootloader..." << std::flush;
- session.ctrl_xport->send(boost::asio::buffer(&pkt_out, sizeof(octoclock_packet_t))); \
- size_t len = session.ctrl_xport->recv(boost::asio::buffer(session.data_in), 2);\
- const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
+ session.ctrl_xport->send(boost::asio::buffer(&pkt_out, sizeof(octoclock_packet_t)));
+ size_t len = session.ctrl_xport->recv(boost::asio::buffer(session.data_in), 2);
+ const octoclock_packet_t* pkt_in =
+ reinterpret_cast<const octoclock_packet_t*>(session.data_in);
- if(UHD_OCTOCLOCK_PACKET_MATCHES(RESET_ACK, pkt_out, pkt_in, len)){
+ if (UHD_OCTOCLOCK_PACKET_MATCHES(RESET_ACK, pkt_out, pkt_in, len)) {
// Make sure this device is now in its bootloader
std::this_thread::sleep_for(std::chrono::milliseconds(500));
uhd::device_addrs_t octoclocks = uhd::device::find(
- uhd::device_addr_t(str(boost::format("addr=%s")
- % session.dev_addr["addr"]
- )));
- if(octoclocks.size() == 0){
+ uhd::device_addr_t(str(boost::format("addr=%s") % session.dev_addr["addr"])));
+ if (octoclocks.size() == 0) {
std::cout << "failed." << std::endl;
throw uhd::runtime_error("Failed to reset OctoClock.");
- }
- else if(octoclocks[0]["type"] != "octoclock-bootloader"){
+ } else if (octoclocks[0]["type"] != "octoclock-bootloader") {
std::cout << "failed." << std::endl;
throw uhd::runtime_error("Failed to reset OctoClock.");
- }
- else{
+ } else {
std::cout << "successful." << std::endl;
session.dev_addr = octoclocks[0];
}
- }
- else{
+ } else {
std::cout << "failed." << std::endl;
throw uhd::runtime_error("Failed to reset OctoClock.");
}
}
-static void octoclock_burn(octoclock_session_t &session){
-
+static void octoclock_burn(octoclock_session_t& session)
+{
// Make sure we're in the bootloader for this
octoclock_reset_into_bootloader(session);
octoclock_packet_t pkt_out;
pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
- const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
+ const octoclock_packet_t* pkt_in =
+ reinterpret_cast<const octoclock_packet_t*>(session.data_in);
// Tell OctoClock to prepare for burn
pkt_out.len = htonx<uint16_t>(session.image.size());
- size_t len = 0;
+ size_t len = 0;
std::cout << " -- Preparing OctoClock for firmware load..." << std::flush;
pkt_out.len = session.image.size();
pkt_out.crc = session.crc;
- UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, OCTOCLOCK_FW_COMPAT_NUM, PREPARE_FW_BURN_CMD, pkt_out, len, session.data_in);
- if(UHD_OCTOCLOCK_PACKET_MATCHES(FW_BURN_READY_ACK, pkt_out, pkt_in, len)){
+ UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport,
+ OCTOCLOCK_FW_COMPAT_NUM,
+ PREPARE_FW_BURN_CMD,
+ pkt_out,
+ len,
+ session.data_in);
+ if (UHD_OCTOCLOCK_PACKET_MATCHES(FW_BURN_READY_ACK, pkt_out, pkt_in, len)) {
std::cout << "successful." << std::endl;
- }
- else{
+ } else {
std::cout << "failed." << std::endl;
throw uhd::runtime_error("Failed to prepare OctoClock for firmware load.");
}
// Start burning
- for(size_t i = 0; i < session.num_blocks; i++){
+ for (size_t i = 0; i < session.num_blocks; i++) {
pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
- pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE;
+ pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE;
std::cout << str(boost::format("\r -- Loading firmware: %d%% (%d/%d blocks)")
- % int((double(i)/double(session.num_blocks))*100)
- % i % session.num_blocks)
+ % int((double(i) / double(session.num_blocks)) * 100) % i
+ % session.num_blocks)
<< std::flush;
memset(pkt_out.data, 0, OCTOCLOCK_BLOCK_SIZE);
memcpy((char*)pkt_out.data, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE);
- UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, OCTOCLOCK_FW_COMPAT_NUM, FILE_TRANSFER_CMD, pkt_out, len, session.data_in);
- if(not UHD_OCTOCLOCK_PACKET_MATCHES(FILE_TRANSFER_ACK, pkt_out, pkt_in, len)){
+ UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport,
+ OCTOCLOCK_FW_COMPAT_NUM,
+ FILE_TRANSFER_CMD,
+ pkt_out,
+ len,
+ session.data_in);
+ if (not UHD_OCTOCLOCK_PACKET_MATCHES(FILE_TRANSFER_ACK, pkt_out, pkt_in, len)) {
std::cout << std::endl;
throw uhd::runtime_error("Failed to load firmware.");
}
@@ -267,36 +282,43 @@ static void octoclock_burn(octoclock_session_t &session){
<< std::endl;
}
-static void octoclock_verify(octoclock_session_t &session){
-
+static void octoclock_verify(octoclock_session_t& session)
+{
octoclock_packet_t pkt_out;
pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
- const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
+ const octoclock_packet_t* pkt_in =
+ reinterpret_cast<const octoclock_packet_t*>(session.data_in);
size_t len = 0;
uint8_t image_part[OCTOCLOCK_BLOCK_SIZE];
uint16_t cmp_len = 0;
- for(size_t i = 0; i < session.num_blocks; i++){
+ for (size_t i = 0; i < session.num_blocks; i++) {
pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
- pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE;
+ pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE;
- std::cout << str(boost::format("\r -- Verifying firmware load: %d%% (%d/%d blocks)")
- % int((double(i)/double(session.num_blocks))*100)
- % i % session.num_blocks)
+ std::cout << str(boost::format(
+ "\r -- Verifying firmware load: %d%% (%d/%d blocks)")
+ % int((double(i) / double(session.num_blocks)) * 100) % i
+ % session.num_blocks)
<< std::flush;
memset(image_part, 0, OCTOCLOCK_BLOCK_SIZE);
memcpy((char*)image_part, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE);
- cmp_len = std::min<size_t>(OCTOCLOCK_BLOCK_SIZE, session.image.size() - size_t(pkt_out.addr));
-
- UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, OCTOCLOCK_FW_COMPAT_NUM, READ_FW_CMD, pkt_out, len, session.data_in);
- if(UHD_OCTOCLOCK_PACKET_MATCHES(READ_FW_ACK, pkt_out, pkt_in, len)){
- if(memcmp(pkt_in->data, image_part, cmp_len)){
+ cmp_len = std::min<size_t>(
+ OCTOCLOCK_BLOCK_SIZE, session.image.size() - size_t(pkt_out.addr));
+
+ UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport,
+ OCTOCLOCK_FW_COMPAT_NUM,
+ READ_FW_CMD,
+ pkt_out,
+ len,
+ session.data_in);
+ if (UHD_OCTOCLOCK_PACKET_MATCHES(READ_FW_ACK, pkt_out, pkt_in, len)) {
+ if (memcmp(pkt_in->data, image_part, cmp_len)) {
std::cout << std::endl;
throw uhd::runtime_error("Failed to verify OctoClock firmware.");
}
- }
- else{
+ } else {
std::cout << std::endl;
throw uhd::runtime_error("Failed to verify OctoClock firmware.");
}
@@ -307,34 +329,38 @@ static void octoclock_verify(octoclock_session_t &session){
<< std::endl;
}
-static void octoclock_finalize(octoclock_session_t &session){
-
+static void octoclock_finalize(octoclock_session_t& session)
+{
octoclock_packet_t pkt_out;
pkt_out.sequence = uhd::htonx<uint32_t>(++session.sequence);
- const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
+ const octoclock_packet_t* pkt_in =
+ reinterpret_cast<const octoclock_packet_t*>(session.data_in);
size_t len = 0;
std::cout << " -- Finalizing firmware load..." << std::flush;
- UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, OCTOCLOCK_FW_COMPAT_NUM, FINALIZE_BURNING_CMD, pkt_out, len, session.data_in);
- if(UHD_OCTOCLOCK_PACKET_MATCHES(FINALIZE_BURNING_ACK, pkt_out, pkt_in, len)){
+ UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport,
+ OCTOCLOCK_FW_COMPAT_NUM,
+ FINALIZE_BURNING_CMD,
+ pkt_out,
+ len,
+ session.data_in);
+ if (UHD_OCTOCLOCK_PACKET_MATCHES(FINALIZE_BURNING_ACK, pkt_out, pkt_in, len)) {
std::cout << "successful." << std::endl;
- }
- else{
+ } else {
std::cout << "failed." << std::endl;
throw uhd::runtime_error("Failed to finalize OctoClock firmware load.");
}
}
-bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loader_args){
+bool octoclock_image_loader(const image_loader::image_loader_args_t& image_loader_args)
+{
octoclock_session_t session;
- octoclock_setup_session(session,
- image_loader_args.args,
- image_loader_args.firmware_path
- );
- if(!session.found or !image_loader_args.load_firmware) return false;
-
- std::cout << boost::format("Unit: OctoClock (%s)")
- % session.dev_addr["addr"]
+ octoclock_setup_session(
+ session, image_loader_args.args, image_loader_args.firmware_path);
+ if (!session.found or !image_loader_args.load_firmware)
+ return false;
+
+ std::cout << boost::format("Unit: OctoClock (%s)") % session.dev_addr["addr"]
<< std::endl;
std::cout << "Firmware: " << session.image_filepath << std::endl;
@@ -345,14 +371,15 @@ bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loade
return true;
}
-UHD_STATIC_BLOCK(register_octoclock_image_loader){
- std::string recovery_instructions = "Aborting. Your OctoClock firmware is now corrupt. The bootloader\n"
- "is functional, but the device will not have functional clock distribution.\n"
- "Run this utility again to restore functionality or refer to:\n\n"
- "http://files.ettus.com/manual/page_octoclock.html\n\n"
- "for alternative setups.";
-
- image_loader::register_image_loader("octoclock",
- octoclock_image_loader,
- recovery_instructions);
+UHD_STATIC_BLOCK(register_octoclock_image_loader)
+{
+ std::string recovery_instructions =
+ "Aborting. Your OctoClock firmware is now corrupt. The bootloader\n"
+ "is functional, but the device will not have functional clock distribution.\n"
+ "Run this utility again to restore functionality or refer to:\n\n"
+ "http://files.ettus.com/manual/page_octoclock.html\n\n"
+ "for alternative setups.";
+
+ image_loader::register_image_loader(
+ "octoclock", octoclock_image_loader, recovery_instructions);
}