Skip to content

Commit

Permalink
Initial ARM Flash/Patch/Breakpoint unit support
Browse files Browse the repository at this point in the history
  • Loading branch information
azonenberg committed Jul 31, 2018
1 parent 4b27604 commit 0310d43
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 168 deletions.
67 changes: 2 additions & 65 deletions ARMCortexM4.cpp
Expand Up @@ -49,17 +49,7 @@ using namespace std;
ARMCortexM4::ARMCortexM4(DebuggerInterface* iface, ARMDebugMemAccessPort* ap, uint32_t address, ARMDebugPeripheralIDRegisterBits idreg)
: ARMv7MProcessor(iface, ap, address, idreg)
{
//LogTrace("Found ARM Cortex-M4 at %08x, probing...\n", address);

/*
//DBGDSMCR turn off MMU
//TODO: Write to DBGDRCR to halt the CPU (C11.11.17)
//TODO: Write to DBGDSCCR to force write-through cache (C11.11.19)
//DBGDEVID[3:0] 2226
*/
}

ARMCortexM4::~ARMCortexM4()
Expand All @@ -78,61 +68,8 @@ void ARMCortexM4::PrintInfo()
if(HaltedDueToUnrecoverableException())
LogVerbose("Core is halted due to unrecoverable exception\n");

//LogTrace("asdf\n");


/*
PrintIDRegister(m_deviceID);
//Read DBGDSCR to get status stuff (TODO: make struct) for this
//uint32_t dbgdscr = ReadRegisterByIndex(DBGDSCR_EXT);
//LogDebug("DBGDSCR = %x\n", dbgdscr);
//Pins of interest are MIO bank 1, pins 50/51
//Read MCTRL
//Read PSS_IDCODE from the zynq
//uint32_t pss_idcode = ReadMemory(0xF8000530);
//LogDebug("pss_idcode = %08x\n", pss_idcode);
//Read MCTRL
uint32_t mctrl = ReadMemory(0xF8007080);
LogDebug("mctrl = %08x\n", mctrl);
//Set MIO7 (MIO LED) to output
m_ap->GetDebugPort()->WriteMemory(0xf800071c, 0x00000600); //sclr.MIO_PIN_07
m_ap->GetDebugPort()->WriteMemory(0xe000a204, 0x00000080); //gpio.XGPIOPS_DIRM_OFFSET
m_ap->GetDebugPort()->WriteMemory(0xe000a208, 0x00000080); //gpio.XGPIOPS_OUTEN_OFFSET
for(int i=0; i<10; i++)
{
LogDebug("toggle\n");
m_ap->GetDebugPort()->WriteMemory(0xe000a040, 0x00000080); //gpio.XGPIOPS_DATA_OFFSET
usleep(500 * 1000);
m_ap->GetDebugPort()->WriteMemory(0xe000a040, 0x00000000); //gpio.XGPIOPS_DATA_OFFSET
usleep(500 * 1000);
}
//MIO LED @ MIO7
//MIO inputs at MIO50, 51
//GPIO controller is at 0xe000a000
//Input data (DATA_RO) is at +0x60 - 6c
//
//Read L0_SEL
*/
//Read the PC and dump the instruction at that address
//uint32_t pc = SampleProgramCounter();
//LogVerbose("PC = %08x\n", pc);

//DEBUG
//EnterDebugState();

/*
//uint32_t value = ReadMemory(0xE0000000);//m_ap->ReadWord(0x80000000); //ReadMemory(0xFC000000);
//LogDebug(" value = %08x\n", value);
*/
if(m_fpb)
m_fpb->PrintInfo();
}

string ARMCortexM4::GetDescription()
Expand Down
26 changes: 26 additions & 0 deletions ARMDebugMemAccessPort.cpp
Expand Up @@ -403,6 +403,32 @@ void ARMDebugMemAccessPort::ProcessDebugBlock(uint32_t base_address, uint32_t id
//Handle fully supported devices first, then just make a generic CoreSight device for the rest
switch(reg.bits.partnum)
{
//Cortex-M4 FPB
case 0x003:
{
//Find the CPU it goes to
ARMv7MProcessor* cpu = NULL;
for(size_t i=m_debugDevices.size() - 1; ; i--)
{
cpu = dynamic_cast<ARMv7MProcessor*>(m_debugDevices[i]);
if(cpu)
break;
if(i == 0)
break;
}

if(!cpu)
{
LogError("Found Cortex-M4 Flash Patch/Breakpoint unit but unable to match it to a CPU core");
return;
}

//Create the FPB unit and attach it to the CPU (rather than having it show up as a separate device)
ARMFlashPatchBreakpoint* fpb = new ARMFlashPatchBreakpoint(cpu, this, base_address, reg.bits);
cpu->AddFlashPatchUnit(fpb);
};
break;

//Cortex-M4 SCS
case 0x00c:
{
Expand Down
186 changes: 186 additions & 0 deletions ARMFlashPatchBreakpoint.cpp
@@ -0,0 +1,186 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2018 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

/**
@file
@author Andrew D. Zonenberg
@brief ARM Cortex-M Flash Patch/Breakpoint
*/
#include "jtaghal.h"
#include "ARMAPBDevice.h"
#include "ARMFlashPatchBreakpoint.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

ARMFlashPatchBreakpoint::ARMFlashPatchBreakpoint(
ARMv7MProcessor* cpu,
ARMDebugMemAccessPort* ap,
uint32_t address,
ARMDebugPeripheralIDRegisterBits idreg)
: ARMCoreSightDevice(ap, address, idreg)
, m_cpu(cpu)
{
//Assume RAM is at 0x20000000 for now.
//TODO: is this always true for Cortex-M's?
m_sramBase = 0x20000000;

//Read the control register to get read-only config
uint32_t ctrl = ReadRegisterByIndex(FP_CTRL);
m_literalComparators = (ctrl >> 8) & 0xf;
m_codeComparators = ( (ctrl >> 4) & 0xf ) | ( (ctrl >> 8) & 0xf0 );

//Read the remap register to see if we can remap or just to breakpoints
uint32_t remap = ReadRegisterByIndex(FP_REMAP);
m_canRemap = false;
if(remap & 0x20000000)
m_canRemap = true;

//Pull volatile config
ProbeStatusRegisters();
}

ARMFlashPatchBreakpoint::~ARMFlashPatchBreakpoint()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pretty printing

void ARMFlashPatchBreakpoint::ProbeStatusRegisters()
{
uint32_t ctrl = ReadRegisterByIndex(FP_CTRL);
m_enabled = (ctrl & 1) ? true : false;

uint32_t remap = ReadRegisterByIndex(FP_REMAP);
m_tableBase = (remap & 0x1FFFFFE0) | m_sramBase;
}

void ARMFlashPatchBreakpoint::PrintInfo()
{
ProbeStatusRegisters();

//Heading
LogNotice("%s rev %d.%d.%d\n",
GetDescription().c_str(),
m_idreg.revnum, m_idreg.cust_mod, m_idreg.revand);
LogIndenter li;

//LogNotice("Attached to CPU: %s\n", m_cpu->GetDescription().c_str());

//Summary
if(m_enabled)
LogNotice("FPB enabled\n");
else
LogNotice("FPB disabled\n");

if(m_canRemap)
{
LogNotice("Remap supported\n");
LogNotice("Remap table is at 0x%08x\n", m_tableBase);
}
else
LogNotice("Remap not supported, breakpoints only\n");

//Code
LogNotice("%d code comparators\n", m_codeComparators);
for(uint32_t i=0; i<m_codeComparators; i++)
{
LogIndenter li2;
}

//Literals
LogNotice("%d literal comparators\n", m_literalComparators);
}

string ARMFlashPatchBreakpoint::GetDescription()
{
switch(m_idreg.partnum)
{
case 0x003:
return "Cortex-M4 Flash Patch/Breakpoint";

default:
LogWarning("Unknown ARM FPB device (part number 0x%x)\n", m_idreg.partnum);
return "unknown FPB device";
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fun commands that actually do stuff

void ARMFlashPatchBreakpoint::Enable()
{
uint32_t ctrl = ReadRegisterByIndex(FP_CTRL);
ctrl |= 1; //set ENABLE
ctrl |= 2; //must also set KEY for writes to take effect
WriteRegisterByIndex(FP_CTRL, ctrl);

m_enabled = true;
}

void ARMFlashPatchBreakpoint::Disable()
{
uint32_t ctrl = ReadRegisterByIndex(FP_CTRL);
ctrl &= ~1; //clear ENABLE
ctrl |= 2; //must also set KEY for writes to take effect
WriteRegisterByIndex(FP_CTRL, ctrl);

m_enabled = false;
}

void ARMFlashPatchBreakpoint::SetRemapTableBase(uint32_t base)
{
//TODO: Sanity check that address is within SRAM region

//Align to 8 word boundary
base &= 0x1FFFFFE0;
WriteRegisterByIndex(FP_REMAP, base);

//Save the actual address including SRAM offset
m_tableBase = base | m_sramBase;
}

void ARMFlashPatchBreakpoint::RemapFlashWord(uint32_t slot, uint32_t flashAddress, uint32_t newValue)
{
if(flashAddress & 3)
{
LogWarning("ARM FPB requres word-aligned address\n");
return;
}

//Write the patched data to the remap table
m_ap->WriteWord(m_tableBase + slot*4, newValue);

//Write to FP_COMPx to enable the comparator. Mask off unused address bits.
flashAddress &= 0x1ffffffc;
WriteRegisterByIndex(GetCodeComparatorIndex(slot), flashAddress | 1);
}
92 changes: 92 additions & 0 deletions ARMFlashPatchBreakpoint.h
@@ -0,0 +1,92 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2018 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

/**
@file
@author Andrew D. Zonenberg
@brief ARMv7-M Flash Patch/Breakpoint Unit
*/
#ifndef ARMFlashPatchBreakpoint_h
#define ARMFlashPatchBreakpoint_h

class ARMv7MProcessor;

class ARMFlashPatchBreakpoint : public ARMCoreSightDevice
{
public:
ARMFlashPatchBreakpoint(
ARMv7MProcessor* cpu,
ARMDebugMemAccessPort* ap,
uint32_t address,
ARMDebugPeripheralIDRegisterBits idreg);
virtual ~ARMFlashPatchBreakpoint();

virtual std::string GetDescription();
virtual void PrintInfo();

enum FpbRegisters
{
FP_CTRL = 0,
FP_REMAP = 1,
FP_COMP0 = 2 //plus comparator number
};

uint32_t GetCodeComparatorIndex(uint32_t i)
{ return FP_COMP0 + i; }

uint32_t GetLiteralComparatorIndex(uint32_t i)
{ return FP_COMP0 + m_codeComparators + i; }

uint32_t GetCodeComparatorCount()
{ return m_codeComparators; }

uint32_t GetLiteralComparatorCount()
{ return m_literalComparators; }

void Enable();
void Disable();

void SetRemapTableBase(uint32_t base);
void RemapFlashWord(uint32_t slot, uint32_t flashAddress, uint32_t newValue);
//TODO: literal comparator support

protected:
ARMv7MProcessor* m_cpu;

uint32_t m_codeComparators;
uint32_t m_literalComparators;
bool m_enabled;
bool m_canRemap;
uint32_t m_tableBase;
uint32_t m_sramBase;

void ProbeStatusRegisters();
};

#endif

0 comments on commit 0310d43

Please sign in to comment.