/* * Ethernet communication functions */ static UHD_INLINE size_t x300_send_and_recv(udp_simple::sptr xport, uint32_t pkt_code, x300_fpga_update_data_t *pkt_out, uint8_t* data){ pkt_out->flags = uhd::htonx<uint32_t>(pkt_code); xport->send(boost::asio::buffer(pkt_out, sizeof(*pkt_out))); return xport->recv(boost::asio::buffer(data, udp_simple::mtu), UDP_TIMEOUT); }
void erase_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint32_t memory_size){ //Making sure this won't attempt to erase past end of device if(is_fw){ if(PROD_FW_IMAGE_LOCATION_ADDR+FW_IMAGE_SIZE_BYTES > memory_size) throw std::runtime_error("Cannot erase past end of device."); } else{ if(PROD_FPGA_IMAGE_LOCATION_ADDR+FPGA_IMAGE_SIZE_BYTES > memory_size) throw std::runtime_error("Cannot erase past end of device."); } //Setting up UDP transport boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu]; const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t erase_pkt = usrp2_fw_update_data_t(); erase_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL); erase_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); if(is_fw){ erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(PROD_FW_IMAGE_LOCATION_ADDR); erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(FW_IMAGE_SIZE_BYTES); } else{ erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(PROD_FPGA_IMAGE_LOCATION_ADDR); erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(FPGA_IMAGE_SIZE_BYTES); } //Begin erasing udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG){ if(is_fw) std::cout << "Erasing firmware image." << std::endl; else std::cout << "Erasing FPGA image." << std::endl; } else if(ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG){ throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id))); } //Check for erase completion erase_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL); while(true){ udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG){ if(is_fw) std::cout << boost::format(" * Successfully erased %d bytes at %d.\n") % FW_IMAGE_SIZE_BYTES % PROD_FW_IMAGE_LOCATION_ADDR; else std::cout << boost::format(" * Successfully erased %d bytes at %d.\n") % FPGA_IMAGE_SIZE_BYTES % PROD_FPGA_IMAGE_LOCATION_ADDR; break; } else if(ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG){ throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id))); } } }
void erase_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint32_t memory_size, bool overwrite_safe) { boost::uint32_t image_location_addr = is_fw ? overwrite_safe ? SAFE_FW_IMAGE_LOCATION_ADDR : PROD_FW_IMAGE_LOCATION_ADDR : overwrite_safe ? SAFE_FPGA_IMAGE_LOCATION_ADDR : PROD_FPGA_IMAGE_LOCATION_ADDR; boost::uint32_t image_size = is_fw ? FW_IMAGE_SIZE_BYTES : FPGA_IMAGE_SIZE_BYTES; //Making sure this won't attempt to erase past end of device if((image_location_addr+image_size) > memory_size) throw std::runtime_error("Cannot erase past end of device."); //UDP receive buffer const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t erase_pkt = usrp2_fw_update_data_t(); erase_pkt.id = htonx<boost::uint32_t>(ERASE_FLASH_CMD); erase_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(image_location_addr); erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(image_size); //Begin erasing udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == ERASE_FLASH_ACK) { if(is_fw) std::cout << "Erasing firmware image." << std::endl; else std::cout << "Erasing FPGA image." << std::endl; } else if(ntohl(update_data_in->id) != ERASE_FLASH_ACK) { throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id))); } //Check for erase completion erase_pkt.id = htonx<boost::uint32_t>(CHECK_ERASING_DONE_CMD); while(true) { udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == DONE_ERASING_ACK) { std::cout << boost::format(" * Successfully erased %d bytes at %d.\n") % image_size % image_location_addr; break; } else if(ntohl(update_data_in->id) != NOT_DONE_ERASING_ACK) { throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id))); } } }
void verify_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size, bool overwrite_safe) { int current_index = 0; boost::uint32_t begin_addr = is_fw ? overwrite_safe ? SAFE_FW_IMAGE_LOCATION_ADDR : PROD_FW_IMAGE_LOCATION_ADDR : overwrite_safe ? SAFE_FPGA_IMAGE_LOCATION_ADDR : PROD_FPGA_IMAGE_LOCATION_ADDR; boost::uint32_t current_addr = begin_addr; std::string type = is_fw ? "firmware" : "FPGA"; //Array size needs to be known at runtime, this constant is guaranteed to be larger than any firmware or FPGA image boost::uint8_t from_usrp[FPGA_IMAGE_SIZE_BYTES]; //Making sure this won't attempt to read past end of device if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot read past end of device."); //UDP receive buffer const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t verify_pkt = usrp2_fw_update_data_t(); verify_pkt.id = htonx<boost::uint32_t>(READ_FLASH_CMD); verify_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); verify_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE); for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++) { //Print progress std::cout << "\rVerifying " << type << " image (" << int((double(current_addr-begin_addr)/double(image_size))*100) << "%)." << std::flush; verify_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr); udp_transport->send(boost::asio::buffer(&verify_pkt, sizeof(verify_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != READ_FLASH_ACK) { throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id))); } for(int j = 0; j < FLASH_DATA_PACKET_SIZE; j++) from_usrp[current_index+j] = update_data_in->data.flash_args.data[j]; current_addr += FLASH_DATA_PACKET_SIZE; current_index += FLASH_DATA_PACKET_SIZE; } for(int i = 0; i < image_size; i++) if(from_usrp[i] != image[i]) throw std::runtime_error("Image write failed."); std::cout << std::flush << "\rVerifying " << type << " image (100%)." << std::endl; std::cout << " * Successful." << std::endl; }
void reset_usrp(udp_simple::sptr udp_transport){ //Set up UDP transport const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Set up UDP packet usrp2_fw_update_data_t reset_pkt = usrp2_fw_update_data_t(); reset_pkt.id = htonx<boost::uint32_t>(RESET_USRP_CMD); reset_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); //Reset USRP udp_transport->send(boost::asio::buffer(&reset_pkt, sizeof(reset_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == RESET_USRP_ACK){ throw std::runtime_error("USRP reset failed."); //There should be no response to this UDP packet } else std::cout << std::endl << "Resetting USRP." << std::endl; }
void verify_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size){ int current_index = 0; boost::uint32_t current_addr; if(is_fw) current_addr = PROD_FW_IMAGE_LOCATION_ADDR; else current_addr = PROD_FPGA_IMAGE_LOCATION_ADDR; //Array size needs to be known at runtime, this constant is guaranteed to be larger than any firmware or FPGA image boost::uint8_t from_usrp[FPGA_IMAGE_SIZE_BYTES]; //Making sure this won't attempt to read past end of device if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot read past end of device."); //Setting up UDP transport boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu]; const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t verify_pkt = usrp2_fw_update_data_t(); verify_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL); verify_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); verify_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE); //Verify image if(is_fw) std::cout << "Verifying firmware image." << std::endl; else std::cout << "Verifying FPGA image." << std::endl; for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++){ verify_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr); udp_transport->send(boost::asio::buffer(&verify_pkt, sizeof(verify_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG){ throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id))); } for(int j = 0; j < FLASH_DATA_PACKET_SIZE; j++) from_usrp[current_index+j] = update_data_in->data.flash_args.data[j]; current_addr += FLASH_DATA_PACKET_SIZE; current_index += FLASH_DATA_PACKET_SIZE; } for(int i = 0; i < image_size; i++) if(from_usrp[i] != image[i]) throw std::runtime_error("Image write failed."); std::cout << " * Successful." << std::endl; }
void write_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size, bool overwrite_safe) { boost::uint32_t begin_addr = is_fw ? overwrite_safe ? SAFE_FW_IMAGE_LOCATION_ADDR : PROD_FW_IMAGE_LOCATION_ADDR : overwrite_safe ? SAFE_FPGA_IMAGE_LOCATION_ADDR : PROD_FPGA_IMAGE_LOCATION_ADDR; boost::uint32_t current_addr = begin_addr; std::string type = is_fw ? "firmware" : "FPGA"; //Making sure this won't attempt to write past end of device if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot write past end of device."); //UDP receive buffer const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t write_pkt = usrp2_fw_update_data_t(); write_pkt.id = htonx<boost::uint32_t>(WRITE_FLASH_CMD); write_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); write_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE); for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++) { //Print progress std::cout << "\rWriting " << type << " image (" << int((double(current_addr-begin_addr)/double(image_size))*100) << "%)." << std::flush; write_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr); std::copy(image+(i*FLASH_DATA_PACKET_SIZE), image+((i+1)*FLASH_DATA_PACKET_SIZE), write_pkt.data.flash_args.data); udp_transport->send(boost::asio::buffer(&write_pkt, sizeof(write_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != WRITE_FLASH_ACK) { throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id))); } current_addr += FLASH_DATA_PACKET_SIZE; } std::cout << std::flush << "\rWriting " << type << " image (100%)." << std::endl; std::cout << boost::format(" * Successfully wrote %d bytes.\n") % image_size; }
/*********************************************************************** * Find USRP N2XX with specified IP address and return type **********************************************************************/ boost::uint32_t find_usrp(udp_simple::sptr udp_transport, bool check_rev) { boost::uint32_t hw_rev; bool found_it = false; // If the user chooses to not care about the rev, simply check // for the presence of a USRP N2XX. boost::uint32_t cmd_id = (check_rev) ? GET_HW_REV_CMD : USRP2_QUERY; boost::uint32_t ack_id = (check_rev) ? GET_HW_REV_ACK : USRP2_ACK; const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); usrp2_fw_update_data_t hw_info_pkt = usrp2_fw_update_data_t(); hw_info_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); hw_info_pkt.id = htonx<boost::uint32_t>(cmd_id); udp_transport->send(boost::asio::buffer(&hw_info_pkt, sizeof(hw_info_pkt))); //Loop and receive until the timeout size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == ack_id) { hw_rev = ntohl(update_data_in->data.hw_rev); if(filename_map.has_key(hw_rev)) { std::cout << boost::format("Found %s.\n\n") % filename_map[hw_rev]; found_it = true; } else { if(check_rev) throw std::runtime_error("Invalid revision found."); else { hw_rev = 0; std::cout << "Found USRP N2XX." << std::endl; found_it = true; } } } if(not found_it) throw std::runtime_error("No USRP N2XX found."); return hw_rev; }
void write_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size){ boost::uint32_t current_addr; if(is_fw) current_addr = PROD_FW_IMAGE_LOCATION_ADDR; else current_addr = PROD_FPGA_IMAGE_LOCATION_ADDR; //Making sure this won't attempt to write past end of device if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot write past end of device."); //Setting up UDP transport boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu]; const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); //Setting up UDP packet usrp2_fw_update_data_t write_pkt = usrp2_fw_update_data_t(); write_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL); write_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); write_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE); //Write image if(is_fw) std::cout << "Writing firmware image." << std::endl; else std::cout << "Writing FPGA image." << std::endl; for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++){ write_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr); std::copy(image+(i*FLASH_DATA_PACKET_SIZE), image+((i+1)*FLASH_DATA_PACKET_SIZE), write_pkt.data.flash_args.data); udp_transport->send(boost::asio::buffer(&write_pkt, sizeof(write_pkt))); size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG){ throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id))); } current_addr += FLASH_DATA_PACKET_SIZE; } std::cout << boost::format(" * Successfully wrote %d bytes.\n") % image_size; }
/*********************************************************************** * Find USRP N2XX with specified IP address and return type **********************************************************************/ boost::uint32_t find_usrp(udp_simple::sptr udp_transport){ boost::uint32_t hw_rev; bool found_it = false; const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem); usrp2_fw_update_data_t hw_info_pkt = usrp2_fw_update_data_t(); hw_info_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION); hw_info_pkt.id = htonx<boost::uint32_t>(GET_HW_REV_CMD); udp_transport->send(boost::asio::buffer(&hw_info_pkt, sizeof(hw_info_pkt))); //Loop and receive until the timeout size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT); if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == GET_HW_REV_ACK){ hw_rev = ntohl(update_data_in->data.hw_rev); if(filename_map.has_key(hw_rev)){ std::cout << boost::format("Found %s.\n\n") % filename_map[hw_rev]; found_it = true; } else throw std::runtime_error("Invalid revision found."); } if(not found_it) throw std::runtime_error("No USRP N2XX found."); return hw_rev; }