Skip to content

Commit

Permalink
target/nrf54l: Initial support
Browse files Browse the repository at this point in the history
  • Loading branch information
zyp committed Dec 1, 2024
1 parent b0eb8d0 commit 5eaa6df
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 5 deletions.
9 changes: 8 additions & 1 deletion src/target/adi.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ bool adi_configure_mem_ap(adiv5_access_port_s *const ap)
/* Check the Debug Base Address register for not-present. See ADIv5 Specification C2.6.1 */
if (base_flags == (ADIV5_AP_BASE_FORMAT_ADIV5 | ADIV5_AP_BASE_PRESENT_NO_ENTRY) ||
(!(ap->flags & ADIV5_AP_FLAGS_64BIT) && (uint32_t)ap->base == ADIV5_AP_BASE_NOT_PRESENT)) {
bool ignore_not_present = false;
/*
* Debug Base Address not present in this MEM-AP
* No debug entries... useless AP
Expand All @@ -380,7 +381,13 @@ bool adi_configure_mem_ap(adiv5_access_port_s *const ap)
* valid debug components on AP0, so we have to have an exception
* for this part family.
*/
if (ap->dp->target_designer_code != JEP106_MANUFACTURER_TEXAS || ap->base != 0xf0000002U) {
if (ap->dp->target_designer_code == JEP106_MANUFACTURER_TEXAS && ap->base == 0xf0000002U)
ignore_not_present = true;

if (ap->dp->target_designer_code == JEP106_MANUFACTURER_NORDIC && ap->base != 0x00000002U)
ignore_not_present = true;

if (!ignore_not_present) {
DEBUG_INFO(" -> Not Present\n");
return false;
}
Expand Down
12 changes: 8 additions & 4 deletions src/target/adiv5.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,10 +512,14 @@ void adiv5_dp_init(adiv5_debug_port_s *const dp)
continue;
}

kinetis_mdm_probe(ap);
nrf51_mdm_probe(ap);
efm32_aap_probe(ap);
lpc55_dmap_probe(ap);
/* Check if this is a vendor specific AP */
bool vendor_specific_ap = kinetis_mdm_probe(ap) || nrf51_mdm_probe(ap) || nrf54l_ctrl_ap_probe(ap) ||
efm32_aap_probe(ap) || lpc55_dmap_probe(ap);

if (vendor_specific_ap) {
adiv5_ap_unref(ap);
continue;
}

/* Try to prepare the AP if it seems to be a AHB3 MEM-AP */
if (!ap->apsel && ADIV5_AP_IDR_CLASS(ap->idr) == 8U && ADIV5_AP_IDR_TYPE(ap->idr) == ARM_AP_TYPE_AHB3) {
Expand Down
1 change: 1 addition & 0 deletions src/target/cortexm.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ bool cortexm_probe(adiv5_access_port_s *ap)
break;
case JEP106_MANUFACTURER_NORDIC:
PROBE(nrf51_probe);
PROBE(nrf54l_probe);
PROBE(nrf91_probe);
break;
case JEP106_MANUFACTURER_ATMEL:
Expand Down
1 change: 1 addition & 0 deletions src/target/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ target_lpc = declare_dependency(
target_nrf = declare_dependency(
sources: files(
'nrf51.c',
'nrf54l.c',
'nrf91.c',
),
dependencies: target_cortexm,
Expand Down
166 changes: 166 additions & 0 deletions src/target/nrf54l.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#include "adiv5.h"

#define NRF54L_FICR_INFO_RAM 0x00ffc328U
#define NRF54L_FICR_INFO_RRAM 0x00ffc32cU

#define NRF54L_UICR 0x00ffd000U

#define NRF54L_RRAMC_READY 0x5004b400U
#define NRF54L_RRAMC_CONFIG 0x5004b500U
#define NRF54L_RRAMC_ERASE_ERASEALL 0x5004b540U

#define NRF54L_CTRL_AP_IDR_VALUE 0x32880000U
#define NRF54L_CTRL_AP_RESET ADIV5_AP_REG(0x00U)
#define NRF54L_CTRL_AP_ERASEALL ADIV5_AP_REG(0x04U)
#define NRF54L_CTRL_AP_ERASEALLSTATUS ADIV5_AP_REG(0x08U)
#define NRF54L_CTRL_AP_APPROTECT_STATUS ADIV5_AP_REG(0x14U)

static bool rram_erase(target_flash_s *f, target_addr_t addr, size_t len)
{
(void)f;
(void)addr;
(void)len;
// RRAM doesn't need to be erased before being written, so we just return ok.
return true;
}

static bool rram_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
{
target_mem32_write(f->t, dest, src, len);
return true;
}

static bool rram_prepare(target_flash_s *f)
{
target_mem32_write32(f->t, NRF54L_RRAMC_CONFIG, 1);
return true;
}

static bool rram_done(target_flash_s *f)
{
target_mem32_write32(f->t, NRF54L_RRAMC_CONFIG, 0);
return true;
}

static bool rram_mass_erase(target_s *const t, platform_timeout_s *const print_progess)
{
target_mem32_write32(t, NRF54L_RRAMC_ERASE_ERASEALL, 1);

uint32_t ready;
do {
ready = target_mem32_read32(t, NRF54L_RRAMC_READY);
target_print_progress(print_progess);
} while (ready == 0);

return true;
}

static void add_rram(target_s *t, uint32_t addr, size_t length)
{
target_flash_s *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */
DEBUG_ERROR("calloc: failed in %s\n", __func__);
return;
}

f->start = addr;
f->length = length;
f->blocksize = 1024U;
f->writesize = 1024U;
f->erase = rram_erase;
f->write = rram_write;
f->prepare = rram_prepare;
f->done = rram_done;
f->erased = 0xff;
target_add_flash(t, f);
}

bool nrf54l_probe(target_s *target)
{
DEBUG_INFO("nrf54l_probe:\n");

adiv5_access_port_s *ap = cortex_ap(target);

if (ap->dp->version < 2U)
return false;

switch (ap->dp->target_partno) {
case 0x1c0:
target->driver = "Nordic nRF54L";
target->target_options |= TOPT_INHIBIT_NRST;
break;
default:
return false;
}

target->mass_erase = rram_mass_erase;

uint32_t info_ram = target_mem32_read32(target, NRF54L_FICR_INFO_RAM);
uint32_t info_rram = target_mem32_read32(target, NRF54L_FICR_INFO_RRAM);

target_add_ram32(target, 0x20000000U, info_ram * 1024U);
add_rram(target, 0x0, info_rram * 1024U);
add_rram(target, NRF54L_UICR, 0x1000U);

return true;
}

static bool nrf54l_ctrl_ap_mass_erase(target_s *t, platform_timeout_s *print_progess);

bool nrf54l_ctrl_ap_probe(adiv5_access_port_s *ap)
{
switch (ap->idr) {
case NRF54L_CTRL_AP_IDR_VALUE:
break;
default:
return false;
}

target_s *t = target_new();
if (!t)
return false;

t->mass_erase = nrf54l_ctrl_ap_mass_erase;
adiv5_ap_ref(ap);
t->priv = ap;
t->priv_free = (void *)adiv5_ap_unref;

uint32_t status = adiv5_ap_read(ap, NRF54L_CTRL_AP_APPROTECT_STATUS);

if ((status & 0x3) == 0)
t->driver = "Nordic nRF54L Access Port";
else
t->driver = "Nordic nRF54L Access Port (protected)";
t->regs_size = 0;

return true;
}

static bool nrf54l_ctrl_ap_mass_erase(target_s *const t, platform_timeout_s *const print_progess)
{
adiv5_access_port_s *const ap = t->priv;

const uint32_t ctrl = adiv5_dp_read(ap->dp, ADIV5_DP_CTRLSTAT);
adiv5_dp_write(ap->dp, ADIV5_DP_CTRLSTAT, ctrl | ADIV5_DP_CTRLSTAT_CDBGPWRUPREQ);

adiv5_ap_write(ap, NRF54L_CTRL_AP_ERASEALL, 0x00000001U);

uint32_t status;
// Read until 0, probably should have a timeout here...
do {
status = adiv5_ap_read(ap, NRF54L_CTRL_AP_ERASEALLSTATUS);
target_print_progress(print_progess);
} while (status == 2);

// Assert reset.
adiv5_ap_write(ap, NRF54L_CTRL_AP_RESET, 0x2U);

// Deassert reset.
adiv5_ap_write(ap, NRF54L_CTRL_AP_RESET, 0x0U);

return true;
}
2 changes: 2 additions & 0 deletions src/target/target_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ CORTEXM_PROBE_WEAK_NOP(efm32_aap_probe)
CORTEXM_PROBE_WEAK_NOP(kinetis_mdm_probe)
CORTEXM_PROBE_WEAK_NOP(lpc55_dmap_probe)
CORTEXM_PROBE_WEAK_NOP(nrf51_mdm_probe)
CORTEXM_PROBE_WEAK_NOP(nrf54l_ctrl_ap_probe)
CORTEXM_PROBE_WEAK_NOP(rp2040_rescue_probe)

TARGET_PROBE_WEAK_NOP(apollo_3_probe)
Expand Down Expand Up @@ -127,6 +128,7 @@ TARGET_PROBE_WEAK_NOP(msp432e4_probe)
TARGET_PROBE_WEAK_NOP(msp432p4_probe)
TARGET_PROBE_WEAK_NOP(mspm0_probe)
TARGET_PROBE_WEAK_NOP(nrf51_probe)
TARGET_PROBE_WEAK_NOP(nrf54l_probe)
TARGET_PROBE_WEAK_NOP(nrf91_probe)
TARGET_PROBE_WEAK_NOP(puya_probe)
TARGET_PROBE_WEAK_NOP(renesas_ra_probe)
Expand Down
2 changes: 2 additions & 0 deletions src/target/target_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ bool efm32_aap_probe(adiv5_access_port_s *ap);
bool kinetis_mdm_probe(adiv5_access_port_s *ap);
bool lpc55_dmap_probe(adiv5_access_port_s *ap);
bool nrf51_mdm_probe(adiv5_access_port_s *ap);
bool nrf54l_ctrl_ap_probe(adiv5_access_port_s *ap);
bool rp2040_rescue_probe(adiv5_access_port_s *ap);

bool at32f40x_probe(target_s *target); // STM32 clones from Artery
Expand Down Expand Up @@ -78,6 +79,7 @@ bool msp432e4_probe(target_s *target);
bool msp432p4_probe(target_s *target);
bool mspm0_probe(target_s *target);
bool nrf51_probe(target_s *target);
bool nrf54l_probe(target_s *target);
bool nrf91_probe(target_s *target);
bool puya_probe(target_s *target);
bool renesas_ra_probe(target_s *target);
Expand Down

0 comments on commit 5eaa6df

Please sign in to comment.