Merge commit 'db544e9b671719e553bb6aec9e2e39294c3ee027' into sam-update

This commit is contained in:
Jason Kotzin 2022-08-01 20:03:40 -07:00
commit 6b2f0aeb63
8 changed files with 585 additions and 7 deletions

View File

@ -54,6 +54,7 @@ SRC = \
samd.c \ samd.c \
stm32f1.c \ stm32f1.c \
stm32f4.c \ stm32f4.c \
stm32h7.c \
stm32l0.c \ stm32l0.c \
stm32l4.c \ stm32l4.c \
swdptap.c \ swdptap.c \

View File

@ -171,6 +171,7 @@ static const struct {
{0x00b, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 BPU", "(Breakpoint Unit)")}, {0x00b, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 BPU", "(Breakpoint Unit)")},
{0x00c, aa_cortexm, cidc_gipc, PIDR_PN_BIT_STRINGS("Cortex-M4 SCS", "(System Control Space)")}, {0x00c, aa_cortexm, cidc_gipc, PIDR_PN_BIT_STRINGS("Cortex-M4 SCS", "(System Control Space)")},
{0x00d, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")}, {0x00d, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")},
{0x00e, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 FBP", "(Flash Patch and Breakpoint)")},
{0x490, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 GIC", "(Generic Interrupt Controller)")}, {0x490, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 GIC", "(Generic Interrupt Controller)")},
{0x4c7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)")}, {0x4c7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)")},
{0x906, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CTI", "(Cross Trigger)")}, {0x906, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CTI", "(Cross Trigger)")},
@ -194,8 +195,10 @@ static const struct {
{0x95f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PTM", "(Program Trace Macrocell)")}, {0x95f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PTM", "(Program Trace Macrocell)")},
{0x961, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TMC", "(Trace Memory Controller)")}, {0x961, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TMC", "(Trace Memory Controller)")},
{0x962, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight STM", "(System Trace Macrocell)")}, {0x962, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight STM", "(System Trace Macrocell)")},
{0x975, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 ETM", "(Embedded Trace)")},
{0x9a0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight PMU", "(Performance Monitoring Unit)")}, {0x9a0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight PMU", "(Performance Monitoring Unit)")},
{0x9a1, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 TPIU", "(Trace Port Interface Unit)")}, {0x9a1, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 TPIU", "(Trace Port Interface Unit)")},
{0x9a9, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 TPIU", "(Trace Port Interface Unit)")},
{0x9a5, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A5 ETM", "(Embedded Trace)")}, {0x9a5, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A5 ETM", "(Embedded Trace)")},
{0x9a7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A7 PMU", "(Performance Monitor Unit)")}, {0x9a7, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A7 PMU", "(Performance Monitor Unit)")},
{0x9af, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PMU", "(Performance Monitor Unit)")}, {0x9af, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PMU", "(Performance Monitor Unit)")},
@ -462,6 +465,9 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
extern void kinetis_mdm_probe(ADIv5_AP_t *); extern void kinetis_mdm_probe(ADIv5_AP_t *);
kinetis_mdm_probe(ap); kinetis_mdm_probe(ap);
extern void nrf51_mdm_probe(ADIv5_AP_t *);
nrf51_mdm_probe(ap);
if (ap->base == 0xffffffff) { if (ap->base == 0xffffffff) {
/* No debug entries... useless AP */ /* No debug entries... useless AP */
adiv5_ap_unref(ap); adiv5_ap_unref(ap);

View File

@ -330,11 +330,11 @@ bool cortexm_probe(ADIv5_AP_t *ap)
PROBE(stm32f1_probe); PROBE(stm32f1_probe);
PROBE(stm32f4_probe); PROBE(stm32f4_probe);
PROBE(stm32h7_probe);
PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */ PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */
PROBE(stm32l4_probe); PROBE(stm32l4_probe);
PROBE(lpc11xx_probe); PROBE(lpc11xx_probe);
PROBE(lpc15xx_probe); PROBE(lpc15xx_probe);
PROBE(lpc17xx_probe);
PROBE(lpc43xx_probe); PROBE(lpc43xx_probe);
PROBE(sam3x_probe); PROBE(sam3x_probe);
PROBE(sam4l_probe); PROBE(sam4l_probe);
@ -344,6 +344,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
PROBE(kinetis_probe); PROBE(kinetis_probe);
PROBE(efm32_probe); PROBE(efm32_probe);
PROBE(msp432_probe); PROBE(msp432_probe);
PROBE(lpc17xx_probe);
#undef PROBE #undef PROBE
return true; return true;

View File

@ -341,7 +341,7 @@ const struct command_s kinetis_mdm_cmd_list[] = {
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
bool nop_function(void) static bool nop_function(void)
{ {
return true; return true;
} }

View File

@ -164,8 +164,9 @@ bool nrf51_probe(target *t)
target_add_commands(t, nrf51_cmd_list, "nRF51"); target_add_commands(t, nrf51_cmd_list, "nRF51");
return true; return true;
case 0x00AC: /* nRF52832 Preview QFAA BA0 */ case 0x00AC: /* nRF52832 Preview QFAA BA0 */
case 0x00C7: /* nRF52832 Revision 1 QFAA B00 */ case 0x00C7: /* nRF52832 (rev 1) QFAA B00 */
case 0x00E3: /* nRF52832-CIAA CSP */ case 0x00E3: /* nRF52832 (rev 1) CIAA B?? */
case 0x0139: /* nRF82832 (rev 2) ??AA B?0 */
t->driver = "Nordic nRF52"; t->driver = "Nordic nRF52";
target_add_ram(t, 0x20000000, 64*1024); target_add_ram(t, 0x20000000, 64*1024);
nrf51_add_flash(t, 0x00000000, 512*1024, NRF52_PAGE_SIZE); nrf51_add_flash(t, 0x00000000, 512*1024, NRF52_PAGE_SIZE);
@ -335,3 +336,81 @@ static bool nrf51_cmd_read(target *t, int argc, const char *argv[])
return nrf51_cmd_read_help(t); 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;
}

View File

@ -99,6 +99,8 @@ static int stm32f4_flash_write(struct target_flash *f,
#define F7_FLASHSIZE 0x1FF0F442 #define F7_FLASHSIZE 0x1FF0F442
#define F72X_FLASHSIZE 0x1FF07A22 #define F72X_FLASHSIZE 0x1FF07A22
#define DBGMCU_IDCODE 0xE0042000 #define DBGMCU_IDCODE 0xE0042000
#define DBGMCU_CR 0xE0042004
#define DBG_SLEEP (1 << 0)
#define ARM_CPUID 0xE000ED00 #define ARM_CPUID 0xE000ED00
#define AXIM_BASE 0x8000000 #define AXIM_BASE 0x8000000
@ -194,6 +196,11 @@ bool stm32f4_probe(target *t)
idcode = ID_STM32F40X; idcode = ID_STM32F40X;
} }
switch(idcode) { switch(idcode) {
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
case ID_STM32F76X: /* F76x F77x RM0410 */
case ID_STM32F72X: /* F72x F73x RM0431 */
target_mem_write32(t, DBGMCU_CR, DBG_SLEEP);
/* fallthrough */
case ID_STM32F40X: case ID_STM32F40X:
case ID_STM32F42X: /* 427/437 */ case ID_STM32F42X: /* 427/437 */
case ID_STM32F46X: /* 469/479 */ case ID_STM32F46X: /* 469/479 */
@ -204,9 +211,6 @@ bool stm32f4_probe(target *t)
case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */ case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */ case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
case ID_STM32F76X: /* F76x F77x RM0410 */
case ID_STM32F72X: /* F72x F73x RM0431 */
t->idcode = idcode; t->idcode = idcode;
t->driver = stm32f4_get_chip_name(idcode); t->driver = stm32f4_get_chip_name(idcode);
t->attach = stm32f4_attach; t->attach = stm32f4_attach;

486
src/target/stm32h7.c Normal file
View File

@ -0,0 +1,486 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2017-2018 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* This file implements STM32H7 target specific functions for detecting
* the device, providing the XML memory map and Flash memory programming.
*
* Refereces:
* ST doc - RM0433
* Reference manual - STM32H7x3 advanced ARM®-based 32-bit MCUs Rev.3
*/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
static bool stm32h7_cmd_erase_mass(target *t);
/* static bool stm32h7_cmd_option(target *t, int argc, char *argv[]); */
static bool stm32h7_uid(target *t);
static bool stm32h7_crc(target *t);
static bool stm32h7_cmd_psize(target *t, int argc, char *argv[]);
const struct command_s stm32h7_cmd_list[] = {
{"erase_mass", (cmd_handler)stm32h7_cmd_erase_mass,
"Erase entire flash memory"},
/* {"option", (cmd_handler)stm32h7_cmd_option,
"Manipulate option bytes"},*/
{"psize", (cmd_handler)stm32h7_cmd_psize,
"Configure flash write parallelism: (x8|x16|x32|x64(default))"},
{"uid", (cmd_handler)stm32h7_uid, "Print unique device ID"},
{"crc", (cmd_handler)stm32h7_crc, "Print CRC of both banks"},
{NULL, NULL, NULL}
};
static int stm32h7_flash_erase(struct target_flash *f, target_addr addr,
size_t len);
static int stm32h7_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len);
static const char stm32h74_driver_str[] = "STM32H74x";
enum stm32h7_regs
{
FLASH_ACR = 0x00,
FLASH_KEYR = 0x04,
FLASH_OPTKEYR = 0x08,
FLASH_CR = 0x0c,
FLASH_SR = 0x10,
FLASH_CCR = 0x14,
FLASH_OPTCR = 0x18,
FLASH_OPTSR_CUR = 0x1C,
FLASH_OPTSR = 0x20,
FLASH_CRCCR = 0x50,
FLASH_CRCDATA = 0x5C,
};
/* Flash Program and Erase Controller Register Map */
#define H7_IWDG_BASE 0x58004c00
#define FPEC1_BASE 0x52002000
#define FPEC2_BASE 0x52002100
#define FLASH_SR_BSY (1 << 0)
#define FLASH_SR_WBNE (1 << 1)
#define FLASH_SR_QW (1 << 2)
#define FLASH_SR_CRC_BUSY (1 << 3)
#define FLASH_SR_EOP (1 << 16)
#define FLASH_SR_WRPERR (1 << 17)
#define FLASH_SR_PGSERR (1 << 18)
#define FLASH_SR_STRBERR (1 << 19)
#define FLASH_SR_INCERR (1 << 21)
#define FLASH_SR_OPERR (1 << 22)
#define FLASH_SR_OPERR (1 << 22)
#define FLASH_SR_RDPERR (1 << 23)
#define FLASH_SR_RDSERR (1 << 24)
#define FLASH_SR_SNECCERR (1 << 25)
#define FLASH_SR_DBERRERR (1 << 26)
#define FLASH_SR_ERROR_READ (FLASH_SR_RDPERR | FLASH_SR_RDSERR | \
FLASH_SR_SNECCERR |FLASH_SR_DBERRERR)
#define FLASH_SR_ERROR_MASK ( \
FLASH_SR_WRPERR | FLASH_SR_PGSERR | FLASH_SR_STRBERR | \
FLASH_SR_INCERR | FLASH_SR_OPERR | FLASH_SR_ERROR_READ)
#define FLASH_CR_LOCK (1 << 0)
#define FLASH_CR_PG (1 << 1)
#define FLASH_CR_SER (1 << 2)
#define FLASH_CR_BER (1 << 3)
#define FLASH_CR_PSIZE8 (0 << 4)
#define FLASH_CR_PSIZE16 (1 << 4)
#define FLASH_CR_PSIZE32 (2 << 4)
#define FLASH_CR_PSIZE64 (3 << 4)
#define FLASH_CR_FW (1 << 6)
#define FLASH_CR_START (1 << 7)
#define FLASH_CR_SNB_1 (1 << 8)
#define FLASH_CR_SNB (3 << 8)
#define FLASH_CR_CRC_EN (1 << 15)
#define FLASH_OPTCR_OPTLOCK (1 << 0)
#define FLASH_OPTCR_OPTSTRT (1 << 1)
#define FLASH_OPTSR_IWDG1_SW (1 << 4)
#define FLASH_CRCCR_ALL_BANK (1 << 7)
#define FLASH_CRCCR_START_CRC (1 << 16)
#define FLASH_CRCCR_CLEAN_CRC (1 << 17)
#define FLASH_CRCCR_CRC_BURST_3 (3 << 20)
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB
#define OPTKEY1 0x08192A3B
#define OPTKEY2 0x4C5D6E7F
#define DBGMCU_IDCODE 0x5c001000
/* Access via 0xe00e1000 does not show device! */
#define DBGMCU_CR (DBGMCU_IDCODE + 4)
#define DBGSLEEP_D1 (1 << 0)
#define DBGSTOP_D1 (1 << 1)
#define DBGSTBY_D1 (1 << 2)
#define DBGSTOP_D3 (1 << 7)
#define DBGSTBY_D3 (1 << 8)
#define D1DBGCKEN (1 << 21)
#define D3DBGCKEN (1 << 22)
#define FLASH_SIZE_REG 0x1ff1e880
#define BANK1_START 0x08000000
#define NUM_SECTOR_PER_BANK 8
#define FLASH_SECTOR_SIZE 0x20000
#define BANK2_START 0x08100000
enum ID_STM32H7 {
ID_STM32H74x = 0x450,
};
struct stm32h7_flash {
struct target_flash f;
enum align psize;
uint32_t regbase;
};
static void stm32h7_add_flash(target *t,
uint32_t addr, size_t length, size_t blocksize)
{
struct stm32h7_flash *sf = calloc(1, sizeof(*sf));
struct target_flash *f = &sf->f;
f->start = addr;
f->length = length;
f->blocksize = blocksize;
f->erase = stm32h7_flash_erase;
f->write = stm32h7_flash_write;
f->buf_size = 2048;
f->erased = 0xff;
sf->regbase = FPEC1_BASE;
if (addr >= BANK2_START)
sf->regbase = FPEC2_BASE;
sf->psize = ALIGN_DWORD;
target_add_flash(t, f);
}
bool stm32h7_probe(target *t)
{
uint32_t idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xFFF;
if (idcode == ID_STM32H74x) {
/* RM0433 Rev 4 is not really clear, what bits are needed.
* Set all possible relevant bits for now. */
target_mem_write32(t, DBGMCU_CR, DBGSLEEP_D1 | D1DBGCKEN);
t->idcode = idcode;
t->driver = stm32h74_driver_str;
target_add_commands(t, stm32h7_cmd_list, stm32h74_driver_str);
target_add_ram(t, 0x00000000, 0x10000); /* ITCM Ram, 64 k */
target_add_ram(t, 0x20000000, 0x20000); /* DTCM Ram, 128 k */
target_add_ram(t, 0x24000000, 0x80000); /* AXI Ram, 512 k */
target_add_ram(t, 0x30000000, 0x20000); /* AHB SRAM1, 128 k */
target_add_ram(t, 0x32000000, 0x20000); /* AHB SRAM2, 128 k */
target_add_ram(t, 0x34000000, 0x08000); /* AHB SRAM3, 32 k */
target_add_ram(t, 0x38000000, 0x01000); /* AHB SRAM4, 32 k */
stm32h7_add_flash(t, 0x8000000, 0x100000, FLASH_SECTOR_SIZE);
stm32h7_add_flash(t, 0x8100000, 0x100000, FLASH_SECTOR_SIZE);
/* If IWDG runs as HARDWARE watchdog (44.3.4) erase
* will be aborted by the Watchdog and erase fails!
* Setting IWDG_KR to 0xaaaa does not seem to help!*/
uint32_t optsr = target_mem_read32(t, FPEC1_BASE + FLASH_OPTSR);
if (!(optsr & FLASH_OPTSR_IWDG1_SW))
tc_printf(t, "Hardware IWDG running. Expect failure. Set IWDG1_SW!");
return true;
}
return false;
}
static bool stm32h7_flash_unlock(target *t, uint32_t addr)
{
uint32_t regbase = FPEC1_BASE;
if (addr >= BANK2_START) {
regbase = FPEC2_BASE;
}
while(target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_BSY) {
if(target_check_error(t))
return false;
}
uint32_t sr = target_mem_read32(t, regbase + FLASH_SR);
if (sr & FLASH_SR_ERROR_MASK) {
tc_printf(t, "Error 0x%08lx", sr & FLASH_SR_ERROR_MASK);
target_mem_write32(t, regbase + FLASH_CCR, sr & FLASH_SR_ERROR_MASK);
return false;
}
if (target_mem_read32(t, regbase + FLASH_CR) & FLASH_CR_LOCK) {
/* Enable FLASH controller access */
target_mem_write32(t, regbase + FLASH_KEYR, KEY1);
target_mem_write32(t, regbase + FLASH_KEYR, KEY2);
}
if (target_mem_read32(t, regbase + FLASH_CR) & FLASH_CR_LOCK)
return false;
else
return true;
}
static int stm32h7_flash_erase(struct target_flash *f, target_addr addr,
size_t len)
{
target *t = f->t;
struct stm32h7_flash *sf = (struct stm32h7_flash *)f;
if (stm32h7_flash_unlock(t, addr) == false)
return -1;
/* We come out of reset with HSI 64 MHz. Adapt FLASH_ACR.*/
target_mem_write32(t, sf->regbase + FLASH_ACR, 0);
addr &= (NUM_SECTOR_PER_BANK * FLASH_SECTOR_SIZE) - 1;
int start_sector = addr / FLASH_SECTOR_SIZE;
int end_sector = (addr + len - 1) / FLASH_SECTOR_SIZE;
enum align psize = ((struct stm32h7_flash *)f)->psize;
uint32_t sr;
while (start_sector <= end_sector) {
uint32_t cr = (psize * FLASH_CR_PSIZE16) | FLASH_CR_SER |
(start_sector * FLASH_CR_SNB_1);
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
cr |= FLASH_CR_START;
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
DEBUG(" started cr %08" PRIx32 " sr %08" PRIx32 "\n",
target_mem_read32(t, sf->regbase + FLASH_CR),
target_mem_read32(t, sf->regbase + FLASH_SR));
do {
sr = target_mem_read32(t, sf->regbase + FLASH_SR);
if (target_check_error(t)) {
DEBUG("stm32h7_flash_erase: comm failed\n");
return -1;
}
// target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa);
}while (sr & (FLASH_SR_QW | FLASH_SR_BSY));
if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32h7_flash_erase: error, sr: %08" PRIx32 "\n", sr);
return -1;
}
start_sector++;
}
return 0;
}
static int stm32h7_flash_write(struct target_flash *f, target_addr dest,
const void *src, size_t len)
{
target *t = f->t;
struct stm32h7_flash *sf = (struct stm32h7_flash *)f;
enum align psize = sf->psize;
if (stm32h7_flash_unlock(t, dest) == false)
return -1;
uint32_t cr = psize * FLASH_CR_PSIZE16;
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
cr |= FLASH_CR_PG;
target_mem_write32(t, sf->regbase + FLASH_CR, cr);
/* does H7 stall?*/
uint32_t sr_reg = sf->regbase + FLASH_SR;
uint32_t sr;
target_mem_write(t, dest, src, len);
while ((sr = target_mem_read32(t, sr_reg)) & FLASH_SR_BSY) {
if(target_check_error(t)) {
DEBUG("stm32h7_flash_write: BSY comm failed\n");
return -1;
}
}
if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32h7_flash_write: error sr %08" PRIx32 "\n", sr);
return -1;
}
/* Close write windows.*/
target_mem_write32(t, sf->regbase + FLASH_CR, 0);
return 0;
}
/* Both banks are erased in parallel.*/
static bool stm32h7_cmd_erase(target *t, int bank_mask)
{
const char spinner[] = "|/-\\";
int spinindex = 0;
bool do_bank1 = bank_mask & 1, do_bank2 = bank_mask & 2;
uint32_t cr;
bool result = false;
enum align psize = ALIGN_DWORD;
for (struct target_flash *f = t->flash; f; f = f->next) {
if (f->write == stm32h7_flash_write) {
psize = ((struct stm32h7_flash *)f)->psize;
}
}
cr = (psize * FLASH_CR_PSIZE16) | FLASH_CR_BER | FLASH_CR_START;
/* Flash mass erase start instruction */
if (do_bank1) {
if (stm32h7_flash_unlock(t, BANK1_START) == false) {
DEBUG("ME: Unlock bank1 failed\n");
goto done;
}
uint32_t regbase = FPEC1_BASE;
/* BER and start can be merged (3.3.10).*/
target_mem_write32(t, regbase + FLASH_CR, cr);
DEBUG("ME bank1 started\n");
}
if (do_bank2) {
if (stm32h7_flash_unlock(t, BANK2_START) == false) {
DEBUG("ME: Unlock bank2 failed\n");
goto done;
}
uint32_t regbase = FPEC2_BASE;
/* BER and start can be merged (3.3.10).*/
target_mem_write32(t, regbase + FLASH_CR, cr);
DEBUG("ME bank2 started\n");
}
/* Read FLASH_SR to poll for QW bit */
if (do_bank1) {
uint32_t regbase = FPEC1_BASE;
while (target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_QW) {
// target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa);
tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
if(target_check_error(t)) {
DEBUG("ME bank1: comm failed\n");
goto done;
}
}
}
if (do_bank2) {
uint32_t regbase = FPEC2_BASE;
while (target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_QW) {
// target_mem_write32(t, H7_IWDG_BASE 0x0000aaaa);
tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
if(target_check_error(t)) {
DEBUG("ME bank2: comm failed\n");
goto done;
}
}
}
if (do_bank1) {
/* Check for error */
uint32_t regbase = FPEC1_BASE;
uint32_t sr = target_mem_read32(t, regbase + FLASH_SR);
if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("ME bank1: sr %" PRIx32 "\n", sr);
goto done;
}
}
if (do_bank2) {
/* Check for error */
uint32_t regbase = FPEC2_BASE;
uint32_t sr = target_mem_read32(t, regbase + FLASH_SR);
if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("ME bank2: sr %" PRIx32 "\n", sr);
goto done;
}
}
result = true;
done:
tc_printf(t, "\n");
return result;
}
static bool stm32h7_cmd_erase_mass(target *t)
{
tc_printf(t, "Erasing flash... This may take a few seconds. ");
return stm32h7_cmd_erase(t, 3);
}
/* Print the Unique device ID.
* Can be reused for other STM32 devices With uid as parameter.
*/
static bool stm32h7_uid(target *t)
{
uint32_t uid = 0x1ff1e800;
int i;
tc_printf(t, "0x");
for (i = 0; i < 12; i = i + 4) {
uint32_t val = target_mem_read32(t, uid + i);
tc_printf(t, "%02X", (val >> 24) & 0xff);
tc_printf(t, "%02X", (val >> 16) & 0xff);
tc_printf(t, "%02X", (val >> 8) & 0xff);
tc_printf(t, "%02X", (val >> 0) & 0xff);
}
tc_printf(t, "\n");
return true;
}
static int stm32h7_crc_bank(target *t, uint32_t bank)
{
uint32_t regbase = FPEC1_BASE;
if (bank >= BANK2_START)
regbase = FPEC2_BASE;
if (stm32h7_flash_unlock(t, bank) == false)
return -1;
uint32_t cr = FLASH_CR_CRC_EN;
target_mem_write32(t, regbase + FLASH_CR, cr);
uint32_t crccr= FLASH_CRCCR_CRC_BURST_3 |
FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_ALL_BANK;
target_mem_write32(t, regbase + FLASH_CRCCR, crccr);
target_mem_write32(t, regbase + FLASH_CRCCR, crccr | FLASH_CRCCR_START_CRC);
uint32_t sr;
while ((sr = target_mem_read32(t, regbase + FLASH_SR)) & FLASH_SR_CRC_BUSY) {
if(target_check_error(t)) {
DEBUG("CRC bank %d: comm failed\n", (bank < BANK2_START) ? 1 : 2);
return -1;
}
if (sr & FLASH_SR_ERROR_READ) {
DEBUG("CRC bank %d: error sr %08" PRIx32 "\n",
(bank < BANK2_START) ? 1 : 2, sr);
return -1;
}
}
return 0;
}
static bool stm32h7_crc(target *t)
{
if (stm32h7_crc_bank(t, BANK1_START) ) return false;
uint32_t crc1 = target_mem_read32(t, FPEC1_BASE + FLASH_CRCDATA);
if (stm32h7_crc_bank(t, BANK2_START) ) return false;
uint32_t crc2 = target_mem_read32(t, FPEC1_BASE + FLASH_CRCDATA);
tc_printf(t, "CRC: bank1 0x%08lx, bank2 0x%08lx\n", crc1, crc2);
return true;
}
static bool stm32h7_cmd_psize(target *t, int argc, char *argv[])
{
if (argc == 1) {
enum align psize = ALIGN_DWORD;
for (struct target_flash *f = t->flash; f; f = f->next) {
if (f->write == stm32h7_flash_write) {
psize = ((struct stm32h7_flash *)f)->psize;
}
}
tc_printf(t, "Flash write parallelism: %s\n",
psize == ALIGN_DWORD ? "x64" :
psize == ALIGN_WORD ? "x32" :
psize == ALIGN_HALFWORD ? "x16" : "x8");
} else {
enum align psize;
if (!strcmp(argv[1], "x8")) {
psize = ALIGN_BYTE;
} else if (!strcmp(argv[1], "x16")) {
psize = ALIGN_HALFWORD;
} else if (!strcmp(argv[1], "x32")) {
psize = ALIGN_WORD;
} else if (!strcmp(argv[1], "x64")) {
psize = ALIGN_DWORD;
} else {
tc_printf(t, "usage: monitor psize (x8|x16|x32|x64)\n");
return false;
}
for (struct target_flash *f = t->flash; f; f = f->next) {
if (f->write == stm32h7_flash_write) {
((struct stm32h7_flash *)f)->psize = psize;
}
}
}
return true;
}

View File

@ -161,6 +161,7 @@ int tc_system(target *t, target_addr cmd, size_t cmdlen);
*/ */
bool stm32f1_probe(target *t); bool stm32f1_probe(target *t);
bool stm32f4_probe(target *t); bool stm32f4_probe(target *t);
bool stm32h7_probe(target *t);
bool stm32l0_probe(target *t); bool stm32l0_probe(target *t);
bool stm32l1_probe(target *t); bool stm32l1_probe(target *t);
bool stm32l4_probe(target *t); bool stm32l4_probe(target *t);