Skip to content
Snippets Groups Projects
Commit 151e3ab7 authored by Micah Elizabeth Scott's avatar Micah Elizabeth Scott
Browse files

Testing AHB-AP access

Some silly bugs are undoubtedly lurking here, but sometimes this will successfully read and write target RAM :)
parent 860cf11c
No related branches found
No related tags found
No related merge requests found
...@@ -42,15 +42,54 @@ int ARMDebug::begin(unsigned clockPin, unsigned dataPin, libswd_loglevel_t logLe ...@@ -42,15 +42,54 @@ int ARMDebug::begin(unsigned clockPin, unsigned dataPin, libswd_loglevel_t logLe
libswdctx->config.autofixerrors = false; libswdctx->config.autofixerrors = false;
libswd_log_level_set(libswdctx, logLevel); libswd_log_level_set(libswdctx, logLevel);
// Identify the attached chip
ret = libswd_dap_detect(libswdctx, LIBSWD_OPERATION_EXECUTE, &idcode); ret = libswd_dap_detect(libswdctx, LIBSWD_OPERATION_EXECUTE, &idcode);
if (ret >= 0) { if (ret < 0) return ret;
libswd_log(libswdctx, LIBSWD_LOGLEVEL_NORMAL, libswd_log(libswdctx, LIBSWD_LOGLEVEL_NORMAL,
"Found ARM processor. IDCODE: 0x%X (%s)\n", "Found ARM processor. IDCODE: 0x%X (%s)\n", *idcode, libswd_bin32_string(idcode));
*idcode, libswd_bin32_string(idcode));
// Initialize CTRL/STAT, request system and debugger power-up
int ctrlstat = LIBSWD_DP_CTRLSTAT_CDBGPWRUPREQ | LIBSWD_DP_CTRLSTAT_CSYSPWRUPREQ;
ret = libswd_dp_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_DP_CTRLSTAT_ADDR, &ctrlstat);
if (ret < 0) return ret;
// Wait for power-up acknowledgment
uint32_t powerAck = LIBSWD_DP_CTRLSTAT_CDBGPWRUPACK | LIBSWD_DP_CTRLSTAT_CSYSPWRUPACK;
unsigned retries = 4;
while (retries-- && (ctrlstat & powerAck) != powerAck) {
int *ptr;
ret = libswd_dp_read(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_DP_CTRLSTAT_ADDR, &ptr);
if (ret < 0) return ret;
ctrlstat = *ptr;
}
if ((ctrlstat & powerAck) != powerAck) {
libswd_log(libswdctx, LIBSWD_LOGLEVEL_ERROR,
"ARMDebug: Debug port failed to power on (CTRLSTAT: %08x)\n", ctrlstat);
return LIBSWD_ERROR_MAXRETRY;
} }
libswd_cmdq_free_head(libswdctx->cmdq); // Select the default debug access port
return ret; ret = libswd_ap_select(libswdctx, LIBSWD_OPERATION_EXECUTE, 0);
if (ret < 0) return ret;
// We expect this to be an AHB (memory bus) access port. Make sure this is right.
int *idr;
ret = libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_IDR, &idr);
if (ret < 0) return ret;
if ((*idr & 0xF) != 1) {
libswd_log(libswdctx, LIBSWD_LOGLEVEL_ERROR,
"ARMDebug: Default access port is not an AHB-AP as expected! (IDR: %08x)\n", *idr);
return LIBSWD_ERROR_GENERAL;
}
// Set up default CSW values for the AHB-AP. Use 32-bit accesses with auto-increment.
int csw = (1 << 6) | // Device enable
(1 << 4) | // Increment by a single word
(2 << 0) ; // 32-bit data size
ret = libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_CONTROLSTATUS, &csw);
if (ret < 0) return ret;
return 0;
} }
void ARMDebug::end() void ARMDebug::end()
...@@ -63,28 +102,46 @@ void ARMDebug::end() ...@@ -63,28 +102,46 @@ void ARMDebug::end()
} }
} }
int ARMDebug::memStore(uint32_t addr, uint32_t data, uint8_t accessPort) int ARMDebug::memStore(uint32_t addr, uint32_t data)
{ {
return 0; return memStore(addr, &data, 1);
} }
int ARMDebug::memLoad(uint32_t addr, uint32_t &data, uint8_t accessPort) int ARMDebug::memLoad(uint32_t addr, uint32_t &data)
{ {
int ret = 0; return memLoad(addr, &data, 1);
}
ret = libswd_ap_select(libswdctx, LIBSWD_OPERATION_EXECUTE, accessPort); int ARMDebug::memStore(uint32_t addr, uint32_t *data, unsigned count)
if (ret >= 0) { {
int ret = libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_TAR, (int*) &addr);
if (ret < 0) return ret;
int *result = 0; while (count) {
ret = libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, 0xFC, &result); ret = libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_DRW, (int*) data);
if (ret >= 0) { if (ret < 0) return ret;
libswd_log(libswdctx, LIBSWD_LOGLEVEL_NORMAL, data++;
"FC -> %p %08x\n", result, *result); count--;
}
} }
libswd_cmdq_free_head(libswdctx->cmdq); return 0;
return ret; }
int ARMDebug::memLoad(uint32_t addr, uint32_t *data, unsigned count)
{
int ret = libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_TAR, (int*) &addr);
if (ret < 0) return ret;
while (count) {
int *ptr;
ret = libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, AHB_AP_DRW, &ptr);
if (ret < 0) return ret;
*data = *ptr;
data++;
count--;
}
return 0;
} }
void ARMDebug::mosi_transfer(uint32_t data, unsigned nBits) void ARMDebug::mosi_transfer(uint32_t data, unsigned nBits)
...@@ -114,6 +171,7 @@ uint32_t ARMDebug::miso_transfer(unsigned nBits) ...@@ -114,6 +171,7 @@ uint32_t ARMDebug::miso_transfer(unsigned nBits)
void ARMDebug::mosi_trn(unsigned nClocks) void ARMDebug::mosi_trn(unsigned nClocks)
{ {
digitalWrite(dataPin, HIGH);
pinMode(dataPin, INPUT_PULLUP); pinMode(dataPin, INPUT_PULLUP);
while (nClocks--) { while (nClocks--) {
digitalWrite(clockPin, LOW); digitalWrite(clockPin, LOW);
......
...@@ -47,14 +47,13 @@ public: ...@@ -47,14 +47,13 @@ public:
/// Deinitialize the debug interface, if it's been initialized. /// Deinitialize the debug interface, if it's been initialized.
void end(); void end();
/// Memory store, using a memory access port /// Memory store
int memStore(uint32_t addr, uint32_t data, uint8_t accessPort = CortexM_AHB_AP); int memStore(uint32_t addr, uint32_t data);
int memStore(uint32_t addr, uint32_t *data, unsigned count);
/// Memory load, using a memory access port /// Memory load
int memLoad(uint32_t addr, uint32_t &data, uint8_t accessPort = CortexM_AHB_AP); int memLoad(uint32_t addr, uint32_t &data);
int memLoad(uint32_t addr, uint32_t *data, unsigned count);
// Memory access port (MEM-AP) types.
static const uint8_t CortexM_AHB_AP = 0x11; // AHB-AP on ARM Cortex-M parts
// Low-level interface (LSB-first) // Low-level interface (LSB-first)
void mosi_transfer(uint32_t data, unsigned nBits); void mosi_transfer(uint32_t data, unsigned nBits);
...@@ -62,6 +61,9 @@ public: ...@@ -62,6 +61,9 @@ public:
void mosi_trn(unsigned nClocks); void mosi_trn(unsigned nClocks);
void miso_trn(unsigned nClocks); void miso_trn(unsigned nClocks);
// Low-level access to libswd
libswd_ctx_t *getContext() { return libswdctx; }
private: private:
uint8_t clockPin, dataPin; uint8_t clockPin, dataPin;
libswd_ctx_t *libswdctx; libswd_ctx_t *libswdctx;
......
...@@ -30,6 +30,7 @@ void loop() ...@@ -30,6 +30,7 @@ void loop()
Serial.println(""); Serial.println("");
while (digitalRead(buttonPin) == LOW); while (digitalRead(buttonPin) == LOW);
delay(20); // Debounce delay
while (digitalRead(buttonPin) == HIGH) { while (digitalRead(buttonPin) == HIGH) {
// While we're waiting, blink the LED to indicate we're alive // While we're waiting, blink the LED to indicate we're alive
digitalWrite(ledPin, (millis() % 1000) < 150); digitalWrite(ledPin, (millis() % 1000) < 150);
...@@ -40,5 +41,14 @@ void loop() ...@@ -40,5 +41,14 @@ void loop()
return; return;
uint32_t data; uint32_t data;
target.memLoad(0x000000, data); if (target.memLoad(0x20000000, data) < 0)
return;
libswd_log(target.getContext(), LIBSWD_LOGLEVEL_NORMAL, "data = 0x%08x\n", data);
data ^= 0xFFFFFFFF;
libswd_log(target.getContext(), LIBSWD_LOGLEVEL_NORMAL, "data = 0x%08x\n", data);
if (target.memStore(0x20000000, data) < 0)
return;
if (target.memLoad(0x20000000, data) < 0)
return;
libswd_log(target.getContext(), LIBSWD_LOGLEVEL_NORMAL, "data = 0x%08x\n", data);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment