Tidied structure of all classes within the entire code base
Also some other small bits of tidying
This commit is contained in:
@@ -14,18 +14,8 @@ namespace Bloom
|
||||
*/
|
||||
class DebugTool
|
||||
{
|
||||
private:
|
||||
bool initialised = false;
|
||||
|
||||
protected:
|
||||
void setInitialised(bool initialised) {
|
||||
this->initialised = initialised;
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] bool isInitialised() const {
|
||||
return this->initialised;
|
||||
}
|
||||
virtual ~DebugTool() = default;
|
||||
|
||||
/**
|
||||
* Should establish a connection to the device and prepare it for a debug session.
|
||||
@@ -55,6 +45,16 @@ namespace Bloom
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
virtual ~DebugTool() = default;
|
||||
[[nodiscard]] bool isInitialised() const {
|
||||
return this->initialised;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setInitialised(bool initialised) {
|
||||
this->initialised = initialised;
|
||||
}
|
||||
|
||||
private:
|
||||
bool initialised = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,25 +40,6 @@ namespace Bloom::DebugToolDrivers
|
||||
*/
|
||||
class AtmelIce: public DebugTool, public Usb::UsbDevice
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The EDBG interface implements additional functionality via vendor specific CMSIS-DAP commands.
|
||||
* In other words, all EDBG commands are just CMSIS-DAP vendor commands that allow the debug tool
|
||||
* to support additional functionality, like AVR programming and debugging.
|
||||
*
|
||||
* Any non-EDBG CMSIS-DAP commands for the Atmel-ICE can be sent through the EdbgInterface (as the
|
||||
* EdbgInterface extends the CmsisDapInterface).
|
||||
*/
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The Atmel-ICE employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||
* implemented in EdbgAvr8Interface. See the EdbgAvr8Interface class for more information.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||
|
||||
bool sessionStarted = false;
|
||||
|
||||
public:
|
||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||
static const std::uint16_t USB_PRODUCT_ID = 8513;
|
||||
@@ -97,5 +78,24 @@ namespace Bloom::DebugToolDrivers
|
||||
* Ends the active session with the debug tool.
|
||||
*/
|
||||
void endSession();
|
||||
|
||||
private:
|
||||
/**
|
||||
* The EDBG interface implements additional functionality via vendor specific CMSIS-DAP commands.
|
||||
* In other words, all EDBG commands are just CMSIS-DAP vendor commands that allow the debug tool
|
||||
* to support additional functionality, like AVR programming and debugging.
|
||||
*
|
||||
* Any non-EDBG CMSIS-DAP commands for the Atmel-ICE can be sent through the EdbgInterface (as the
|
||||
* EdbgInterface extends the CmsisDapInterface).
|
||||
*/
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The Atmel-ICE employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||
* implemented in EdbgAvr8Interface. See the EdbgAvr8Interface class for more information.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||
|
||||
bool sessionStarted = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,17 +34,6 @@ namespace Bloom::DebugToolDrivers
|
||||
*/
|
||||
class MplabSnap: public DebugTool, public Usb::UsbDevice
|
||||
{
|
||||
private:
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The MPLAB Snap employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||
* implemented in EdbgAvr8Interface. See the EdbgAvr8Interface class for more information.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||
|
||||
bool sessionStarted = false;
|
||||
|
||||
public:
|
||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||
static const std::uint16_t USB_PRODUCT_ID = 8576;
|
||||
@@ -83,5 +72,16 @@ namespace Bloom::DebugToolDrivers
|
||||
* Ends the active session with the debug tool.
|
||||
*/
|
||||
void endSession();
|
||||
|
||||
private:
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The MPLAB Snap employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||
* implemented in EdbgAvr8Interface. See the EdbgAvr8Interface class for more information.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||
|
||||
bool sessionStarted = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,24 +27,6 @@ namespace Bloom::DebugToolDrivers
|
||||
*/
|
||||
class PowerDebugger: public DebugTool, public Usb::UsbDevice
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The EDBG interface implements additional functionality via vendor specific CMSIS-DAP commands.
|
||||
* In other words, all EDBG commands are just CMSIS-DAP vendor commands that allow the debug tool
|
||||
* to support additional functionality, like AVR programming and debugging.
|
||||
*
|
||||
* Any non-EDBG CMSIS-DAP commands for the Power Debugger can be sent through the EDBGInterface (as the
|
||||
* EdbgInterface extends the CmsisDapInterface).
|
||||
*/
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The Power Debugger employs the EDBG AVR8Generic protocol for interfacing with AVR8 targets.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface;
|
||||
|
||||
bool sessionStarted = false;
|
||||
|
||||
public:
|
||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||
static const std::uint16_t USB_PRODUCT_ID = 8516;
|
||||
@@ -83,5 +65,23 @@ namespace Bloom::DebugToolDrivers
|
||||
* Ends the active session with the debug tool.
|
||||
*/
|
||||
void endSession();
|
||||
|
||||
private:
|
||||
/**
|
||||
* The EDBG interface implements additional functionality via vendor specific CMSIS-DAP commands.
|
||||
* In other words, all EDBG commands are just CMSIS-DAP vendor commands that allow the debug tool
|
||||
* to support additional functionality, like AVR programming and debugging.
|
||||
*
|
||||
* Any non-EDBG CMSIS-DAP commands for the Power Debugger can be sent through the EDBGInterface (as the
|
||||
* EdbgInterface extends the CmsisDapInterface).
|
||||
*/
|
||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
||||
|
||||
/**
|
||||
* The Power Debugger employs the EDBG AVR8Generic protocol for interfacing with AVR8 targets.
|
||||
*/
|
||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface;
|
||||
|
||||
bool sessionStarted = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "CmsisDapInterface.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.hpp"
|
||||
|
||||
@@ -17,27 +17,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
*/
|
||||
class CmsisDapInterface
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* All CMSIS-DAP devices employ the USB HID interface for communication.
|
||||
*
|
||||
* For many CMSIS-DAP devices, the USB HID interface parameters (interface number, endpoint config, etc) vary
|
||||
* amongst devices, so we'll need to be able to preActivationConfigure the CMSISDAPInterface from a
|
||||
* higher level. For an example, see the constructor of the AtmelIce device class.
|
||||
*/
|
||||
Usb::HidInterface usbHidInterface = Usb::HidInterface();
|
||||
|
||||
/**
|
||||
* Some CMSIS-DAP debug tools fail to operate properly when we send commands too quickly. Even if we've
|
||||
* received a response from every previous command.
|
||||
*
|
||||
* Because of this, we may need to enforce a minimum time gap between sending CMSIS commands.
|
||||
* Setting msSendCommandDelay to any value above 0 will enforce an x millisecond gap between each command
|
||||
* being sent, where x is the value of msSendCommandDelay.
|
||||
*/
|
||||
std::chrono::milliseconds msSendCommandDelay = std::chrono::milliseconds(0);
|
||||
long lastCommandSentTimeStamp = 0;
|
||||
|
||||
public:
|
||||
explicit CmsisDapInterface() = default;
|
||||
|
||||
@@ -81,5 +60,26 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
virtual std::unique_ptr<Protocols::CmsisDap::Response> sendCommandAndWaitForResponse(
|
||||
const Protocols::CmsisDap::Command& cmsisDapCommand
|
||||
);
|
||||
|
||||
private:
|
||||
/**
|
||||
* All CMSIS-DAP devices employ the USB HID interface for communication.
|
||||
*
|
||||
* For many CMSIS-DAP devices, the USB HID interface parameters (interface number, endpoint config, etc) vary
|
||||
* amongst devices, so we'll need to be able to preActivationConfigure the CMSISDAPInterface from a
|
||||
* higher level. For an example, see the constructor of the AtmelIce device class.
|
||||
*/
|
||||
Usb::HidInterface usbHidInterface = Usb::HidInterface();
|
||||
|
||||
/**
|
||||
* Some CMSIS-DAP debug tools fail to operate properly when we send commands too quickly. Even if we've
|
||||
* received a response from every previous command.
|
||||
*
|
||||
* Because of this, we may need to enforce a minimum time gap between sending CMSIS commands.
|
||||
* Setting msSendCommandDelay to any value above 0 will enforce an x millisecond gap between each command
|
||||
* being sent, where x is the value of msSendCommandDelay.
|
||||
*/
|
||||
std::chrono::milliseconds msSendCommandDelay = std::chrono::milliseconds(0);
|
||||
long lastCommandSentTimeStamp = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,11 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
{
|
||||
class Command
|
||||
{
|
||||
private:
|
||||
unsigned char commandId = 0x00;
|
||||
std::vector<unsigned char> data;
|
||||
|
||||
public:
|
||||
virtual ~Command() = default;
|
||||
|
||||
[[nodiscard]] unsigned char getCommandId() const {
|
||||
return this->commandId;
|
||||
}
|
||||
@@ -45,6 +43,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
*/
|
||||
explicit virtual operator std::vector<unsigned char>() const;
|
||||
|
||||
virtual ~Command() = default;
|
||||
private:
|
||||
unsigned char commandId = 0x00;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,22 +6,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
{
|
||||
class Response
|
||||
{
|
||||
private:
|
||||
unsigned char responseId = 0x00;
|
||||
|
||||
std::vector<unsigned char> data;
|
||||
|
||||
protected:
|
||||
void setResponseId(unsigned char commandId) {
|
||||
this->responseId = commandId;
|
||||
}
|
||||
|
||||
void setData(const std::vector<unsigned char>& data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
public:
|
||||
Response() = default;
|
||||
virtual ~Response() = default;
|
||||
|
||||
virtual void init(const std::vector<unsigned char>& rawResponse);
|
||||
|
||||
[[nodiscard]] unsigned char getResponseId() const {
|
||||
@@ -32,6 +20,17 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
return this->data;
|
||||
}
|
||||
|
||||
virtual ~Response() = default;
|
||||
protected:
|
||||
void setResponseId(unsigned char commandId) {
|
||||
this->responseId = commandId;
|
||||
}
|
||||
|
||||
void setData(const std::vector<unsigned char>& data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char responseId = 0x00;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,12 +8,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
class AvrCommand: public Command
|
||||
{
|
||||
private:
|
||||
size_t fragmentNumber = 1;
|
||||
size_t fragmentCount = 1;
|
||||
|
||||
std::vector<unsigned char> commandPacket;
|
||||
|
||||
public:
|
||||
AvrCommand() {
|
||||
this->setCommandId(0x80);
|
||||
@@ -49,5 +43,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
void setCommandPacket(const std::vector<unsigned char>& commandPacket) {
|
||||
this->commandPacket = commandPacket;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t fragmentNumber = 1;
|
||||
size_t fragmentCount = 1;
|
||||
|
||||
std::vector<unsigned char> commandPacket;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ void AvrEvent::init(const std::vector<unsigned char>& rawResponse) {
|
||||
if (responseData.size() < 2) {
|
||||
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
|
||||
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
|
||||
"returned no additional data.");
|
||||
"returned no additional data.");
|
||||
}
|
||||
|
||||
// Response size is two bytes, MSB
|
||||
auto responsePacketSize = static_cast<size_t>((responseData[0] << 8) | responseData[1]);
|
||||
auto responsePacketSize = static_cast<std::size_t>((responseData[0] << 8) | responseData[1]);
|
||||
|
||||
if (responseData.size() < 2) {
|
||||
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
|
||||
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
|
||||
"contained invalid event data size.");
|
||||
"contained invalid event data size.");
|
||||
}
|
||||
|
||||
auto eventData = std::vector<unsigned char>();
|
||||
|
||||
@@ -22,16 +22,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
|
||||
class AvrEvent: public Response
|
||||
{
|
||||
private:
|
||||
unsigned char eventId = 0;
|
||||
|
||||
std::vector<unsigned char> eventData;
|
||||
|
||||
protected:
|
||||
void setEventData(const std::vector<unsigned char>& eventData) {
|
||||
this->eventData = eventData;
|
||||
}
|
||||
|
||||
public:
|
||||
AvrEvent() = default;
|
||||
|
||||
@@ -59,5 +49,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
[[nodiscard]] AvrEventId getEventId() const {
|
||||
return static_cast<AvrEventId>(this->eventId);
|
||||
}
|
||||
|
||||
protected:
|
||||
void setEventData(const std::vector<unsigned char>& eventData) {
|
||||
this->eventData = eventData;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char eventId = 0;
|
||||
std::vector<unsigned char> eventData;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "AvrResponse.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
|
||||
@@ -9,25 +9,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
class AvrResponse: public Response
|
||||
{
|
||||
private:
|
||||
std::uint8_t fragmentNumber = 0;
|
||||
std::uint8_t fragmentCount = 0;
|
||||
|
||||
std::vector<unsigned char> responsePacket;
|
||||
|
||||
protected:
|
||||
void setFragmentNumber(std::uint8_t fragmentNumber) {
|
||||
this->fragmentNumber = fragmentNumber;
|
||||
}
|
||||
|
||||
void setFragmentCount(std::uint8_t fragmentCount) {
|
||||
this->fragmentCount = fragmentCount;
|
||||
}
|
||||
|
||||
void setResponsePacket(const std::vector<unsigned char>& responsePacket) {
|
||||
this->responsePacket = responsePacket;
|
||||
}
|
||||
|
||||
public:
|
||||
AvrResponse() = default;
|
||||
|
||||
@@ -55,5 +36,24 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
[[nodiscard]] const std::vector<unsigned char>& getResponsePacket() const {
|
||||
return this->responsePacket;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setFragmentNumber(std::uint8_t fragmentNumber) {
|
||||
this->fragmentNumber = fragmentNumber;
|
||||
}
|
||||
|
||||
void setFragmentCount(std::uint8_t fragmentCount) {
|
||||
this->fragmentCount = fragmentCount;
|
||||
}
|
||||
|
||||
void setResponsePacket(const std::vector<unsigned char>& responsePacket) {
|
||||
this->responsePacket = responsePacket;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint8_t fragmentNumber = 0;
|
||||
std::uint8_t fragmentCount = 0;
|
||||
|
||||
std::vector<unsigned char> responsePacket;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.hpp"
|
||||
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
|
||||
@@ -6,9 +6,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class ActivatePhysical: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
bool reset = false;
|
||||
|
||||
public:
|
||||
ActivatePhysical() = default;
|
||||
explicit ActivatePhysical(bool reset): reset(reset) {};
|
||||
@@ -31,6 +28,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
bool reset = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class Attach: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
bool breakAfterAttach = false;
|
||||
|
||||
public:
|
||||
Attach() = default;
|
||||
explicit Attach(bool breakAfterAttach): breakAfterAttach(breakAfterAttach) {};
|
||||
@@ -31,6 +28,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
bool breakAfterAttach = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class ClearAllSoftwareBreakpoints: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
ClearAllSoftwareBreakpoints() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -18,10 +23,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
ClearAllSoftwareBreakpoints() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class ClearSoftwareBreakpoints: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
std::vector<std::uint32_t> addresses;
|
||||
|
||||
public:
|
||||
ClearSoftwareBreakpoints() = default;
|
||||
|
||||
@@ -43,5 +40,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::uint32_t> addresses;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class DeactivatePhysical: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
DeactivatePhysical() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -18,10 +23,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
DeactivatePhysical() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class Detach: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
Detach() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -18,10 +23,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
Detach() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class DisableDebugWire: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
DisableDebugWire() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -18,10 +23,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
DisableDebugWire() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class GetDeviceId: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetDeviceId;
|
||||
|
||||
GetDeviceId() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -19,12 +26,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetDeviceId;
|
||||
|
||||
GetDeviceId() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class GetParameter: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
Avr8EdbgParameter parameter;
|
||||
std::uint8_t size = 0;
|
||||
|
||||
public:
|
||||
GetParameter() = default;
|
||||
|
||||
@@ -49,5 +45,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
Avr8EdbgParameter parameter;
|
||||
std::uint8_t size = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class GetProgramCounter: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetProgramCounter;
|
||||
|
||||
GetProgramCounter() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -19,12 +26,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetProgramCounter;
|
||||
|
||||
GetProgramCounter() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,12 +10,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class ReadMemory: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
Avr8MemoryType type = Avr8MemoryType::SRAM;
|
||||
std::uint32_t address = 0;
|
||||
std::uint32_t bytes = 0;
|
||||
std::set<std::uint32_t> excludedAddresses;
|
||||
|
||||
public:
|
||||
using ResponseFrameType = ResponseFrames::Avr8Generic::ReadMemory;
|
||||
|
||||
@@ -38,5 +32,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override;
|
||||
|
||||
private:
|
||||
Avr8MemoryType type = Avr8MemoryType::SRAM;
|
||||
std::uint32_t address = 0;
|
||||
std::uint32_t bytes = 0;
|
||||
std::set<std::uint32_t> excludedAddresses;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class Reset: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
bool stopAtMainAddress = false;
|
||||
|
||||
public:
|
||||
Reset() = default;
|
||||
explicit Reset(bool stopAtMainAddress): stopAtMainAddress(stopAtMainAddress) {};
|
||||
@@ -31,5 +28,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
bool stopAtMainAddress = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class Run: public Avr8GenericCommandFrame
|
||||
{
|
||||
public:
|
||||
Run() {
|
||||
init();
|
||||
};
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -18,10 +23,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
Run() {
|
||||
init();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class RunTo: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
std::uint32_t address = 0;
|
||||
|
||||
public:
|
||||
RunTo() = default;
|
||||
|
||||
@@ -41,5 +38,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t address = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class SetParameter: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
Avr8EdbgParameter parameter;
|
||||
std::vector<unsigned char> value;
|
||||
|
||||
public:
|
||||
SetParameter() = default;
|
||||
|
||||
@@ -57,5 +53,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
Avr8EdbgParameter parameter;
|
||||
std::vector<unsigned char> value;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class SetProgramCounter: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
std::uint32_t programCounter = 0;
|
||||
|
||||
public:
|
||||
explicit SetProgramCounter(std::uint32_t programCounter): programCounter(programCounter) {}
|
||||
|
||||
@@ -31,5 +28,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t programCounter = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class SetSoftwareBreakpoints: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
std::vector<std::uint32_t> addresses;
|
||||
|
||||
public:
|
||||
SetSoftwareBreakpoints() = default;
|
||||
|
||||
@@ -43,5 +40,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::uint32_t> addresses;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class SetXmegaSoftwareBreakpoint: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
std::uint32_t address = 0;
|
||||
|
||||
public:
|
||||
SetXmegaSoftwareBreakpoint() = default;
|
||||
|
||||
@@ -40,5 +37,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t address = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class Stop: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
bool stopImmediately = true;
|
||||
|
||||
public:
|
||||
Stop() = default;
|
||||
explicit Stop(bool stopImmediately): stopImmediately(stopImmediately) {};
|
||||
@@ -31,5 +28,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
bool stopImmediately = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,11 +9,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
{
|
||||
class WriteMemory: public Avr8GenericCommandFrame
|
||||
{
|
||||
private:
|
||||
Avr8MemoryType type = Avr8MemoryType::SRAM;
|
||||
std::uint32_t address = 0;
|
||||
Targets::TargetMemoryBuffer buffer;
|
||||
|
||||
public:
|
||||
WriteMemory() = default;
|
||||
|
||||
@@ -62,5 +57,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
Avr8MemoryType type = Avr8MemoryType::SRAM;
|
||||
std::uint32_t address = 0;
|
||||
Targets::TargetMemoryBuffer buffer;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,24 +14,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
class AvrCommandFrame
|
||||
{
|
||||
private:
|
||||
unsigned char SOF = 0x0E;
|
||||
|
||||
unsigned char protocolVersion = 0x00;
|
||||
|
||||
/**
|
||||
* Incrementing from 0x00
|
||||
*/
|
||||
std::uint16_t sequenceId = 0;
|
||||
inline static std::uint16_t lastSequenceId = 0;
|
||||
|
||||
/**
|
||||
* Destination sub-protocol handler ID
|
||||
*/
|
||||
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::DISCOVERY;
|
||||
|
||||
std::vector<unsigned char> payload;
|
||||
|
||||
public:
|
||||
using ResponseFrameType = AvrResponseFrame;
|
||||
|
||||
@@ -102,6 +84,24 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
* @return
|
||||
*/
|
||||
explicit virtual operator std::vector<unsigned char> () const;
|
||||
|
||||
private:
|
||||
unsigned char SOF = 0x0E;
|
||||
|
||||
unsigned char protocolVersion = 0x00;
|
||||
|
||||
/**
|
||||
* Incrementing from 0x00
|
||||
*/
|
||||
std::uint16_t sequenceId = 0;
|
||||
inline static std::uint16_t lastSequenceId = 0;
|
||||
|
||||
/**
|
||||
* Destination sub-protocol handler ID
|
||||
*/
|
||||
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::DISCOVERY;
|
||||
|
||||
std::vector<unsigned char> payload;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
*/
|
||||
class Query: public DiscoveryCommandFrame
|
||||
{
|
||||
private:
|
||||
QueryContext context = QueryContext::COMMAND_HANDLERS;
|
||||
|
||||
public:
|
||||
Query(): DiscoveryCommandFrame() {}
|
||||
|
||||
@@ -45,5 +42,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
QueryContext context = QueryContext::COMMAND_HANDLERS;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
*/
|
||||
class EndSession: public HouseKeepingCommandFrame
|
||||
{
|
||||
public:
|
||||
EndSession(): HouseKeepingCommandFrame() {
|
||||
this->init();
|
||||
}
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -21,10 +26,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[2] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
EndSession(): HouseKeepingCommandFrame() {
|
||||
this->init();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
*/
|
||||
class StartSession: public HouseKeepingCommandFrame
|
||||
{
|
||||
public:
|
||||
StartSession(): HouseKeepingCommandFrame() {
|
||||
this->init();
|
||||
}
|
||||
|
||||
private:
|
||||
void init() {
|
||||
/*
|
||||
@@ -20,10 +25,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
||||
payload[1] = 0x00;
|
||||
this->setPayload(payload);
|
||||
}
|
||||
|
||||
public:
|
||||
StartSession(): HouseKeepingCommandFrame() {
|
||||
this->init();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,198 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
*/
|
||||
class EdbgAvr8Interface: public TargetInterfaces::Microchip::Avr::Avr8::Avr8Interface
|
||||
{
|
||||
public:
|
||||
explicit EdbgAvr8Interface(EdbgInterface& edbgInterface)
|
||||
: edbgInterface(edbgInterface) {};
|
||||
|
||||
/**
|
||||
* Disables use of the masked read memory EDBG command. Masking will be performed at the driver-side.
|
||||
*
|
||||
* @param avoidMaskedMemoryRead
|
||||
*/
|
||||
void setAvoidMaskedMemoryRead(bool avoidMaskedMemoryRead) {
|
||||
this->avoidMaskedMemoryRead = avoidMaskedMemoryRead;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public methods below implement the interface defined by the Avr8Interface class.
|
||||
* See the comments in that class for more info on the expected behaviour of each method.
|
||||
*/
|
||||
|
||||
/**
|
||||
* As already mentioned in numerous comments above, the EdbgAvr8Interface requires some configuration from
|
||||
* the user. This is supplied via the user's Bloom configuration.
|
||||
*
|
||||
* @param targetConfig
|
||||
*/
|
||||
void configure(const TargetConfig& targetConfig) override;
|
||||
|
||||
/**
|
||||
* Configures the target family. For some physical interfaces, the target family is required in order
|
||||
* properly configure the EDBG tool. See EdbgAvr8Interface::resolveConfigVariant() for more.
|
||||
*
|
||||
* @param family
|
||||
*/
|
||||
void setFamily(Targets::Microchip::Avr::Avr8Bit::Family family) override {
|
||||
this->family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts target parameters from the AVR8 target instance and sends the necessary target parameters to the
|
||||
* debug tool.
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
void setTargetParameters(const Targets::Microchip::Avr::Avr8Bit::TargetParameters& config) override;
|
||||
|
||||
/**
|
||||
* Initialises the AVR8 Generic protocol interface by setting the appropriate parameters on the debug tool.
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/**
|
||||
* Issues the "stop" command to the debug tool, halting target execution.
|
||||
*/
|
||||
void stop() override;
|
||||
|
||||
/**
|
||||
* Issues the "run" command to the debug tool, resuming execution on the target.
|
||||
*/
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* Issues the "run to" command to the debug tool, resuming execution on the target, up to a specific byte
|
||||
* address. The target will dispatch an AVR BREAK event once it reaches the specified address.
|
||||
*
|
||||
* @param address
|
||||
* The (byte) address to run to.
|
||||
*/
|
||||
void runTo(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "step" command to the debug tool, stepping the execution on the target. The stepping can be
|
||||
* configured to step in, out or over. But currently we only support stepping in. The target will dispatch
|
||||
* an AVR BREAK event once it reaches the next instruction.
|
||||
*/
|
||||
void step() override;
|
||||
|
||||
/**
|
||||
* Issues the "reset" command to the debug tool, resetting target execution.
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
* Activates the physical interface and starts a debug session on the target (via attach()).
|
||||
*/
|
||||
void activate() override;
|
||||
|
||||
/**
|
||||
* Terminates any active debug session on the target and severs the connection between the debug tool and
|
||||
* the target (by deactivating the physical interface).
|
||||
*/
|
||||
void deactivate() override;
|
||||
|
||||
/**
|
||||
* Issues the "PC Read" command to the debug tool, to extract the current program counter.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::uint32_t getProgramCounter() override;
|
||||
|
||||
/**
|
||||
* Issues the "PC Write" command to the debug tool, setting the program counter on the target.
|
||||
*
|
||||
* @param programCounter
|
||||
* The byte address to set as the program counter.
|
||||
*/
|
||||
void setProgramCounter(std::uint32_t programCounter) override;
|
||||
|
||||
/**
|
||||
* Issues the "Get ID" command to the debug tool, to extract the signature from the target.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Targets::Microchip::Avr::TargetSignature getDeviceId() override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Set" command to the debug tool, setting a software breakpoint at the given
|
||||
* byte address.
|
||||
*
|
||||
* @param address
|
||||
* The byte address to position the breakpoint.
|
||||
*/
|
||||
void setBreakpoint(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Clear" command to the debug tool, clearing any breakpoint at the given
|
||||
* byte address.
|
||||
*
|
||||
* @param address
|
||||
* The byte address of the breakpoint to clear.
|
||||
*/
|
||||
void clearBreakpoint(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Clear All" command to the debug tool, clearing all software breakpoints
|
||||
* that were set *in the current debug session*.
|
||||
*
|
||||
* If the debug session ended before any of the set breakpoints were cleared, this will *not* clear them.
|
||||
*/
|
||||
void clearAllBreakpoints() override;
|
||||
|
||||
/**
|
||||
* Reads registers from the target.
|
||||
*
|
||||
* @param descriptors
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetRegisters readRegisters(const Targets::TargetRegisterDescriptors& descriptors) override;
|
||||
|
||||
/**
|
||||
* Writes registers to target.
|
||||
*
|
||||
* @param registers
|
||||
*/
|
||||
void writeRegisters(const Targets::TargetRegisters& registers) override;
|
||||
|
||||
/**
|
||||
* This is an overloaded method.
|
||||
*
|
||||
* Resolves the correct Avr8MemoryType from the given TargetMemoryType and calls readMemory().
|
||||
*
|
||||
* @param memoryType
|
||||
* @param startAddress
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetMemoryBuffer readMemory(
|
||||
Targets::TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
std::uint32_t bytes
|
||||
) override;
|
||||
|
||||
/**
|
||||
* This is an overloaded method.
|
||||
*
|
||||
* Resolves the correct Avr8MemoryType from the given TargetMemoryType and calls writeMemory().
|
||||
*
|
||||
* @param memoryType
|
||||
* @param startAddress
|
||||
* @param buffer
|
||||
*/
|
||||
void writeMemory(
|
||||
Targets::TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
const Targets::TargetMemoryBuffer& buffer
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Returns the current state of the target.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetState getTargetState() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The AVR8 Generic protocol is a sub-protocol of the EDBG AVR protocol, which is served via CMSIS-DAP vendor
|
||||
@@ -459,197 +651,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
* This should only be used when a BreakEvent is always expected.
|
||||
*/
|
||||
void waitForStoppedEvent();
|
||||
|
||||
public:
|
||||
explicit EdbgAvr8Interface(EdbgInterface& edbgInterface)
|
||||
: edbgInterface(edbgInterface) {};
|
||||
|
||||
/**
|
||||
* Disables use of the masked read memory EDBG command. Masking will be performed at the driver-side.
|
||||
*
|
||||
* @param avoidMaskedMemoryRead
|
||||
*/
|
||||
void setAvoidMaskedMemoryRead(bool avoidMaskedMemoryRead) {
|
||||
this->avoidMaskedMemoryRead = avoidMaskedMemoryRead;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public methods below implement the interface defined by the Avr8Interface class.
|
||||
* See the comments in that class for more info on the expected behaviour of each method.
|
||||
*/
|
||||
|
||||
/**
|
||||
* As already mentioned in numerous comments above, the EdbgAvr8Interface requires some configuration from
|
||||
* the user. This is supplied via the user's Bloom configuration.
|
||||
*
|
||||
* @param targetConfig
|
||||
*/
|
||||
void configure(const TargetConfig& targetConfig) override;
|
||||
|
||||
/**
|
||||
* Configures the target family. For some physical interfaces, the target family is required in order
|
||||
* properly configure the EDBG tool. See EdbgAvr8Interface::resolveConfigVariant() for more.
|
||||
*
|
||||
* @param family
|
||||
*/
|
||||
void setFamily(Targets::Microchip::Avr::Avr8Bit::Family family) override {
|
||||
this->family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts target parameters from the AVR8 target instance and sends the necessary target parameters to the
|
||||
* debug tool.
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
void setTargetParameters(const Targets::Microchip::Avr::Avr8Bit::TargetParameters& config) override;
|
||||
|
||||
/**
|
||||
* Initialises the AVR8 Generic protocol interface by setting the appropriate parameters on the debug tool.
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/**
|
||||
* Issues the "stop" command to the debug tool, halting target execution.
|
||||
*/
|
||||
void stop() override;
|
||||
|
||||
/**
|
||||
* Issues the "run" command to the debug tool, resuming execution on the target.
|
||||
*/
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* Issues the "run to" command to the debug tool, resuming execution on the target, up to a specific byte
|
||||
* address. The target will dispatch an AVR BREAK event once it reaches the specified address.
|
||||
*
|
||||
* @param address
|
||||
* The (byte) address to run to.
|
||||
*/
|
||||
void runTo(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "step" command to the debug tool, stepping the execution on the target. The stepping can be
|
||||
* configured to step in, out or over. But currently we only support stepping in. The target will dispatch
|
||||
* an AVR BREAK event once it reaches the next instruction.
|
||||
*/
|
||||
void step() override;
|
||||
|
||||
/**
|
||||
* Issues the "reset" command to the debug tool, resetting target execution.
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
* Activates the physical interface and starts a debug session on the target (via attach()).
|
||||
*/
|
||||
void activate() override;
|
||||
|
||||
/**
|
||||
* Terminates any active debug session on the target and severs the connection between the debug tool and
|
||||
* the target (by deactivating the physical interface).
|
||||
*/
|
||||
void deactivate() override;
|
||||
|
||||
/**
|
||||
* Issues the "PC Read" command to the debug tool, to extract the current program counter.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::uint32_t getProgramCounter() override;
|
||||
|
||||
/**
|
||||
* Issues the "PC Write" command to the debug tool, setting the program counter on the target.
|
||||
*
|
||||
* @param programCounter
|
||||
* The byte address to set as the program counter.
|
||||
*/
|
||||
void setProgramCounter(std::uint32_t programCounter) override;
|
||||
|
||||
/**
|
||||
* Issues the "Get ID" command to the debug tool, to extract the signature from the target.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Targets::Microchip::Avr::TargetSignature getDeviceId() override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Set" command to the debug tool, setting a software breakpoint at the given
|
||||
* byte address.
|
||||
*
|
||||
* @param address
|
||||
* The byte address to position the breakpoint.
|
||||
*/
|
||||
void setBreakpoint(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Clear" command to the debug tool, clearing any breakpoint at the given
|
||||
* byte address.
|
||||
*
|
||||
* @param address
|
||||
* The byte address of the breakpoint to clear.
|
||||
*/
|
||||
void clearBreakpoint(std::uint32_t address) override;
|
||||
|
||||
/**
|
||||
* Issues the "Software Breakpoint Clear All" command to the debug tool, clearing all software breakpoints
|
||||
* that were set *in the current debug session*.
|
||||
*
|
||||
* If the debug session ended before any of the set breakpoints were cleared, this will *not* clear them.
|
||||
*/
|
||||
void clearAllBreakpoints() override;
|
||||
|
||||
/**
|
||||
* Reads registers from the target.
|
||||
*
|
||||
* @param descriptors
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetRegisters readRegisters(const Targets::TargetRegisterDescriptors& descriptors) override;
|
||||
|
||||
/**
|
||||
* Writes registers to target.
|
||||
*
|
||||
* @param registers
|
||||
*/
|
||||
void writeRegisters(const Targets::TargetRegisters& registers) override;
|
||||
|
||||
/**
|
||||
* This is an overloaded method.
|
||||
*
|
||||
* Resolves the correct Avr8MemoryType from the given TargetMemoryType and calls readMemory().
|
||||
*
|
||||
* @param memoryType
|
||||
* @param startAddress
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetMemoryBuffer readMemory(
|
||||
Targets::TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
std::uint32_t bytes
|
||||
) override;
|
||||
|
||||
/**
|
||||
* This is an overloaded method.
|
||||
*
|
||||
* Resolves the correct Avr8MemoryType from the given TargetMemoryType and calls writeMemory().
|
||||
*
|
||||
* @param memoryType
|
||||
* @param startAddress
|
||||
* @param buffer
|
||||
*/
|
||||
void writeMemory(
|
||||
Targets::TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
const Targets::TargetMemoryBuffer& buffer
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Returns the current state of the target.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetState getTargetState() override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "BreakEvent.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
|
||||
@@ -9,12 +9,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
class BreakEvent: public AvrEvent
|
||||
{
|
||||
private:
|
||||
std::uint32_t programCounter = 0;
|
||||
Targets::TargetBreakCause breakCause = Targets::TargetBreakCause::UNKNOWN;
|
||||
|
||||
void init(const AvrEvent& event);
|
||||
|
||||
public:
|
||||
explicit BreakEvent(const AvrEvent& event) {
|
||||
this->init(event);
|
||||
@@ -27,5 +21,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
[[nodiscard]] Targets::TargetBreakCause getBreakCause() const {
|
||||
return this->breakCause;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t programCounter = 0;
|
||||
Targets::TargetBreakCause breakCause = Targets::TargetBreakCause::UNKNOWN;
|
||||
|
||||
void init(const AvrEvent& event);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,27 @@ namespace Bloom::Exceptions
|
||||
{
|
||||
class Avr8CommandFailure: public TargetOperationFailure
|
||||
{
|
||||
public:
|
||||
explicit Avr8CommandFailure(const std::string& message): TargetOperationFailure(message) {
|
||||
this->message = message;
|
||||
}
|
||||
|
||||
explicit Avr8CommandFailure(const char* message): TargetOperationFailure(message) {
|
||||
this->message = std::string(message);
|
||||
}
|
||||
|
||||
explicit Avr8CommandFailure(
|
||||
const std::string& message,
|
||||
DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic::Avr8GenericResponseFrame& responseFrame
|
||||
): TargetOperationFailure(message) {
|
||||
this->message = message;
|
||||
|
||||
auto responsePayload = responseFrame.getPayload();
|
||||
if (responsePayload.size() == 3 && this->failureCodeToDescription.contains(responsePayload[2])) {
|
||||
this->message += " - Failure reason: " + this->failureCodeToDescription.find(responsePayload[2])->second;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static inline auto failureCodeToDescription = std::map<unsigned char, std::string>({
|
||||
{0x10, "debugWIRE physical error"},
|
||||
@@ -57,26 +78,5 @@ namespace Bloom::Exceptions
|
||||
{0x91, "Command has not been implemented"},
|
||||
{0xFF, "Unknown error reported by EDBG device"},
|
||||
});
|
||||
|
||||
public:
|
||||
explicit Avr8CommandFailure(const std::string& message): TargetOperationFailure(message) {
|
||||
this->message = message;
|
||||
}
|
||||
|
||||
explicit Avr8CommandFailure(const char* message): TargetOperationFailure(message) {
|
||||
this->message = std::string(message);
|
||||
}
|
||||
|
||||
explicit Avr8CommandFailure(
|
||||
const std::string& message,
|
||||
DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic::Avr8GenericResponseFrame& responseFrame
|
||||
): TargetOperationFailure(message) {
|
||||
this->message = message;
|
||||
|
||||
auto responsePayload = responseFrame.getPayload();
|
||||
if (responsePayload.size() == 3 && this->failureCodeToDescription.contains(responsePayload[2])) {
|
||||
this->message += " - Failure reason: " + this->failureCodeToDescription.find(responsePayload[2])->second;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Avr8GenericResponseFrame.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
|
||||
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic
|
||||
|
||||
@@ -27,5 +27,4 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
|
||||
return static_cast<std::uint32_t>(payload[5] << 24 | payload[4] << 16 | payload[3] << 8 | payload[2]) * 2;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "AvrResponseFrame.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
|
||||
@@ -13,40 +13,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
class AvrResponseFrame
|
||||
{
|
||||
private:
|
||||
unsigned char SOF = 0x0E;
|
||||
|
||||
/**
|
||||
* Incrementing from 0x00
|
||||
*/
|
||||
std::uint16_t sequenceID = 1;
|
||||
|
||||
/**
|
||||
* Destination sub-protocol handler ID
|
||||
*/
|
||||
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::AVR8_GENERIC;
|
||||
|
||||
std::vector<unsigned char> payload;
|
||||
|
||||
protected:
|
||||
virtual void initFromRawFrame(const std::vector<unsigned char>& rawFrame);
|
||||
|
||||
void setSequenceId(std::uint16_t sequenceId) {
|
||||
this->sequenceID = sequenceId;
|
||||
}
|
||||
|
||||
void setProtocolHandlerId(ProtocolHandlerId protocolHandlerId) {
|
||||
this->protocolHandlerID = protocolHandlerId;
|
||||
}
|
||||
|
||||
void setProtocolHandlerId(unsigned char protocolHandlerId) {
|
||||
this->protocolHandlerID = static_cast<ProtocolHandlerId>(protocolHandlerId);
|
||||
}
|
||||
|
||||
void setPayload(const std::vector<unsigned char>& payload) {
|
||||
this->payload = payload;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit AvrResponseFrame() = default;
|
||||
|
||||
@@ -82,5 +48,39 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
[[nodiscard]] virtual std::vector<unsigned char> getPayloadData() {
|
||||
return this->payload;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void initFromRawFrame(const std::vector<unsigned char>& rawFrame);
|
||||
|
||||
void setSequenceId(std::uint16_t sequenceId) {
|
||||
this->sequenceID = sequenceId;
|
||||
}
|
||||
|
||||
void setProtocolHandlerId(ProtocolHandlerId protocolHandlerId) {
|
||||
this->protocolHandlerID = protocolHandlerId;
|
||||
}
|
||||
|
||||
void setProtocolHandlerId(unsigned char protocolHandlerId) {
|
||||
this->protocolHandlerID = static_cast<ProtocolHandlerId>(protocolHandlerId);
|
||||
}
|
||||
|
||||
void setPayload(const std::vector<unsigned char>& payload) {
|
||||
this->payload = payload;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char SOF = 0x0E;
|
||||
|
||||
/**
|
||||
* Incrementing from 0x00
|
||||
*/
|
||||
std::uint16_t sequenceID = 1;
|
||||
|
||||
/**
|
||||
* Destination sub-protocol handler ID
|
||||
*/
|
||||
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::AVR8_GENERIC;
|
||||
|
||||
std::vector<unsigned char> payload;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "EdbgInterface.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
|
||||
@@ -39,11 +39,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
||||
|
||||
Protocols::CmsisDap::Edbg::Avr::AvrResponse getAvrResponse();
|
||||
|
||||
virtual std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> requestAvrResponses();
|
||||
|
||||
virtual std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> requestAvrEvent();
|
||||
|
||||
|
||||
template<class CommandFrameType>
|
||||
typename CommandFrameType::ResponseFrameType sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
const CommandFrameType& avrCommandFrame
|
||||
@@ -72,5 +67,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
||||
responseFrame.initFromAvrResponses(responses);
|
||||
return responseFrame;
|
||||
}
|
||||
|
||||
virtual std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> requestAvrEvent();
|
||||
|
||||
private:
|
||||
virtual std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> requestAvrResponses();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,36 +1,13 @@
|
||||
#include "HidInterface.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "hidapi.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
|
||||
using namespace Bloom::Usb;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
|
||||
hid_device_info* hidDeviceInfoList = hid_enumerate(this->getVendorId(), this->getProductId());
|
||||
|
||||
while (hidDeviceInfoList != nullptr) {
|
||||
if (hidDeviceInfoList->interface_number == interfaceNumber) {
|
||||
break;
|
||||
}
|
||||
|
||||
hidDeviceInfoList = hidDeviceInfoList->next;
|
||||
}
|
||||
|
||||
if (hidDeviceInfoList == nullptr) {
|
||||
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
|
||||
}
|
||||
|
||||
auto path = std::string(hidDeviceInfoList->path);
|
||||
hid_free_enumeration(hidDeviceInfoList);
|
||||
return path;
|
||||
}
|
||||
|
||||
void HidInterface::init() {
|
||||
if (this->libUsbDevice == nullptr) {
|
||||
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
|
||||
@@ -72,20 +49,24 @@ void HidInterface::close() {
|
||||
Interface::close();
|
||||
}
|
||||
|
||||
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
|
||||
int transferred;
|
||||
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
|
||||
std::vector<unsigned char> output;
|
||||
auto readSize = this->getInputReportSize();
|
||||
|
||||
if ((transferred = hid_read_timeout(
|
||||
this->hidDevice,
|
||||
buffer,
|
||||
maxLength,
|
||||
timeout == 0 ? -1 : static_cast<int>(timeout))
|
||||
) == -1
|
||||
) {
|
||||
throw DeviceCommunicationFailure("Failed to read from HID device.");
|
||||
// Attempt to read the first HID report packet, and whatever is left after that.
|
||||
output.resize(readSize);
|
||||
auto transferredByteCount = this->read(output.data(), readSize, timeout);
|
||||
auto totalByteCount = transferredByteCount;
|
||||
|
||||
while (transferredByteCount >= readSize) {
|
||||
output.resize(totalByteCount + readSize);
|
||||
|
||||
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
|
||||
totalByteCount += transferredByteCount;
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(transferred);
|
||||
output.resize(totalByteCount);
|
||||
return output;
|
||||
}
|
||||
|
||||
void HidInterface::write(std::vector<unsigned char> buffer) {
|
||||
@@ -107,27 +88,43 @@ void HidInterface::write(std::vector<unsigned char> buffer) {
|
||||
|
||||
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
|
||||
Logger::debug("Attempted to write " + std::to_string(length)
|
||||
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
|
||||
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
|
||||
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
|
||||
std::vector<unsigned char> output;
|
||||
auto readSize = this->getInputReportSize();
|
||||
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
|
||||
int transferred;
|
||||
|
||||
// Attempt to read the first HID report packet, and whatever is left after that.
|
||||
output.resize(readSize);
|
||||
auto transferredByteCount = this->read(output.data(), readSize, timeout);
|
||||
auto totalByteCount = transferredByteCount;
|
||||
|
||||
while (transferredByteCount >= readSize) {
|
||||
output.resize(totalByteCount + readSize);
|
||||
|
||||
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
|
||||
totalByteCount += transferredByteCount;
|
||||
if ((transferred = hid_read_timeout(
|
||||
this->hidDevice,
|
||||
buffer,
|
||||
maxLength,
|
||||
timeout == 0 ? -1 : static_cast<int>(timeout))
|
||||
) == -1
|
||||
) {
|
||||
throw DeviceCommunicationFailure("Failed to read from HID device.");
|
||||
}
|
||||
|
||||
output.resize(totalByteCount);
|
||||
return output;
|
||||
return static_cast<std::size_t>(transferred);
|
||||
}
|
||||
|
||||
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
|
||||
hid_device_info* hidDeviceInfoList = hid_enumerate(this->getVendorId(), this->getProductId());
|
||||
|
||||
while (hidDeviceInfoList != nullptr) {
|
||||
if (hidDeviceInfoList->interface_number == interfaceNumber) {
|
||||
break;
|
||||
}
|
||||
|
||||
hidDeviceInfoList = hidDeviceInfoList->next;
|
||||
}
|
||||
|
||||
if (hidDeviceInfoList == nullptr) {
|
||||
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
|
||||
}
|
||||
|
||||
auto path = std::string(hidDeviceInfoList->path);
|
||||
hid_free_enumeration(hidDeviceInfoList);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,54 @@ namespace Bloom::Usb
|
||||
*/
|
||||
class HidInterface: public Interface
|
||||
{
|
||||
public:
|
||||
std::size_t getInputReportSize() const {
|
||||
return this->inputReportSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Claims the USB HID interface and obtains a hid_device instance
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/**
|
||||
* Closes the hid_device and releases any claimed interfaces (via hid_close())
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
/**
|
||||
* Reads as much data as the device has to offer, into a vector.
|
||||
*
|
||||
* If `timeout` is set to 0, this method will block until at least one HID report
|
||||
* packet is received.
|
||||
*
|
||||
* @param timeout
|
||||
*
|
||||
* @return
|
||||
* A vector of the data received from the device.
|
||||
*/
|
||||
std::vector<unsigned char> read(unsigned int timeout = 0);
|
||||
|
||||
/**
|
||||
* Writes buffer to HID output endpoint.
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void write(std::vector<unsigned char> buffer);
|
||||
|
||||
/**
|
||||
* Resolves a device path from a USB interface number.
|
||||
*
|
||||
* @param interfaceNumber
|
||||
* @return
|
||||
*/
|
||||
std::string getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber);
|
||||
|
||||
protected:
|
||||
hid_device* getHidDevice() const {
|
||||
return this->hidDevice;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The HIDAPI library provides a hid_device data structure to represent a USB HID interface.
|
||||
@@ -58,53 +106,5 @@ namespace Bloom::Usb
|
||||
* Number of bytes read.
|
||||
*/
|
||||
std::size_t read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout);
|
||||
|
||||
protected:
|
||||
hid_device* getHidDevice() const {
|
||||
return this->hidDevice;
|
||||
}
|
||||
|
||||
public:
|
||||
std::size_t getInputReportSize() const {
|
||||
return this->inputReportSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Claims the USB HID interface and obtains a hid_device instance
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/**
|
||||
* Closes the hid_device and releases any claimed interfaces (via hid_close())
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
/**
|
||||
* Writes buffer to HID output endpoint.
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void write(std::vector<unsigned char> buffer);
|
||||
|
||||
/**
|
||||
* Reads as much data as the device has to offer, into a vector.
|
||||
*
|
||||
* If `timeout` is set to 0, this method will block until at least one HID report
|
||||
* packet is received.
|
||||
*
|
||||
* @param timeout
|
||||
*
|
||||
* @return
|
||||
* A vector of the data received from the device.
|
||||
*/
|
||||
std::vector<unsigned char> read(unsigned int timeout = 0);
|
||||
|
||||
/**
|
||||
* Resolves a device path from a USB interface number.
|
||||
*
|
||||
* @param interfaceNumber
|
||||
* @return
|
||||
*/
|
||||
std::string getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,19 +10,6 @@ namespace Bloom::Usb
|
||||
{
|
||||
class Interface
|
||||
{
|
||||
protected:
|
||||
libusb_device* libUsbDevice = nullptr;
|
||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
||||
|
||||
std::uint16_t vendorId = 0;
|
||||
std::uint16_t productId = 0;
|
||||
|
||||
std::uint8_t number = 0;
|
||||
std::string name;
|
||||
|
||||
bool initialised = false;
|
||||
bool claimed = false;
|
||||
|
||||
public:
|
||||
explicit Interface(const std::uint8_t& interfaceNumber = 0) {
|
||||
this->setNumber(interfaceNumber);
|
||||
@@ -112,5 +99,18 @@ namespace Bloom::Usb
|
||||
*/
|
||||
virtual int read(unsigned char* buffer, unsigned char endPoint, std::size_t length, std::size_t timeout);
|
||||
virtual void write(unsigned char* buffer, unsigned char endPoint, int length);
|
||||
|
||||
protected:
|
||||
libusb_device* libUsbDevice = nullptr;
|
||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
||||
|
||||
std::uint16_t vendorId = 0;
|
||||
std::uint16_t productId = 0;
|
||||
|
||||
std::uint8_t number = 0;
|
||||
std::string name;
|
||||
|
||||
bool initialised = false;
|
||||
bool claimed = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,61 @@
|
||||
#include "UsbDevice.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using Bloom::Usb::UsbDevice;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void UsbDevice::init() {
|
||||
libusb_init(&this->libUsbContext);
|
||||
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
|
||||
auto devices = this->findMatchingDevices();
|
||||
|
||||
if (devices.empty()) {
|
||||
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
|
||||
|
||||
} else if (devices.size() > 1) {
|
||||
// TODO: implement support for multiple devices (maybe via serial number?)
|
||||
throw DeviceInitializationFailure(
|
||||
"Numerous devices of matching vendor & product ID found.\n"
|
||||
"Please ensure that only one debug tool is connected and then try again."
|
||||
);
|
||||
}
|
||||
|
||||
// For now, just use the first device found.
|
||||
auto device = devices.front();
|
||||
this->setLibUsbDevice(device);
|
||||
|
||||
int libUsbStatusCode;
|
||||
|
||||
// Obtain a device handle from libusb
|
||||
if ((libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle)) < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void UsbDevice::setConfiguration(int configIndex) {
|
||||
libusb_config_descriptor* configDescriptor = {};
|
||||
int libUsbStatusCode;
|
||||
|
||||
if ((libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor))) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
|
||||
+ " returned."
|
||||
);
|
||||
}
|
||||
|
||||
if ((libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue))) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(configDescriptor);
|
||||
}
|
||||
|
||||
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
||||
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
|
||||
) {
|
||||
@@ -45,36 +92,6 @@ std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
||||
return matchedDevices;
|
||||
}
|
||||
|
||||
void UsbDevice::init() {
|
||||
libusb_init(&this->libUsbContext);
|
||||
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
|
||||
auto devices = this->findMatchingDevices();
|
||||
|
||||
if (devices.empty()) {
|
||||
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
|
||||
|
||||
} else if (devices.size() > 1) {
|
||||
// TODO: implement support for multiple devices (maybe via serial number?)
|
||||
throw DeviceInitializationFailure(
|
||||
"Numerous devices of matching vendor & product ID found.\n"
|
||||
"Please ensure that only one debug tool is connected and then try again."
|
||||
);
|
||||
}
|
||||
|
||||
// For now, just use the first device found.
|
||||
auto device = devices.front();
|
||||
this->setLibUsbDevice(device);
|
||||
|
||||
int libUsbStatusCode;
|
||||
|
||||
// Obtain a device handle from libusb
|
||||
if ((libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle)) < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void UsbDevice::close() {
|
||||
if (this->libUsbDeviceHandle != nullptr) {
|
||||
libusb_close(this->libUsbDeviceHandle);
|
||||
@@ -85,23 +102,3 @@ void UsbDevice::close() {
|
||||
libusb_exit(this->libUsbContext);
|
||||
}
|
||||
}
|
||||
|
||||
void UsbDevice::setConfiguration(int configIndex) {
|
||||
libusb_config_descriptor* configDescriptor = {};
|
||||
int libUsbStatusCode;
|
||||
|
||||
if ((libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor))) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
|
||||
+ " returned."
|
||||
);
|
||||
}
|
||||
|
||||
if ((libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue))) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(configDescriptor);
|
||||
}
|
||||
|
||||
@@ -12,25 +12,8 @@ namespace Bloom::Usb
|
||||
{
|
||||
class UsbDevice
|
||||
{
|
||||
protected:
|
||||
libusb_context* libUsbContext = nullptr;
|
||||
libusb_device* libUsbDevice = nullptr;
|
||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
||||
std::uint16_t vendorId;
|
||||
std::uint16_t productId;
|
||||
|
||||
std::vector<libusb_device*> findMatchingDevices(
|
||||
std::optional<std::uint16_t> vendorId = std::nullopt, std::optional<std::uint16_t> productId = std::nullopt
|
||||
);
|
||||
|
||||
void close();
|
||||
|
||||
public:
|
||||
UsbDevice(std::uint16_t vendorId, std::uint16_t productId) {
|
||||
this->vendorId = vendorId;
|
||||
this->productId = productId;
|
||||
};
|
||||
|
||||
UsbDevice(std::uint16_t vendorId, std::uint16_t productId): vendorId(vendorId), productId(productId) {};
|
||||
~UsbDevice() = default;
|
||||
|
||||
void init();
|
||||
@@ -57,5 +40,18 @@ namespace Bloom::Usb
|
||||
* @param configIndex
|
||||
*/
|
||||
virtual void setConfiguration(int configIndex);
|
||||
|
||||
protected:
|
||||
libusb_context* libUsbContext = nullptr;
|
||||
libusb_device* libUsbDevice = nullptr;
|
||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
||||
std::uint16_t vendorId;
|
||||
std::uint16_t productId;
|
||||
|
||||
std::vector<libusb_device*> findMatchingDevices(
|
||||
std::optional<std::uint16_t> vendorId = std::nullopt, std::optional<std::uint16_t> productId = std::nullopt
|
||||
);
|
||||
|
||||
void close();
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user