forked from sysprogs/msp430-gdbproxy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit aae9135
Showing
25 changed files
with
5,186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
#include "stdafx.h" | ||
#include "GDBTarget.h" | ||
#include "MSP430Util.h" | ||
|
||
using namespace GDBServerFoundation; | ||
using namespace MSP430Proxy; | ||
|
||
#define REPORT_AND_RETURN(msg, result) { ReportLastMSP430Error(msg); return result; } | ||
|
||
bool MSP430Proxy::MSP430GDBTarget::Initialize( const char *pPortName ) | ||
{ | ||
if (m_bClosePending) | ||
return m_bValid; | ||
|
||
LONG version = 0; | ||
if (MSP430_Initialize((char *)pPortName, &version) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot initialize MSP430.DLL", false); | ||
m_bClosePending = true; | ||
|
||
if (MSP430_VCC(3333) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot enable Vcc", false); | ||
|
||
if (MSP430_Identify((char *)&m_DeviceInfo, sizeof(m_DeviceInfo), DEVICE_UNKNOWN) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot identify the MSP430 device", false); | ||
|
||
if (MSP430_Reset(ALL_RESETS, FALSE, FALSE) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot reset the MSP430 device", false); | ||
|
||
m_UsedBreakpoints.resize(m_DeviceInfo.nBreakpoints); | ||
|
||
m_bValid = true; | ||
return true; | ||
} | ||
|
||
MSP430Proxy::MSP430GDBTarget::~MSP430GDBTarget() | ||
{ | ||
if (m_bClosePending) | ||
MSP430_Close(FALSE); | ||
} | ||
|
||
bool MSP430Proxy::MSP430GDBTarget::WaitForJTAGEvent() | ||
{ | ||
for (;;) | ||
{ | ||
LONG state = 0; | ||
if (MSP430_State(&state, m_BreakInPending, NULL) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot query device state", false); | ||
if (state != RUNNING) | ||
{ | ||
m_BreakInPending = false; | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430Proxy::MSP430GDBTarget::ExecuteRemoteCommand( const std::string &command, std::string &output ) | ||
{ | ||
if (command == "help") | ||
{ | ||
output = "Supported stub commands:\n\ | ||
\tmon help - Display this message\n\ | ||
\tmon erase - Erase the FLASH memory\n"; | ||
return kGDBSuccess; | ||
} | ||
else if (command == "erase") | ||
{ | ||
if (MSP430_Erase(ERASE_MAIN, m_DeviceInfo.mainStart, m_DeviceInfo.mainEnd - m_DeviceInfo.mainStart) != STATUS_OK) | ||
{ | ||
output = "Cannot erase FLASH: "; | ||
output += GetLastMSP430Error(); | ||
output += "\n"; | ||
} | ||
else | ||
output = "Flash memory erased. Run \"load\" to program your binary.\n"; | ||
|
||
return kGDBSuccess; | ||
} | ||
else | ||
return kGDBNotSupported; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430Proxy::MSP430GDBTarget::GetEmbeddedMemoryRegions( std::vector<EmbeddedMemoryRegion> ®ions ) | ||
{ | ||
if (m_DeviceInfo.mainStart || m_DeviceInfo.mainEnd) | ||
regions.push_back(EmbeddedMemoryRegion(mtFLASH, m_DeviceInfo.mainStart, m_DeviceInfo.mainEnd - m_DeviceInfo.mainStart + 1)); | ||
if (m_DeviceInfo.ramStart || m_DeviceInfo.ramEnd) | ||
regions.push_back(EmbeddedMemoryRegion(mtRAM, m_DeviceInfo.ramStart, m_DeviceInfo.ramEnd- m_DeviceInfo.ramStart + 1)); | ||
if (m_DeviceInfo.ram2Start || m_DeviceInfo.ram2End) | ||
regions.push_back(EmbeddedMemoryRegion(mtRAM, m_DeviceInfo.ram2Start, m_DeviceInfo.ram2End- m_DeviceInfo.ram2Start + 1)); | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::GetLastStopRecord( TargetStopRecord *pRec ) | ||
{ | ||
pRec->Reason = kSignalReceived; | ||
pRec->Extension.SignalNumber = SIGTRAP; | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::ResumeAndWait( int threadID ) | ||
{ | ||
if (MSP430_Run(RUN_TO_BREAKPOINT, FALSE) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot resume device", kGDBUnknownError); | ||
|
||
if (!WaitForJTAGEvent()) | ||
return kGDBUnknownError; | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::Step( int threadID ) | ||
{ | ||
if (MSP430_Run(SINGLE_STEP, FALSE) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot perform single stepping", kGDBUnknownError); | ||
|
||
if (!WaitForJTAGEvent()) | ||
return kGDBUnknownError; | ||
|
||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::SendBreakInRequestAsync() | ||
{ | ||
m_BreakInPending = true; | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::ReadFrameRelatedRegisters( int threadID, TargetRegisterValues ®isters ) | ||
{ | ||
LONG rawRegs[16]; | ||
if (MSP430_Read_Registers(rawRegs, MASKREG(PC) | MASKREG(SP)) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot read frame-related registers", kGDBUnknownError); | ||
|
||
registers[PC] = RegisterValue(rawRegs[PC], 2); | ||
registers[SP] = RegisterValue(rawRegs[SP], 2); | ||
|
||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::ReadTargetRegisters( int threadID, TargetRegisterValues ®isters ) | ||
{ | ||
LONG rawRegs[16]; | ||
if (MSP430_Read_Registers(rawRegs, ALL_REGS) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot read device registers", kGDBUnknownError); | ||
|
||
for (size_t i = 0; i < __countof(rawRegs); i++) | ||
registers[i] = RegisterValue(rawRegs[i], 16); | ||
|
||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::WriteTargetRegisters( int threadID, const TargetRegisterValues ®isters ) | ||
{ | ||
LONG rawRegs[16]; | ||
int mask = 0; | ||
|
||
for (size_t i = 0; i < 16; i++) | ||
if (registers[i].Valid) | ||
{ | ||
mask |= MASKREG(i); | ||
rawRegs[i] = registers[i].ToUInt32(); | ||
} | ||
|
||
if (MSP430_Write_Registers(rawRegs, mask) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot write device registers", kGDBUnknownError); | ||
|
||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::ReadTargetMemory( ULONGLONG Address, void *pBuffer, size_t *pSizeInBytes ) | ||
{ | ||
if (MSP430_Read_Memory((LONG)Address, (char *)pBuffer, *pSizeInBytes) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot read device memory", kGDBUnknownError); | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::WriteTargetMemory( ULONGLONG Address, const void *pBuffer, size_t sizeInBytes ) | ||
{ | ||
if (MSP430_Write_Memory((LONG)Address, (char *)pBuffer, sizeInBytes) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot write device memory", kGDBUnknownError); | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::GetDynamicLibraryList( std::vector<DynamicLibraryRecord> &libraries ) | ||
{ | ||
return kGDBNotSupported; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::GetThreadList( std::vector<ThreadRecord> &threads ) | ||
{ | ||
return kGDBNotSupported; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::SetThreadModeForNextCont( int threadID, DebugThreadMode mode, OUT bool *pNeedRestoreCall, IN OUT INT_PTR *pRestoreCookie ) | ||
{ | ||
return kGDBNotSupported; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::Terminate() | ||
{ | ||
return kGDBNotSupported; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::CreateBreakpoint( BreakpointType type, ULONGLONG Address, unsigned kind, OUT INT_PTR *pCookie ) | ||
{ | ||
if (type != bptHardwareBreakpoint) | ||
return kGDBNotSupported; | ||
|
||
for (size_t i = 0; i < m_UsedBreakpoints.size(); i++) | ||
if (!m_UsedBreakpoints[i]) | ||
{ | ||
if (MSP430_Breakpoint(i, (LONG)Address) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot set a hardware breakpoint", kGDBUnknownError); | ||
m_UsedBreakpoints[i] = true; | ||
*pCookie = i; | ||
return kGDBSuccess; | ||
} | ||
|
||
return kGDBUnknownError; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430GDBTarget::RemoveBreakpoint( BreakpointType type, ULONGLONG Address, INT_PTR Cookie ) | ||
{ | ||
if (type != bptHardwareBreakpoint) | ||
return kGDBNotSupported; | ||
|
||
size_t i = (size_t)Cookie; | ||
MSP430_Clear_Breakpoint(i); | ||
m_UsedBreakpoints[i] = false; | ||
|
||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430Proxy::MSP430GDBTarget::EraseFLASH( ULONGLONG addr, size_t length ) | ||
{ | ||
if (MSP430_Erase(ERASE_MAIN, (LONG)addr, length) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot erase FLASH memory", kGDBUnknownError); | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430Proxy::MSP430GDBTarget::WriteFLASH( ULONGLONG addr, const void *pBuffer, size_t length ) | ||
{ | ||
if (MSP430_Write_Memory((LONG)addr, (char *)pBuffer, length) != STATUS_OK) | ||
REPORT_AND_RETURN("Cannot program FLASH memory", kGDBUnknownError); | ||
return kGDBSuccess; | ||
} | ||
|
||
GDBServerFoundation::GDBStatus MSP430Proxy::MSP430GDBTarget::CommitFLASHWrite() | ||
{ | ||
return kGDBSuccess; | ||
} | ||
|
||
void MSP430Proxy::MSP430GDBTarget::ReportLastMSP430Error( const char *pHint ) | ||
{ | ||
if (pHint) | ||
printf("%s: %s\n", pHint, GetLastMSP430Error()); | ||
else | ||
printf("%s\n", GetLastMSP430Error()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#pragma once | ||
#include "../../GDBServerFoundation/GDBServer.h" | ||
#include "../../GDBServerFoundation/GDBStub.h" | ||
#include "../../GDBServerFoundation/IGDBTarget.h" | ||
#include <MSP430_Debug.h> | ||
|
||
#include "registers-msp430.h" | ||
#include <vector> | ||
|
||
namespace MSP430Proxy | ||
{ | ||
using namespace GDBServerFoundation; | ||
|
||
class MSP430GDBTarget : public ISyncGDBTarget, public IFLASHProgrammer | ||
{ | ||
private: | ||
bool m_bClosePending, m_bValid; | ||
DEVICE_T m_DeviceInfo; | ||
std::vector<bool> m_UsedBreakpoints; | ||
|
||
bool m_BreakInPending; | ||
|
||
private: | ||
bool WaitForJTAGEvent(); | ||
void ReportLastMSP430Error(const char *pHint); | ||
|
||
public: | ||
MSP430GDBTarget() | ||
: m_bClosePending(false) | ||
, m_bValid(false) | ||
, m_BreakInPending(false) | ||
{ | ||
} | ||
|
||
~MSP430GDBTarget(); | ||
|
||
bool Initialize(const char *pPortName); | ||
|
||
virtual GDBStatus GetLastStopRecord(TargetStopRecord *pRec); | ||
virtual GDBStatus ResumeAndWait(int threadID); | ||
virtual GDBStatus Step(int threadID); | ||
virtual GDBStatus SendBreakInRequestAsync(); | ||
|
||
virtual const PlatformRegisterList *GetRegisterList() | ||
{ | ||
return &GDBServerFoundation::MSP430::RegisterList; | ||
} | ||
|
||
public: //Register accessing API | ||
virtual GDBStatus ReadFrameRelatedRegisters(int threadID, TargetRegisterValues ®isters); | ||
virtual GDBStatus ReadTargetRegisters(int threadID, TargetRegisterValues ®isters); | ||
virtual GDBStatus WriteTargetRegisters(int threadID, const TargetRegisterValues ®isters); | ||
|
||
public: //Memory accessing API | ||
virtual GDBStatus ReadTargetMemory(ULONGLONG Address, void *pBuffer, size_t *pSizeInBytes); | ||
virtual GDBStatus WriteTargetMemory(ULONGLONG Address, const void *pBuffer, size_t sizeInBytes); | ||
|
||
public: //Optional methods, can be left unimplemented | ||
virtual GDBStatus GetDynamicLibraryList(std::vector<DynamicLibraryRecord> &libraries); | ||
virtual GDBStatus GetThreadList(std::vector<ThreadRecord> &threads); | ||
virtual GDBStatus SetThreadModeForNextCont(int threadID, DebugThreadMode mode, OUT bool *pNeedRestoreCall, IN OUT INT_PTR *pRestoreCookie); | ||
virtual GDBStatus Terminate(); | ||
|
||
virtual GDBStatus CreateBreakpoint(BreakpointType type, ULONGLONG Address, unsigned kind, OUT INT_PTR *pCookie); | ||
virtual GDBStatus RemoveBreakpoint(BreakpointType type, ULONGLONG Address, INT_PTR Cookie); | ||
|
||
virtual GDBStatus ExecuteRemoteCommand(const std::string &command, std::string &output); | ||
|
||
virtual IFLASHProgrammer *GetFLASHProgrammer() {return this;} | ||
|
||
public: | ||
virtual GDBStatus GetEmbeddedMemoryRegions(std::vector<EmbeddedMemoryRegion> ®ions); | ||
virtual GDBStatus EraseFLASH(ULONGLONG addr, size_t length); | ||
virtual GDBStatus WriteFLASH(ULONGLONG addr, const void *pBuffer, size_t length); | ||
virtual GDBStatus CommitFLASHWrite(); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#include "stdafx.h" | ||
#include "MSP430Util.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#pragma once | ||
#include <MSP430.h> | ||
|
||
static const char *GetLastMSP430Error() | ||
{ | ||
return MSP430_Error_String(MSP430_Error_Number()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
======================================================================== | ||
CONSOLE APPLICATION : msp430-gdbproxy Project Overview | ||
======================================================================== | ||
|
||
AppWizard has created this msp430-gdbproxy application for you. | ||
|
||
This file contains a summary of what you will find in each of the files that | ||
make up your msp430-gdbproxy application. | ||
|
||
|
||
msp430-gdbproxy.vcxproj | ||
This is the main project file for VC++ projects generated using an Application Wizard. | ||
It contains information about the version of Visual C++ that generated the file, and | ||
information about the platforms, configurations, and project features selected with the | ||
Application Wizard. | ||
|
||
msp430-gdbproxy.vcxproj.filters | ||
This is the filters file for VC++ projects generated using an Application Wizard. | ||
It contains information about the association between the files in your project | ||
and the filters. This association is used in the IDE to show grouping of files with | ||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the | ||
"Source Files" filter). | ||
|
||
msp430-gdbproxy.cpp | ||
This is the main application source file. | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
Other standard files: | ||
|
||
StdAfx.h, StdAfx.cpp | ||
These files are used to build a precompiled header (PCH) file | ||
named msp430-gdbproxy.pch and a precompiled types file named StdAfx.obj. | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
Other notes: | ||
|
||
AppWizard uses "TODO:" comments to indicate parts of the source code you | ||
should add to or customize. | ||
|
||
///////////////////////////////////////////////////////////////////////////// |
Oops, something went wrong.