From d0a8ce08199b40e29a7c7b3642c56e7158b1ca09 Mon Sep 17 00:00:00 2001 From: Mark Rages Date: Fri, 27 Jul 2018 16:07:19 -0600 Subject: [PATCH] Add extra port for mass erasing / unprotecting nRF52 with APPROTECT set. Mostly copied from the equivalent in kinetis.c and https://devzone.nordicsemi.com/f/nordic-q-a/12484/approtect-and-dap/47301 --- src/target/adiv5.c | 3 ++ src/target/kinetis.c | 2 +- src/target/nrf51.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 109cab3..08baf30 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -445,6 +445,9 @@ void adiv5_dp_init(ADIv5_DP_t *dp) extern void kinetis_mdm_probe(ADIv5_AP_t *); kinetis_mdm_probe(ap); + extern void nrf51_mdm_probe(ADIv5_AP_t *); + nrf51_mdm_probe(ap); + if (ap->base == 0xffffffff) { /* No debug entries... useless AP */ adiv5_ap_unref(ap); diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 4770773..d9f4d0a 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -341,7 +341,7 @@ const struct command_s kinetis_mdm_cmd_list[] = { {NULL, NULL, NULL} }; -bool nop_function(void) +static bool nop_function(void) { return true; } diff --git a/src/target/nrf51.c b/src/target/nrf51.c index f85d182..9948bb1 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -335,3 +335,81 @@ static bool nrf51_cmd_read(target *t, int argc, const char *argv[]) return nrf51_cmd_read_help(t); } + +#include "adiv5.h" +#define NRF52_MDM_IDR 0x02880000 + +static bool nrf51_mdm_cmd_erase_mass(target *t); + +const struct command_s nrf51_mdm_cmd_list[] = { + {"erase_mass", (cmd_handler)nrf51_mdm_cmd_erase_mass, "Erase entire flash memory"}, + {NULL, NULL, NULL} +}; + +static bool nop_function(void) +{ + return true; +} + +void nrf51_mdm_probe(ADIv5_AP_t *ap) +{ + switch(ap->idr) { + case NRF52_MDM_IDR: + break; + default: + return; + } + + target *t = target_new(); + adiv5_ap_ref(ap); + t->priv = ap; + t->priv_free = (void*)adiv5_ap_unref; + + t->driver = "Nordic nRF52 Access Port"; + t->attach = (void*)nop_function; + t->detach = (void*)nop_function; + t->check_error = (void*)nop_function; + t->mem_read = (void*)nop_function; + t->mem_write = (void*)nop_function; + t->regs_size = 4; + t->regs_read = (void*)nop_function; + t->regs_write = (void*)nop_function; + t->reset = (void*)nop_function; + t->halt_request = (void*)nop_function; + //t->halt_poll = mdm_halt_poll; + t->halt_resume = (void*)nop_function; + + target_add_commands(t, nrf51_mdm_cmd_list, t->driver); +} + +#define MDM_POWER_EN ADIV5_DP_REG(0x01) +#define MDM_SELECT_AP ADIV5_DP_REG(0x02) +#define MDM_STATUS ADIV5_AP_REG(0x08) +#define MDM_CONTROL ADIV5_AP_REG(0x04) +#define MDM_PROT_EN ADIV5_AP_REG(0x0C) + + +static bool nrf51_mdm_cmd_erase_mass(target *t) +{ + ADIv5_AP_t *ap = t->priv; + + uint32_t status = adiv5_ap_read(ap, MDM_STATUS); + + adiv5_dp_write(ap->dp, MDM_POWER_EN, 0x50000000); + + adiv5_dp_write(ap->dp, MDM_SELECT_AP, 0x01000000); + + adiv5_ap_write(ap, MDM_CONTROL, 0x00000001); + + // Read until 0, probably should have a timeout here... + do { + status = adiv5_ap_read(ap, MDM_STATUS); + } while (status); + + // The second read will provide true prot status + status = adiv5_ap_read(ap, MDM_PROT_EN); + status = adiv5_ap_read(ap, MDM_PROT_EN); + + // should we return the prot status here? + return true; +}