-
-
Notifications
You must be signed in to change notification settings - Fork 781
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
Showing
7 changed files
with
188 additions
and
5 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
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
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
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
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,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; | ||
} |
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
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