rp: Cleanup in how we define some of the Flash constants
This commit is contained in:
parent
ce94169099
commit
d64992ade8
|
@ -52,10 +52,12 @@
|
||||||
#define SSI_DR0_ADDR 0x18000060
|
#define SSI_DR0_ADDR 0x18000060
|
||||||
#define QSPI_CTRL_ADDR 0x4001800c
|
#define QSPI_CTRL_ADDR 0x4001800c
|
||||||
|
|
||||||
#define FLASHSIZE_4K_SECTOR (4 * 1024)
|
#define FLASHSIZE_4K_SECTOR (4U * 1024U)
|
||||||
#define FLASHSIZE_32K_BLOCK (32 * 1024)
|
#define FLASHSIZE_32K_BLOCK (32U * 1024U)
|
||||||
#define FLASHSIZE_64K_BLOCK (64 * 1024)
|
#define FLASHSIZE_64K_BLOCK (64U * 1024U)
|
||||||
#define MAX_FLASH (16 * 1024 * 1024)
|
#define FLASHSIZE_32K_BLOCK_MASK ~(FLASHSIZE_32K_BLOCK - 1U)
|
||||||
|
#define FLASHSIZE_64K_BLOCK_MASK ~(FLASHSIZE_64K_BLOCK - 1U)
|
||||||
|
#define MAX_FLASH (16U * 1024U * 1024U)
|
||||||
|
|
||||||
/* Instruction codes taken from Winbond W25Q16JV datasheet, as used on the
|
/* Instruction codes taken from Winbond W25Q16JV datasheet, as used on the
|
||||||
* original Pico board from Raspberry Pi.
|
* original Pico board from Raspberry Pi.
|
||||||
|
@ -83,7 +85,7 @@ struct rp_priv_s {
|
||||||
uint16_t reset_usb_boot;
|
uint16_t reset_usb_boot;
|
||||||
bool is_prepared;
|
bool is_prepared;
|
||||||
bool is_monitor;
|
bool is_monitor;
|
||||||
uint32_t regs[0x20];/* Register playground*/
|
uint32_t regs[0x20]; /* Register playground*/
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool rp2040_fill_table(struct rp_priv_s *priv, uint16_t *table, int max)
|
static bool rp2040_fill_table(struct rp_priv_s *priv, uint16_t *table, int max)
|
||||||
|
@ -127,9 +129,8 @@ static bool rp2040_fill_table(struct rp_priv_s *priv, uint16_t *table, int max)
|
||||||
}
|
}
|
||||||
tag = *table++;
|
tag = *table++;
|
||||||
}
|
}
|
||||||
DEBUG_TARGET("connect %04x debug_trampoline %04x end %04x\n",
|
DEBUG_TARGET("connect %04x debug_trampoline %04x end %04x\n", priv->_connect_internal_flash,
|
||||||
priv->_connect_internal_flash, priv->_debug_trampoline,
|
priv->_debug_trampoline, priv->_debug_trampoline_end);
|
||||||
priv->_debug_trampoline_end);
|
|
||||||
return (check != 9);
|
return (check != 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +143,7 @@ static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd, uint32_t timeou
|
||||||
{
|
{
|
||||||
const char spinner[] = "|/-\\";
|
const char spinner[] = "|/-\\";
|
||||||
int spinindex = 0;
|
int spinindex = 0;
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
regs[7] = cmd;
|
regs[7] = cmd;
|
||||||
regs[REG_LR] = ps->_debug_trampoline_end;
|
regs[REG_LR] = ps->_debug_trampoline_end;
|
||||||
regs[REG_PC] = ps->_debug_trampoline;
|
regs[REG_PC] = ps->_debug_trampoline;
|
||||||
|
@ -176,21 +177,20 @@ static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd, uint32_t timeou
|
||||||
} while (!target_halt_poll(t, NULL));
|
} while (!target_halt_poll(t, NULL));
|
||||||
/* Debug */
|
/* Debug */
|
||||||
target_regs_read(t, dbg_regs);
|
target_regs_read(t, dbg_regs);
|
||||||
bool ret = ((dbg_regs[REG_PC] &~1) != (ps->_debug_trampoline_end & ~1));
|
bool ret = ((dbg_regs[REG_PC] & ~1) != (ps->_debug_trampoline_end & ~1));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DEBUG_WARN("rp_rom_call cmd %04" PRIx32 " failed, PC %08" PRIx32 "\n",
|
DEBUG_WARN("rp_rom_call cmd %04" PRIx32 " failed, PC %08" PRIx32 "\n", cmd, dbg_regs[REG_PC]);
|
||||||
cmd, dbg_regs[REG_PC]);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rp_flash_prepare(target *t)
|
static void rp_flash_prepare(target *t)
|
||||||
{
|
{
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
if (!ps->is_prepared) {
|
if (!ps->is_prepared) {
|
||||||
DEBUG_INFO("rp_flash_prepare\n");
|
DEBUG_INFO("rp_flash_prepare\n");
|
||||||
/* connect*/
|
/* connect*/
|
||||||
rp_rom_call(t, ps->regs, ps->_connect_internal_flash,100);
|
rp_rom_call(t, ps->regs, ps->_connect_internal_flash, 100);
|
||||||
/* exit_xip */
|
/* exit_xip */
|
||||||
rp_rom_call(t, ps->regs, ps->_flash_exit_xip, 100);
|
rp_rom_call(t, ps->regs, ps->_flash_exit_xip, 100);
|
||||||
ps->is_prepared = true;
|
ps->is_prepared = true;
|
||||||
|
@ -199,11 +199,11 @@ static void rp_flash_prepare(target *t)
|
||||||
|
|
||||||
static void rp_flash_resume(target *t)
|
static void rp_flash_resume(target *t)
|
||||||
{
|
{
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
if (ps->is_prepared) {
|
if (ps->is_prepared) {
|
||||||
DEBUG_INFO("rp_flash_resume\n");
|
DEBUG_INFO("rp_flash_resume\n");
|
||||||
/* flush */
|
/* flush */
|
||||||
rp_rom_call(t, ps->regs, ps->_flash_flush_cache,100);
|
rp_rom_call(t, ps->regs, ps->_flash_flush_cache, 100);
|
||||||
/* enter_cmd_xip */
|
/* enter_cmd_xip */
|
||||||
rp_rom_call(t, ps->regs, ps->_flash_enter_cmd_xip, 100);
|
rp_rom_call(t, ps->regs, ps->_flash_enter_cmd_xip, 100);
|
||||||
ps->is_prepared = false;
|
ps->is_prepared = false;
|
||||||
|
@ -231,7 +231,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr, size_t len)
|
||||||
addr -= t->flash->start;
|
addr -= t->flash->start;
|
||||||
len = ALIGN(len, FLASHSIZE_4K_SECTOR);
|
len = ALIGN(len, FLASHSIZE_4K_SECTOR);
|
||||||
len = MIN(len, t->flash->length - addr);
|
len = MIN(len, t->flash->length - addr);
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
const bool full_erase = addr == f->start && len == f->length;
|
const bool full_erase = addr == f->start && len == f->length;
|
||||||
platform_timeout timeout;
|
platform_timeout timeout;
|
||||||
platform_timeout_set(&timeout, 500);
|
platform_timeout_set(&timeout, 500);
|
||||||
|
@ -241,17 +241,17 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr, size_t len)
|
||||||
bool ret = 0;
|
bool ret = 0;
|
||||||
while (len) {
|
while (len) {
|
||||||
if (len >= FLASHSIZE_64K_BLOCK) {
|
if (len >= FLASHSIZE_64K_BLOCK) {
|
||||||
const uint32_t chunk = len & ~(FLASHSIZE_64K_BLOCK - 1U);
|
const uint32_t chunk = len & FLASHSIZE_64K_BLOCK_MASK;
|
||||||
ps->regs[0] = addr;
|
ps->regs[0] = addr;
|
||||||
ps->regs[1] = chunk;
|
ps->regs[1] = chunk;
|
||||||
ps->regs[2] = FLASHSIZE_64K_BLOCK;
|
ps->regs[2] = FLASHSIZE_64K_BLOCK;
|
||||||
ps->regs[3] = FLASHCMD_BLOCK64K_ERASE;
|
ps->regs[3] = FLASHCMD_BLOCK64K_ERASE;
|
||||||
DEBUG_WARN("64k_ERASE addr 0x%08" PRIx32 " len 0x%" PRIx32 "\n", addr, chunk);
|
DEBUG_WARN("64k_ERASE addr 0x%08" PRIx32 " len 0x%" PRIx32 "\n", addr, chunk);
|
||||||
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100);
|
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100);
|
||||||
len -= chunk ;
|
len -= chunk;
|
||||||
addr += chunk;
|
addr += chunk;
|
||||||
} else if (len >= FLASHSIZE_32K_BLOCK) {
|
} else if (len >= FLASHSIZE_32K_BLOCK) {
|
||||||
const uint32_t chunk = len & ~(FLASHSIZE_32K_BLOCK - 1U);
|
const uint32_t chunk = len & FLASHSIZE_32K_BLOCK_MASK;
|
||||||
ps->regs[0] = addr;
|
ps->regs[0] = addr;
|
||||||
ps->regs[1] = chunk;
|
ps->regs[1] = chunk;
|
||||||
ps->regs[2] = FLASHSIZE_32K_BLOCK;
|
ps->regs[2] = FLASHSIZE_32K_BLOCK;
|
||||||
|
@ -290,7 +290,7 @@ static int rp_flash_write(struct target_flash *f, target_addr dest, const void *
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dest -= t->flash->start;
|
dest -= t->flash->start;
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
/* Write payload to target ram */
|
/* Write payload to target ram */
|
||||||
rp_flash_prepare(t);
|
rp_flash_prepare(t);
|
||||||
bool ret = 0;
|
bool ret = 0;
|
||||||
|
@ -306,8 +306,7 @@ static int rp_flash_write(struct target_flash *f, target_addr dest, const void *
|
||||||
* however it takes much longer if the XOSC is not enabled
|
* however it takes much longer if the XOSC is not enabled
|
||||||
* so lets give ourselves a little bit more time (x10)
|
* so lets give ourselves a little bit more time (x10)
|
||||||
*/
|
*/
|
||||||
ret |= rp_rom_call(t, ps->regs, ps->flash_range_program,
|
ret |= rp_rom_call(t, ps->regs, ps->flash_range_program, (3 * chunksize * 10) >> 8);
|
||||||
(3 * chunksize * 10) >> 8);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DEBUG_WARN("Write failed!\n");
|
DEBUG_WARN("Write failed!\n");
|
||||||
break;
|
break;
|
||||||
|
@ -323,7 +322,7 @@ static int rp_flash_write(struct target_flash *f, target_addr dest, const void *
|
||||||
|
|
||||||
static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[])
|
static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
ps->regs[1] = atoi(argv[2]);
|
ps->regs[1] = atoi(argv[2]);
|
||||||
} else if (argc < 3) {
|
} else if (argc < 3) {
|
||||||
|
@ -338,7 +337,7 @@ static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[])
|
||||||
|
|
||||||
static bool rp_mass_erase(target *t)
|
static bool rp_mass_erase(target *t)
|
||||||
{
|
{
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
ps->is_monitor = true;
|
ps->is_monitor = true;
|
||||||
const bool result = rp_flash_erase(t->flash, t->flash->start, t->flash->length) == 0;
|
const bool result = rp_flash_erase(t->flash, t->flash->start, t->flash->length) == 0;
|
||||||
ps->is_monitor = false;
|
ps->is_monitor = false;
|
||||||
|
@ -353,24 +352,20 @@ static bool rp_cmd_erase_sector(target *t, int argc, const char *argv[])
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
start = strtoul(argv[1], NULL, 0);
|
start = strtoul(argv[1], NULL, 0);
|
||||||
length = strtoul(argv[2], NULL, 0);
|
length = strtoul(argv[2], NULL, 0);
|
||||||
}
|
} else if (argc == 2)
|
||||||
else if (argc == 2)
|
|
||||||
length = strtoul(argv[1], NULL, 0);
|
length = strtoul(argv[1], NULL, 0);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
ps->is_monitor = true;
|
ps->is_monitor = true;
|
||||||
const bool result = rp_flash_erase(t->flash, start, length) == 0;
|
const bool result = rp_flash_erase(t->flash, start, length) == 0;
|
||||||
ps->is_monitor = false;
|
ps->is_monitor = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct command_s rp_cmd_list[] = {
|
const struct command_s rp_cmd_list[] = {{"erase_sector", rp_cmd_erase_sector, "Erase a sector: [start address] length"},
|
||||||
{"erase_sector", rp_cmd_erase_sector, "Erase a sector: [start address] length" },
|
{"reset_usb_boot", rp_cmd_reset_usb_boot, "Reboot the device into BOOTSEL mode"}, {NULL, NULL, NULL}};
|
||||||
{"reset_usb_boot", rp_cmd_reset_usb_boot, "Reboot the device into BOOTSEL mode"},
|
|
||||||
{NULL, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void rp_add_flash(target *t, uint32_t addr, size_t length)
|
static void rp_add_flash(target *t, uint32_t addr, size_t length)
|
||||||
{
|
{
|
||||||
|
@ -471,9 +466,9 @@ static bool rp_attach(target *t)
|
||||||
if (!cortexm_attach(t))
|
if (!cortexm_attach(t))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
struct rp_priv_s *ps = (struct rp_priv_s *)t->target_storage;
|
||||||
uint16_t *table = alloca(RP_MAX_TABLE_SIZE);
|
uint16_t *table = alloca(RP_MAX_TABLE_SIZE);
|
||||||
uint16_t table_offset = target_mem_read32( t, BOOTROM_MAGIC_ADDR + 4);
|
uint16_t table_offset = target_mem_read32(t, BOOTROM_MAGIC_ADDR + 4);
|
||||||
if (!table || target_mem_read(t, table, table_offset, RP_MAX_TABLE_SIZE))
|
if (!table || target_mem_read(t, table, table_offset, RP_MAX_TABLE_SIZE))
|
||||||
return false;
|
return false;
|
||||||
if (rp2040_fill_table(ps, table, RP_MAX_TABLE_SIZE))
|
if (rp2040_fill_table(ps, table, RP_MAX_TABLE_SIZE))
|
||||||
|
@ -513,7 +508,7 @@ bool rp_probe(target *t)
|
||||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
t->target_storage = (void*)priv_storage;
|
t->target_storage = (void *)priv_storage;
|
||||||
|
|
||||||
t->mass_erase = rp_mass_erase;
|
t->mass_erase = rp_mass_erase;
|
||||||
t->driver = RP_ID;
|
t->driver = RP_ID;
|
||||||
|
@ -544,8 +539,8 @@ void rp_rescue_probe(ADIv5_AP_t *ap)
|
||||||
}
|
}
|
||||||
|
|
||||||
adiv5_ap_ref(ap);
|
adiv5_ap_ref(ap);
|
||||||
t->attach = (void*)rp_rescue_do_reset;
|
t->attach = (void *)rp_rescue_do_reset;
|
||||||
t->priv = ap;
|
t->priv = ap;
|
||||||
t->priv_free = (void*)adiv5_ap_unref;
|
t->priv_free = (void *)adiv5_ap_unref;
|
||||||
t->driver = "Raspberry RP2040 Rescue (Attach to reset!)";
|
t->driver = "Raspberry RP2040 Rescue (Attach to reset!)";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue