Tidying EDBG driver code:

- Binned a lot of pointless code
- Simplified many EDBG data structure implementations
- Const-correctness
- Many other bits of tidying
This commit is contained in:
Nav
2022-10-01 20:42:37 +01:00
parent a5b0097036
commit 2c6fd25ae4
91 changed files with 591 additions and 689 deletions

View File

@@ -20,6 +20,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/AvrResponse.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AvrResponseFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AVR8Generic/Avr8GenericResponseFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AVR8Generic/GetDeviceId.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/Discovery/DiscoveryResponseFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/HouseKeeping/HouseKeepingResponseFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AVRISP/AvrIspResponseFrame.cpp

View File

@@ -58,17 +58,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -76,11 +76,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Atmel-ICE!");
}
@@ -92,11 +92,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Atmel-ICE!");
}

View File

@@ -55,17 +55,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -73,11 +73,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Curiosity Nano!");
}
@@ -89,11 +89,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Curiosity Nano!");
}

View File

@@ -52,17 +52,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -70,11 +70,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with the JTAGICE3!");
}
@@ -86,11 +86,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with the JTAGICE3!");
}

View File

@@ -51,17 +51,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -69,11 +69,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB PICkit 4!");
}
@@ -85,11 +85,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB PICkit 4!");
}

View File

@@ -51,17 +51,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -69,11 +69,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB Snap!");
}
@@ -85,11 +85,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB Snap!");
}

View File

@@ -51,17 +51,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -69,11 +69,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure(
"Failed to start session with the Power Debugger - device returned failed response ID"
@@ -87,11 +87,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure(
"Failed to end session with the Power Debugger - device returned failed response ID"

View File

@@ -55,17 +55,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -73,11 +73,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Mini!");
}
@@ -89,11 +89,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Mini!");
}

View File

@@ -53,17 +53,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
const auto data = response.getPayloadData();
const auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -71,11 +71,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Nano!");
}
@@ -87,11 +87,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Nano!");
}

View File

@@ -62,17 +62,17 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::Discovery;
using ResponseFrames::Discovery::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
if (responseFrame.id != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
auto data = responseFrame.getPayloadData();
return std::string(data.begin(), data.end());
}
@@ -80,11 +80,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Pro!");
}
@@ -96,11 +96,11 @@ namespace Bloom::DebugToolDrivers
using namespace CommandFrames::HouseKeeping;
using ResponseFrames::HouseKeeping::ResponseId;
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
if (responseFrame.id == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Pro!");
}

View File

@@ -98,7 +98,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
this->sendCommand(cmsisDapCommand);
auto response = this->getResponse<typename CommandType::ExpectedResponseType>();
if (response.getResponseId() != cmsisDapCommand.getCommandId()) {
if (response.id != cmsisDapCommand.commandId) {
throw Exceptions::DeviceCommunicationFailure("Unexpected response to CMSIS-DAP command.");
}

View File

@@ -2,10 +2,13 @@
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
{
Command::Command(unsigned char commandId)
: commandId(commandId)
{}
Command::operator std::vector<unsigned char>() const {
auto rawCommand = std::vector<unsigned char>(1, this->getCommandId());
auto commandData = this->getData();
rawCommand.insert(rawCommand.end(), commandData.begin(), commandData.end());
auto rawCommand = std::vector<unsigned char>(1, this->commandId);
rawCommand.insert(rawCommand.end(), this->data.begin(), this->data.end());
return rawCommand;
}

View File

@@ -50,9 +50,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
*/
using ExpectedResponseType = Response;
explicit Command(unsigned char commandId): commandId(commandId) {};
unsigned char commandId;
std::vector<unsigned char> data;
Command() = default;
explicit Command(unsigned char commandId);
virtual ~Command() = default;
Command(const Command& other) = default;
@@ -61,29 +62,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
Command& operator = (const Command& other) = default;
Command& operator = (Command&& other) = default;
[[nodiscard]] unsigned char getCommandId() const {
return this->commandId;
}
void setCommandId(unsigned char commandId) {
this->commandId = commandId;
}
[[nodiscard]] virtual std::vector<unsigned char> getData() const {
return this->data;
}
void setData(const std::vector<unsigned char>& data) {
this->data = data;
}
[[nodiscard]] int getCommandSize() const {
// +1 for the command ID
return static_cast<int>(1 + this->getData().size());
return static_cast<int>(1 + this->data.size());
}
[[nodiscard]] std::uint16_t getDataSize() const {
return static_cast<std::uint16_t>(this->getData().size());
return static_cast<std::uint16_t>(this->data.size());
}
/**
@@ -93,9 +78,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
* @return
*/
explicit virtual operator std::vector<unsigned char>() const;
private:
unsigned char commandId = 0x00;
std::vector<unsigned char> data;
};
}

View File

@@ -9,7 +9,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
throw Exceptions::Exception("Failed to process CMSIS-DAP response - invalid response");
}
this->setResponseId(rawResponse[0]);
this->setData(std::vector<unsigned char>(rawResponse.begin() + 1, rawResponse.end()));
this->id = rawResponse[0];
this->data = std::vector<unsigned char>(rawResponse.begin() + 1, rawResponse.end());
}
}

View File

@@ -7,6 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
class Response
{
public:
unsigned char id = 0x00;
std::vector<unsigned char> data;
Response(const std::vector<unsigned char>& rawResponse);
virtual ~Response() = default;
@@ -15,26 +18,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
Response& operator = (const Response& other) = default;
Response& operator = (Response&& other) = default;
[[nodiscard]] unsigned char getResponseId() const {
return this->responseId;
}
[[nodiscard]] virtual const std::vector<unsigned char>& getData() const {
return this->data;
}
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;
};
}

View File

@@ -2,22 +2,26 @@
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
std::vector<unsigned char> AvrCommand::getData() const {
std::vector<unsigned char> data;
auto commandPacket = this->getCommandPacket();
std::size_t commandPacketSize = commandPacket.size();
data.reserve(3 + commandPacketSize);
AvrCommand::AvrCommand(
std::size_t fragmentCount,
std::size_t fragmentNumber,
const std::vector<unsigned char>& commandPacket
)
: Command(0x80)
{
const auto commandPacketSize = commandPacket.size();
this->data.reserve(commandPacketSize + 3);
// FragmentInfo byte
data.emplace_back(static_cast<unsigned char>((this->getFragmentNumber() << 4) | this->getFragmentCount()));
this->data.emplace_back(static_cast<unsigned char>((fragmentNumber << 4) | fragmentCount));
// Size byte
data.emplace_back(static_cast<unsigned char>(commandPacketSize >> 8));
data.emplace_back(static_cast<unsigned char>(commandPacketSize & 0xFF));
this->data.emplace_back(static_cast<unsigned char>(commandPacketSize >> 8));
this->data.emplace_back(static_cast<unsigned char>(commandPacketSize & 0xFF));
if (commandPacketSize > 0) {
data.insert(data.begin() + 3, commandPacket.begin(), commandPacket.end());
// Packet data
this->data.insert(this->data.begin() + 3, commandPacket.begin(), commandPacket.end());
}
return data;
}
}

View File

@@ -31,38 +31,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
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);
}
/**
* Constructs raw command data on the fly.
*
* @return
*/
[[nodiscard]] std::vector<unsigned char> getData() const override;
[[nodiscard]] std::size_t getFragmentNumber() const {
return this->fragmentNumber;
}
[[nodiscard]] std::size_t getFragmentCount() const {
return this->fragmentCount;
}
[[nodiscard]] const std::vector<unsigned char>& getCommandPacket() const {
return this->commandPacket;
}
private:
std::size_t fragmentNumber = 1;
std::size_t fragmentCount = 1;
std::vector<unsigned char> commandPacket;
const std::vector<unsigned char>& commandPacket
);
};
}

View File

@@ -6,39 +6,38 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
using namespace Bloom::Exceptions;
AvrEvent::AvrEvent(const std::vector<unsigned char>& rawResponse): Response(rawResponse) {
if (this->getResponseId() != 0x82) {
AvrEvent::AvrEvent(const std::vector<unsigned char>& rawResponse)
: Response(rawResponse)
{
if (this->id != 0x82) {
throw Exception("Failed to construct AvrEvent object - invalid response ID.");
}
const auto& responseData = this->getData();
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.");
if (this->data.size() < 7) {
throw Exception("Failed to construct AvrEvent object - unexpected size of AVR_EVT response.");
}
// Response size is two bytes, MSB
auto responsePacketSize = static_cast<std::size_t>((responseData[0] << 8) | responseData[1]);
const auto responsePacketSize = static_cast<std::size_t>((this->data[0] << 8) | this->data[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.");
if (responsePacketSize == 0) {
// No event available
return;
}
if (this->data.size() < responsePacketSize + 7) {
throw Exception("Failed to construct AvrEvent object - invalid size of AVR_EVT response packet.");
}
/*
* Ignore the SOF, protocol version, handler id and sequence ID (which all make up 5 bytes in total, 7 if we
* include the two size bytes)
* Ignore the SOF, protocol version, handler ID, sequence ID and size bytes (which all make up 7 bytes
* in total).
*/
this->eventData = std::vector<unsigned char>(
responseData.begin() + 7,
responseData.begin() + 7 + static_cast<std::int64_t>(responsePacketSize)
this->data.begin() + 7,
this->data.begin() + 7 + static_cast<std::int64_t>(responsePacketSize)
);
if (!this->eventData.empty()) {
this->eventId = this->eventData[0];
}
this->eventId = static_cast<AvrEventId>(this->eventData[0]);
}
}

View File

@@ -1,9 +1,9 @@
#pragma once
#include <optional>
#include <vector>
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Response.hpp"
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/Edbg.hpp"
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
@@ -12,38 +12,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
AVR8_BREAK_EVENT = 0x40,
};
inline bool operator == (unsigned char rawId, AvrEventId id) {
return static_cast<unsigned char>(id) == rawId;
}
inline bool operator == (AvrEventId id, unsigned char rawId) {
return rawId == id;
}
class AvrEvent: public Response
{
public:
std::optional<AvrEventId> eventId = std::nullopt;
std::vector<unsigned char> eventData = {};
explicit AvrEvent(const std::vector<unsigned char>& rawResponse);
[[nodiscard]] const std::vector<unsigned char>& getEventData() const {
return this->eventData;
}
[[nodiscard]] size_t getEventDataSize() const {
return this->eventData.size();
}
[[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;
};
}

View File

@@ -10,8 +10,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
public:
using ExpectedResponseType = AvrEvent;
AvrEventCommand() {
this->setCommandId(0x82);
}
AvrEventCommand()
: Command(0x82)
{}
};
}

View File

@@ -6,36 +6,36 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
using namespace Bloom::Exceptions;
AvrResponse::AvrResponse(const std::vector<unsigned char>& rawResponse): Response(rawResponse) {
if (this->getResponseId() != 0x81) {
AvrResponse::AvrResponse(const std::vector<unsigned char>& rawResponse)
: Response(rawResponse)
{
if (this->id != 0x81) {
throw Exception("Failed to construct AvrResponse object - invalid response ID.");
}
const auto& responseData = this->getData();
if (responseData.empty()) {
if (this->data.empty()) {
// All AVR responses should contain at least one byte (the fragment info byte)
throw Exception("Failed to construct AvrResponse object - AVR_RSP response "
"returned no additional data");
throw Exception("Failed to construct AvrResponse object - malformed AVR_RSP data");
}
if (responseData[0] == 0x00) {
if (this->data[0] == 0x00) {
// This AVR Response contains no data (the device had no data to send), so we can stop here.
return;
}
this->setFragmentCount(static_cast<std::uint8_t>(responseData[0] & 0x0FU));
this->setFragmentNumber(static_cast<std::uint8_t>(responseData[0] >> 4));
this->fragmentCount = static_cast<std::uint8_t>(this->data[0] & 0x0FU);
this->fragmentNumber = static_cast<std::uint8_t>(this->data[0] >> 4);
// Response size is two bytes, MSB
const auto responsePacketSize = static_cast<std::size_t>((responseData[1] << 8U) + responseData[2]);
std::vector<unsigned char> responsePacket;
responsePacket.resize(responsePacketSize);
const auto responsePacketSize = static_cast<std::uint16_t>((this->data[1] << 8U) + this->data[2]);
for (std::size_t i = 0; i < responsePacketSize; i++) {
responsePacket[i] = responseData[i + 3];
if (responsePacketSize > 0) {
// Packet data
this->responsePacket.insert(
this->responsePacket.begin(),
this->data.begin() + 3,
this->data.begin() + 3 + responsePacketSize
);
}
this->setResponsePacket(responsePacket);
}
}

View File

@@ -10,37 +10,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
class AvrResponse: public Response
{
public:
explicit AvrResponse(const std::vector<unsigned char>& rawResponse);
[[nodiscard]] std::uint8_t getFragmentNumber() const {
return this->fragmentNumber;
}
[[nodiscard]] std::uint8_t getFragmentCount() const {
return this->fragmentCount;
}
[[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;
explicit AvrResponse(const std::vector<unsigned char>& rawResponse);
};
}

View File

@@ -28,8 +28,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
public:
using ExpectedResponseType = AvrResponse;
AvrResponseCommand() {
this->setCommandId(0x81);
}
AvrResponseCommand()
: Command(0x81)
{}
};
}

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class ActivatePhysical: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
{
public:
explicit ActivatePhysical(bool reset) {
explicit ActivatePhysical(bool reset)
: Avr8GenericCommandFrame()
{
/*
* The activate physical command consists of 3 bytes:
* 1. Command ID (0x10)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Attach: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
{
public:
explicit Attach(bool breakAfterAttach) {
explicit Attach(bool breakAfterAttach)
: Avr8GenericCommandFrame()
{
/*
* The attach command consists of 3 bytes:
* 1. Command ID (0x13)

View File

@@ -13,6 +13,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::Avr8Generic::Avr8GenericResponseFrame;
Avr8GenericCommandFrame(): AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::AVR8_GENERIC) {}
Avr8GenericCommandFrame()
: AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::AVR8_GENERIC)
{}
};
}

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class ClearAllSoftwareBreakpoints: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
ClearAllSoftwareBreakpoints() {
ClearAllSoftwareBreakpoints()
: Avr8GenericCommandFrame()
{
/*
* The clear all software breakpoints command consists of 2 bytes:
* 1. Command ID (0x45)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class ClearSoftwareBreakpoints: public Avr8GenericCommandFrame<std::vector<unsigned char>>
{
public:
explicit ClearSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses) {
explicit ClearSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses)
: Avr8GenericCommandFrame()
{
/*
* The clear software breakpoints command consists of 2 bytes + 4*n bytes, where n is the number
* of breakpoints to clear:

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class DeactivatePhysical: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
DeactivatePhysical() {
DeactivatePhysical()
: Avr8GenericCommandFrame()
{
/*
* The deactivate physical command consists of 2 bytes:
* 1. Command ID (0x11)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Detach: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
Detach() {
Detach()
: Avr8GenericCommandFrame()
{
/*
* The detach command consists of 2 bytes:
* 1. Command ID (0x14)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class DisableDebugWire: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
DisableDebugWire() {
DisableDebugWire()
: Avr8GenericCommandFrame()
{
/*
* The disable debugWire command consists of 2 bytes:
* 1. Command ID (0x17)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class EnterProgrammingMode: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
EnterProgrammingMode() {
EnterProgrammingMode()
: Avr8GenericCommandFrame()
{
/*
* The enter programming mode command consists of 2 bytes:
* 1. Command ID (0x15)

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class EraseMemory: public Avr8GenericCommandFrame<std::array<unsigned char, 7>>
{
public:
EraseMemory(Avr8EraseMemoryMode mode) {
EraseMemory(Avr8EraseMemoryMode mode)
: Avr8GenericCommandFrame()
{
/*
* The erase memory command consists of 7 bytes:
* 1. Command ID (0x20)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::Avr8Generic::GetDeviceId;
GetDeviceId() {
GetDeviceId()
: Avr8GenericCommandFrame()
{
/*
* The get device ID command consists of 2 bytes:
* 1. Command ID (0x12)

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class GetParameter: public Avr8GenericCommandFrame<std::array<unsigned char, 5>>
{
public:
GetParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
GetParameter(const Avr8EdbgParameter& parameter, std::uint8_t size)
: Avr8GenericCommandFrame()
{
/*
* The get param command consists of 5 bytes:
* 1. Command ID (0x02)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::Avr8Generic::GetProgramCounter;
GetProgramCounter() {
GetProgramCounter()
: Avr8GenericCommandFrame()
{
/*
* The PC Read command consists of 2 bytes:
* 1. Command ID (0x35)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class LeaveProgrammingMode: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
LeaveProgrammingMode() {
LeaveProgrammingMode()
: Avr8GenericCommandFrame()
{
/*
* The leave programming mode command consists of 2 bytes:
* 1. Command ID (0x16)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
std::uint32_t address,
std::uint32_t bytes,
const std::set<std::uint32_t>& excludedAddresses
) {
)
: Avr8GenericCommandFrame()
{
/*
* The read memory command consists of 11 + (bytes / 8) bytes:
* 1. Command ID (0x21 for the general read memory command, 0x22 for reading with a mask)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Reset: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
{
public:
explicit Reset(bool stopAtMainAddress = false) {
explicit Reset(bool stopAtMainAddress = false)
: Avr8GenericCommandFrame()
{
/*
* The reset command consists of 3 bytes:
* 1. Command ID (0x30)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Run: public Avr8GenericCommandFrame<std::array<unsigned char, 2>>
{
public:
Run() {
Run()
: Avr8GenericCommandFrame()
{
/*
* The run command consists of 2 bytes:
* 1. Command ID (0x32)

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class RunTo: public Avr8GenericCommandFrame<std::array<unsigned char, 6>>
{
public:
explicit RunTo(const std::uint32_t& address) {
explicit RunTo(const std::uint32_t& address)
: Avr8GenericCommandFrame()
{
/*
* The run-to command consists of 6 bytes:
*

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class SetParameter: public Avr8GenericCommandFrame<std::vector<unsigned char>>
{
public:
SetParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
SetParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value)
: Avr8GenericCommandFrame()
{
/*
* The set param command consists of value.size() + 5 bytes. The first five bytes consist of:
* 1. Command ID (0x01)

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class SetProgramCounter: public Avr8GenericCommandFrame<std::array<unsigned char, 6>>
{
public:
explicit SetProgramCounter(std::uint32_t programCounter) {
explicit SetProgramCounter(std::uint32_t programCounter)
: Avr8GenericCommandFrame()
{
/*
* The PC write command consists of 6 bytes:
* 1. Command ID (0x36)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class SetSoftwareBreakpoints: public Avr8GenericCommandFrame<std::vector<unsigned char>>
{
public:
explicit SetSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses) {
explicit SetSoftwareBreakpoints(const std::vector<std::uint32_t>& addresses)
: Avr8GenericCommandFrame()
{
/*
* The set software breakpoint command consists of 2 bytes + 4*n bytes, where n is the number
* of breakpoints to set:

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class SetXmegaSoftwareBreakpoint: public Avr8GenericCommandFrame<std::array<unsigned char, 15>>
{
public:
explicit SetXmegaSoftwareBreakpoint(std::uint32_t address) {
explicit SetXmegaSoftwareBreakpoint(std::uint32_t address)
: Avr8GenericCommandFrame()
{
this->payload = {
0x42,
0x00,

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Step: public Avr8GenericCommandFrame<std::array<unsigned char, 4>>
{
public:
Step() {
Step()
: Avr8GenericCommandFrame()
{
/*
* The step command consists of 4 bytes:
* 1. Command ID (0x34)

View File

@@ -7,7 +7,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Stop: public Avr8GenericCommandFrame<std::array<unsigned char, 3>>
{
public:
explicit Stop(bool stopImmediately = true) {
explicit Stop(bool stopImmediately = true)
: Avr8GenericCommandFrame()
{
/*
* The stop command consists of 3 bytes:
* 1. Command ID (0x31)

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class WriteMemory: public Avr8GenericCommandFrame<std::vector<unsigned char>>
{
public:
WriteMemory(const Avr8MemoryType& type, std::uint32_t address, const Targets::TargetMemoryBuffer& buffer) {
WriteMemory(const Avr8MemoryType& type, std::uint32_t address, const Targets::TargetMemoryBuffer& buffer)
: Avr8GenericCommandFrame()
{
/*
* The write memory command consists of 12 bytes + the buffer size:
* 1. Command ID (0x23)

View File

@@ -13,6 +13,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::AvrIsp::AvrIspResponseFrame;
AvrIspCommandFrame(): AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::AVRISP) {}
AvrIspCommandFrame()
: AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::AVRISP)
{}
};
}

View File

@@ -17,7 +17,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
std::uint8_t byteDelay,
std::uint8_t pollValue,
std::uint8_t pollIndex
) {
)
: AvrIspCommandFrame()
{
/*
* The enter programming mode command consists of 12 bytes:
*

View File

@@ -12,7 +12,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
LeaveProgrammingMode(
std::uint8_t preDelay,
std::uint8_t postDelay
) {
)
: AvrIspCommandFrame()
{
/*
* The leave programming mode command consists of 3 bytes:
*

View File

@@ -11,7 +11,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class ProgramFuse: public AvrIspCommandFrame<std::array<unsigned char, 5>>
{
public:
ProgramFuse(Targets::Microchip::Avr::FuseType fuseType, unsigned char value) {
ProgramFuse(Targets::Microchip::Avr::FuseType fuseType, unsigned char value)
: AvrIspCommandFrame()
{
using Targets::Microchip::Avr::FuseType;
/*

View File

@@ -14,7 +14,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
ReadFuse(
Targets::Microchip::Avr::FuseType fuseType,
std::uint8_t returnAddress
) {
)
: AvrIspCommandFrame()
{
using Targets::Microchip::Avr::FuseType;
/*

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class ReadLock: public AvrIspCommandFrame<std::array<unsigned char, 6>>
{
public:
explicit ReadLock(std::uint8_t returnAddress) {
explicit ReadLock(std::uint8_t returnAddress)
: AvrIspCommandFrame()
{
/*
* The read lock command consists of 6 bytes:
*

View File

@@ -15,7 +15,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
ReadSignature(
std::uint8_t signatureByteAddress,
std::uint8_t returnAddress
) {
)
: AvrIspCommandFrame()
{
using Targets::Microchip::Avr::FuseType;
/*

View File

@@ -15,7 +15,7 @@
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
static inline std::atomic<std::uint16_t> LAST_SEQUENCE_ID = 0;
static inline std::atomic<std::uint16_t> lastSequenceId = 0;
template <class PayloadContainerType = std::vector<unsigned char>>
class AvrCommandFrame
@@ -76,15 +76,22 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
*/
using ExpectedResponseFrameType = AvrResponseFrame;
explicit AvrCommandFrame(ProtocolHandlerId protocolHandlerId): protocolHandlerId(protocolHandlerId) {
if (LAST_SEQUENCE_ID < std::numeric_limits<decltype(LAST_SEQUENCE_ID)>::max()) {
this->sequenceId = ++(LAST_SEQUENCE_ID);
/**
* Incrementing from 0
*/
std::uint16_t sequenceId = 0;
} else {
this->sequenceId = 0;
LAST_SEQUENCE_ID = 0;
}
};
/**
* Destination sub-protocol handler ID
*/
ProtocolHandlerId protocolHandlerId = ProtocolHandlerId::DISCOVERY;
PayloadContainerType payload;
explicit AvrCommandFrame(ProtocolHandlerId protocolHandlerId)
: sequenceId(++lastSequenceId)
, protocolHandlerId(protocolHandlerId)
{};
virtual ~AvrCommandFrame() = default;
@@ -94,10 +101,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
AvrCommandFrame& operator = (const AvrCommandFrame& other) = default;
AvrCommandFrame& operator = (AvrCommandFrame&& other) noexcept = default;
[[nodiscard]] virtual const PayloadContainerType& getPayload() const {
return this->payload;
};
/**
* Converts the command frame into a container of unsigned char - a raw buffer to include in an AVR
* command packet, for sending to the EDBG device.
@@ -109,7 +112,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
[[nodiscard]] auto getRawCommandFrame() const {
auto rawCommand = std::vector<unsigned char>(5 + this->payload.size());
rawCommand[0] = 0x0E; // Start of frame
rawCommand[0] = 0x0E; // Start of frame (SOF) byte
rawCommand[1] = 0x00; // Protocol version
rawCommand[2] = static_cast<unsigned char>(this->sequenceId);
@@ -169,18 +172,5 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
return avrCommands;
}
protected:
/**
* Incrementing from 0
*/
std::uint16_t sequenceId = 0;
/**
* Destination sub-protocol handler ID
*/
ProtocolHandlerId protocolHandlerId = ProtocolHandlerId::DISCOVERY;
PayloadContainerType payload;
};
}

View File

@@ -11,6 +11,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::Discovery::DiscoveryResponseFrame;
DiscoveryCommandFrame(): AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::DISCOVERY) {}
DiscoveryCommandFrame()
: AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::DISCOVERY)
{}
};
}

View File

@@ -22,7 +22,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class Query: public DiscoveryCommandFrame<std::array<unsigned char, 3>>
{
public:
explicit Query(QueryContext context) {
explicit Query(QueryContext context)
: DiscoveryCommandFrame()
{
/*
* The payload for the Query command consists of three bytes. A command ID (0x00), version (0x00) and a
* query context.

View File

@@ -11,6 +11,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::EdbgControl::EdbgControlResponseFrame;
EdbgControlCommandFrame(): AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::EDBG_CONTROL) {}
EdbgControlCommandFrame()
: AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::EDBG_CONTROL)
{}
};
}

View File

@@ -9,7 +9,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class GetParameter: public EdbgControlCommandFrame<std::array<unsigned char, 5>>
{
public:
explicit GetParameter(const EdbgParameter& parameter) {
GetParameter(const EdbgParameter& parameter)
: EdbgControlCommandFrame()
{
/*
* The EDBG Get Parameter command consists of 5 bytes:
*

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class SetParameter: public EdbgControlCommandFrame<std::array<unsigned char, 6>>
{
public:
explicit SetParameter(const EdbgParameter& parameter, unsigned char value) {
SetParameter(const EdbgParameter& parameter, unsigned char value)
: EdbgControlCommandFrame()
{
assert(parameter.size == 1);
/*

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class EndSession: public HouseKeepingCommandFrame<std::array<unsigned char, 3>>
{
public:
EndSession() {
EndSession()
: HouseKeepingCommandFrame()
{
/*
* 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).

View File

@@ -10,7 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class GetParameter: public HouseKeepingCommandFrame<std::array<unsigned char, 5>>
{
public:
explicit GetParameter(const Parameter& parameter, std::uint8_t size) {
GetParameter(const Parameter& parameter, std::uint8_t size)
: HouseKeepingCommandFrame()
{
/*
* The get param command consists of 5 bytes:
* 1. Command ID (0x02)

View File

@@ -11,6 +11,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
public:
using ExpectedResponseFrameType = ResponseFrames::HouseKeeping::HouseKeepingResponseFrame;
HouseKeepingCommandFrame(): AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::HOUSE_KEEPING) {}
HouseKeepingCommandFrame()
: AvrCommandFrame<PayloadContainerType>(ProtocolHandlerId::HOUSE_KEEPING)
{}
};
}

View File

@@ -16,11 +16,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
struct Parameter
{
ParameterContext context;
unsigned char id = 0x00;
std::uint8_t size = 0x00;
unsigned char id;
std::uint8_t size;
constexpr Parameter(ParameterContext context, unsigned char id, std::uint8_t size)
: context(context), id(id), size(size) {};
: context(context)
, id(id)
, size(size)
{};
};
struct Parameters

View File

@@ -12,7 +12,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames
class StartSession: public HouseKeepingCommandFrame<std::array<unsigned char, 2>>
{
public:
StartSession() {
StartSession()
: HouseKeepingCommandFrame()
{
/*
* The payload for the Start Session command consists of two bytes. A command ID byte (0x10) and a
* version byte (0x00).

View File

@@ -195,12 +195,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvr8Interface::stop() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Stop()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Stop target command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Stop target command failed", responseFrame);
}
if (this->getTargetState() == TargetState::RUNNING) {
@@ -210,12 +210,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
void EdbgAvr8Interface::run() {
this->clearEvents();
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Run()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Run command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Run command failed", responseFrame);
}
this->targetState = TargetState::RUNNING;
@@ -223,36 +223,36 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
void EdbgAvr8Interface::runTo(TargetProgramCounter address) {
this->clearEvents();
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
RunTo(address)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Run-to command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Run-to command failed", responseFrame);
}
this->targetState = TargetState::RUNNING;
}
void EdbgAvr8Interface::step() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Step()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Step target command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Step target command failed", responseFrame);
}
this->targetState = TargetState::RUNNING;
}
void EdbgAvr8Interface::reset() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Reset()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Reset target command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Reset target command failed", responseFrame);
}
try {
@@ -335,15 +335,15 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
this->stop();
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
GetProgramCounter()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Get program counter command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Get program counter command failed", responseFrame);
}
return response.extractProgramCounter();
return responseFrame.extractProgramCounter();
}
void EdbgAvr8Interface::setProgramCounter(TargetProgramCounter programCounter) {
@@ -355,12 +355,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
* The program counter will be given in byte address form, but the EDBG tool will be expecting it in word
* address (16-bit) form. This is why we divide it by 2.
*/
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
SetProgramCounter(programCounter / 2)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Set program counter command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Set program counter command failed", responseFrame);
}
}
@@ -390,44 +390,44 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
return TargetSignature(signatureMemory[0], signatureMemory[1], signatureMemory[2]);
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
GetDeviceId()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Get device ID command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Get device ID command failed", responseFrame);
}
return response.extractSignature(this->targetConfig->physicalInterface);
return responseFrame.extractSignature(this->targetConfig->physicalInterface);
}
void EdbgAvr8Interface::setBreakpoint(TargetMemoryAddress address) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
SetSoftwareBreakpoints({address})
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Set software breakpoint command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Set software breakpoint command failed", responseFrame);
}
}
void EdbgAvr8Interface::clearBreakpoint(TargetMemoryAddress address) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ClearSoftwareBreakpoints({address})
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Clear software breakpoint command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Clear software breakpoint command failed", responseFrame);
}
}
void EdbgAvr8Interface::clearAllBreakpoints() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ClearAllSoftwareBreakpoints()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Clear all software breakpoints command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Clear all software breakpoints command failed", responseFrame);
}
}
@@ -750,7 +750,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
throw Exception("AVR8 erase command not supported for debugWire config variant.");
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EraseMemory(
section.has_value()
? section == ProgramMemorySection::BOOT
@@ -760,8 +760,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 erase memory command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 erase memory command failed", responseFrame);
}
}
@@ -785,12 +785,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
return;
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EnterProgrammingMode()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to enter programming mode on EDBG debug tool", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to enter programming mode on EDBG debug tool", responseFrame);
}
this->programmingModeEnabled = true;
@@ -801,12 +801,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
return;
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
LeaveProgrammingMode()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to leave programming mode on EDBG debug tool", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to leave programming mode on EDBG debug tool", responseFrame);
}
this->programmingModeEnabled = false;
@@ -909,25 +909,25 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
SetParameter(parameter, value)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to set parameter on device!", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to set parameter on device!", responseFrame);
}
}
std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
GetParameter(parameter, size)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to get parameter from device!", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("Failed to get parameter from device!", responseFrame);
}
return response.getPayloadData();
return responseFrame.getPayloadData();
}
void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
@@ -1371,11 +1371,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ActivatePhysical(applyExternalReset)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
if (responseFrame.id == Avr8ResponseId::FAILED) {
if (!applyExternalReset) {
// Try again with external reset applied
Logger::debug("Failed to activate physical interface on AVR8 target "
@@ -1383,19 +1383,19 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
return this->activatePhysical(true);
}
throw Avr8CommandFailure("AVR8 Activate physical interface command failed", response);
throw Avr8CommandFailure("AVR8 Activate physical interface command failed", responseFrame);
}
this->physicalInterfaceActivated = true;
}
void EdbgAvr8Interface::deactivatePhysical() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
DeactivatePhysical()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Deactivate physical interface command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Deactivate physical interface command failed", responseFrame);
}
this->physicalInterfaceActivated = false;
@@ -1410,14 +1410,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
* value of the breakAfterAttach flag. So we still expect a stop event to be received shortly after issuing
* the attach command.
*/
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Attach(
this->configVariant != Avr8ConfigVariant::MEGAJTAG
)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Attach command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Attach command failed", responseFrame);
}
this->targetAttached = true;
@@ -1434,25 +1434,25 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvr8Interface::detach() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
Detach()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Detach command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Detach command failed", responseFrame);
}
this->targetAttached = false;
}
std::unique_ptr<AvrEvent> EdbgAvr8Interface::getAvrEvent() {
auto event = this->edbgInterface.requestAvrEvent();
auto event = this->edbgInterface->requestAvrEvent();
if (!event.has_value()) {
return nullptr;
}
switch (event->getEventId()) {
switch (event->eventId.value()) {
case AvrEventId::AVR8_BREAK_EVENT: {
// Break event
return std::make_unique<BreakEvent>(event.value());
@@ -1713,7 +1713,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ReadMemory(
type,
startAddress,
@@ -1722,11 +1722,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Read memory command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Read memory command failed", responseFrame);
}
return response.getMemoryBuffer();
return responseFrame.getMemoryBuffer();
}
void EdbgAvr8Interface::writeMemory(
@@ -1780,7 +1780,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
}
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
WriteMemory(
type,
startAddress,
@@ -1788,15 +1788,15 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
)
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Write memory command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Write memory command failed", responseFrame);
}
}
void EdbgAvr8Interface::refreshTargetState() {
const auto avrEvent = this->getAvrEvent();
if (avrEvent != nullptr && avrEvent->getEventId() == AvrEventId::AVR8_BREAK_EVENT) {
if (avrEvent != nullptr && avrEvent->eventId == AvrEventId::AVR8_BREAK_EVENT) {
auto* breakEvent = dynamic_cast<BreakEvent*>(avrEvent.get());
if (breakEvent == nullptr) {
@@ -1811,12 +1811,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvr8Interface::disableDebugWire() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
DisableDebugWire()
);
if (response.getResponseId() == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Disable debugWire command failed", response);
if (responseFrame.id == Avr8ResponseId::FAILED) {
throw Avr8CommandFailure("AVR8 Disable debugWire command failed", responseFrame);
}
}

View File

@@ -35,7 +35,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvrIspInterface::activate() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
EnterProgrammingMode(
this->ispParameters.programModeTimeout,
this->ispParameters.programModeStabilizationDelay,
@@ -47,7 +47,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
)
);
if (response.getStatusCode() != StatusCode::OK) {
if (responseFrame.statusCode != StatusCode::OK) {
throw TargetOperationFailure(
"Failed to enable programming mode via the ISP interface - check target's SPI connection "
"and/or its SPIEN fuse bit."
@@ -56,14 +56,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
void EdbgAvrIspInterface::deactivate() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
LeaveProgrammingMode(
this->ispParameters.programModePreDelay,
this->ispParameters.programModePostDelay
)
);
if (response.getStatusCode() != StatusCode::OK) {
if (responseFrame.statusCode != StatusCode::OK) {
throw TargetOperationFailure("Failed to disable programming mode via the ISP interface.");
}
}
@@ -78,50 +78,47 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
Fuse EdbgAvrIspInterface::readFuse(FuseType fuseType) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ReadFuse(fuseType, this->ispParameters.readFusePollIndex)
);
const auto& payload = response.getPayload();
if (
response.getStatusCode() != StatusCode::OK
|| payload.size() < 4
|| static_cast<StatusCode>(payload[3]) != StatusCode::OK
responseFrame.statusCode != StatusCode::OK
|| responseFrame.payload.size() < 4
|| static_cast<StatusCode>(responseFrame.payload[3]) != StatusCode::OK
) {
throw TargetOperationFailure(
"Failed to read fuse via ISP - response frame status code/size indicates a failure."
);
}
return Fuse(fuseType, payload[2]);
return Fuse(fuseType, responseFrame.payload[2]);
}
unsigned char EdbgAvrIspInterface::readLockBitByte() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ReadLock(this->ispParameters.readLockPollIndex)
);
const auto& payload = response.getPayload();
if (
response.getStatusCode() != StatusCode::OK
|| payload.size() < 4
|| static_cast<StatusCode>(payload[3]) != StatusCode::OK
responseFrame.statusCode != StatusCode::OK
|| responseFrame.payload.size() < 4
|| static_cast<StatusCode>(responseFrame.payload[3]) != StatusCode::OK
) {
throw TargetOperationFailure(
"Failed to read lock bit byte via ISP - response frame status code/size indicates a failure."
);
}
return payload[2];
return responseFrame.payload[2];
}
void EdbgAvrIspInterface::programFuse(Targets::Microchip::Avr::Fuse fuse) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ProgramFuse(fuse.type, fuse.value)
);
const auto& payload = response.getPayload();
if (response.getStatusCode() != StatusCode::OK || payload.size() < 2) {
if (responseFrame.statusCode != StatusCode::OK || responseFrame.payload.size() < 2) {
throw TargetOperationFailure(
"Failed to program fuse via ISP - response frame status code/size indicates a failure."
);
@@ -129,16 +126,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
}
unsigned char EdbgAvrIspInterface::readSignatureByte(std::uint8_t signatureByteAddress) {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
ReadSignature(signatureByteAddress, this->ispParameters.readSignaturePollIndex)
);
const auto& payload = response.getPayload();
if (
response.getStatusCode() != StatusCode::OK
|| payload.size() < 4
|| static_cast<StatusCode>(payload[3]) != StatusCode::OK
responseFrame.statusCode != StatusCode::OK
|| responseFrame.payload.size() < 4
|| static_cast<StatusCode>(responseFrame.payload[3]) != StatusCode::OK
) {
throw TargetOperationFailure(
"Failed to read signature byte (address: " + std::to_string(signatureByteAddress)
@@ -146,6 +141,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
);
}
return payload[2];
return responseFrame.payload[2];
}
}

View File

@@ -8,10 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
using Bloom::Targets::TargetBreakCause;
BreakEvent::BreakEvent(const AvrEvent& event): AvrEvent(event) {
const auto& data = this->getEventData();
if (data.size() < 8) {
BreakEvent::BreakEvent(const AvrEvent& event)
: AvrEvent(event)
{
if (this->eventData.size() < 8) {
/*
* All BreakEvent packets must consist of at least 8 bytes:
* 1 byte for event ID
@@ -24,10 +24,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
// Program counter consists of 4 bytes
this->programCounter = static_cast<std::uint32_t>(
(data[4] << 24) | (data[3] << 16) | (data[2] << 8) | data[1]
(this->eventData[4] << 24) | (this->eventData[3] << 16) | (this->eventData[2] << 8) | this->eventData[1]
) * 2;
// Break cause is 1 byte, where 0x01 is 'program breakpoint' and 0x00 'unspecified'
this->breakCause = data[7] == 0x01 ? TargetBreakCause::BREAKPOINT : TargetBreakCause::UNKNOWN;
this->breakCause = this->eventData[7] == 0x01 ? TargetBreakCause::BREAKPOINT : TargetBreakCause::UNKNOWN;
}
}

View File

@@ -10,20 +10,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
class BreakEvent: public AvrEvent
{
public:
std::uint32_t programCounter;
Targets::TargetBreakCause breakCause;
explicit BreakEvent(const AvrEvent& event);
[[nodiscard]] std::uint32_t getProgramCounter() const {
return this->programCounter;
}
[[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);
};
}

View File

@@ -3,7 +3,7 @@
#include "src/TargetController/Exceptions/TargetOperationFailure.hpp"
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AVR8Generic/Avr8GenericResponseFrame.hpp"
namespace Bloom::Exceptions
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
{
enum class Avr8CommandFailureCode: std::uint8_t
{
@@ -55,7 +55,8 @@ namespace Bloom::Exceptions
UNKNOWN_COMMAND = 0x91,
UNKNOWN_ERROR = 0xFF,
};
class Avr8CommandFailure: public TargetOperationFailure
class Avr8CommandFailure: public Bloom::Exceptions::TargetOperationFailure
{
public:
std::optional<Avr8CommandFailureCode> code;
@@ -70,15 +71,15 @@ namespace Bloom::Exceptions
explicit Avr8CommandFailure(
const std::string& message,
DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic::Avr8GenericResponseFrame& responseFrame
const ResponseFrames::Avr8Generic::Avr8GenericResponseFrame& responseFrame
): TargetOperationFailure(message) {
this->message = message;
auto responsePayload = responseFrame.getPayload();
if (responsePayload.size() == 3
&& this->failureCodeToDescription.contains(static_cast<Avr8CommandFailureCode>(responsePayload[2]))
if (
responseFrame.payload.size() == 3
&& this->failureCodeToDescription.contains(static_cast<Avr8CommandFailureCode>(responseFrame.payload[2]))
) {
this->code = static_cast<Avr8CommandFailureCode>(responsePayload[2]);
this->code = static_cast<Avr8CommandFailureCode>(responseFrame.payload[2]);
this->message += " - Failure reason: " + this->failureCodeToDescription.at(*(this->code));
}
}

View File

@@ -6,25 +6,24 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
using namespace Bloom::Exceptions;
unsigned char Avr8GenericResponseFrame::getResponseId() {
const auto& payload = this->getPayload();
if (payload.empty()) {
Avr8GenericResponseFrame::Avr8GenericResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses)
{
if (this->payload.empty()) {
throw Exception("Response ID missing from AVR8 Generic response frame payload.");
}
return payload[0];
this->id = static_cast<Avr8ResponseId>(this->payload[0]);
}
std::vector<unsigned char> Avr8GenericResponseFrame::getPayloadData() {
const auto& payload = this->getPayload();
std::vector<unsigned char> Avr8GenericResponseFrame::getPayloadData() const {
/*
* AVR8 data payloads are in little endian form and include two bytes before the data (response ID and
* version byte) as well as an additional byte after the data, known as the 'status code'.
*/
auto data = std::vector<unsigned char>(
payload.begin() + 2,
payload.end() - 1
this->payload.begin() + 2,
this->payload.end() - 1
);
std::reverse(data.begin(), data.end());

View File

@@ -1,21 +1,17 @@
#pragma once
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/ResponseFrames/AvrResponseFrame.hpp"
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Avr8Generic.hpp"
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic
{
class Avr8GenericResponseFrame: public AvrResponseFrame
{
public:
Avr8GenericResponseFrame() = default;
explicit Avr8GenericResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses) {}
Avr8ResponseId id;
[[nodiscard]] unsigned char getResponseId();
explicit Avr8GenericResponseFrame(const std::vector<AvrResponse>& avrResponses);
/**
* See parent method.
*/
[[nodiscard]] std::vector<unsigned char> getPayloadData() override;
[[nodiscard]] std::vector<unsigned char> getPayloadData() const;
};
}

View File

@@ -0,0 +1,68 @@
#include "GetDeviceId.hpp"
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic
{
GetDeviceId::GetDeviceId(const std::vector<AvrResponse>& AvrResponses)
: Avr8GenericResponseFrame(AvrResponses)
{}
Targets::Microchip::Avr::TargetSignature GetDeviceId::extractSignature(
Targets::Microchip::Avr::Avr8Bit::PhysicalInterface physicalInterface
) const {
using Targets::Microchip::Avr::Avr8Bit::PhysicalInterface;
const auto payloadData = this->getPayloadData();
switch (physicalInterface) {
case PhysicalInterface::DEBUG_WIRE: {
/*
* When using the DebugWire physical interface, the get device ID command will return
* four bytes, where the first can be ignored.
*/
return Targets::Microchip::Avr::TargetSignature(payloadData[1], payloadData[2], payloadData[3]);
}
case PhysicalInterface::PDI:
case PhysicalInterface::UPDI: {
/*
* When using the PDI physical interface, the signature is returned in LSB format.
*/
return Targets::Microchip::Avr::TargetSignature(payloadData[3], payloadData[2], payloadData[1]);
}
case PhysicalInterface::JTAG: {
/*
* When using the JTAG interface, the get device ID command returns a 32 bit JTAG ID. This takes
* the following form:
*
* VVVV PPPPPPPPPPPPPPPP MMMMMMMMMMM L
*
* - (V) - Version nibble (4 bits)
* - (P) - Part number (this is typically the AVR signature excluding the manufacture
* byte (0x1E)) (16 bits)
* - (M) - Manufacture identity (11 bits)
* - (L) - LSB indicator (1 bit)
*
* We convert this into a Avr::TargetSignature by extracting the relevant part number and assuming
* a manufacture byte of 0x1E.
*
* TODO: We're not considering the value of the LSB indicator bit. We're just assuming it will
* always be MSB. Is this assumption correct?
*/
const auto jtagId = static_cast<std::uint32_t>(
(payloadData[0] << 24) | (payloadData[1] << 16) | (payloadData[2] << 8) | (payloadData[3])
);
return Targets::Microchip::Avr::TargetSignature(
0x1E,
static_cast<unsigned char>((jtagId << 4) >> 24),
static_cast<unsigned char>((jtagId << 12) >> 24)
);
}
default: {
return Targets::Microchip::Avr::TargetSignature(
payloadData[0],
payloadData[1],
payloadData[2]
);
}
}
}
}

View File

@@ -2,6 +2,7 @@
#include "Avr8GenericResponseFrame.hpp"
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrames::Avr8Generic
@@ -9,67 +10,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class GetDeviceId: public Avr8GenericResponseFrame
{
public:
GetDeviceId() = default;
explicit GetDeviceId(const std::vector<AvrResponse>& AvrResponses): Avr8GenericResponseFrame(AvrResponses) {}
explicit GetDeviceId(const std::vector<AvrResponse>& AvrResponses);
Targets::Microchip::Avr::TargetSignature extractSignature(
Targets::Microchip::Avr::Avr8Bit::PhysicalInterface physicalInterface
) {
using Targets::Microchip::Avr::Avr8Bit::PhysicalInterface;
auto payloadData = this->getPayloadData();
switch (physicalInterface) {
case PhysicalInterface::DEBUG_WIRE: {
/*
* When using the DebugWire physical interface, the get device ID command will return
* four bytes, where the first can be ignored.
*/
return Targets::Microchip::Avr::TargetSignature(payloadData[1], payloadData[2], payloadData[3]);
}
case PhysicalInterface::PDI:
case PhysicalInterface::UPDI: {
/*
* When using the PDI physical interface, the signature is returned in LSB format.
*/
return Targets::Microchip::Avr::TargetSignature(payloadData[3], payloadData[2], payloadData[1]);
}
case PhysicalInterface::JTAG: {
/*
* When using the JTAG interface, the get device ID command returns a 32 bit JTAG ID. This takes
* the following form:
*
* VVVV PPPPPPPPPPPPPPPP MMMMMMMMMMM L
*
* - (V) - Version nibble (4 bits)
* - (P) - Part number (this is typically the AVR signature excluding the manufacture
* byte (0x1E)) (16 bits)
* - (M) - Manufacture identity (11 bits)
* - (L) - LSB indicator (1 bit)
*
* We convert this into a Avr::TargetSignature by extracting the relevant part number and assuming
* a manufacture byte of 0x1E.
*
* TODO: We're not considering the value of the LSB indicator bit. We're just assuming it will
* always be MSB. Is this assumption correct?
*/
auto jtagId = static_cast<std::uint32_t>(
(payloadData[0] << 24) | (payloadData[1] << 16) | (payloadData[2] << 8) | (payloadData[3])
);
return Targets::Microchip::Avr::TargetSignature(
0x1E,
static_cast<unsigned char>((jtagId << 4) >> 24),
static_cast<unsigned char>((jtagId << 12) >> 24)
);
}
default: {
return Targets::Microchip::Avr::TargetSignature(
payloadData[0],
payloadData[1],
payloadData[2]
);
}
}
}
) const;
};
}

View File

@@ -13,24 +13,22 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class GetProgramCounter: public Avr8GenericResponseFrame
{
public:
GetProgramCounter() = default;
explicit GetProgramCounter(const std::vector<AvrResponse>& avrResponses)
: Avr8GenericResponseFrame(avrResponses)
{}
Targets::TargetProgramCounter extractProgramCounter() {
Targets::TargetProgramCounter extractProgramCounter() const {
/*
* The payload for the PC Read command should always consist of six bytes. Thr first two being the
* command ID and version, the other four being the PC. The four PC bytes are little-endian.
*/
auto& payload = this->getPayload();
if (payload.size() != 6) {
if (this->payload.size() != 6) {
throw Exceptions::Exception("Failed to extract PC from payload of PC read command response "
"frame - unexpected payload size.");
}
return static_cast<Targets::TargetProgramCounter>(
payload[5] << 24 | payload[4] << 16 | payload[3] << 8 | payload[2]
this->payload[5] << 24 | this->payload[4] << 16 | this->payload[3] << 8 | this->payload[2]
) * 2;
}
};

View File

@@ -8,20 +8,19 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class ReadMemory: public Avr8GenericResponseFrame
{
public:
ReadMemory() = default;
explicit ReadMemory(const std::vector<AvrResponse>& avrResponses): Avr8GenericResponseFrame(avrResponses) {}
explicit ReadMemory(const std::vector<AvrResponse>& avrResponses)
: Avr8GenericResponseFrame(avrResponses)
{}
Targets::TargetMemoryBuffer getMemoryBuffer() {
Targets::TargetMemoryBuffer getMemoryBuffer() const {
/*
* AVR8 data payloads are typically in little endian form, but this does not apply the data returned
* from the READ MEMORY commands.
*/
auto data = std::vector<unsigned char>(
this->getPayload().begin() + 2,
this->getPayload().end() - 1
return std::vector<unsigned char>(
this->payload.begin() + 2,
this->payload.end() - 1
);
return data;
}
};
}

View File

@@ -6,13 +6,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
using namespace Bloom::Exceptions;
StatusCode AvrIspResponseFrame::getStatusCode() {
const auto& payload = this->getPayload();
if (payload.size() < 2) {
AvrIspResponseFrame::AvrIspResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses)
{
if (this->payload.size() < 2) {
throw Exception("Status code missing from AVRISP response frame payload.");
}
return static_cast<StatusCode>(payload[1]);
this->statusCode = static_cast<StatusCode>(this->payload[1]);
}
}

View File

@@ -14,15 +14,8 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class AvrIspResponseFrame: public AvrResponseFrame
{
public:
AvrIspResponseFrame() = default;
explicit AvrIspResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses) {}
StatusCode statusCode;
/**
* Extracts the status code from the response frame payload.
*
* @return
*/
[[nodiscard]] StatusCode getStatusCode();
explicit AvrIspResponseFrame(const std::vector<AvrResponse>& avrResponses);
};
}

View File

@@ -8,11 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
void AvrResponseFrame::initFromAvrResponses(const std::vector<AvrResponse>& avrResponses) {
// Build a raw frame buffer from the AvrResponse objects and just call initFromRawFrame()
std::vector<unsigned char> rawFrame;
auto rawFrame = std::vector<unsigned char>();
for (const auto& avrResponse : avrResponses) {
auto responsePacket = avrResponse.getResponsePacket();
rawFrame.insert(rawFrame.end(), responsePacket.begin(), responsePacket.end());
rawFrame.insert(rawFrame.end(), avrResponse.responsePacket.begin(), avrResponse.responsePacket.end());
}
return this->initFromRawFrame(rawFrame);
@@ -20,20 +19,21 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
void AvrResponseFrame::initFromRawFrame(const std::vector<unsigned char>& rawFrame) {
if (rawFrame.size() < 4) {
// All AVR response frames must consist of at least four bytes (SOF, sequence ID (two bytes) and
// a protocol handler ID)
/*
* All AVR response frames must consist of at least four bytes (SOF, sequence ID (two bytes) and
* a protocol handler ID).
*/
throw Exception("Failed to construct AvrResponseFrame - unexpected end to raw frame");
}
if (rawFrame[0] != 0x0E) {
// The SOF field must always be 0x0E
throw Exception("Failed to construct AvrResponseFrame - unexpected SOF field value in raw frame");
// Invalid SOF byte value
throw Exception("Failed to construct AvrResponseFrame - unexpected SOF byte value in raw frame");
}
this->setSequenceId(static_cast<std::uint16_t>((rawFrame[2] << 8) + rawFrame[1]));
this->setProtocolHandlerId(rawFrame[3]);
this->sequenceId = static_cast<std::uint16_t>((rawFrame[2] << 8) + rawFrame[1]);
this->protocolHandlerId = static_cast<ProtocolHandlerId>(rawFrame[3]);
auto& payload = this->getPayload();
payload.insert(payload.begin(), rawFrame.begin() + 4, rawFrame.end());
this->payload.insert(payload.begin(), rawFrame.begin() + 4, rawFrame.end());
}
}

View File

@@ -14,7 +14,17 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
class AvrResponseFrame
{
public:
explicit AvrResponseFrame() = default;
/**
* Incrementing from 0x00
*/
std::uint16_t sequenceId = 0;
/**
* Destination sub-protocol handler ID
*/
ProtocolHandlerId protocolHandlerId = ProtocolHandlerId::AVR8_GENERIC;
std::vector<unsigned char> payload;
explicit AvrResponseFrame(const std::vector<AvrResponse>& avrResponses) {
this->initFromAvrResponses(avrResponses);
@@ -37,54 +47,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
*/
void initFromAvrResponses(const std::vector<AvrResponse>& avrResponses);
[[nodiscard]] std::uint16_t getSequenceId() const {
return this->sequenceID;
}
[[nodiscard]] ProtocolHandlerId getProtocolHandlerId() const {
return this->protocolHandlerID;
}
std::vector<unsigned char>& getPayload() {
return this->payload;
}
[[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;
virtual void initFromRawFrame(const std::vector<unsigned char>& rawFrame);
};
}

View File

@@ -6,25 +6,25 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
using namespace Bloom::Exceptions;
ResponseId DiscoveryResponseFrame::getResponseId() {
const auto& payload = this->getPayload();
if (payload.empty()) {
DiscoveryResponseFrame::DiscoveryResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses)
{
if (this->payload.empty()) {
throw Exception("Response ID missing from DISCOVERY response frame payload.");
}
return static_cast<ResponseId>(payload[0]);
this->id = static_cast<ResponseId>(payload[0]);
}
std::vector<unsigned char> DiscoveryResponseFrame::getPayloadData() {
const auto& payload = this->getPayload();
std::vector<unsigned char> DiscoveryResponseFrame::getPayloadData() const {
if (this->payload.size() <= 2) {
return {};
}
// DISCOVERY payloads include two bytes before the data (response ID and version byte).
auto data = std::vector<unsigned char>(
payload.begin() + 2,
payload.end()
return std::vector<unsigned char>(
this->payload.begin() + 2,
this->payload.end()
);
return data;
}
}

View File

@@ -11,7 +11,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
/*
* According to the protocol docs, response ID 0x81 is for a LIST response, but this doesn't seem to be
* well defined. So just going to use a generic name.
* well-defined. So just going to use a generic name.
*/
OK = 0x81,
FAILED = 0xA0,
@@ -20,14 +20,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class DiscoveryResponseFrame: public AvrResponseFrame
{
public:
DiscoveryResponseFrame() = default;
explicit DiscoveryResponseFrame(const std::vector<AvrResponse>& avrResponses): AvrResponseFrame(avrResponses) {}
ResponseId id;
ResponseId getResponseId();
explicit DiscoveryResponseFrame(const std::vector<AvrResponse>& avrResponses);
/**
* See parent method.
*/
std::vector<unsigned char> getPayloadData() override;
std::vector<unsigned char> getPayloadData() const;
};
}

View File

@@ -6,27 +6,28 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
using namespace Bloom::Exceptions;
EdbgControlResponseId EdbgControlResponseFrame::getResponseId() {
const auto& payload = this->getPayload();
if (payload.empty()) {
EdbgControlResponseFrame::EdbgControlResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses)
{
if (this->payload.empty()) {
throw Exception("Response ID missing from EDBG Control response frame payload.");
}
return static_cast<EdbgControlResponseId>(payload[0]);
this->id = static_cast<EdbgControlResponseId>(this->payload[0]);
}
std::vector<unsigned char> EdbgControlResponseFrame::getPayloadData() {
const auto& payload = this->getPayload();
if (this->payload.size() <= 3) {
return {};
}
/*
* EDBG Control data payloads include two bytes before the data (response ID and version byte) as well as an
* additional byte after the data, known as the 'status code'.
*/
auto data = std::vector<unsigned char>(
payload.begin() + 2,
payload.end() - 1
return std::vector<unsigned char>(
this->payload.begin() + 2,
this->payload.end() - 1
);
return data;
}
}

View File

@@ -14,12 +14,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
class EdbgControlResponseFrame: public AvrResponseFrame
{
public:
EdbgControlResponseFrame() = default;
explicit EdbgControlResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses) {}
EdbgControlResponseId id;
[[nodiscard]] EdbgControlResponseId getResponseId();
explicit EdbgControlResponseFrame(const std::vector<AvrResponse>& avrResponses);
[[nodiscard]] std::vector<unsigned char> getPayloadData() override;
[[nodiscard]] std::vector<unsigned char> getPayloadData();
};
}

View File

@@ -6,13 +6,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
{
using namespace Bloom::Exceptions;
ResponseId HouseKeepingResponseFrame::getResponseId() {
const auto& payload = this->getPayload();
if (payload.empty()) {
HouseKeepingResponseFrame::HouseKeepingResponseFrame(const std::vector<AvrResponse>& avrResponses)
: AvrResponseFrame(avrResponses)
{
if (this->payload.empty()) {
throw Exception("Response ID missing from HOUSEKEEPING response frame payload.");
}
return static_cast<ResponseId>(payload[0]);
this->id = static_cast<ResponseId>(this->payload[0]);
}
}

View File

@@ -10,15 +10,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::ResponseFrame
LIST = 0x81,
DATA = 0x84,
FAILED = 0xA0,
FAILED_WITH_DATA = 0xA1
FAILED_WITH_DATA = 0xA1,
};
class HouseKeepingResponseFrame: public AvrResponseFrame
{
public:
HouseKeepingResponseFrame() = default;
explicit HouseKeepingResponseFrame(const std::vector<AvrResponse>& avrResponses): AvrResponseFrame(avrResponses) {}
ResponseId id;
ResponseId getResponseId();
explicit HouseKeepingResponseFrame(const std::vector<AvrResponse>& avrResponses);
};
}

View File

@@ -16,13 +16,15 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
struct EdbgParameter
{
unsigned char context = 0x00;
unsigned char id = 0x00;
std::uint8_t size = 0;
unsigned char context;
unsigned char id;
std::uint8_t size;
constexpr EdbgParameter() = default;
constexpr EdbgParameter(unsigned char context, unsigned char id, std::uint8_t size)
: context(context), id(id), size(size) {};
: context(context)
, id(id)
, size(size)
{};
};
struct EdbgParameters

View File

@@ -33,11 +33,11 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> EdbgInterface::requestAvrEvent() {
auto avrEventResponse = this->sendCommandAndWaitForResponse(Avr::AvrEventCommand());
if (avrEventResponse.getResponseId() != 0x82) {
if (avrEventResponse.id != 0x82) {
throw DeviceCommunicationFailure("Unexpected response to AvrEventCommand from device");
}
return avrEventResponse.getEventDataSize() > 0 ? std::optional(avrEventResponse) : std::nullopt;
return !avrEventResponse.eventData.empty() ? std::optional(avrEventResponse) : std::nullopt;
}
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestAvrResponses() {
@@ -48,25 +48,25 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
auto avrResponse = this->sendCommandAndWaitForResponse(responseCommand);
responses.push_back(avrResponse);
const auto fragmentCount = avrResponse.getFragmentCount();
const auto fragmentCount = avrResponse.fragmentCount;
while (responses.size() < fragmentCount) {
// There are more response packets
auto avrResponse = this->sendCommandAndWaitForResponse(responseCommand);
if (avrResponse.getFragmentCount() != fragmentCount) {
if (avrResponse.fragmentCount != fragmentCount) {
throw DeviceCommunicationFailure(
"Failed to fetch AvrResponse objects - invalid fragment count returned."
);
}
if (avrResponse.getFragmentCount() == 0 && avrResponse.getFragmentNumber() == 0) {
if (avrResponse.fragmentCount == 0 && avrResponse.fragmentNumber == 0) {
throw DeviceCommunicationFailure(
"Failed to fetch AvrResponse objects - unexpected empty response"
);
}
if (avrResponse.getFragmentNumber() == 0) {
if (avrResponse.fragmentNumber == 0) {
// End of response data ( &this packet can be ignored)
break;
}

View File

@@ -38,8 +38,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
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.
/*
* 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() - 4 // Minus 4 to accommodate AVR command bytes
));
@@ -61,19 +63,16 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
"AVR Command must specify a valid response frame type, derived from AvrResponseFrame."
);
auto response = this->sendAvrCommandFrameAndWaitForResponse(avrCommandFrame);
const auto response = this->sendAvrCommandFrameAndWaitForResponse(avrCommandFrame);
if (response.getData()[0] != 0x01) {
if (response.data[0] != 0x01) {
// The last response packet should always acknowledge receipt of the AvrCommandFrame
throw Exceptions::DeviceCommunicationFailure(
"Failed to send AvrCommandFrame to device - device did not acknowledge receipt."
);
}
auto responses = this->requestAvrResponses();
auto responseFrame = typename CommandFrameType::ExpectedResponseFrameType();
responseFrame.initFromAvrResponses(responses);
return responseFrame;
return typename CommandFrameType::ExpectedResponseFrameType(this->requestAvrResponses());
}
virtual std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> requestAvrEvent();

View File

@@ -17,21 +17,21 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
{}
void EdbgTargetPowerManagementInterface::enableTargetPower() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x01)
);
if (response.getResponseId() == EdbgControlResponseId::FAILED) {
if (responseFrame.id == EdbgControlResponseId::FAILED) {
throw Exception("Failed to enable target power via EDBG Control protocol");
}
}
void EdbgTargetPowerManagementInterface::disableTargetPower() {
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
const auto responseFrame = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x00)
);
if (response.getResponseId() == EdbgControlResponseId::FAILED) {
if (responseFrame.id == EdbgControlResponseId::FAILED) {
throw Exception("Failed to disable target power via EDBG Control protocol");
}
}