From ade9550ea2e7ba3ab03fc47354d1939e269d3405 Mon Sep 17 00:00:00 2001 From: Nav Date: Mon, 22 Nov 2021 23:05:46 +0000 Subject: [PATCH] New Xplained Pro debug tool driver --- CMakeLists.txt | 1 + src/DebugToolDrivers/DebugTools.hpp | 1 + .../Microchip/XplainedPro/XplainedPro.cpp | 85 +++++++++++++++++++ .../Microchip/XplainedPro/XplainedPro.hpp | 74 ++++++++++++++++ src/TargetController/TargetController.hpp | 6 ++ 5 files changed, 167 insertions(+) create mode 100644 src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp create mode 100644 src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bf0335e5..d4c367d2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ add_executable(Bloom src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.cpp src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.cpp src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.cpp + src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.cpp src/DebugToolDrivers/Protocols/CMSIS-DAP/Response.cpp src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrCommand.cpp diff --git a/src/DebugToolDrivers/DebugTools.hpp b/src/DebugToolDrivers/DebugTools.hpp index fd0216f1..83f5c754 100644 --- a/src/DebugToolDrivers/DebugTools.hpp +++ b/src/DebugToolDrivers/DebugTools.hpp @@ -4,3 +4,4 @@ #include "src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.hpp" #include "src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.hpp" #include "src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.hpp" +#include "src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp" diff --git a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp new file mode 100644 index 00000000..f9c644fd --- /dev/null +++ b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp @@ -0,0 +1,85 @@ +#include "XplainedPro.hpp" + +#include "src/TargetController/Exceptions/DeviceFailure.hpp" +#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp" + +using namespace Bloom::DebugToolDrivers; +using namespace Protocols::CmsisDap::Edbg::Avr; +using namespace Bloom::Exceptions; + +void XplainedPro::init() { + UsbDevice::init(); + + // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number + auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); + usbHidInterface.setNumber(0); + usbHidInterface.setLibUsbDevice(this->libUsbDevice); + usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); + usbHidInterface.setVendorId(this->vendorId); + usbHidInterface.setProductId(this->productId); + + if (!usbHidInterface.isInitialised()) { + usbHidInterface.detachKernelDriver(); + usbHidInterface.init(); + } + + this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + + if (!this->sessionStarted) { + this->startSession(); + } + + this->edbgAvr8Interface = std::make_unique(this->edbgInterface); + + this->setInitialised(true); +} + +void XplainedPro::close() { + if (this->sessionStarted) { + this->endSession(); + } + + this->getEdbgInterface().getUsbHidInterface().close(); + UsbDevice::close(); +} + +std::string XplainedPro::getSerialNumber() { + auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER) + ); + + if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) { + throw DeviceInitializationFailure( + "Failed to fetch serial number from device - invalid Discovery Protocol response ID." + ); + } + + auto data = response.getPayloadData(); + return std::string(data.begin(), data.end()); +} + +void XplainedPro::startSession() { + auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + CommandFrames::HouseKeeping::StartSession() + ); + + if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) { + // Failed response returned! + throw DeviceInitializationFailure("Failed to start session with Xplained Pro!"); + } + + this->sessionStarted = true; +} + +void XplainedPro::endSession() { + auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + CommandFrames::HouseKeeping::EndSession() + ); + + if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) { + // Failed response returned! + throw DeviceFailure("Failed to end session with Xplained Pro!"); + } + + this->sessionStarted = false; +} diff --git a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp new file mode 100644 index 00000000..3febf401 --- /dev/null +++ b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +#include "src/DebugToolDrivers/DebugTool.hpp" +#include "src/DebugToolDrivers/USB/UsbDevice.hpp" +#include "src/DebugToolDrivers/USB/HID/HidInterface.hpp" +#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.hpp" +#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.hpp" +#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp" +#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/AvrCommandFrames.hpp" + +namespace Bloom::DebugToolDrivers +{ + /** + * The Xplained Pro is an evaluation board featuring an on-board debugger. The debugger is EDBG-based. + * + * Because the on-board debugger is EDBG-based, we can employ the same AVR8 driver implementation as we do with + * other EDBG-based debuggers. See the EdbgAvr8Interface class for more. + * + * USB Setup: + * Vendor ID: 0x03eb (1003) + * Product ID: 0x2111 (8465) + */ + class XplainedPro: public DebugTool, public Usb::UsbDevice + { + public: + static const std::uint16_t USB_VENDOR_ID = 1003; + static const std::uint16_t USB_PRODUCT_ID = 8465; + + XplainedPro(): UsbDevice(XplainedPro::USB_VENDOR_ID, XplainedPro::USB_PRODUCT_ID) {} + + void init() override; + + void close() override; + + Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { + return this->edbgInterface; + } + + TargetInterfaces::Microchip::Avr::Avr8::Avr8Interface* getAvr8Interface() override { + return this->edbgAvr8Interface.get(); + } + + std::string getName() override { + return "Xplained Pro"; + }; + + /** + * Retrieves the device serial number via the Discovery Protocol. + * + * @return + */ + std::string getSerialNumber() override; + + /** + * Starts a session with the EDBG-based tool using the Housekeeping protocol. + */ + void startSession(); + + /** + * Ends the active session with the debug tool. + */ + void endSession(); + + private: + Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgAvr8Interface = nullptr; + + bool sessionStarted = false; + }; +} diff --git a/src/TargetController/TargetController.hpp b/src/TargetController/TargetController.hpp index df2f2df0..b495f2eb 100644 --- a/src/TargetController/TargetController.hpp +++ b/src/TargetController/TargetController.hpp @@ -118,6 +118,12 @@ namespace Bloom return std::make_unique(); } }, + { + "xplained-pro", + [] { + return std::make_unique(); + } + }, }; return mapping;