Switched to automatic storage for EDBG AVR command frame payloads that are fixed in size, in the EDBG driver.
This means we don't have to keep allocating space (using std::vector) for each command payload, when the payload is fixed in size. Also, some general tidying of the EDBG AVR command frames.
This commit is contained in:
@@ -97,7 +97,6 @@ add_executable(Bloom
|
|||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.cpp
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/Response.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/Response.cpp
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrCommand.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrCommand.cpp
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/AvrCommandFrame.cpp
|
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/AVR8Generic/ReadMemory.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/AVR8Generic/ReadMemory.cpp
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrResponse.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrResponse.cpp
|
||||||
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AvrResponseFrame.cpp
|
src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AvrResponseFrame.cpp
|
||||||
|
|||||||
@@ -10,7 +10,15 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
class AvrCommand: public Command
|
class AvrCommand: public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AvrCommand() {
|
AvrCommand(
|
||||||
|
std::size_t fragmentCount,
|
||||||
|
std::size_t fragmentNumber,
|
||||||
|
std::vector<unsigned char> commandPacket
|
||||||
|
)
|
||||||
|
: fragmentCount(fragmentCount)
|
||||||
|
, fragmentNumber(fragmentNumber)
|
||||||
|
, commandPacket(std::move(commandPacket))
|
||||||
|
{
|
||||||
this->setCommandId(0x80);
|
this->setCommandId(0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,26 +33,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
return this->fragmentNumber;
|
return this->fragmentNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFragmentNumber(std::size_t fragmentNumber) {
|
|
||||||
this->fragmentNumber = fragmentNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::size_t getFragmentCount() const {
|
[[nodiscard]] std::size_t getFragmentCount() const {
|
||||||
return this->fragmentCount;
|
return this->fragmentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFragmentCount(std::size_t fragmentCount) {
|
|
||||||
this->fragmentCount = fragmentCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<unsigned char>& getCommandPacket() const {
|
[[nodiscard]] const std::vector<unsigned char>& getCommandPacket() const {
|
||||||
return this->commandPacket;
|
return this->commandPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCommandPacket(const std::vector<unsigned char>& commandPacket) {
|
|
||||||
this->commandPacket = commandPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t fragmentNumber = 1;
|
std::size_t fragmentNumber = 1;
|
||||||
std::size_t fragmentCount = 1;
|
std::size_t fragmentCount = 1;
|
||||||
|
|||||||
@@ -4,33 +4,22 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class ActivatePhysical: public Avr8GenericCommandFrame
|
class ActivatePhysical: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ActivatePhysical() = default;
|
explicit ActivatePhysical(bool reset) {
|
||||||
explicit ActivatePhysical(bool reset): reset(reset) {};
|
|
||||||
|
|
||||||
void setReset(bool reset) {
|
|
||||||
this->reset = reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The activate physical command consists of 3 bytes:
|
* The activate physical command consists of 3 bytes:
|
||||||
* 1. Command ID (0x10)
|
* 1. Command ID (0x10)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. Reset flag (to apply external reset)
|
* 3. Reset flag (to apply external reset)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(3, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x10;
|
0x10,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = static_cast<unsigned char>(this->reset);
|
static_cast<unsigned char>(reset)
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool reset = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,33 +4,21 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Attach: public Avr8GenericCommandFrame
|
class Attach: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Attach() = default;
|
explicit Attach(bool breakAfterAttach) {
|
||||||
explicit Attach(bool breakAfterAttach): breakAfterAttach(breakAfterAttach) {};
|
|
||||||
|
|
||||||
void setBreadAfterAttach(bool breakAfterAttach) {
|
|
||||||
this->breakAfterAttach = breakAfterAttach;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The attach command consists of 3 bytes:
|
* The attach command consists of 3 bytes:
|
||||||
* 1. Command ID (0x13)
|
* 1. Command ID (0x13)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. Break (stop) after attach flag
|
* 3. Break (stop) after attach flag
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(3, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x13;
|
0x13,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = static_cast<unsigned char>(this->breakAfterAttach);
|
static_cast<unsigned char>(breakAfterAttach)
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool breakAfterAttach = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Avr8GenericCommandFrame: public AvrCommandFrame
|
template<class PayloadContainerType>
|
||||||
|
class Avr8GenericCommandFrame: public AvrCommandFrame<PayloadContainerType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = ResponseFrames::Avr8Generic::Avr8GenericResponseFrame;
|
using ResponseFrameType = ResponseFrames::Avr8Generic::Avr8GenericResponseFrame;
|
||||||
|
|||||||
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class ClearAllSoftwareBreakpoints: public Avr8GenericCommandFrame
|
class ClearAllSoftwareBreakpoints: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClearAllSoftwareBreakpoints() {
|
ClearAllSoftwareBreakpoints() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The clear all software breakpoints command consists of 2 bytes:
|
* The clear all software breakpoints command consists of 2 bytes:
|
||||||
* 1. Command ID (0x45)
|
* 1. Command ID (0x45)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x45;
|
0x45,
|
||||||
payload[1] = 0x00;
|
0x00,
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class ClearSoftwareBreakpoints: public Avr8GenericCommandFrame
|
class ClearSoftwareBreakpoints: public Avr8GenericCommandFrame<std::vector<unsigned char>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClearSoftwareBreakpoints() = default;
|
explicit ClearSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses) {
|
||||||
|
|
||||||
explicit ClearSoftwareBreakpoints(std::vector<std::uint32_t> addresses): addresses(std::move(addresses)) {}
|
|
||||||
|
|
||||||
void setAddresses(const std::vector<std::uint32_t>& addresses) {
|
|
||||||
this->addresses = addresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The clear software breakpoints command consists of 2 bytes + 4*n bytes, where n is the number
|
* The clear software breakpoints command consists of 2 bytes + 4*n bytes, where n is the number
|
||||||
* of breakpoints to clear:
|
* of breakpoints to clear:
|
||||||
@@ -27,21 +19,17 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* ... addresses
|
* ... addresses
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(2, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x44;
|
0x44,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
for (const auto& address : this->addresses) {
|
for (const auto& address : addresses) {
|
||||||
output.push_back(static_cast<unsigned char>(address));
|
this->payload.emplace_back(static_cast<unsigned char>(address));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 8));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 8));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 16));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 16));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 24));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::uint32_t> addresses;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class DeactivatePhysical: public Avr8GenericCommandFrame
|
class DeactivatePhysical: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DeactivatePhysical() {
|
DeactivatePhysical() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The deactivate physical command consists of 2 bytes:
|
* The deactivate physical command consists of 2 bytes:
|
||||||
* 1. Command ID (0x11)
|
* 1. Command ID (0x11)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x11;
|
0x11,
|
||||||
payload[1] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Detach: public Avr8GenericCommandFrame
|
class Detach: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Detach() {
|
Detach() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The detach command consists of 2 bytes:
|
* The detach command consists of 2 bytes:
|
||||||
* 1. Command ID (0x11)
|
* 1. Command ID (0x14)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x11;
|
0x14,
|
||||||
payload[1] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class DisableDebugWire: public Avr8GenericCommandFrame
|
class DisableDebugWire: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DisableDebugWire() {
|
DisableDebugWire() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The disable debugWire command consists of 2 bytes:
|
* The disable debugWire command consists of 2 bytes:
|
||||||
* 1. Command ID (0x17)
|
* 1. Command ID (0x17)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x17;
|
0x17,
|
||||||
payload[1] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,21 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class GetDeviceId: public Avr8GenericCommandFrame
|
class GetDeviceId: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetDeviceId;
|
using ResponseFrameType = ResponseFrames::Avr8Generic::GetDeviceId;
|
||||||
|
|
||||||
GetDeviceId() {
|
GetDeviceId() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The get device ID command consists of 2 bytes:
|
* The get device ID command consists of 2 bytes:
|
||||||
* 1. Command ID (0x12)
|
* 1. Command ID (0x12)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x12;
|
0x12,
|
||||||
payload[1] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,28 +6,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class GetParameter: public Avr8GenericCommandFrame
|
class GetParameter: public Avr8GenericCommandFrame<std::array<unsigned char, 5>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GetParameter() = default;
|
GetParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
|
||||||
|
|
||||||
explicit GetParameter(const Avr8EdbgParameter& parameter) {
|
|
||||||
this->setParameter(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
GetParameter(const Avr8EdbgParameter& parameter, std::uint8_t size): GetParameter(parameter) {
|
|
||||||
this->setSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameter(const Avr8EdbgParameter& parameter) {
|
|
||||||
this->parameter = parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSize(std::uint8_t size) {
|
|
||||||
this->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The get param command consists of 5 bytes:
|
* The get param command consists of 5 bytes:
|
||||||
* 1. Command ID (0x02)
|
* 1. Command ID (0x02)
|
||||||
@@ -36,18 +18,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 4. Param ID (Avr8Parameter::id)
|
* 4. Param ID (Avr8Parameter::id)
|
||||||
* 5. Param value length (this->size)
|
* 5. Param value length (this->size)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(5, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x02;
|
0x02,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = static_cast<unsigned char>(this->parameter.context);
|
static_cast<unsigned char>(parameter.context),
|
||||||
output[3] = static_cast<unsigned char>(this->parameter.id);
|
static_cast<unsigned char>(parameter.id),
|
||||||
output[4] = static_cast<unsigned char>(this->size);
|
static_cast<unsigned char>(size)
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Avr8EdbgParameter parameter;
|
|
||||||
std::uint8_t size = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,21 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class GetProgramCounter: public Avr8GenericCommandFrame
|
class GetProgramCounter: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = ResponseFrames::Avr8Generic::GetProgramCounter;
|
using ResponseFrameType = ResponseFrames::Avr8Generic::GetProgramCounter;
|
||||||
|
|
||||||
GetProgramCounter() {
|
GetProgramCounter() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The PC Read command consists of 2 bytes:
|
* The PC Read command consists of 2 bytes:
|
||||||
* 1. Command ID (0x35)
|
* 1. Command ID (0x35)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x35;
|
0x35,
|
||||||
payload[1] = 0x00;
|
0x00,
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,12 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> ReadMemory::getPayload() const {
|
ReadMemory::ReadMemory(
|
||||||
|
const Avr8MemoryType& type,
|
||||||
|
std::uint32_t address,
|
||||||
|
std::uint32_t bytes,
|
||||||
|
const std::set<std::uint32_t>& excludedAddresses
|
||||||
|
) {
|
||||||
/*
|
/*
|
||||||
* The read memory command consists of 11/11 + (this->bytes / 8) bytes:
|
* The read memory command consists of 11/11 + (this->bytes / 8) bytes:
|
||||||
* 1. Command ID (0x21 for the general read memory command, 0x22 for reading with a mask)
|
* 1. Command ID (0x21 for the general read memory command, 0x22 for reading with a mask)
|
||||||
@@ -15,43 +20,41 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 5. Number of bytes to read (4 bytes)
|
* 5. Number of bytes to read (4 bytes)
|
||||||
* 6. Mask to apply (this->bytes / 8) - only required if we're using the masked read command (command ID 0x22).
|
* 6. Mask to apply (this->bytes / 8) - only required if we're using the masked read command (command ID 0x22).
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(11, 0x00);
|
this->payload = std::vector<unsigned char>(11, 0x00);
|
||||||
output[0] = this->excludedAddresses.empty() ? 0x21 : 0x22;
|
this->payload[0] = excludedAddresses.empty() ? 0x21 : 0x22;
|
||||||
output[1] = 0x00;
|
this->payload[1] = 0x00;
|
||||||
output[2] = static_cast<unsigned char>(this->type);
|
this->payload[2] = static_cast<unsigned char>(type);
|
||||||
output[3] = static_cast<unsigned char>(this->address);
|
this->payload[3] = static_cast<unsigned char>(address);
|
||||||
output[4] = static_cast<unsigned char>(this->address >> 8);
|
this->payload[4] = static_cast<unsigned char>(address >> 8);
|
||||||
output[5] = static_cast<unsigned char>(this->address >> 16);
|
this->payload[5] = static_cast<unsigned char>(address >> 16);
|
||||||
output[6] = static_cast<unsigned char>(this->address >> 24);
|
this->payload[6] = static_cast<unsigned char>(address >> 24);
|
||||||
output[7] = static_cast<unsigned char>(this->bytes);
|
this->payload[7] = static_cast<unsigned char>(bytes);
|
||||||
output[8] = static_cast<unsigned char>(this->bytes >> 8);
|
this->payload[8] = static_cast<unsigned char>(bytes >> 8);
|
||||||
output[9] = static_cast<unsigned char>(this->bytes >> 16);
|
this->payload[9] = static_cast<unsigned char>(bytes >> 16);
|
||||||
output[10] = static_cast<unsigned char>(this->bytes >> 24);
|
this->payload[10] = static_cast<unsigned char>(bytes >> 24);
|
||||||
|
|
||||||
if (!this->excludedAddresses.empty()) {
|
if (!excludedAddresses.empty()) {
|
||||||
const auto endAddress = this->address + (this->bytes - 1);
|
const auto endAddress = address + (bytes - 1);
|
||||||
|
|
||||||
constexpr auto byteBitSize = std::numeric_limits<unsigned char>::digits;
|
constexpr auto byteBitSize = std::numeric_limits<unsigned char>::digits;
|
||||||
auto byteBitset = std::bitset<byteBitSize>();
|
auto byteBitset = std::bitset<byteBitSize>();
|
||||||
byteBitset.reset();
|
byteBitset.reset();
|
||||||
|
|
||||||
for (std::uint32_t address = this->address; address <= endAddress; address++) {
|
for (std::uint32_t address = address; address <= endAddress; address++) {
|
||||||
auto addressIndex = address - this->address;
|
auto addressIndex = address - address;
|
||||||
auto bitIndex = static_cast<std::size_t>(
|
auto bitIndex = static_cast<std::size_t>(
|
||||||
addressIndex - (std::floor(addressIndex / byteBitSize) * byteBitSize)
|
addressIndex - (std::floor(addressIndex / byteBitSize) * byteBitSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!this->excludedAddresses.contains(address)) {
|
if (!excludedAddresses.contains(address)) {
|
||||||
byteBitset[bitIndex] = 1;
|
byteBitset[bitIndex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address > 0 && (bitIndex == 7 || address == endAddress)) {
|
if (address > 0 && (bitIndex == 7 || address == endAddress)) {
|
||||||
output.emplace_back(byteBitset.to_ulong());
|
this->payload.emplace_back(byteBitset.to_ulong());
|
||||||
byteBitset.reset();
|
byteBitset.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,35 +8,16 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class ReadMemory: public Avr8GenericCommandFrame
|
class ReadMemory: public Avr8GenericCommandFrame<std::vector<unsigned char>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = ResponseFrames::Avr8Generic::ReadMemory;
|
using ResponseFrameType = ResponseFrames::Avr8Generic::ReadMemory;
|
||||||
|
|
||||||
ReadMemory() = default;
|
ReadMemory(
|
||||||
|
const Avr8MemoryType& type,
|
||||||
void setType(const Avr8MemoryType& type) {
|
std::uint32_t address,
|
||||||
this->type = type;
|
std::uint32_t bytes,
|
||||||
}
|
const std::set<std::uint32_t>& excludedAddresses = {}
|
||||||
|
);
|
||||||
void setAddress(std::uint32_t address) {
|
|
||||||
this->address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes(std::uint32_t bytes) {
|
|
||||||
this->bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setExcludedAddresses(const std::set<std::uint32_t>& excludedAddresses) {
|
|
||||||
this->excludedAddresses = excludedAddresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,32 +4,21 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Reset: public Avr8GenericCommandFrame
|
class Reset: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Reset() = default;
|
explicit Reset(bool stopAtMainAddress = false) {
|
||||||
explicit Reset(bool stopAtMainAddress): stopAtMainAddress(stopAtMainAddress) {};
|
|
||||||
|
|
||||||
void setStopAtMainAddress(bool stopAtMainAddress) {
|
|
||||||
this->stopAtMainAddress = stopAtMainAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The reset command consists of 3 bytes:
|
* The reset command consists of 3 bytes:
|
||||||
* 1. Command ID (0x30)
|
* 1. Command ID (0x30)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. "Level" (0x01 to stop at boot reset vector or 0x02 to stop at main address)
|
* 3. "Level" (0x01 to stop at boot reset vector or 0x02 to stop at main address)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(3, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x30;
|
0x30,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = this->stopAtMainAddress ? 0x02 : 0x01;
|
static_cast<unsigned char>(stopAtMainAddress ? 0x02 : 0x01),
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool stopAtMainAddress = false;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,19 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Run: public Avr8GenericCommandFrame
|
class Run: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Run() {
|
Run() {
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The run command consists of 2 bytes:
|
* The run command consists of 2 bytes:
|
||||||
* 1. Command ID (0x32)
|
* 1. Command ID (0x32)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x32;
|
0x32,
|
||||||
payload[1] = 0x00;
|
0x00,
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class RunTo: public Avr8GenericCommandFrame
|
class RunTo: public Avr8GenericCommandFrame<std::array<unsigned char, 6>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RunTo() = default;
|
explicit RunTo(const std::uint32_t& address) {
|
||||||
|
|
||||||
explicit RunTo(const std::uint32_t& address): address(address) {}
|
|
||||||
|
|
||||||
void setAddress(const std::uint32_t& address) {
|
|
||||||
this->address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The run-to command consists of 6 bytes:
|
* The run-to command consists of 6 bytes:
|
||||||
*
|
*
|
||||||
@@ -25,21 +17,18 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. Address to run to (4 bytes)
|
* 3. Address to run to (4 bytes)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(6, 0x00);
|
|
||||||
output[0] = 0x33;
|
|
||||||
output[1] = 0x00;
|
|
||||||
|
|
||||||
// The address to run to needs to be the 16-bit word address, not the byte address.
|
// The address to run to needs to be the 16-bit word address, not the byte address.
|
||||||
auto wordAddress = this->address / 2;
|
const auto wordAddress = address / 2;
|
||||||
output[2] = (static_cast<unsigned char>(wordAddress));
|
|
||||||
output[3] = (static_cast<unsigned char>(wordAddress >> 8));
|
|
||||||
output[4] = (static_cast<unsigned char>(wordAddress >> 16));
|
|
||||||
output[5] = (static_cast<unsigned char>(wordAddress >> 24));
|
|
||||||
|
|
||||||
return output;
|
this->payload = {
|
||||||
|
0x33,
|
||||||
|
0x00,
|
||||||
|
static_cast<unsigned char>(wordAddress),
|
||||||
|
static_cast<unsigned char>(wordAddress >> 8),
|
||||||
|
static_cast<unsigned char>(wordAddress >> 16),
|
||||||
|
static_cast<unsigned char>(wordAddress >> 24),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
std::uint32_t address = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,36 +4,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class SetParameter: public Avr8GenericCommandFrame
|
class SetParameter: public Avr8GenericCommandFrame<std::vector<unsigned char>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetParameter() = default;
|
SetParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
|
||||||
|
|
||||||
explicit SetParameter(const Avr8EdbgParameter& parameter) {
|
|
||||||
this->setParameter(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value): SetParameter(parameter) {
|
|
||||||
this->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetParameter(const Avr8EdbgParameter& parameter, unsigned char value): SetParameter(parameter) {
|
|
||||||
this->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameter(const Avr8EdbgParameter& parameter) {
|
|
||||||
this->parameter = parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue(const std::vector<unsigned char>& value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue(unsigned char value) {
|
|
||||||
this->value.resize(1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The set param command consists of this->value.size() + 5 bytes. The first five bytes consist of:
|
* The set param command consists of this->value.size() + 5 bytes. The first five bytes consist of:
|
||||||
* 1. Command ID (0x01)
|
* 1. Command ID (0x01)
|
||||||
@@ -43,19 +17,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 5. Param value length (this->value.size()) - this is only one byte in size, so its value should
|
* 5. Param value length (this->value.size()) - this is only one byte in size, so its value should
|
||||||
* never exceed 255.
|
* never exceed 255.
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(this->value.size() + 5, 0x00);
|
this->payload = std::vector<unsigned char>(value.size() + 5, 0x00);
|
||||||
output[0] = 0x01;
|
this->payload[0] = 0x01;
|
||||||
output[1] = 0x00;
|
this->payload[1] = 0x00;
|
||||||
output[2] = static_cast<unsigned char>(this->parameter.context);
|
this->payload[2] = static_cast<unsigned char>(parameter.context);
|
||||||
output[3] = static_cast<unsigned char>(this->parameter.id);
|
this->payload[3] = static_cast<unsigned char>(parameter.id);
|
||||||
output[4] = static_cast<unsigned char>(this->value.size());
|
this->payload[4] = static_cast<unsigned char>(value.size());
|
||||||
output.insert(output.begin() + 5, this->value.begin(), this->value.end());
|
this->payload.insert(this->payload.begin() + 5, value.begin(), value.end());
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Avr8EdbgParameter parameter;
|
|
||||||
std::vector<unsigned char> value;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,24 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class SetProgramCounter: public Avr8GenericCommandFrame
|
class SetProgramCounter: public Avr8GenericCommandFrame<std::array<unsigned char, 6>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SetProgramCounter(std::uint32_t programCounter): programCounter(programCounter) {}
|
explicit SetProgramCounter(std::uint32_t programCounter) {
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The PC write command consists of 6 bytes:
|
* The PC write command consists of 6 bytes:
|
||||||
* 1. Command ID (0x01)
|
* 1. Command ID (0x36)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. PC (4 bytes, LSB)
|
* 3. PC (4 bytes, LSB)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(6, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x36;
|
0x36,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = static_cast<unsigned char>(this->programCounter);
|
static_cast<unsigned char>(programCounter),
|
||||||
output[3] = static_cast<unsigned char>(this->programCounter >> 8);
|
static_cast<unsigned char>(programCounter >> 8),
|
||||||
output[4] = static_cast<unsigned char>(this->programCounter >> 16);
|
static_cast<unsigned char>(programCounter >> 16),
|
||||||
output[5] = static_cast<unsigned char>(this->programCounter >> 24);
|
static_cast<unsigned char>(programCounter >> 24),
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
std::uint32_t programCounter = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class SetSoftwareBreakpoints: public Avr8GenericCommandFrame
|
class SetSoftwareBreakpoints: public Avr8GenericCommandFrame<std::vector<unsigned char>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetSoftwareBreakpoints() = default;
|
explicit SetSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses) {
|
||||||
|
|
||||||
explicit SetSoftwareBreakpoints(std::vector<std::uint32_t> addresses): addresses(std::move(addresses)) {}
|
|
||||||
|
|
||||||
void setAddresses(const std::vector<std::uint32_t>& addresses) {
|
|
||||||
this->addresses = addresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The set software breakpoint command consists of 2 bytes + 4*n bytes, where n is the number
|
* The set software breakpoint command consists of 2 bytes + 4*n bytes, where n is the number
|
||||||
* of breakpoints to set:
|
* of breakpoints to set:
|
||||||
@@ -27,21 +19,17 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* ... addresses
|
* ... addresses
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(2, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x43;
|
0x43,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
for (const auto& address : this->addresses) {
|
for (const auto& address : addresses) {
|
||||||
output.push_back(static_cast<unsigned char>(address));
|
this->payload.emplace_back(static_cast<unsigned char>(address));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 8));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 8));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 16));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 16));
|
||||||
output.push_back(static_cast<unsigned char>(address >> 24));
|
this->payload.emplace_back(static_cast<unsigned char>(address >> 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::uint32_t> addresses;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,39 +6,27 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class SetXmegaSoftwareBreakpoint: public Avr8GenericCommandFrame
|
class SetXmegaSoftwareBreakpoint: public Avr8GenericCommandFrame<std::array<unsigned char, 15>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetXmegaSoftwareBreakpoint() = default;
|
explicit SetXmegaSoftwareBreakpoint(std::uint32_t address) {
|
||||||
|
this->payload = {
|
||||||
explicit SetXmegaSoftwareBreakpoint(std::uint32_t address): address(address) {}
|
0x42,
|
||||||
|
0x00,
|
||||||
void setAddress(std::uint32_t address) {
|
static_cast<unsigned char>(address),
|
||||||
this->address = address;
|
static_cast<unsigned char>(address >> 8),
|
||||||
|
static_cast<unsigned char>(address >> 16),
|
||||||
|
static_cast<unsigned char>(address >> 24),
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
|
||||||
* The set software breakpoint command consists of 6 bytes bytes
|
|
||||||
*
|
|
||||||
* 1. Command ID (0x42)
|
|
||||||
* 2. Version (0x00)
|
|
||||||
* 3. Address (4 bytes)
|
|
||||||
*/
|
|
||||||
auto output = std::vector<unsigned char>(15, 0x00);
|
|
||||||
output[0] = 0x42;
|
|
||||||
output[1] = 0x00;
|
|
||||||
output[2] = static_cast<unsigned char>(address);
|
|
||||||
output[3] = static_cast<unsigned char>(address >> 8);
|
|
||||||
output[4] = static_cast<unsigned char>(address >> 16);
|
|
||||||
output[5] = static_cast<unsigned char>(address >> 24);
|
|
||||||
output[13] = 0x01; // One breakpoint
|
|
||||||
output[14] = 0x00;
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::uint32_t address = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Step: public Avr8GenericCommandFrame
|
class Step: public Avr8GenericCommandFrame<std::array<unsigned char, 4>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Step() = default;
|
Step() {
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The step command consists of 4 bytes:
|
* The step command consists of 4 bytes:
|
||||||
* 1. Command ID (0x34)
|
* 1. Command ID (0x34)
|
||||||
@@ -17,13 +15,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 3. Level (0x01 for instruction level step, 0x02 for statement level step)
|
* 3. Level (0x01 for instruction level step, 0x02 for statement level step)
|
||||||
* 4. Mode (0x00 for step over, 0x01 for step into, 0x02 for step out)
|
* 4. Mode (0x00 for step over, 0x01 for step into, 0x02 for step out)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(4, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x34;
|
0x34,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = 0x01;
|
0x01,
|
||||||
output[3] = 0x01;
|
0x01,
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,32 +4,21 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class Stop: public Avr8GenericCommandFrame
|
class Stop: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Stop() = default;
|
explicit Stop(bool stopImmediately = true) {
|
||||||
explicit Stop(bool stopImmediately): stopImmediately(stopImmediately) {};
|
|
||||||
|
|
||||||
void setStopImmediately(bool stopImmediately) {
|
|
||||||
this->stopImmediately = stopImmediately;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The stop command consists of 3 bytes:
|
* The stop command consists of 3 bytes:
|
||||||
* 1. Command ID (0x31)
|
* 1. Command ID (0x31)
|
||||||
* 2. Version (0x00)
|
* 2. Version (0x00)
|
||||||
* 3. Stop immediately (0x01 to stop immediately or 0x02 to stop at the next symbol)
|
* 3. Stop immediately (0x01 to stop immediately or 0x02 to stop at the next symbol)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(3, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x31;
|
0x31,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = this->stopImmediately ? 0x01 : 0x02;
|
static_cast<unsigned char>(stopImmediately ? 0x01 : 0x02),
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool stopImmediately = true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||||
{
|
{
|
||||||
class WriteMemory: public Avr8GenericCommandFrame
|
class WriteMemory: public Avr8GenericCommandFrame<std::vector<unsigned char>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WriteMemory() = default;
|
WriteMemory(const Avr8MemoryType& type, std::uint32_t address, const Targets::TargetMemoryBuffer& buffer) {
|
||||||
|
|
||||||
void setType(const Avr8MemoryType& type) {
|
|
||||||
this->type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAddress(std::uint32_t address) {
|
|
||||||
this->address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBuffer(const Targets::TargetMemoryBuffer& buffer) {
|
|
||||||
this->buffer = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The write memory command consists of 12 bytes + the buffer size:
|
* The write memory command consists of 12 bytes + the buffer size:
|
||||||
* 1. Command ID (0x23)
|
* 1. Command ID (0x23)
|
||||||
@@ -35,32 +21,25 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 6. Asynchronous flag (0x00 for "write first, then reply" and 0x01 for "reply first, then write")
|
* 6. Asynchronous flag (0x00 for "write first, then reply" and 0x01 for "reply first, then write")
|
||||||
* 7. Buffer
|
* 7. Buffer
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(12, 0x00);
|
this->payload = std::vector<unsigned char>(12 + buffer.size(), 0x00);
|
||||||
output[0] = 0x23;
|
this->payload[0] = 0x23;
|
||||||
output[1] = 0x00;
|
this->payload[1] = 0x00;
|
||||||
output[2] = static_cast<unsigned char>(this->type);
|
this->payload[2] = static_cast<unsigned char>(type);
|
||||||
output[3] = static_cast<unsigned char>(this->address);
|
this->payload[3] = static_cast<unsigned char>(address);
|
||||||
output[4] = static_cast<unsigned char>(this->address >> 8);
|
this->payload[4] = static_cast<unsigned char>(address >> 8);
|
||||||
output[5] = static_cast<unsigned char>(this->address >> 16);
|
this->payload[5] = static_cast<unsigned char>(address >> 16);
|
||||||
output[6] = static_cast<unsigned char>(this->address >> 24);
|
this->payload[6] = static_cast<unsigned char>(address >> 24);
|
||||||
|
|
||||||
auto bytesToWrite = static_cast<std::uint32_t>(this->buffer.size());
|
auto bytesToWrite = static_cast<std::uint32_t>(buffer.size());
|
||||||
output[7] = static_cast<unsigned char>(bytesToWrite);
|
this->payload[7] = static_cast<unsigned char>(bytesToWrite);
|
||||||
output[8] = static_cast<unsigned char>(bytesToWrite >> 8);
|
this->payload[8] = static_cast<unsigned char>(bytesToWrite >> 8);
|
||||||
output[9] = static_cast<unsigned char>(bytesToWrite >> 16);
|
this->payload[9] = static_cast<unsigned char>(bytesToWrite >> 16);
|
||||||
output[10] = static_cast<unsigned char>(bytesToWrite >> 24);
|
this->payload[10] = static_cast<unsigned char>(bytesToWrite >> 24);
|
||||||
|
|
||||||
// We always set the async flag to 0x00 ("write first, then reply")
|
// We always set the async flag to 0x00 ("write first, then reply")
|
||||||
output[11] = 0x00;
|
this->payload[11] = 0x00;
|
||||||
|
|
||||||
output.insert(output.end(), this->buffer.begin(), this->buffer.end());
|
this->payload.insert(this->payload.begin() + 12, buffer.begin(), buffer.end());
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Avr8MemoryType type = Avr8MemoryType::SRAM;
|
|
||||||
std::uint32_t address = 0;
|
|
||||||
Targets::TargetMemoryBuffer buffer;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
#include "AvrCommandFrame.hpp"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|
||||||
{
|
|
||||||
std::vector<AvrCommand> AvrCommandFrame::generateAvrCommands(std::size_t maximumCommandPacketSize) const {
|
|
||||||
auto rawCommandFrame = static_cast<std::vector<unsigned char>>(*this);
|
|
||||||
std::size_t commandFrameSize = rawCommandFrame.size();
|
|
||||||
auto commandsRequired = static_cast<std::size_t>(
|
|
||||||
ceil(static_cast<float>(commandFrameSize) / static_cast<float>(maximumCommandPacketSize))
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<AvrCommand> avrCommands;
|
|
||||||
std::size_t copiedPacketSize = 0;
|
|
||||||
for (std::size_t i = 0; i < commandsRequired; i++) {
|
|
||||||
AvrCommand avrCommand;
|
|
||||||
avrCommand.setFragmentCount(commandsRequired);
|
|
||||||
avrCommand.setFragmentNumber(i + 1);
|
|
||||||
auto commandPacket = avrCommand.getCommandPacket();
|
|
||||||
|
|
||||||
// If we're on the last packet, the packet size will be what ever is left of the AvrCommandFrame
|
|
||||||
std::size_t commandPacketSize = ((i + 1) != commandsRequired) ? maximumCommandPacketSize
|
|
||||||
: (commandFrameSize - (maximumCommandPacketSize * i));
|
|
||||||
|
|
||||||
commandPacket.insert(
|
|
||||||
commandPacket.end(),
|
|
||||||
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize),
|
|
||||||
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize + commandPacketSize)
|
|
||||||
);
|
|
||||||
|
|
||||||
avrCommand.setCommandPacket(commandPacket);
|
|
||||||
avrCommands.push_back(avrCommand);
|
|
||||||
copiedPacketSize += commandPacketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return avrCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
AvrCommandFrame::operator std::vector<unsigned char>() const {
|
|
||||||
auto data = this->getPayload();
|
|
||||||
auto dataSize = data.size();
|
|
||||||
|
|
||||||
auto rawCommand = std::vector<unsigned char>(5);
|
|
||||||
|
|
||||||
rawCommand[0] = this->SOF;
|
|
||||||
rawCommand[1] = this->getProtocolVersion();
|
|
||||||
|
|
||||||
rawCommand[2] = static_cast<unsigned char>(this->getSequenceId());
|
|
||||||
rawCommand[3] = static_cast<unsigned char>(this->getSequenceId() >> 8);
|
|
||||||
|
|
||||||
rawCommand[4] = static_cast<unsigned char>(this->getProtocolHandlerId());
|
|
||||||
|
|
||||||
if (dataSize > 0) {
|
|
||||||
rawCommand.insert(
|
|
||||||
rawCommand.end(),
|
|
||||||
data.begin(),
|
|
||||||
data.end()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rawCommand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <cmath>
|
||||||
|
#include <atomic>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.hpp"
|
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Command.hpp"
|
||||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/Edbg.hpp"
|
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/Edbg.hpp"
|
||||||
@@ -12,27 +15,59 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||||
{
|
{
|
||||||
|
static inline std::atomic<std::uint16_t> LAST_SEQUENCE_ID = 0;
|
||||||
|
|
||||||
|
template <class PayloadContainerType = std::vector<unsigned char>>
|
||||||
class AvrCommandFrame
|
class AvrCommandFrame
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Every AVR command frame contains a payload. For many commands, the payload size is fixed, meaning we can
|
||||||
|
* use automatic storage. In other cases, the size of the payload is determined at runtime, requiring the use
|
||||||
|
* of dynamic storage.
|
||||||
|
*
|
||||||
|
* For example, consider the Get Device ID command from the AVR8 Generic Protocol. The size of the payload
|
||||||
|
* for this command is fixed at 2 bytes. So there is no need to use dynamic storage duration for the payload.
|
||||||
|
*
|
||||||
|
* Now consider the Write Memory command from the same protocol. The payload size for that command depends
|
||||||
|
* on the size of memory we wish to write, which is not known at compile time. For this command, the payload
|
||||||
|
* would have dynamic storage.
|
||||||
|
*
|
||||||
|
* For the above reason, the AvrCommandFrame class is a template class in which the payload container type can
|
||||||
|
* be specified for individual commands.
|
||||||
|
*
|
||||||
|
* For now, we only permit two payload container types:
|
||||||
|
* - std::array<unsigned char> for payloads with automatic storage duration.
|
||||||
|
* - std::vector<unsigned char> for payloads with dynamic storage duration.
|
||||||
|
*/
|
||||||
|
static_assert(
|
||||||
|
(
|
||||||
|
std::is_same_v<PayloadContainerType, std::vector<unsigned char>>
|
||||||
|
|| std::is_same_v<typename PayloadContainerType::value_type, unsigned char>
|
||||||
|
),
|
||||||
|
"Invalid payload container type - must be an std::array<unsigned char, X> or an std::vector<unsigned char>"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = AvrResponseFrame;
|
using ResponseFrameType = AvrResponseFrame;
|
||||||
|
|
||||||
AvrCommandFrame() {
|
AvrCommandFrame() {
|
||||||
if (AvrCommandFrame::lastSequenceId < std::numeric_limits<decltype(AvrCommandFrame::lastSequenceId)>::max()) {
|
if (LAST_SEQUENCE_ID < std::numeric_limits<decltype(LAST_SEQUENCE_ID)>::max()) {
|
||||||
this->sequenceId = ++(AvrCommandFrame::lastSequenceId);
|
this->sequenceId = ++(LAST_SEQUENCE_ID);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this->sequenceId = 0;
|
this->sequenceId = 0;
|
||||||
AvrCommandFrame::lastSequenceId = 0;
|
LAST_SEQUENCE_ID = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~AvrCommandFrame() = default;
|
virtual ~AvrCommandFrame() = default;
|
||||||
|
|
||||||
AvrCommandFrame(const AvrCommandFrame& other) = default;
|
AvrCommandFrame(const AvrCommandFrame& other) = default;
|
||||||
AvrCommandFrame(AvrCommandFrame&& other) = default;
|
AvrCommandFrame(AvrCommandFrame&& other) noexcept = default;
|
||||||
|
|
||||||
AvrCommandFrame& operator = (const AvrCommandFrame& other) = default;
|
AvrCommandFrame& operator = (const AvrCommandFrame& other) = default;
|
||||||
AvrCommandFrame& operator = (AvrCommandFrame&& other) = default;
|
AvrCommandFrame& operator = (AvrCommandFrame&& other) noexcept = default;
|
||||||
|
|
||||||
[[nodiscard]] unsigned char getProtocolVersion() const {
|
[[nodiscard]] unsigned char getProtocolVersion() const {
|
||||||
return this->protocolVersion;
|
return this->protocolVersion;
|
||||||
@@ -58,12 +93,38 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
this->protocolHandlerID = static_cast<ProtocolHandlerId>(protocolHandlerId);
|
this->protocolHandlerID = static_cast<ProtocolHandlerId>(protocolHandlerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual std::vector<unsigned char> getPayload() const {
|
[[nodiscard]] virtual const PayloadContainerType& getPayload() const {
|
||||||
return this->payload;
|
return this->payload;
|
||||||
}
|
};
|
||||||
|
|
||||||
void setPayload(const std::vector<unsigned char>& payload) {
|
/**
|
||||||
this->payload = payload;
|
* Converts the command frame into a container of unsigned char - a raw buffer to send to the EDBG device.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] auto getRawCommandFrame() const {
|
||||||
|
auto data = this->getPayload();
|
||||||
|
const auto dataSize = data.size();
|
||||||
|
|
||||||
|
auto rawCommand = std::vector<unsigned char>(5);
|
||||||
|
|
||||||
|
rawCommand[0] = this->SOF;
|
||||||
|
rawCommand[1] = this->getProtocolVersion();
|
||||||
|
|
||||||
|
rawCommand[2] = static_cast<unsigned char>(this->getSequenceId());
|
||||||
|
rawCommand[3] = static_cast<unsigned char>(this->getSequenceId() >> 8);
|
||||||
|
|
||||||
|
rawCommand[4] = static_cast<unsigned char>(this->getProtocolHandlerId());
|
||||||
|
|
||||||
|
if (dataSize > 0) {
|
||||||
|
rawCommand.insert(
|
||||||
|
rawCommand.end(),
|
||||||
|
data.begin(),
|
||||||
|
data.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,14 +144,37 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
* @return
|
* @return
|
||||||
* A vector of sequenced AVRCommands, each containing a segment of the AvrCommandFrame.
|
* A vector of sequenced AVRCommands, each containing a segment of the AvrCommandFrame.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::vector<AvrCommand> generateAvrCommands(std::size_t maximumCommandPacketSize) const;
|
[[nodiscard]] std::vector<AvrCommand> generateAvrCommands(std::size_t maximumCommandPacketSize) const {
|
||||||
|
auto rawCommandFrame = this->getRawCommandFrame();
|
||||||
|
|
||||||
/**
|
std::size_t commandFrameSize = rawCommandFrame.size();
|
||||||
* Converts instance of a CMSIS Command to an unsigned char, for sending to the Atmel ICE device.
|
auto commandsRequired = static_cast<std::size_t>(
|
||||||
*
|
std::ceil(static_cast<float>(commandFrameSize) / static_cast<float>(maximumCommandPacketSize))
|
||||||
* @return
|
);
|
||||||
*/
|
|
||||||
explicit virtual operator std::vector<unsigned char> () const;
|
std::vector<AvrCommand> avrCommands;
|
||||||
|
std::size_t copiedPacketSize = 0;
|
||||||
|
for (std::size_t i = 0; i < commandsRequired; i++) {
|
||||||
|
// If we're on the last packet, the packet size will be what ever is left of the AvrCommandFrame
|
||||||
|
std::size_t commandPacketSize = ((i + 1) != commandsRequired) ? maximumCommandPacketSize
|
||||||
|
: (commandFrameSize - (maximumCommandPacketSize * i));
|
||||||
|
|
||||||
|
avrCommands.emplace_back(AvrCommand(
|
||||||
|
commandsRequired,
|
||||||
|
i + 1,
|
||||||
|
std::vector<unsigned char>(
|
||||||
|
rawCommandFrame.begin() + static_cast<std::int64_t>(copiedPacketSize),
|
||||||
|
rawCommandFrame.begin() + static_cast<std::int64_t>(copiedPacketSize + commandPacketSize)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
copiedPacketSize += commandPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return avrCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PayloadContainerType payload;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned char SOF = 0x0E;
|
unsigned char SOF = 0x0E;
|
||||||
@@ -101,14 +185,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
* Incrementing from 0x00
|
* Incrementing from 0x00
|
||||||
*/
|
*/
|
||||||
std::uint16_t sequenceId = 0;
|
std::uint16_t sequenceId = 0;
|
||||||
inline static std::uint16_t lastSequenceId = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destination sub-protocol handler ID
|
* Destination sub-protocol handler ID
|
||||||
*/
|
*/
|
||||||
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::DISCOVERY;
|
ProtocolHandlerId protocolHandlerID = ProtocolHandlerId::DISCOVERY;
|
||||||
|
|
||||||
std::vector<unsigned char> payload;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
return static_cast<unsigned char>(id) != rawId;
|
return static_cast<unsigned char>(id) != rawId;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiscoveryCommandFrame: public AvrCommandFrame
|
template<class PayloadContainerType>
|
||||||
|
class DiscoveryCommandFrame: public AvrCommandFrame<PayloadContainerType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ResponseFrameType = ResponseFrames::DiscoveryResponseFrame;
|
using ResponseFrameType = ResponseFrames::DiscoveryResponseFrame;
|
||||||
|
|||||||
@@ -19,31 +19,19 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* The Discovery protocol handler only supports one command; the Query command. This command is used to
|
* The Discovery protocol handler only supports one command; the Query command. This command is used to
|
||||||
* query information from the device, such as device capabilities, manufacture date, serial number, etc.
|
* query information from the device, such as device capabilities, manufacture date, serial number, etc.
|
||||||
*/
|
*/
|
||||||
class Query: public DiscoveryCommandFrame
|
class Query: public DiscoveryCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Query(): DiscoveryCommandFrame() {}
|
explicit Query(QueryContext context) {
|
||||||
|
|
||||||
explicit Query(QueryContext context): DiscoveryCommandFrame() {
|
|
||||||
this->setContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setContext(QueryContext context) {
|
|
||||||
this->context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The payload for the Query command consists of three bytes. A command ID (0x00), version (0x00) and a
|
* The payload for the Query command consists of three bytes. A command ID (0x00), version (0x00) and a
|
||||||
* query context.
|
* query context.
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(3, 0x00);
|
this->payload = {
|
||||||
output[2] = static_cast<unsigned char>(this->context);
|
0x00,
|
||||||
|
0x00,
|
||||||
return output;
|
static_cast<unsigned char>(context)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
QueryContext context = QueryContext::COMMAND_HANDLERS;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,19 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
/**
|
/**
|
||||||
* The End Session command ends the active session with the tool.
|
* The End Session command ends the active session with the tool.
|
||||||
*/
|
*/
|
||||||
class EndSession: public HouseKeepingCommandFrame
|
class EndSession: public HouseKeepingCommandFrame<std::array<unsigned char, 3>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EndSession(): HouseKeepingCommandFrame() {
|
EndSession() {
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The payload for the End Session command consists of three bytes. A command ID byte (0x11), a
|
* The payload for the End Session command consists of three bytes. A command ID byte (0x11), a
|
||||||
* version byte (0x00) and a reset flag (0x00 for no reset, 0x01 for tool reset).
|
* version byte (0x00) and a reset flag (0x00 for no reset, 0x01 for tool reset).
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(3);
|
this->payload = {
|
||||||
payload[0] = 0x11;
|
0x11,
|
||||||
payload[1] = 0x00;
|
0x00,
|
||||||
payload[2] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,10 @@
|
|||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::HouseKeeping
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::HouseKeeping
|
||||||
{
|
{
|
||||||
class GetParameter: public HouseKeepingCommandFrame
|
class GetParameter: public HouseKeepingCommandFrame<std::array<unsigned char, 5>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GetParameter(const Parameter& parameter): parameter(parameter) {}
|
explicit GetParameter(const Parameter& parameter, std::uint8_t size) {
|
||||||
|
|
||||||
GetParameter(const Parameter& parameter, std::uint8_t size): GetParameter(parameter) {
|
|
||||||
this->setSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameter(const Parameter& parameter) {
|
|
||||||
this->parameter = parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSize(std::uint8_t size) {
|
|
||||||
this->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::vector<unsigned char> getPayload() const override {
|
|
||||||
/*
|
/*
|
||||||
* The get param command consists of 5 bytes:
|
* The get param command consists of 5 bytes:
|
||||||
* 1. Command ID (0x02)
|
* 1. Command ID (0x02)
|
||||||
@@ -33,18 +19,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
* 4. Param ID (Parameter::id)
|
* 4. Param ID (Parameter::id)
|
||||||
* 5. Param value length (this->size)
|
* 5. Param value length (this->size)
|
||||||
*/
|
*/
|
||||||
auto output = std::vector<unsigned char>(5, 0x00);
|
this->payload = {
|
||||||
output[0] = 0x02;
|
0x02,
|
||||||
output[1] = 0x00;
|
0x00,
|
||||||
output[2] = static_cast<unsigned char>(this->parameter.context);
|
static_cast<unsigned char>(parameter.context),
|
||||||
output[3] = static_cast<unsigned char>(this->parameter.id);
|
static_cast<unsigned char>(parameter.id),
|
||||||
output[4] = static_cast<unsigned char>(this->size);
|
static_cast<unsigned char>(size)
|
||||||
|
};
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Parameter parameter;
|
|
||||||
std::uint8_t size = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
return rawId == id;
|
return rawId == id;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HouseKeepingCommandFrame: public AvrCommandFrame
|
template<class PayloadContainerType>
|
||||||
|
class HouseKeepingCommandFrame: public AvrCommandFrame<PayloadContainerType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HouseKeepingCommandFrame() {
|
HouseKeepingCommandFrame() {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "HouseKeepingCommandFrame.hpp"
|
#include "HouseKeepingCommandFrame.hpp"
|
||||||
|
|
||||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::HouseKeeping
|
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::HouseKeeping
|
||||||
@@ -7,23 +9,18 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
|
|||||||
/**
|
/**
|
||||||
* The Start Session command begins a session with the tool.
|
* The Start Session command begins a session with the tool.
|
||||||
*/
|
*/
|
||||||
class StartSession: public HouseKeepingCommandFrame
|
class StartSession: public HouseKeepingCommandFrame<std::array<unsigned char, 2>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StartSession(): HouseKeepingCommandFrame() {
|
StartSession() {
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() {
|
|
||||||
/*
|
/*
|
||||||
* The payload for the Start Session command consists of two bytes. A command ID byte (0x10) and a
|
* The payload for the Start Session command consists of two bytes. A command ID byte (0x10) and a
|
||||||
* version byte (0x00).
|
* version byte (0x00).
|
||||||
*/
|
*/
|
||||||
auto payload = std::vector<unsigned char>(2);
|
this->payload = {
|
||||||
payload[0] = 0x10;
|
0x10,
|
||||||
payload[1] = 0x00;
|
0x00
|
||||||
this->setPayload(payload);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1459,11 +1459,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto commandFrame = CommandFrames::Avr8Generic::ReadMemory();
|
auto commandFrame = CommandFrames::Avr8Generic::ReadMemory(
|
||||||
commandFrame.setType(type);
|
type,
|
||||||
commandFrame.setAddress(startAddress);
|
startAddress,
|
||||||
commandFrame.setBytes(bytes);
|
bytes,
|
||||||
commandFrame.setExcludedAddresses(excludedAddresses);
|
excludedAddresses
|
||||||
|
);
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||||
@@ -1479,10 +1480,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
throw Exception("Writing to flash memory is not supported.");
|
throw Exception("Writing to flash memory is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto commandFrame = CommandFrames::Avr8Generic::WriteMemory();
|
auto commandFrame = CommandFrames::Avr8Generic::WriteMemory(
|
||||||
commandFrame.setType(type);
|
type,
|
||||||
commandFrame.setAddress(address);
|
address,
|
||||||
commandFrame.setBuffer(buffer);
|
buffer
|
||||||
|
);
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||||
|
|||||||
@@ -8,18 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
{
|
{
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandFrameAndWaitForResponse(
|
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandsAndWaitForResponse(
|
||||||
const Protocols::CmsisDap::Edbg::Avr::AvrCommandFrame& avrCommandFrame
|
const std::vector<Avr::AvrCommand>& avrCommands
|
||||||
) {
|
) {
|
||||||
// An AVR command frame can be split into multiple CMSIS-DAP commands. Each command
|
for (const auto& avrCommand : avrCommands) {
|
||||||
// containing a fragment of the AvrCommandFrame.
|
|
||||||
|
|
||||||
// Minus 3 to accommodate AVR command meta data
|
|
||||||
std::size_t maximumCommandPacketSize = (this->getUsbHidInputReportSize() - 3);
|
|
||||||
|
|
||||||
auto avrCommands = avrCommandFrame.generateAvrCommands(maximumCommandPacketSize);
|
|
||||||
|
|
||||||
for (auto& avrCommand : avrCommands) {
|
|
||||||
// Send command to device
|
// Send command to device
|
||||||
auto response = this->sendCommandAndWaitForResponse(avrCommand);
|
auto response = this->sendCommandAndWaitForResponse(avrCommand);
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,19 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
* @param avrCommandFrame
|
* @param avrCommandFrame
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual Protocols::CmsisDap::Response sendAvrCommandFrameAndWaitForResponse(
|
template <class PayloadContainerType>
|
||||||
const Protocols::CmsisDap::Edbg::Avr::AvrCommandFrame& avrCommandFrame
|
Protocols::CmsisDap::Response sendAvrCommandFrameAndWaitForResponse(
|
||||||
|
const Protocols::CmsisDap::Edbg::Avr::AvrCommandFrame<PayloadContainerType>& avrCommandFrame
|
||||||
|
) {
|
||||||
|
// An AVR command frame can be split into multiple CMSIS-DAP commands. Each command
|
||||||
|
// containing a fragment of the AvrCommandFrame.
|
||||||
|
return this->sendAvrCommandsAndWaitForResponse(avrCommandFrame.generateAvrCommands(
|
||||||
|
this->getUsbHidInputReportSize() - 3 // Minus 3 to accommodate AVR command bytes
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Protocols::CmsisDap::Response sendAvrCommandsAndWaitForResponse(
|
||||||
|
const std::vector<Avr::AvrCommand>& avrCommands
|
||||||
);
|
);
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::Avr::AvrResponse getAvrResponse();
|
Protocols::CmsisDap::Edbg::Avr::AvrResponse getAvrResponse();
|
||||||
@@ -44,12 +55,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
const CommandFrameType& avrCommandFrame
|
const CommandFrameType& avrCommandFrame
|
||||||
) {
|
) {
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_base_of<Protocols::CmsisDap::Edbg::Avr::AvrCommandFrame, CommandFrameType>::value,
|
std::is_base_of<
|
||||||
"AVR Command must be base of AvrCommandFrame."
|
Protocols::CmsisDap::Edbg::Avr::AvrResponseFrame,
|
||||||
);
|
typename CommandFrameType::ResponseFrameType
|
||||||
|
>::value,
|
||||||
static_assert(
|
|
||||||
std::is_base_of<Protocols::CmsisDap::Edbg::Avr::AvrResponseFrame, typename CommandFrameType::ResponseFrameType>::value,
|
|
||||||
"AVR Command must specify a valid response frame type, derived from AvrResponseFrame."
|
"AVR Command must specify a valid response frame type, derived from AvrResponseFrame."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user