stm32h7: Start of support.
Implement probe, memory map, erase, write, uid, crc, parallelism.
This commit is contained in:
parent
a988bba035
commit
f234074099
|
@ -54,6 +54,7 @@ SRC = \
|
|||
samd.c \
|
||||
stm32f1.c \
|
||||
stm32f4.c \
|
||||
stm32h7.c \
|
||||
stm32l0.c \
|
||||
stm32l4.c \
|
||||
swdptap.c \
|
||||
|
|
|
@ -330,6 +330,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
|||
|
||||
PROBE(stm32f1_probe);
|
||||
PROBE(stm32f4_probe);
|
||||
PROBE(stm32h7_probe);
|
||||
PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */
|
||||
PROBE(stm32l4_probe);
|
||||
PROBE(lpc11xx_probe);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -161,6 +161,7 @@ int tc_system(target *t, target_addr cmd, size_t cmdlen);
|
|||
*/
|
||||
bool stm32f1_probe(target *t);
|
||||
bool stm32f4_probe(target *t);
|
||||
bool stm32h7_probe(target *t);
|
||||
bool stm32l0_probe(target *t);
|
||||
bool stm32l1_probe(target *t);
|
||||
bool stm32l4_probe(target *t);
|
||||
|
|
Loading…
Reference in New Issue