From a6794f2ccd644a01dbc33df1c223f1382acb5536 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Tue, 9 Dec 2025 17:00:36 -0700 Subject: [PATCH 1/9] stm32h7rs: Adding zyp's old STM32H7R/S code. Updated for newer API. Almost works. --- src/target/cortexm.c | 1 + src/target/meson.build | 1 + src/target/stm32h7rs.c | 583 ++++++++++++++++++++++++++++++++++++++ src/target/target_probe.c | 1 + src/target/target_probe.h | 1 + 5 files changed, 587 insertions(+) create mode 100644 src/target/stm32h7rs.c diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 71b571b4fde..f0e63029fb9 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -395,6 +395,7 @@ bool cortexm_probe(adiv5_access_port_s *ap) PROBE(stm32f4_probe); PROBE(stm32h5_probe); PROBE(stm32h7_probe); + PROBE(stm32h7rs_probe); PROBE(stm32mp15_cm4_probe); PROBE(stm32l0_probe); PROBE(stm32l1_probe); diff --git a/src/target/meson.build b/src/target/meson.build index be10d0d317a..f73e5287b80 100644 --- a/src/target/meson.build +++ b/src/target/meson.build @@ -330,6 +330,7 @@ target_stm = declare_dependency( 'stm32g0.c', 'stm32h5.c', 'stm32h7.c', + 'stm32h7rs.c', 'stm32l0.c', 'stm32l4.c', 'stm32mp15.c', diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c new file mode 100644 index 00000000000..9be5c9af0dd --- /dev/null +++ b/src/target/stm32h7rs.c @@ -0,0 +1,583 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2017-2020 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de + * Copyright (C) 2022-2023 1BitSquared + * Modified by Rachel Mant + * + * 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 . + */ + +/* + * This file implements STM32H7R/S target specific functions for detecting + * the device, providing the XML memory map and Flash memory programming. + * + * References: + * RM0477 - STM32H7Rx/7Sx Arm®-based 32-bit MCUs, Rev. 6 + * https://www.st.com/resource/en/reference_manual/rm0477-stm32h7rx7sx-armbased-32bit-mcus-stmicroelectronics.pdf + */ + +#include "general.h" +#include "target.h" +#include "target_internal.h" +#include "cortexm.h" +#include "stm32_common.h" + +#define FLASH_ACR 0x000U +#define FLASH_KEYR 0x004U +#define FLASH_CR 0x010U +#define FLASH_SR 0x014U +#define FLASH_IER 0x020U +#define FLASH_ISR 0x024U +#define FLASH_ICR 0x028U +//#define FLASH_OPTKEYR 0x008U +//#define FLASH_CCR 0x014U +//#define FLASH_OPTCR 0x018U +//#define FLASH_OPTSR_CUR 0x01cU +//#define FLASH_OPTSR 0x020U +//#define FLASH_CRCCR 0x050U +//#define FLASH_CRCDATA 0x05cU + +/* Flash Program and Erase Controller Register Map */ +#define FPEC1_BASE 0x52002000U +#define FLASH_SR_BSY (1U << 0U) +#define FLASH_SR_WBNE (1U << 1U) +#define FLASH_SR_QW (1U << 2U) +#define FLASH_SR_CRC_BUSY (1U << 3U) +#define FLASH_ISR_EOP (1U << 16U) +#define FLASH_ISR_WRPERR (1U << 17U) +#define FLASH_ISR_PGSERR (1U << 18U) +#define FLASH_ISR_STRBERR (1U << 19U) +#define FLASH_ISR_INCERR (1U << 21U) +#define FLASH_ISR_RDSERR (1U << 24U) +#define FLASH_ISR_SNECCERR (1U << 25U) +#define FLASH_ISR_DBECCERR (1U << 26U) +#define FLASH_ISR_CRCEND (1U << 27U) +#define FLASH_ISR_CRCRDERR (1U << 28U) +#define FLASH_ISR_ERROR_READ (FLASH_ISR_RDSERR | FLASH_ISR_SNECCERR | FLASH_ISR_DBECCERR) +#define FLASH_ISR_ERROR_MASK \ + (FLASH_ISR_WRPERR | FLASH_ISR_PGSERR | FLASH_ISR_STRBERR | FLASH_ISR_INCERR | FLASH_ISR_ERROR_READ) +#define FLASH_CR_LOCK (1U << 0U) +#define FLASH_CR_PG (1U << 1U) +#define FLASH_CR_SER (1U << 2U) +#define FLASH_CR_BER (1U << 3U) +//#define FLASH_CR_PSIZE8 (0U << 4U) +//#define FLASH_CR_PSIZE16 (1U << 4U) +//#define FLASH_CR_PSIZE32 (2U << 4U) +//#define FLASH_CR_PSIZE64 (3U << 4U) +#define FLASH_CR_FW (1U << 4U) +#define FLASH_CR_START (1U << 5U) +#define FLASH_CR_SSN_SHIFT 6U +//#define FLASH_CR_SNB_1 (1U << 8U) +//#define FLASH_CR_SNB (3U << 8U) +//#define FLASH_CR_CRC_EN (1U << 15U) +// +//#define FLASH_OPTCR_OPTLOCK (1U << 0U) +//#define FLASH_OPTCR_OPTSTRT (1U << 1U) +// +//#define FLASH_OPTSR_IWDG1_SW (1U << 4U) +// +//#define FLASH_CRCCR_ALL_BANK (1U << 7U) +//#define FLASH_CRCCR_START_CRC (1U << 16U) +//#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) +//#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) + +#define STM32H7RS_FLASH_KEY1 0x45670123U +#define STM32H7RS_FLASH_KEY2 0xcdef89abU + +#define STM32H7RS_OPT_KEY1 0x08192a3bU +#define STM32H7RS_OPT_KEY2 0x4c5d6e7fU + +#define DBGMCU_IDCODE 0x5c001000U +#define STM32H7RS_FLASH_SIZE 0x1ff1e880U +#define STM32H7Bx_FLASH_SIZE 0x08fff80cU +/* Access from processor address space. + * Access via the APB-D is at 0xe00e1000 */ +#define DBGMCU_IDC (DBGMCU_IDCODE + 0U) +#define DBGMCU_CR (DBGMCU_IDCODE + 4U) +#define DBGSLEEP_D1 (1U << 0U) +#define DBGSTOP_D1 (1U << 1U) +#define DBGSTBY_D1 (1U << 2U) +#define DBGSTOP_D3 (1U << 7U) +#define DBGSTBY_D3 (1U << 8U) +#define D1DBGCKEN (1U << 21U) +#define D3DBGCKEN (1U << 22U) + +#define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU +#define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U + +#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U +#define STM32H7RS_FLASH_BANK_SIZE 0x00100000U +#define NUM_SECTOR_PER_BANK 8U +#define FLASH_SECTOR_SIZE 0x20000U + +#define ID_STM32H7RS 0x485U /* RM0477 */ + +typedef struct stm32h7rs_flash { + target_flash_s target_flash; + align_e psize; + uint32_t regbase; +} stm32h7rs_flash_s; + +typedef struct stm32h7rs_priv { + uint32_t dbg_cr; +} stm32h7rs_priv_s; + +static bool stm32h7rs_uid(target_s *target, int argc, const char **argv); +//static bool stm32h7rs_crc(target_s *target, int argc, const char **argv); +static bool stm32h7rs_cmd_psize(target_s *target, int argc, const char **argv); +static bool stm32h7rs_cmd_rev(target_s *target, int argc, const char **argv); + +const command_s stm32h7rs_cmd_list[] = { + {"psize", stm32h7rs_cmd_psize, "Configure flash write parallelism: (x8|x16|x32|x64(default))"}, + {"uid", stm32h7rs_uid, "Print unique device ID"}, + //{"crc", stm32h7rs_crc, "Print CRC of both banks"}, + {"revision", stm32h7rs_cmd_rev, "Returns the Device ID and Revision"}, + {NULL, NULL, NULL}, +}; + +static bool stm32h7rs_attach(target_s *target); +static void stm32h7rs_detach(target_s *target); +static bool stm32h7rs_flash_erase(target_flash_s *target_flash, target_addr_t addr, size_t len); +static bool stm32h7rs_flash_write(target_flash_s *target_flash, target_addr_t dest, const void *src, size_t len); +static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const print_progess); + +static void stm32h7rs_add_flash(target_s *target, uint32_t addr, size_t length, size_t blocksize) +{ + stm32h7rs_flash_s *flash = calloc(1, sizeof(*flash)); + if (!flash) { /* calloc failed: heap exhaustion */ + DEBUG_ERROR("calloc: failed in %s\n", __func__); + return; + } + + target_flash_s *target_flash = &flash->target_flash; + target_flash->start = addr; + target_flash->length = length; + target_flash->blocksize = blocksize; + target_flash->erase = stm32h7rs_flash_erase; + target_flash->write = stm32h7rs_flash_write; + target_flash->writesize = 2048; + target_flash->erased = 0xffU; + flash->regbase = FPEC1_BASE; + flash->psize = ALIGN_64BIT; + target_add_flash(target, target_flash); +} + +bool stm32h7rs_probe(target_s *target) +{ + const adiv5_access_port_s *const ap = cortex_ap(target); + if (ap->partno != ID_STM32H7RS) + return false; + + target->part_id = ap->partno; + + /* Save private storage */ + stm32h7rs_priv_s *priv = calloc(1, sizeof(*priv)); + if (!priv) { /* calloc failed: heap exhaustion */ + DEBUG_ERROR("calloc: failed in %s\n", __func__); + return false; + } + target->target_storage = priv; + priv->dbg_cr = target_mem32_read32(target, DBGMCU_CR); + + target->driver = "STM32H7R/S"; + target->attach = stm32h7rs_attach; + target->detach = stm32h7rs_detach; + target->mass_erase = stm32h7rs_mass_erase; + target_add_commands(target, stm32h7rs_cmd_list, target->driver); + + /* EMEB - Decide which of these is correct */ +#if 1 + /* RM0433 Rev 4 is not really clear, what bits are needed in DBGMCU_CR. Maybe more flags needed? */ + const uint32_t dbgmcu_ctrl = DBGSLEEP_D1 | D1DBGCKEN; + target_mem32_write32(target, DBGMCU_CR, dbgmcu_ctrl); +#else + /* Now we have a stable debug environment, make sure the WDTs can't bonk the processor out from under us */ + target_mem32_write32(target, STM32H7_DBGMCU_APB3FREEZE, STM32H7_DBGMCU_APB3FREEZE_WWDG1); + target_mem32_write32(target, STM32H7_DBGMCU_APB4FREEZE, STM32H7_DBGMCU_APB4FREEZE_IWDG1); + /* + * Make sure that both domain D1 and D3 debugging are enabled and that we can keep + * debugging through sleep, stop and standby states for domain D1 + */ + target_mem32_write32(target, STM32H7_DBGMCU_CONFIG, + target_mem32_read32(target, STM32H7_DBGMCU_CONFIG) | STM32H7_DBGMCU_CONFIG_DBGSLEEP_D1 | + STM32H7_DBGMCU_CONFIG_DBGSTOP_D1 | STM32H7_DBGMCU_CONFIG_DBGSTBY_D1 | STM32H7_DBGMCU_CONFIG_D1DBGCKEN | + STM32H7_DBGMCU_CONFIG_D3DBGCKEN); + stm32h7_configure_wdts(target); +#endif + + /* Build the RAM map - EMEB: ITCM/DTCM are too big -shared w/ AXI */ + switch (target->part_id) { + case ID_STM32H7RS: { + /* Table 6. Memory map and default device memory area attributes RM0477, pg151 */ + target_add_ram32(target, 0x00000000, 0x30000); /* ITCM RAM, 192 KiB */ + target_add_ram32(target, 0x20000000, 0x30000); /* DTCM RAM, 192 KiB */ + target_add_ram32(target, 0x24000000, 0x72000); /* AXI RAM1+2+3+4, 456 KiB [128+128+128+72] contiguous, */ + target_add_ram32(target, 0x30000000, 0x8000); /* AHB SRAM1+2, 32 KiB [16+16] contiguous, */ + break; + } + default: + break; + } + + /* + * Note on SRD from AN5293, 3. System architecture differences between STM32F7 and STM32H7 Series + * > The D3 domain evolved into a domain called SRD domain (or smart-run domain). + */ + + /* Build the Flash map */ + switch (target->part_id) { + case ID_STM32H7RS: + stm32h7rs_add_flash(target, STM32H7RS_FLASH_BANK1_BASE, 0x10000U, 0x2000U); + break; + default: + break; + } + + return true; +} + +static bool stm32h7rs_attach(target_s *target) +{ + if (!cortexm_attach(target)) + return false; + /* + * 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! + */ + //const uint32_t optsr = target_mem_read32(target, FPEC1_BASE + FLASH_OPTSR); + //if (!(optsr & FLASH_OPTSR_IWDG1_SW)) + // tc_printf(target, "Hardware IWDG running. Expect failure. Set IWDG1_SW!"); + return true; +} + +static void stm32h7rs_detach(target_s *target) +{ + //stm32h7rs_priv_s *ps = (stm32h7rs_priv_s *)target->target_storage; + //target_mem_write32(target, DBGMCU_CR, ps->dbg_cr); + cortexm_detach(target); +} + +static bool stm32h7rs_flash_busy_wait(target_s *const target, const uint32_t regbase) +{ + uint32_t status = FLASH_SR_BSY | FLASH_SR_QW; + while (status & (FLASH_SR_BSY | FLASH_SR_QW)) { + status = target_mem32_read32(target, regbase + FLASH_SR); + uint32_t istatus = target_mem32_read32(target, regbase + FLASH_ISR); + if ((istatus & FLASH_ISR_ERROR_MASK) || target_check_error(target)) { + DEBUG_ERROR("%s: error status %08" PRIx32 "\n", __func__, istatus); + target_mem32_write32(target, regbase + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); + return false; + } + } + return true; +} + +static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) +{ + (void)addr; + const uint32_t regbase = FPEC1_BASE; + /* Wait for any pending operations to complete */ + if (!stm32h7rs_flash_busy_wait(target, regbase)) + return false; + /* Unlock the device Flash if not already unlocked (it's an error to re-key the controller if it is) */ + if (target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK) { + /* Enable Flash controller access */ + target_mem32_write32(target, regbase + FLASH_KEYR, STM32H7RS_FLASH_KEY1); + target_mem32_write32(target, regbase + FLASH_KEYR, STM32H7RS_FLASH_KEY2); + } + /* Return whether we were able to put the device into unlocked mode */ + return !(target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK); +} + +///* Helper for offsetting FLASH_CR bits correctly */ +//static uint32_t stm32h7rs_flash_cr(uint32_t sector_size, const uint32_t ctrl, int snb) +//{ +// uint32_t command = ctrl; +// /* H74x, H72x IP: 128 KiB and has PSIZE */ +// if (sector_size == FLASH_SECTOR_SIZE) { +// command = ctrl | (snb * FLASH_CR_SNB_1); +// DEBUG_TARGET("%s: patching FLASH_CR from 0x%08" PRIx32 " to 0x%08" PRIx32 "\n", __func__, ctrl, command); +// return command; +// } +// +// /* H7Bx IP: 8 KiB and no PSIZE */ +// /* Save and right-shift FW, START bits */ +// const uint32_t temp_fw_start = command & (FLASH_CR_FW | FLASH_CR_START); +// /* Parallelism is ignored */ +// command &= ~(FLASH_CR_PSIZE64 | FLASH_CR_FW | FLASH_CR_START); +// /* Restore FW, START to H7Bx-correct bits */ +// command |= (temp_fw_start >> 2U); +// /* SNB offset is different, too */ +// command |= (snb << 6U); +// DEBUG_TARGET("%s: patching FLASH_CR from 0x%08" PRIx32 " to 0x%08" PRIx32 "\n", __func__, ctrl, command); +// return command; +//} + +static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) +{ + const uint32_t sector_size = target_flash->blocksize; + target_s *target = target_flash->t; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + /* Unlock the Flash */ + if (!stm32h7rs_flash_unlock(target, addr)) + return false; + /* We come out of reset with HSI 64 MHz. Adapt FLASH_ACR.*/ + target_mem32_write32(target, flash->regbase + FLASH_ACR, 0); + /* Calculate SNB span */ + addr &= target_flash->length - 1U; + const size_t end_sector = (addr + len - 1U) / sector_size; + //const align_e psize = flash->psize; + const uint32_t reg_base = flash->regbase; + + for (size_t begin_sector = addr / sector_size; begin_sector <= end_sector; ++begin_sector) { + /* Erase the current Flash sector */ + //const uint32_t ctrl = stm32h7rs_flash_cr(sector_size, (psize * FLASH_CR_PSIZE16) | FLASH_CR_SER, begin_sector); + const uint32_t ctrl = FLASH_CR_SER | (begin_sector << FLASH_CR_SSN_SHIFT); + target_mem32_write32(target, reg_base + FLASH_CR, ctrl); + //const uint32_t ctrl_start = stm32h7rs_flash_cr(sector_size, ctrl | FLASH_CR_START, begin_sector); + const uint32_t ctrl_start = ctrl | FLASH_CR_START; + target_mem32_write32(target, reg_base + FLASH_CR, ctrl_start); + + /* Wait for the operation to complete and report errors */ + DEBUG_INFO("Erasing, ctrl = %08" PRIx32 " status = %08" PRIx32 "\n", + target_mem32_read32(target, reg_base + FLASH_CR), target_mem32_read32(target, reg_base + FLASH_SR)); + + if (!stm32h7rs_flash_busy_wait(target, reg_base)) + return false; + } + return true; +} + +static bool stm32h7rs_flash_write( + target_flash_s *const target_flash, const target_addr_t dest, const void *const src, const size_t len) +{ + target_s *target = target_flash->t; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + /* Unlock the Flash */ + if (!stm32h7rs_flash_unlock(target, dest)) + return false; + + /* Prepare the Flash write operation */ + //const uint32_t ctrl = stm32h7rs_flash_cr(target_flash->blocksize, flash->psize * FLASH_CR_PSIZE16, 0); + //target_mem_write32(target, flash->regbase + FLASH_CR, ctrl); + //const uint32_t ctrl_pg = stm32h7rs_flash_cr(target_flash->blocksize, ctrl | FLASH_CR_PG, 0); + const uint32_t ctrl_pg = FLASH_CR_PG; + target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl_pg); + /* does H7 stall?*/ + + /* Write the data to the Flash */ + target_mem32_write(target, dest, src, len); + + /* Wait for the operation to complete and report errors */ + if (!stm32h7rs_flash_busy_wait(target, flash->regbase)) + return false; + + /* Close write windows */ + target_mem32_write32(target, flash->regbase + FLASH_CR, 0); + return true; +} + +static bool stm32h7rs_erase_bank( + target_s *const target, const align_e psize, const uint32_t start_addr, const uint32_t reg_base) +{ + if (!stm32h7rs_flash_unlock(target, start_addr)) { + DEBUG_ERROR("Bank erase: Unlock bank failed\n"); + return false; + } + /* BER and start can be merged (§3.3.10). */ + //const uint32_t ctrl = stm32h7rs_flash_cr(target->flash->blocksize, (psize * FLASH_CR_PSIZE16) | FLASH_CR_BER | FLASH_CR_START, 0); + const uint32_t ctrl = FLASH_CR_BER | FLASH_CR_START; + target_mem32_write32(target, reg_base + FLASH_CR, ctrl); + DEBUG_INFO("Mass erase of bank started\n"); + return true; +} + +static bool stm32h7rs_wait_erase_bank(target_s *const target, platform_timeout_s *const timeout, const uint32_t reg_base) +{ + while (target_mem32_read32(target, reg_base + FLASH_SR) & FLASH_SR_QW) { + if (target_check_error(target)) { + DEBUG_ERROR("mass erase bank: comm failed\n"); + return false; + } + target_print_progress(timeout); + } + return true; +} + +static bool stm32h7rs_check_bank(target_s *const target, const uint32_t reg_base) +{ + uint32_t status = target_mem32_read32(target, reg_base + FLASH_ISR); + if (status & FLASH_ISR_ERROR_MASK) + DEBUG_ERROR("mass erase bank: error sr %" PRIx32 "\n", status); + return !(status & FLASH_ISR_ERROR_MASK); +} + +/* Both banks are erased in parallel.*/ +static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const print_progess) +{ + align_e psize = ALIGN_64BIT; + /* + * XXX: What is this and why does it exist? + * A dry-run walk-through says it'll pull out the psize for the first Flash region added by stm32h7rs_probe() + * because all Flash regions added by stm32h7rs_add_flash match the if condition. This looks redundant and wrong. + */ + for (target_flash_s *flash = target->flash; flash; flash = flash->next) { + if (flash->write == stm32h7rs_flash_write) + psize = ((struct stm32h7rs_flash *)flash)->psize; + } + /* Send mass erase Flash start instruction */ + if (!stm32h7rs_erase_bank(target, psize, STM32H7RS_FLASH_BANK1_BASE, FPEC1_BASE)) + return false; + + /* Wait for the banks to finish erasing */ + if (!stm32h7rs_wait_erase_bank(target, print_progess, FPEC1_BASE)) + return false; + + /* Check the banks for final errors */ + return stm32h7rs_check_bank(target, FPEC1_BASE); +} + +/* + * Print the Unique device ID. + * Can be reused for other STM32 devices with uid as parameter. + */ +static bool stm32h7rs_uid(target_s *target, int argc, const char **argv) +{ + (void)argc; + (void)argv; + + const uint32_t uid_addr = 0x08fff800U; + + tc_printf(target, "0x"); + for (size_t i = 0; i < 12U; i += 4U) { + const uint32_t value = target_mem32_read32(target, uid_addr + i); + tc_printf(target, "%02X%02X%02X%02X", (value >> 24U) & 0xffU, (value >> 16U) & 0xffU, (value >> 8U) & 0xffU, + value & 0xffU); + } + tc_printf(target, "\n"); + return true; +} + +//static bool stm32h7rs_crc_bank(target_s *target, uint32_t addr) +//{ +// const uint32_t reg_base = FPEC1_BASE; +// if (!stm32h7rs_flash_unlock(target, addr)) +// return false; +// +// target_mem_write32(target, reg_base + FLASH_CR, FLASH_CR_CRC_EN); +// const uint32_t crc_ctrl = FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_ALL_BANK; +// target_mem_write32(target, reg_base + FLASH_CRCCR, crc_ctrl); +// target_mem_write32(target, reg_base + FLASH_CRCCR, crc_ctrl | FLASH_CRCCR_START_CRC); +// uint32_t status = FLASH_SR_CRC_BUSY; +//#if ENABLE_DEBUG == 1 +// const uint8_t bank = reg_base == FPEC1_BASE ? 1 : 2; +//#endif +// while (status & FLASH_SR_CRC_BUSY) { +// status = target_mem_read32(target, reg_base + FLASH_SR); +// if (target_check_error(target)) { +// DEBUG_ERROR("CRC bank %u: comm failed\n", bank); +// return false; +// } +// if (status & FLASH_SR_ERROR_READ) { +// DEBUG_ERROR("CRC bank %u: error status %08" PRIx32 "\n", bank, status); +// return false; +// } +// } +// return true; +//} +// +//static bool stm32h7rs_crc(target_s *target, int argc, const char **argv) +//{ +// (void)argc; +// (void)argv; +// if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK1_BASE)) +// return false; +// uint32_t crc1 = target_mem_read32(target, FPEC1_BASE + FLASH_CRCDATA); +// if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK2_BASE)) +// return false; +// uint32_t crc2 = 0;//TODO: remove: target_mem_read32(target, FPEC2_BASE + FLASH_CRCDATA); +// tc_printf(target, "CRC: bank1 0x%08lx, bank2 0x%08lx\n", crc1, crc2); +// return true; +//} + +static bool stm32h7rs_cmd_psize(target_s *target, int argc, const char **argv) +{ + if (argc == 1) { + align_e psize = ALIGN_64BIT; + /* + * XXX: What is this and why does it exist? + * A dry-run walk-through says it'll pull out the psize for the first Flash region added by stm32h7rs_probe() + * because all Flash regions added by stm32h7rs_add_flash match the if condition. This looks redundant and wrong. + */ + for (target_flash_s *flash = target->flash; flash; flash = flash->next) { + if (flash->write == stm32h7rs_flash_write) + psize = ((stm32h7rs_flash_s *)flash)->psize; + } + tc_printf(target, "Flash write parallelism: %s\n", stm32_psize_to_string(psize)); + } else { + align_e psize; + if (!stm32_psize_from_string(target, argv[1], &psize)) + return false; + + /* + * XXX: What is this and why does it exist? + * A dry-run walk-through says it'll overwrite psize for every Flash region added by stm32h7rs_probe() + * because all Flash regions added by stm32h7rs_add_flash match the if condition. This looks redundant and wrong. + */ + for (target_flash_s *flash = target->flash; flash; flash = flash->next) { + if (flash->write == stm32h7rs_flash_write) + ((stm32h7rs_flash_s *)flash)->psize = psize; + } + } + return true; +} + +static const struct { + uint16_t rev_id; + char revision; +} stm32h7rs_revisions[] = { + {0x1003U, 'Y'}, +}; + +static bool stm32h7rs_cmd_rev(target_s *target, int argc, const char **argv) +{ + (void)argc; + (void)argv; + /* DBGMCU identity code register */ + const uint32_t dbgmcu_idc = target_mem32_read32(target, DBGMCU_IDC); + const uint16_t rev_id = dbgmcu_idc >> STM32H7RS_DBGMCU_IDCODE_REV_SHIFT; + const uint16_t dev_id = dbgmcu_idc & STM32H7RS_DBGMCU_IDCODE_DEV_MASK; + + /* Print device */ + switch (dev_id) { + case ID_STM32H7RS: + tc_printf(target, "STM32H7Rx/Sx\n"); + break; + default: + tc_printf(target, "Unknown %s. BMP may not correctly support it!\n", target->driver); + return false; + } + /* Print revision */ + char rev = '?'; + for (size_t i = 0; i < ARRAY_LENGTH(stm32h7rs_revisions); i++) { + /* Check for matching revision */ + if (stm32h7rs_revisions[i].rev_id == rev_id) + rev = stm32h7rs_revisions[i].revision; + } + tc_printf(target, "Revision %c\n", rev); + + return true; +} diff --git a/src/target/target_probe.c b/src/target/target_probe.c index 0171dccb644..6740399abca 100644 --- a/src/target/target_probe.c +++ b/src/target/target_probe.c @@ -150,6 +150,7 @@ TARGET_PROBE_WEAK_NOP(stm32f4_probe) TARGET_PROBE_WEAK_NOP(stm32g0_probe) TARGET_PROBE_WEAK_NOP(stm32h5_probe) TARGET_PROBE_WEAK_NOP(stm32h7_probe) +TARGET_PROBE_WEAK_NOP(stm32h7rs_probe) TARGET_PROBE_WEAK_NOP(stm32l0_probe) TARGET_PROBE_WEAK_NOP(stm32l1_probe) TARGET_PROBE_WEAK_NOP(stm32l4_probe) diff --git a/src/target/target_probe.h b/src/target/target_probe.h index 9c906cb3ef0..292c6fceb53 100644 --- a/src/target/target_probe.h +++ b/src/target/target_probe.h @@ -101,6 +101,7 @@ bool stm32f4_probe(target_s *target); bool stm32g0_probe(target_s *target); bool stm32h5_probe(target_s *target); bool stm32h7_probe(target_s *target); +bool stm32h7rs_probe(target_s *target); bool stm32l0_probe(target_s *target); bool stm32l1_probe(target_s *target); bool stm32l4_probe(target_s *target); From 6b90767200a56f029a33dc0293db1631e23d36c4 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Wed, 10 Dec 2025 14:27:08 -0700 Subject: [PATCH 2/9] stm32h7rs: Added code to clear FLASH_ISR bits during unlock. Helps. --- src/target/stm32h7rs.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index 9be5c9af0dd..6089b0cedd8 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -273,9 +273,19 @@ static void stm32h7rs_detach(target_s *target) static bool stm32h7rs_flash_busy_wait(target_s *const target, const uint32_t regbase) { uint32_t status = FLASH_SR_BSY | FLASH_SR_QW; + + /* EMEB - clear any pending flash interrupts that could hurt us */ + uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR) & + FLASH_ISR_ERROR_MASK; + if(istatus != 0U) + { + DEBUG_INFO("%s: FLASH_ISR %08" PRIx32 " - clearing\n", __func__, istatus); + target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus); + } + while (status & (FLASH_SR_BSY | FLASH_SR_QW)) { status = target_mem32_read32(target, regbase + FLASH_SR); - uint32_t istatus = target_mem32_read32(target, regbase + FLASH_ISR); + istatus = target_mem32_read32(target, regbase + FLASH_ISR); if ((istatus & FLASH_ISR_ERROR_MASK) || target_check_error(target)) { DEBUG_ERROR("%s: error status %08" PRIx32 "\n", __func__, istatus); target_mem32_write32(target, regbase + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); @@ -365,7 +375,7 @@ static bool stm32h7rs_flash_write( target_flash_s *const target_flash, const target_addr_t dest, const void *const src, const size_t len) { target_s *target = target_flash->t; - const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; /* Unlock the Flash */ if (!stm32h7rs_flash_unlock(target, dest)) return false; From 6be312bea565bbbb6de44d51df4cbf0c46d5433b Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Thu, 11 Dec 2025 16:21:03 -0700 Subject: [PATCH 3/9] stm32h7rs: Bringing old code up to latest standards. Starting to work! --- src/target/stm32h7rs.c | 133 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 15 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index 6089b0cedd8..ae9a32443cc 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -118,9 +118,9 @@ #define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U #define STM32H7RS_FLASH_BANK1_BASE 0x08000000U -#define STM32H7RS_FLASH_BANK_SIZE 0x00100000U +#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U #define NUM_SECTOR_PER_BANK 8U -#define FLASH_SECTOR_SIZE 0x20000U +#define FLASH_SECTOR_SIZE 0x2000U #define ID_STM32H7RS 0x485U /* RM0477 */ @@ -151,6 +151,8 @@ static bool stm32h7rs_attach(target_s *target); static void stm32h7rs_detach(target_s *target); static bool stm32h7rs_flash_erase(target_flash_s *target_flash, target_addr_t addr, size_t len); static bool stm32h7rs_flash_write(target_flash_s *target_flash, target_addr_t dest, const void *src, size_t len); +static bool stm32h7rs_flash_prepare(target_flash_s *target_flash); +static bool stm32h7rs_flash_done(target_flash_s *target_flash); static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const print_progess); static void stm32h7rs_add_flash(target_s *target, uint32_t addr, size_t length, size_t blocksize) @@ -167,6 +169,8 @@ static void stm32h7rs_add_flash(target_s *target, uint32_t addr, size_t length, target_flash->blocksize = blocksize; target_flash->erase = stm32h7rs_flash_erase; target_flash->write = stm32h7rs_flash_write; + target_flash->prepare = stm32h7rs_flash_prepare; + target_flash->done = stm32h7rs_flash_done; target_flash->writesize = 2048; target_flash->erased = 0xffU; flash->regbase = FPEC1_BASE; @@ -239,7 +243,7 @@ bool stm32h7rs_probe(target_s *target) /* Build the Flash map */ switch (target->part_id) { case ID_STM32H7RS: - stm32h7rs_add_flash(target, STM32H7RS_FLASH_BANK1_BASE, 0x10000U, 0x2000U); + stm32h7rs_add_flash(target, STM32H7RS_FLASH_BANK1_BASE, STM32H7RS_FLASH_BANK_SIZE, FLASH_SECTOR_SIZE); break; default: break; @@ -274,18 +278,9 @@ static bool stm32h7rs_flash_busy_wait(target_s *const target, const uint32_t reg { uint32_t status = FLASH_SR_BSY | FLASH_SR_QW; - /* EMEB - clear any pending flash interrupts that could hurt us */ - uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR) & - FLASH_ISR_ERROR_MASK; - if(istatus != 0U) - { - DEBUG_INFO("%s: FLASH_ISR %08" PRIx32 " - clearing\n", __func__, istatus); - target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus); - } - while (status & (FLASH_SR_BSY | FLASH_SR_QW)) { status = target_mem32_read32(target, regbase + FLASH_SR); - istatus = target_mem32_read32(target, regbase + FLASH_ISR); + uint32_t istatus = target_mem32_read32(target, regbase + FLASH_ISR); if ((istatus & FLASH_ISR_ERROR_MASK) || target_check_error(target)) { DEBUG_ERROR("%s: error status %08" PRIx32 "\n", __func__, istatus); target_mem32_write32(target, regbase + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); @@ -295,13 +290,57 @@ static bool stm32h7rs_flash_busy_wait(target_s *const target, const uint32_t reg return true; } +static bool stm32h7rs_flash_wait_complete(target_s *const target, const uint32_t regbase) +{ + uint32_t status = FLASH_SR_QW, istatus = 0U; + /* Loop waiting for the queuewait bit to clear and EOP to set, indicating completion of all ongoing operations */ + while (!(istatus & FLASH_ISR_EOP) && (status & FLASH_SR_QW)) { + status = target_mem32_read32(target, regbase + FLASH_SR); + istatus = target_mem32_read32(target, regbase + FLASH_ISR); + /* If an error occurs, make noises */ + if (target_check_error(target)) { + DEBUG_ERROR("%s: error reading status\n", __func__); + return false; + } + } + /* Now the operation's complete, we can check the error bits */ + if (istatus & FLASH_ISR_ERROR_MASK) + DEBUG_ERROR("%s: Flash error: %08" PRIx32 "\n", __func__, istatus); + target_mem32_write32(target, regbase + FLASH_ICR, + istatus & (FLASH_ISR_EOP | FLASH_ISR_ERROR_MASK)); + /* Return whether any errors occured */ + return !(istatus & FLASH_ISR_ERROR_MASK); +} + static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) { (void)addr; const uint32_t regbase = FPEC1_BASE; + /* EMEB - clear any pending flash interrupts that could hurt us */ + uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR) & + FLASH_ISR_ERROR_MASK; + if(istatus != 0U) + { + DEBUG_INFO("%s: FLASH_ISR %08" PRIx32 " - clearing\n", __func__, istatus); + target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus); + } + +#if 0 + // EMEB original zyp code /* Wait for any pending operations to complete */ if (!stm32h7rs_flash_busy_wait(target, regbase)) return false; +#else + // EMEB new code based on H7 driver + /* Read out the Flash status and tend to any pending conditions */ + const uint32_t status = target_mem32_read32(target, regbase + FLASH_SR); + /* Start by checking if there are any pending ongoing operations */ + if (status & FLASH_SR_QW) { + /* Wait for any pending operations to complete */ + if (!stm32h7rs_flash_wait_complete(target, regbase)) + return false; + } +#endif /* Unlock the device Flash if not already unlocked (it's an error to re-key the controller if it is) */ if (target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK) { /* Enable Flash controller access */ @@ -312,7 +351,25 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) return !(target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK); } -///* Helper for offsetting FLASH_CR bits correctly */ +static bool stm32h7rs_flash_prepare(target_flash_s *const target_flash) +{ + target_s *target = target_flash->t; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + + /* Unlock the Flash controller to prepare it for operations */ + return stm32h7rs_flash_unlock(target, flash->regbase); +} + +static bool stm32h7rs_flash_done(target_flash_s *const target_flash) +{ + target_s *target = target_flash->t; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + /* Lock the Flash controller to complete operations */ + target_mem32_write32(target, flash->regbase + FLASH_CR, FLASH_CR_LOCK); + return true; +} + +///* Helper for offsetting FLASH_CR bits correctly EMEB - not needed for just H7R/S */ //static uint32_t stm32h7rs_flash_cr(uint32_t sector_size, const uint32_t ctrl, int snb) //{ // uint32_t command = ctrl; @@ -338,6 +395,8 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) { +#if 0 + // EMEB original zyp code const uint32_t sector_size = target_flash->blocksize; target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; @@ -368,7 +427,28 @@ static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_add if (!stm32h7rs_flash_busy_wait(target, reg_base)) return false; } - return true; + return stm32h7rs_flash_wait_complete(target, flash->regbase); +#else + // EMEB new code based on latest H7 driver + (void)len; + /* Erases are always done one sector at a time - the target Flash API guarantees this */ + target_s *target = target_flash->t; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + + /* Calculate the sector to erase and set the operation runnning */ + const uint32_t sector = (addr - target_flash->start) / target_flash->blocksize; + const uint32_t ctrl = FLASH_CR_SER | (sector << FLASH_CR_SSN_SHIFT); + target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl); + target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl | FLASH_CR_START); + + /* Wait for the operation to complete and report errors */ + DEBUG_INFO("Erasing, ctrl = %08" PRIx32 " status = %08" PRIx32 "\n", + target_mem32_read32(target, flash->regbase + FLASH_CR), target_mem32_read32(target, flash->regbase + FLASH_SR)); + + /* Wait for the operation to complete and report errors */ + return stm32h7rs_flash_wait_complete(target, flash->regbase); + +#endif } static bool stm32h7rs_flash_write( @@ -389,6 +469,8 @@ static bool stm32h7rs_flash_write( /* does H7 stall?*/ /* Write the data to the Flash */ +#if 0 + /* original from zyp's 2024 version w/o queue waiting */ target_mem32_write(target, dest, src, len); /* Wait for the operation to complete and report errors */ @@ -398,6 +480,27 @@ static bool stm32h7rs_flash_write( /* Close write windows */ target_mem32_write32(target, flash->regbase + FLASH_CR, 0); return true; +#else + /* New stuff from H7 driver - adapted for 16 byte flash wordsize */ + for (size_t offset = 0U; offset < len; offset += 16U) { + const size_t amount = MIN(len - offset, 16U); + target_mem32_write(target, dest + offset, ((const uint8_t *)src) + offset, amount); + /* + * If this is the final chunk and the amount is not a multiple of 16 + * bytes, make sure the write is forced to complete per RM0468 §5.3.8 + * "Single write sequence" pg215 + */ + if (amount < 16U) + target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl_pg | FLASH_CR_FW); + + /* wait for QW bit to clear */ + while (target_mem32_read32(target, flash->regbase + FLASH_SR) & FLASH_SR_QW) + continue; + } + + /* Wait for the operation to complete and report errors */ + return stm32h7rs_flash_wait_complete(target, flash->regbase); +#endif } static bool stm32h7rs_erase_bank( From 4704134e935701ac09377a421a7b9e9d4e16b2a4 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Thu, 11 Dec 2025 16:42:53 -0700 Subject: [PATCH 4/9] stm32h7rs: Cleaned out dead code & comments --- src/target/stm32h7rs.c | 110 +---------------------------------------- 1 file changed, 1 insertion(+), 109 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index ae9a32443cc..83f57e9a117 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -274,22 +274,6 @@ static void stm32h7rs_detach(target_s *target) cortexm_detach(target); } -static bool stm32h7rs_flash_busy_wait(target_s *const target, const uint32_t regbase) -{ - uint32_t status = FLASH_SR_BSY | FLASH_SR_QW; - - while (status & (FLASH_SR_BSY | FLASH_SR_QW)) { - status = target_mem32_read32(target, regbase + FLASH_SR); - uint32_t istatus = target_mem32_read32(target, regbase + FLASH_ISR); - if ((istatus & FLASH_ISR_ERROR_MASK) || target_check_error(target)) { - DEBUG_ERROR("%s: error status %08" PRIx32 "\n", __func__, istatus); - target_mem32_write32(target, regbase + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); - return false; - } - } - return true; -} - static bool stm32h7rs_flash_wait_complete(target_s *const target, const uint32_t regbase) { uint32_t status = FLASH_SR_QW, istatus = 0U; @@ -325,13 +309,6 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus); } -#if 0 - // EMEB original zyp code - /* Wait for any pending operations to complete */ - if (!stm32h7rs_flash_busy_wait(target, regbase)) - return false; -#else - // EMEB new code based on H7 driver /* Read out the Flash status and tend to any pending conditions */ const uint32_t status = target_mem32_read32(target, regbase + FLASH_SR); /* Start by checking if there are any pending ongoing operations */ @@ -340,7 +317,7 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) if (!stm32h7rs_flash_wait_complete(target, regbase)) return false; } -#endif + /* Unlock the device Flash if not already unlocked (it's an error to re-key the controller if it is) */ if (target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK) { /* Enable Flash controller access */ @@ -369,68 +346,8 @@ static bool stm32h7rs_flash_done(target_flash_s *const target_flash) return true; } -///* Helper for offsetting FLASH_CR bits correctly EMEB - not needed for just H7R/S */ -//static uint32_t stm32h7rs_flash_cr(uint32_t sector_size, const uint32_t ctrl, int snb) -//{ -// uint32_t command = ctrl; -// /* H74x, H72x IP: 128 KiB and has PSIZE */ -// if (sector_size == FLASH_SECTOR_SIZE) { -// command = ctrl | (snb * FLASH_CR_SNB_1); -// DEBUG_TARGET("%s: patching FLASH_CR from 0x%08" PRIx32 " to 0x%08" PRIx32 "\n", __func__, ctrl, command); -// return command; -// } -// -// /* H7Bx IP: 8 KiB and no PSIZE */ -// /* Save and right-shift FW, START bits */ -// const uint32_t temp_fw_start = command & (FLASH_CR_FW | FLASH_CR_START); -// /* Parallelism is ignored */ -// command &= ~(FLASH_CR_PSIZE64 | FLASH_CR_FW | FLASH_CR_START); -// /* Restore FW, START to H7Bx-correct bits */ -// command |= (temp_fw_start >> 2U); -// /* SNB offset is different, too */ -// command |= (snb << 6U); -// DEBUG_TARGET("%s: patching FLASH_CR from 0x%08" PRIx32 " to 0x%08" PRIx32 "\n", __func__, ctrl, command); -// return command; -//} - static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) { -#if 0 - // EMEB original zyp code - const uint32_t sector_size = target_flash->blocksize; - target_s *target = target_flash->t; - const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; - /* Unlock the Flash */ - if (!stm32h7rs_flash_unlock(target, addr)) - return false; - /* We come out of reset with HSI 64 MHz. Adapt FLASH_ACR.*/ - target_mem32_write32(target, flash->regbase + FLASH_ACR, 0); - /* Calculate SNB span */ - addr &= target_flash->length - 1U; - const size_t end_sector = (addr + len - 1U) / sector_size; - //const align_e psize = flash->psize; - const uint32_t reg_base = flash->regbase; - - for (size_t begin_sector = addr / sector_size; begin_sector <= end_sector; ++begin_sector) { - /* Erase the current Flash sector */ - //const uint32_t ctrl = stm32h7rs_flash_cr(sector_size, (psize * FLASH_CR_PSIZE16) | FLASH_CR_SER, begin_sector); - const uint32_t ctrl = FLASH_CR_SER | (begin_sector << FLASH_CR_SSN_SHIFT); - target_mem32_write32(target, reg_base + FLASH_CR, ctrl); - //const uint32_t ctrl_start = stm32h7rs_flash_cr(sector_size, ctrl | FLASH_CR_START, begin_sector); - const uint32_t ctrl_start = ctrl | FLASH_CR_START; - target_mem32_write32(target, reg_base + FLASH_CR, ctrl_start); - - /* Wait for the operation to complete and report errors */ - DEBUG_INFO("Erasing, ctrl = %08" PRIx32 " status = %08" PRIx32 "\n", - target_mem32_read32(target, reg_base + FLASH_CR), target_mem32_read32(target, reg_base + FLASH_SR)); - - if (!stm32h7rs_flash_busy_wait(target, reg_base)) - return false; - } - return stm32h7rs_flash_wait_complete(target, flash->regbase); -#else - // EMEB new code based on latest H7 driver - (void)len; /* Erases are always done one sector at a time - the target Flash API guarantees this */ target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; @@ -447,8 +364,6 @@ static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_add /* Wait for the operation to complete and report errors */ return stm32h7rs_flash_wait_complete(target, flash->regbase); - -#endif } static bool stm32h7rs_flash_write( @@ -456,32 +371,12 @@ static bool stm32h7rs_flash_write( { target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; - /* Unlock the Flash */ - if (!stm32h7rs_flash_unlock(target, dest)) - return false; /* Prepare the Flash write operation */ - //const uint32_t ctrl = stm32h7rs_flash_cr(target_flash->blocksize, flash->psize * FLASH_CR_PSIZE16, 0); - //target_mem_write32(target, flash->regbase + FLASH_CR, ctrl); - //const uint32_t ctrl_pg = stm32h7rs_flash_cr(target_flash->blocksize, ctrl | FLASH_CR_PG, 0); const uint32_t ctrl_pg = FLASH_CR_PG; target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl_pg); - /* does H7 stall?*/ /* Write the data to the Flash */ -#if 0 - /* original from zyp's 2024 version w/o queue waiting */ - target_mem32_write(target, dest, src, len); - - /* Wait for the operation to complete and report errors */ - if (!stm32h7rs_flash_busy_wait(target, flash->regbase)) - return false; - - /* Close write windows */ - target_mem32_write32(target, flash->regbase + FLASH_CR, 0); - return true; -#else - /* New stuff from H7 driver - adapted for 16 byte flash wordsize */ for (size_t offset = 0U; offset < len; offset += 16U) { const size_t amount = MIN(len - offset, 16U); target_mem32_write(target, dest + offset, ((const uint8_t *)src) + offset, amount); @@ -500,7 +395,6 @@ static bool stm32h7rs_flash_write( /* Wait for the operation to complete and report errors */ return stm32h7rs_flash_wait_complete(target, flash->regbase); -#endif } static bool stm32h7rs_erase_bank( @@ -511,7 +405,6 @@ static bool stm32h7rs_erase_bank( return false; } /* BER and start can be merged (§3.3.10). */ - //const uint32_t ctrl = stm32h7rs_flash_cr(target->flash->blocksize, (psize * FLASH_CR_PSIZE16) | FLASH_CR_BER | FLASH_CR_START, 0); const uint32_t ctrl = FLASH_CR_BER | FLASH_CR_START; target_mem32_write32(target, reg_base + FLASH_CR, ctrl); DEBUG_INFO("Mass erase of bank started\n"); @@ -538,7 +431,6 @@ static bool stm32h7rs_check_bank(target_s *const target, const uint32_t reg_base return !(status & FLASH_ISR_ERROR_MASK); } -/* Both banks are erased in parallel.*/ static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const print_progess) { align_e psize = ALIGN_64BIT; From c661312b9247db8060535925733115922fe29024 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Thu, 11 Dec 2025 18:18:10 -0700 Subject: [PATCH 5/9] stm32h7rs: cleanup warnings --- src/target/stm32h7rs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index 83f57e9a117..476656a62b8 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -348,6 +348,7 @@ static bool stm32h7rs_flash_done(target_flash_s *const target_flash) static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) { + (void) len; // prevent unused param warning /* Erases are always done one sector at a time - the target Flash API guarantees this */ target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; @@ -400,6 +401,7 @@ static bool stm32h7rs_flash_write( static bool stm32h7rs_erase_bank( target_s *const target, const align_e psize, const uint32_t start_addr, const uint32_t reg_base) { + (void) psize; // prevent unused param warning if (!stm32h7rs_flash_unlock(target, start_addr)) { DEBUG_ERROR("Bank erase: Unlock bank failed\n"); return false; From d4e617e4984cebbec8ecc81520910c388ff559b1 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Thu, 11 Dec 2025 21:42:43 -0700 Subject: [PATCH 6/9] stm32h7rs: align w/ latest H7 driver, clean out unused stuff. --- src/target/stm32h7rs.c | 192 ++++++++++++++++++++++------------------- 1 file changed, 104 insertions(+), 88 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index 476656a62b8..6ae11aa3f3e 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -46,8 +46,8 @@ //#define FLASH_OPTCR 0x018U //#define FLASH_OPTSR_CUR 0x01cU //#define FLASH_OPTSR 0x020U -//#define FLASH_CRCCR 0x050U -//#define FLASH_CRCDATA 0x05cU +#define FLASH_CRCCR 0x050U +#define FLASH_CRCDATA 0x05cU /* Flash Program and Erase Controller Register Map */ #define FPEC1_BASE 0x52002000U @@ -81,17 +81,17 @@ #define FLASH_CR_SSN_SHIFT 6U //#define FLASH_CR_SNB_1 (1U << 8U) //#define FLASH_CR_SNB (3U << 8U) -//#define FLASH_CR_CRC_EN (1U << 15U) +#define FLASH_CR_CRC_EN (1U << 15U) // //#define FLASH_OPTCR_OPTLOCK (1U << 0U) //#define FLASH_OPTCR_OPTSTRT (1U << 1U) // //#define FLASH_OPTSR_IWDG1_SW (1U << 4U) // -//#define FLASH_CRCCR_ALL_BANK (1U << 7U) -//#define FLASH_CRCCR_START_CRC (1U << 16U) -//#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) -//#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) +#define FLASH_CRCCR_ALL_BANK (1U << 7U) +#define FLASH_CRCCR_START_CRC (1U << 16U) +#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) +#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) #define STM32H7RS_FLASH_KEY1 0x45670123U #define STM32H7RS_FLASH_KEY2 0xcdef89abU @@ -99,13 +99,29 @@ #define STM32H7RS_OPT_KEY1 0x08192a3bU #define STM32H7RS_OPT_KEY2 0x4c5d6e7fU -#define DBGMCU_IDCODE 0x5c001000U #define STM32H7RS_FLASH_SIZE 0x1ff1e880U -#define STM32H7Bx_FLASH_SIZE 0x08fff80cU +#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U +#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U +#define NUM_SECTOR_PER_BANK 8U +#define FLASH_SECTOR_SIZE 0x2000U + +/* WWDG base address and register map */ +#define STM32H7RS_WWDG_BASE 0x40002c00U +#define STM32H7RS_WWDG_CR (STM32H7RS_WWDG_BASE + 0x00) +#define STM32H7RS_WWDG_CR_RESET 0x0000007fU + +/* IWDG base address and register map */ +#define STM32H7RS_IWDG_BASE 0x58004800U +#define STM32H7RS_IWDG_KEY (STM32H7RS_IWDG_BASE + 0x00U) +#define STM32H7RS_IWDG_KEY_RESET 0x0000aaaaU + /* Access from processor address space. * Access via the APB-D is at 0xe00e1000 */ +#define DBGMCU_IDCODE 0x5c001000U #define DBGMCU_IDC (DBGMCU_IDCODE + 0U) #define DBGMCU_CR (DBGMCU_IDCODE + 4U) +#define DBGMCU_APB1FREEZE (DBGMCU_IDCODE + 0x03cU) +#define DBGMCU_APB4FREEZE (DBGMCU_IDCODE + 0x054U) #define DBGSLEEP_D1 (1U << 0U) #define DBGSTOP_D1 (1U << 1U) #define DBGSTBY_D1 (1U << 2U) @@ -113,15 +129,12 @@ #define DBGSTBY_D3 (1U << 8U) #define D1DBGCKEN (1U << 21U) #define D3DBGCKEN (1U << 22U) +#define DBGMCU_APB1FREEZE_WWDG1 (1U << 11U) +#define DBGMCU_APB4FREEZE_IWDG1 (1U << 18U) #define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU #define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U -#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U -#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U -#define NUM_SECTOR_PER_BANK 8U -#define FLASH_SECTOR_SIZE 0x2000U - #define ID_STM32H7RS 0x485U /* RM0477 */ typedef struct stm32h7rs_flash { @@ -135,14 +148,14 @@ typedef struct stm32h7rs_priv { } stm32h7rs_priv_s; static bool stm32h7rs_uid(target_s *target, int argc, const char **argv); -//static bool stm32h7rs_crc(target_s *target, int argc, const char **argv); +static bool stm32h7rs_crc(target_s *target, int argc, const char **argv); static bool stm32h7rs_cmd_psize(target_s *target, int argc, const char **argv); static bool stm32h7rs_cmd_rev(target_s *target, int argc, const char **argv); const command_s stm32h7rs_cmd_list[] = { {"psize", stm32h7rs_cmd_psize, "Configure flash write parallelism: (x8|x16|x32|x64(default))"}, {"uid", stm32h7rs_uid, "Print unique device ID"}, - //{"crc", stm32h7rs_crc, "Print CRC of both banks"}, + {"crc", stm32h7rs_crc, "Print CRC of bank 1"}, {"revision", stm32h7rs_cmd_rev, "Returns the Device ID and Revision"}, {NULL, NULL, NULL}, }; @@ -202,23 +215,24 @@ bool stm32h7rs_probe(target_s *target) target_add_commands(target, stm32h7rs_cmd_list, target->driver); /* EMEB - Decide which of these is correct */ -#if 1 +#if 0 /* RM0433 Rev 4 is not really clear, what bits are needed in DBGMCU_CR. Maybe more flags needed? */ const uint32_t dbgmcu_ctrl = DBGSLEEP_D1 | D1DBGCKEN; target_mem32_write32(target, DBGMCU_CR, dbgmcu_ctrl); #else /* Now we have a stable debug environment, make sure the WDTs can't bonk the processor out from under us */ - target_mem32_write32(target, STM32H7_DBGMCU_APB3FREEZE, STM32H7_DBGMCU_APB3FREEZE_WWDG1); - target_mem32_write32(target, STM32H7_DBGMCU_APB4FREEZE, STM32H7_DBGMCU_APB4FREEZE_IWDG1); + target_mem32_write32(target, DBGMCU_APB1FREEZE, DBGMCU_APB1FREEZE_WWDG1); + target_mem32_write32(target, DBGMCU_APB4FREEZE, DBGMCU_APB4FREEZE_IWDG1); /* + * EMEB - this is redundant w/ stuff that happens at attach() * Make sure that both domain D1 and D3 debugging are enabled and that we can keep * debugging through sleep, stop and standby states for domain D1 */ - target_mem32_write32(target, STM32H7_DBGMCU_CONFIG, - target_mem32_read32(target, STM32H7_DBGMCU_CONFIG) | STM32H7_DBGMCU_CONFIG_DBGSLEEP_D1 | - STM32H7_DBGMCU_CONFIG_DBGSTOP_D1 | STM32H7_DBGMCU_CONFIG_DBGSTBY_D1 | STM32H7_DBGMCU_CONFIG_D1DBGCKEN | - STM32H7_DBGMCU_CONFIG_D3DBGCKEN); - stm32h7_configure_wdts(target); + target_mem32_write32(target, DBGMCU_CR, + target_mem32_read32(target, DBGMCU_CR) | DBGSLEEP_D1 | + DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); + target_mem32_write32(target, STM32H7RS_WWDG_CR, STM32H7RS_WWDG_CR_RESET); + target_mem32_write32(target, STM32H7RS_IWDG_KEY, STM32H7RS_IWDG_KEY_RESET); #endif /* Build the RAM map - EMEB: ITCM/DTCM are too big -shared w/ AXI */ @@ -256,6 +270,7 @@ static bool stm32h7rs_attach(target_s *target) { if (!cortexm_attach(target)) return false; +#if 0 /* * If IWDG runs as HARDWARE watchdog (§44.3.4) erase * will be aborted by the Watchdog and erase fails! @@ -264,13 +279,29 @@ static bool stm32h7rs_attach(target_s *target) //const uint32_t optsr = target_mem_read32(target, FPEC1_BASE + FLASH_OPTSR); //if (!(optsr & FLASH_OPTSR_IWDG1_SW)) // tc_printf(target, "Hardware IWDG running. Expect failure. Set IWDG1_SW!"); +#else + /* + * Make sure that both domain D1 and D3 debugging are enabled and that we can keep + * debugging through sleep, stop and standby states for domain D1 - this is duplicated as it's undone by detach. + */ + target_mem32_write32(target, DBGMCU_CR, + DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); + target_mem32_write32(target, STM32H7RS_WWDG_CR, STM32H7RS_WWDG_CR_RESET); + target_mem32_write32(target, STM32H7RS_IWDG_KEY, STM32H7RS_IWDG_KEY_RESET); +#endif return true; } static void stm32h7rs_detach(target_s *target) { +#if 0 //stm32h7rs_priv_s *ps = (stm32h7rs_priv_s *)target->target_storage; //target_mem_write32(target, DBGMCU_CR, ps->dbg_cr); +#else + target_mem32_write32(target, DBGMCU_CR, + target_mem32_read32(target, DBGMCU_CR) & + ~(DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN)); +#endif cortexm_detach(target); } @@ -296,17 +327,14 @@ static bool stm32h7rs_flash_wait_complete(target_s *const target, const uint32_t return !(istatus & FLASH_ISR_ERROR_MASK); } -static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t addr) +static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t regbase) { - (void)addr; - const uint32_t regbase = FPEC1_BASE; - /* EMEB - clear any pending flash interrupts that could hurt us */ - uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR) & - FLASH_ISR_ERROR_MASK; - if(istatus != 0U) + /* clear any pending flash interrupts that could hurt us */ + uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR); + if (istatus & FLASH_ISR_ERROR_MASK) { DEBUG_INFO("%s: FLASH_ISR %08" PRIx32 " - clearing\n", __func__, istatus); - target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus); + target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); } /* Read out the Flash status and tend to any pending conditions */ @@ -348,7 +376,7 @@ static bool stm32h7rs_flash_done(target_flash_s *const target_flash) static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) { - (void) len; // prevent unused param warning + (void) len; /* Erases are always done one sector at a time - the target Flash API guarantees this */ target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; @@ -399,10 +427,9 @@ static bool stm32h7rs_flash_write( } static bool stm32h7rs_erase_bank( - target_s *const target, const align_e psize, const uint32_t start_addr, const uint32_t reg_base) + target_s *const target, const uint32_t reg_base) { - (void) psize; // prevent unused param warning - if (!stm32h7rs_flash_unlock(target, start_addr)) { + if (!stm32h7rs_flash_unlock(target, reg_base)) { DEBUG_ERROR("Bank erase: Unlock bank failed\n"); return false; } @@ -435,18 +462,8 @@ static bool stm32h7rs_check_bank(target_s *const target, const uint32_t reg_base static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const print_progess) { - align_e psize = ALIGN_64BIT; - /* - * XXX: What is this and why does it exist? - * A dry-run walk-through says it'll pull out the psize for the first Flash region added by stm32h7rs_probe() - * because all Flash regions added by stm32h7rs_add_flash match the if condition. This looks redundant and wrong. - */ - for (target_flash_s *flash = target->flash; flash; flash = flash->next) { - if (flash->write == stm32h7rs_flash_write) - psize = ((struct stm32h7rs_flash *)flash)->psize; - } /* Send mass erase Flash start instruction */ - if (!stm32h7rs_erase_bank(target, psize, STM32H7RS_FLASH_BANK1_BASE, FPEC1_BASE)) + if (!stm32h7rs_erase_bank(target, FPEC1_BASE)) return false; /* Wait for the banks to finish erasing */ @@ -478,47 +495,46 @@ static bool stm32h7rs_uid(target_s *target, int argc, const char **argv) return true; } -//static bool stm32h7rs_crc_bank(target_s *target, uint32_t addr) -//{ -// const uint32_t reg_base = FPEC1_BASE; -// if (!stm32h7rs_flash_unlock(target, addr)) -// return false; -// -// target_mem_write32(target, reg_base + FLASH_CR, FLASH_CR_CRC_EN); -// const uint32_t crc_ctrl = FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_ALL_BANK; -// target_mem_write32(target, reg_base + FLASH_CRCCR, crc_ctrl); -// target_mem_write32(target, reg_base + FLASH_CRCCR, crc_ctrl | FLASH_CRCCR_START_CRC); -// uint32_t status = FLASH_SR_CRC_BUSY; -//#if ENABLE_DEBUG == 1 -// const uint8_t bank = reg_base == FPEC1_BASE ? 1 : 2; -//#endif -// while (status & FLASH_SR_CRC_BUSY) { -// status = target_mem_read32(target, reg_base + FLASH_SR); -// if (target_check_error(target)) { -// DEBUG_ERROR("CRC bank %u: comm failed\n", bank); -// return false; -// } -// if (status & FLASH_SR_ERROR_READ) { -// DEBUG_ERROR("CRC bank %u: error status %08" PRIx32 "\n", bank, status); -// return false; -// } -// } -// return true; -//} -// -//static bool stm32h7rs_crc(target_s *target, int argc, const char **argv) -//{ -// (void)argc; -// (void)argv; -// if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK1_BASE)) -// return false; -// uint32_t crc1 = target_mem_read32(target, FPEC1_BASE + FLASH_CRCDATA); -// if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK2_BASE)) -// return false; -// uint32_t crc2 = 0;//TODO: remove: target_mem_read32(target, FPEC2_BASE + FLASH_CRCDATA); -// tc_printf(target, "CRC: bank1 0x%08lx, bank2 0x%08lx\n", crc1, crc2); -// return true; -//} +static bool stm32h7rs_crc_bank(target_s *target, uint32_t addr) +{ + (void) addr; + const uint32_t reg_base = FPEC1_BASE; + if (!stm32h7rs_flash_unlock(target, reg_base)) + return false; + + target_mem32_write32(target, reg_base + FLASH_CR, FLASH_CR_CRC_EN); + const uint32_t crc_ctrl = FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_ALL_BANK; + target_mem32_write32(target, reg_base + FLASH_CRCCR, crc_ctrl); + target_mem32_write32(target, reg_base + FLASH_CRCCR, crc_ctrl | FLASH_CRCCR_START_CRC); + uint32_t status = FLASH_SR_CRC_BUSY; +#if ENABLE_DEBUG == 1 + const uint8_t bank = reg_base == FPEC1_BASE ? 1 : 2; +#endif + while (status & FLASH_SR_CRC_BUSY) { + status = target_mem32_read32(target, reg_base + FLASH_SR); + if (target_check_error(target)) { + DEBUG_ERROR("CRC bank %u: comm failed\n", bank); + return false; + } + uint32_t istatus = target_mem32_read32(target, reg_base + FLASH_ISR); + if (istatus & FLASH_ISR_ERROR_READ) { + DEBUG_ERROR("CRC bank %u: error status %08" PRIx32 "\n", bank, istatus); + return false; + } + } + return true; +} + +static bool stm32h7rs_crc(target_s *target, int argc, const char **argv) +{ + (void)argc; + (void)argv; + if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK1_BASE)) + return false; + uint32_t crc1 = target_mem32_read32(target, FPEC1_BASE + FLASH_CRCDATA); + tc_printf(target, "CRC: bank1 0x%08" PRIx32 "\n", crc1); + return true; +} static bool stm32h7rs_cmd_psize(target_s *target, int argc, const char **argv) { From 426488b4699416dc99a96afb53ece9dc773dbfbd Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Thu, 11 Dec 2025 21:58:49 -0700 Subject: [PATCH 7/9] stm32h7rs: DBGMCU stuff in attach/detach was causing problems. Disabled. --- src/target/stm32h7rs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index 6ae11aa3f3e..d7be512b6d7 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -270,7 +270,7 @@ static bool stm32h7rs_attach(target_s *target) { if (!cortexm_attach(target)) return false; -#if 0 +#if 1 /* * If IWDG runs as HARDWARE watchdog (§44.3.4) erase * will be aborted by the Watchdog and erase fails! @@ -294,7 +294,7 @@ static bool stm32h7rs_attach(target_s *target) static void stm32h7rs_detach(target_s *target) { -#if 0 +#if 1 //stm32h7rs_priv_s *ps = (stm32h7rs_priv_s *)target->target_storage; //target_mem_write32(target, DBGMCU_CR, ps->dbg_cr); #else From 1a778cbfdc0c77c785a0061aa8e8e2a62fe10092 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Fri, 12 Dec 2025 15:46:21 -0700 Subject: [PATCH 8/9] stm32h7rs: CRC works, tested breakpoints, erase_mass. Minor cleanups. --- src/target/stm32h7rs.c | 250 +++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 145 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index d7be512b6d7..f2093f9b28c 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -34,108 +34,99 @@ #include "cortexm.h" #include "stm32_common.h" -#define FLASH_ACR 0x000U -#define FLASH_KEYR 0x004U -#define FLASH_CR 0x010U -#define FLASH_SR 0x014U -#define FLASH_IER 0x020U -#define FLASH_ISR 0x024U -#define FLASH_ICR 0x028U -//#define FLASH_OPTKEYR 0x008U -//#define FLASH_CCR 0x014U -//#define FLASH_OPTCR 0x018U -//#define FLASH_OPTSR_CUR 0x01cU -//#define FLASH_OPTSR 0x020U -#define FLASH_CRCCR 0x050U -#define FLASH_CRCDATA 0x05cU - /* Flash Program and Erase Controller Register Map */ -#define FPEC1_BASE 0x52002000U -#define FLASH_SR_BSY (1U << 0U) -#define FLASH_SR_WBNE (1U << 1U) -#define FLASH_SR_QW (1U << 2U) -#define FLASH_SR_CRC_BUSY (1U << 3U) -#define FLASH_ISR_EOP (1U << 16U) -#define FLASH_ISR_WRPERR (1U << 17U) -#define FLASH_ISR_PGSERR (1U << 18U) -#define FLASH_ISR_STRBERR (1U << 19U) -#define FLASH_ISR_INCERR (1U << 21U) -#define FLASH_ISR_RDSERR (1U << 24U) -#define FLASH_ISR_SNECCERR (1U << 25U) -#define FLASH_ISR_DBECCERR (1U << 26U) -#define FLASH_ISR_CRCEND (1U << 27U) -#define FLASH_ISR_CRCRDERR (1U << 28U) -#define FLASH_ISR_ERROR_READ (FLASH_ISR_RDSERR | FLASH_ISR_SNECCERR | FLASH_ISR_DBECCERR) -#define FLASH_ISR_ERROR_MASK \ +#define FPEC1_BASE 0x52002000U +#define FLASH_ACR 0x000U +#define FLASH_KEYR 0x004U +#define FLASH_CR 0x010U +#define FLASH_SR 0x014U +#define FLASH_IER 0x020U +#define FLASH_ISR 0x024U +#define FLASH_ICR 0x028U +#define FLASH_CRCCR 0x030U +#define FLASH_CRCDATA 0x03cU +#define FLASH_SR_BSY (1U << 0U) +#define FLASH_SR_WBNE (1U << 1U) +#define FLASH_SR_QW (1U << 2U) +#define FLASH_SR_CRC_BUSY (1U << 3U) +#define FLASH_ISR_EOP (1U << 16U) +#define FLASH_ISR_WRPERR (1U << 17U) +#define FLASH_ISR_PGSERR (1U << 18U) +#define FLASH_ISR_STRBERR (1U << 19U) +#define FLASH_ISR_INCERR (1U << 21U) +#define FLASH_ISR_RDSERR (1U << 24U) +#define FLASH_ISR_SNECCERR (1U << 25U) +#define FLASH_ISR_DBECCERR (1U << 26U) +#define FLASH_ISR_CRCEND (1U << 27U) +#define FLASH_ISR_CRCRDERR (1U << 28U) +#define FLASH_ISR_ERROR_READ (FLASH_ISR_RDSERR | FLASH_ISR_SNECCERR | FLASH_ISR_DBECCERR) +#define FLASH_ISR_ERROR_MASK \ (FLASH_ISR_WRPERR | FLASH_ISR_PGSERR | FLASH_ISR_STRBERR | FLASH_ISR_INCERR | FLASH_ISR_ERROR_READ) -#define FLASH_CR_LOCK (1U << 0U) -#define FLASH_CR_PG (1U << 1U) -#define FLASH_CR_SER (1U << 2U) -#define FLASH_CR_BER (1U << 3U) -//#define FLASH_CR_PSIZE8 (0U << 4U) -//#define FLASH_CR_PSIZE16 (1U << 4U) -//#define FLASH_CR_PSIZE32 (2U << 4U) -//#define FLASH_CR_PSIZE64 (3U << 4U) -#define FLASH_CR_FW (1U << 4U) -#define FLASH_CR_START (1U << 5U) -#define FLASH_CR_SSN_SHIFT 6U -//#define FLASH_CR_SNB_1 (1U << 8U) -//#define FLASH_CR_SNB (3U << 8U) -#define FLASH_CR_CRC_EN (1U << 15U) -// -//#define FLASH_OPTCR_OPTLOCK (1U << 0U) -//#define FLASH_OPTCR_OPTSTRT (1U << 1U) -// -//#define FLASH_OPTSR_IWDG1_SW (1U << 4U) -// -#define FLASH_CRCCR_ALL_BANK (1U << 7U) -#define FLASH_CRCCR_START_CRC (1U << 16U) -#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) -#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) - -#define STM32H7RS_FLASH_KEY1 0x45670123U -#define STM32H7RS_FLASH_KEY2 0xcdef89abU - -#define STM32H7RS_OPT_KEY1 0x08192a3bU -#define STM32H7RS_OPT_KEY2 0x4c5d6e7fU - -#define STM32H7RS_FLASH_SIZE 0x1ff1e880U -#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U -#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U -#define NUM_SECTOR_PER_BANK 8U -#define FLASH_SECTOR_SIZE 0x2000U +#define FLASH_CR_LOCK (1U << 0U) +#define FLASH_CR_PG (1U << 1U) +#define FLASH_CR_SER (1U << 2U) +#define FLASH_CR_BER (1U << 3U) +#define FLASH_CR_FW (1U << 4U) +#define FLASH_CR_START (1U << 5U) +#define FLASH_CR_SSN_SHIFT 6U +#define FLASH_CR_CRC_EN (1U << 17U) +#define FLASH_CRCCR_ALL_BANK (1U << 7U) +#define FLASH_CRCCR_START_CRC (1U << 16U) +#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) +#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) + +#define STM32H7RS_FLASH_KEY1 0x45670123U +#define STM32H7RS_FLASH_KEY2 0xcdef89abU + +#define STM32H7RS_OPT_KEY1 0x08192a3bU +#define STM32H7RS_OPT_KEY2 0x4c5d6e7fU + +#define STM32H7RS_FLASH_SIZE 0x1ff1e880U +#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U +#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U +#define NUM_SECTOR_PER_BANK 8U +#define FLASH_SECTOR_SIZE 0x2000U /* WWDG base address and register map */ -#define STM32H7RS_WWDG_BASE 0x40002c00U -#define STM32H7RS_WWDG_CR (STM32H7RS_WWDG_BASE + 0x00) -#define STM32H7RS_WWDG_CR_RESET 0x0000007fU +#define STM32H7RS_WWDG_BASE 0x40002c00U +#define STM32H7RS_WWDG_CR (STM32H7RS_WWDG_BASE + 0x00) +#define STM32H7RS_WWDG_CR_RESET 0x0000007fU /* IWDG base address and register map */ -#define STM32H7RS_IWDG_BASE 0x58004800U -#define STM32H7RS_IWDG_KEY (STM32H7RS_IWDG_BASE + 0x00U) -#define STM32H7RS_IWDG_KEY_RESET 0x0000aaaaU - -/* Access from processor address space. - * Access via the APB-D is at 0xe00e1000 */ -#define DBGMCU_IDCODE 0x5c001000U -#define DBGMCU_IDC (DBGMCU_IDCODE + 0U) -#define DBGMCU_CR (DBGMCU_IDCODE + 4U) -#define DBGMCU_APB1FREEZE (DBGMCU_IDCODE + 0x03cU) -#define DBGMCU_APB4FREEZE (DBGMCU_IDCODE + 0x054U) -#define DBGSLEEP_D1 (1U << 0U) -#define DBGSTOP_D1 (1U << 1U) -#define DBGSTBY_D1 (1U << 2U) -#define DBGSTOP_D3 (1U << 7U) -#define DBGSTBY_D3 (1U << 8U) -#define D1DBGCKEN (1U << 21U) -#define D3DBGCKEN (1U << 22U) -#define DBGMCU_APB1FREEZE_WWDG1 (1U << 11U) -#define DBGMCU_APB4FREEZE_IWDG1 (1U << 18U) - -#define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU -#define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U - -#define ID_STM32H7RS 0x485U /* RM0477 */ +#define STM32H7RS_IWDG_BASE 0x58004800U +#define STM32H7RS_IWDG_KEY (STM32H7RS_IWDG_BASE + 0x00U) +#define STM32H7RS_IWDG_KEY_RESET 0x0000aaaaU + +/* + * Access from processor address space. + * Access via the APB-D is at 0xe00e1000 + */ +#define DBGMCU_IDCODE 0x5c001000U +#define DBGMCU_IDC (DBGMCU_IDCODE + 0U) +#define DBGMCU_CR (DBGMCU_IDCODE + 4U) +#define DBGMCU_APB1FREEZE (DBGMCU_IDCODE + 0x03cU) +#define DBGMCU_APB4FREEZE (DBGMCU_IDCODE + 0x054U) +#define DBGSLEEP_D1 (1U << 0U) +#define DBGSTOP_D1 (1U << 1U) +#define DBGSTBY_D1 (1U << 2U) +#define DBGSTOP_D3 (1U << 7U) +#define DBGSTBY_D3 (1U << 8U) +#define D1DBGCKEN (1U << 21U) +#define D3DBGCKEN (1U << 22U) +#define DBGMCU_APB1FREEZE_WWDG1 (1U << 11U) +#define DBGMCU_APB4FREEZE_IWDG1 (1U << 18U) + +#define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU +#define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U + +#define ID_STM32H7RS 0x485U /* RM0477 */ + +/* + * Uncomment this to enable DBGMCU setup in attach() and detach() + * This seem to cause problems with reconnecting to the target and is + * also somewhat redundant with similar setup that happens in probe() + */ +//#define CONFIG_EXPERIMENTAL_DBGMCU typedef struct stm32h7rs_flash { target_flash_s target_flash; @@ -214,17 +205,10 @@ bool stm32h7rs_probe(target_s *target) target->mass_erase = stm32h7rs_mass_erase; target_add_commands(target, stm32h7rs_cmd_list, target->driver); - /* EMEB - Decide which of these is correct */ -#if 0 - /* RM0433 Rev 4 is not really clear, what bits are needed in DBGMCU_CR. Maybe more flags needed? */ - const uint32_t dbgmcu_ctrl = DBGSLEEP_D1 | D1DBGCKEN; - target_mem32_write32(target, DBGMCU_CR, dbgmcu_ctrl); -#else /* Now we have a stable debug environment, make sure the WDTs can't bonk the processor out from under us */ target_mem32_write32(target, DBGMCU_APB1FREEZE, DBGMCU_APB1FREEZE_WWDG1); target_mem32_write32(target, DBGMCU_APB4FREEZE, DBGMCU_APB4FREEZE_IWDG1); /* - * EMEB - this is redundant w/ stuff that happens at attach() * Make sure that both domain D1 and D3 debugging are enabled and that we can keep * debugging through sleep, stop and standby states for domain D1 */ @@ -233,9 +217,9 @@ bool stm32h7rs_probe(target_s *target) DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); target_mem32_write32(target, STM32H7RS_WWDG_CR, STM32H7RS_WWDG_CR_RESET); target_mem32_write32(target, STM32H7RS_IWDG_KEY, STM32H7RS_IWDG_KEY_RESET); -#endif + - /* Build the RAM map - EMEB: ITCM/DTCM are too big -shared w/ AXI */ + /* Build the RAM map */ switch (target->part_id) { case ID_STM32H7RS: { /* Table 6. Memory map and default device memory area attributes RM0477, pg151 */ @@ -270,16 +254,7 @@ static bool stm32h7rs_attach(target_s *target) { if (!cortexm_attach(target)) return false; -#if 1 - /* - * 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! - */ - //const uint32_t optsr = target_mem_read32(target, FPEC1_BASE + FLASH_OPTSR); - //if (!(optsr & FLASH_OPTSR_IWDG1_SW)) - // tc_printf(target, "Hardware IWDG running. Expect failure. Set IWDG1_SW!"); -#else +#ifdef CONFIG_EXPERIMENTAL_DBGMCU /* * Make sure that both domain D1 and D3 debugging are enabled and that we can keep * debugging through sleep, stop and standby states for domain D1 - this is duplicated as it's undone by detach. @@ -294,10 +269,10 @@ static bool stm32h7rs_attach(target_s *target) static void stm32h7rs_detach(target_s *target) { -#if 1 - //stm32h7rs_priv_s *ps = (stm32h7rs_priv_s *)target->target_storage; - //target_mem_write32(target, DBGMCU_CR, ps->dbg_cr); -#else +#ifdef CONFIG_EXPERIMENTAL_DBGMCU + /* + * undo DBGMCU setup done in attach() + */ target_mem32_write32(target, DBGMCU_CR, target_mem32_read32(target, DBGMCU_CR) & ~(DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN)); @@ -307,7 +282,8 @@ static void stm32h7rs_detach(target_s *target) static bool stm32h7rs_flash_wait_complete(target_s *const target, const uint32_t regbase) { - uint32_t status = FLASH_SR_QW, istatus = 0U; + uint32_t status = FLASH_SR_QW; + uint32_t istatus = 0U; /* Loop waiting for the queuewait bit to clear and EOP to set, indicating completion of all ongoing operations */ while (!(istatus & FLASH_ISR_EOP) && (status & FLASH_SR_QW)) { status = target_mem32_read32(target, regbase + FLASH_SR); @@ -474,51 +450,34 @@ static bool stm32h7rs_mass_erase(target_s *target, platform_timeout_s *const pri return stm32h7rs_check_bank(target, FPEC1_BASE); } -/* - * Print the Unique device ID. - * Can be reused for other STM32 devices with uid as parameter. - */ static bool stm32h7rs_uid(target_s *target, int argc, const char **argv) { (void)argc; (void)argv; - const uint32_t uid_addr = 0x08fff800U; - - tc_printf(target, "0x"); - for (size_t i = 0; i < 12U; i += 4U) { - const uint32_t value = target_mem32_read32(target, uid_addr + i); - tc_printf(target, "%02X%02X%02X%02X", (value >> 24U) & 0xffU, (value >> 16U) & 0xffU, (value >> 8U) & 0xffU, - value & 0xffU); - } - tc_printf(target, "\n"); - return true; + return stm32_uid(target, uid_addr); } -static bool stm32h7rs_crc_bank(target_s *target, uint32_t addr) +static bool stm32h7rs_crc_bank(target_s *target) { - (void) addr; const uint32_t reg_base = FPEC1_BASE; if (!stm32h7rs_flash_unlock(target, reg_base)) return false; target_mem32_write32(target, reg_base + FLASH_CR, FLASH_CR_CRC_EN); - const uint32_t crc_ctrl = FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_ALL_BANK; - target_mem32_write32(target, reg_base + FLASH_CRCCR, crc_ctrl); + const uint32_t crc_ctrl = + FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_ALL_BANK; target_mem32_write32(target, reg_base + FLASH_CRCCR, crc_ctrl | FLASH_CRCCR_START_CRC); uint32_t status = FLASH_SR_CRC_BUSY; -#if ENABLE_DEBUG == 1 - const uint8_t bank = reg_base == FPEC1_BASE ? 1 : 2; -#endif while (status & FLASH_SR_CRC_BUSY) { status = target_mem32_read32(target, reg_base + FLASH_SR); if (target_check_error(target)) { - DEBUG_ERROR("CRC bank %u: comm failed\n", bank); + DEBUG_ERROR("CRC comm failed\n"); return false; } uint32_t istatus = target_mem32_read32(target, reg_base + FLASH_ISR); if (istatus & FLASH_ISR_ERROR_READ) { - DEBUG_ERROR("CRC bank %u: error status %08" PRIx32 "\n", bank, istatus); + DEBUG_ERROR("CRC error status %08" PRIx32 "\n", istatus); return false; } } @@ -529,10 +488,10 @@ static bool stm32h7rs_crc(target_s *target, int argc, const char **argv) { (void)argc; (void)argv; - if (!stm32h7rs_crc_bank(target, STM32H7RS_FLASH_BANK1_BASE)) + if (!stm32h7rs_crc_bank(target)) return false; uint32_t crc1 = target_mem32_read32(target, FPEC1_BASE + FLASH_CRCDATA); - tc_printf(target, "CRC: bank1 0x%08" PRIx32 "\n", crc1); + tc_printf(target, "CRC: 0x%08" PRIx32 "\n", crc1); return true; } @@ -573,6 +532,7 @@ static const struct { char revision; } stm32h7rs_revisions[] = { {0x1003U, 'Y'}, + {0x2000U, 'B'}, }; static bool stm32h7rs_cmd_rev(target_s *target, int argc, const char **argv) From 2d9e26de8faed62522e9bdd224dc7718604546e0 Mon Sep 17 00:00:00 2001 From: Eric Brombaugh Date: Fri, 12 Dec 2025 19:24:18 -0700 Subject: [PATCH 9/9] stm32h7rs: fix formatting issues found by CI --- src/target/stm32h7rs.c | 193 ++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 100 deletions(-) diff --git a/src/target/stm32h7rs.c b/src/target/stm32h7rs.c index f2093f9b28c..176fd80966c 100644 --- a/src/target/stm32h7rs.c +++ b/src/target/stm32h7rs.c @@ -35,91 +35,91 @@ #include "stm32_common.h" /* Flash Program and Erase Controller Register Map */ -#define FPEC1_BASE 0x52002000U -#define FLASH_ACR 0x000U -#define FLASH_KEYR 0x004U -#define FLASH_CR 0x010U -#define FLASH_SR 0x014U -#define FLASH_IER 0x020U -#define FLASH_ISR 0x024U -#define FLASH_ICR 0x028U -#define FLASH_CRCCR 0x030U -#define FLASH_CRCDATA 0x03cU -#define FLASH_SR_BSY (1U << 0U) -#define FLASH_SR_WBNE (1U << 1U) -#define FLASH_SR_QW (1U << 2U) -#define FLASH_SR_CRC_BUSY (1U << 3U) -#define FLASH_ISR_EOP (1U << 16U) -#define FLASH_ISR_WRPERR (1U << 17U) -#define FLASH_ISR_PGSERR (1U << 18U) -#define FLASH_ISR_STRBERR (1U << 19U) -#define FLASH_ISR_INCERR (1U << 21U) -#define FLASH_ISR_RDSERR (1U << 24U) -#define FLASH_ISR_SNECCERR (1U << 25U) -#define FLASH_ISR_DBECCERR (1U << 26U) -#define FLASH_ISR_CRCEND (1U << 27U) -#define FLASH_ISR_CRCRDERR (1U << 28U) -#define FLASH_ISR_ERROR_READ (FLASH_ISR_RDSERR | FLASH_ISR_SNECCERR | FLASH_ISR_DBECCERR) -#define FLASH_ISR_ERROR_MASK \ +#define FPEC1_BASE 0x52002000U +#define FLASH_ACR 0x000U +#define FLASH_KEYR 0x004U +#define FLASH_CR 0x010U +#define FLASH_SR 0x014U +#define FLASH_IER 0x020U +#define FLASH_ISR 0x024U +#define FLASH_ICR 0x028U +#define FLASH_CRCCR 0x030U +#define FLASH_CRCDATA 0x03cU +#define FLASH_SR_BSY (1U << 0U) +#define FLASH_SR_WBNE (1U << 1U) +#define FLASH_SR_QW (1U << 2U) +#define FLASH_SR_CRC_BUSY (1U << 3U) +#define FLASH_ISR_EOP (1U << 16U) +#define FLASH_ISR_WRPERR (1U << 17U) +#define FLASH_ISR_PGSERR (1U << 18U) +#define FLASH_ISR_STRBERR (1U << 19U) +#define FLASH_ISR_INCERR (1U << 21U) +#define FLASH_ISR_RDSERR (1U << 24U) +#define FLASH_ISR_SNECCERR (1U << 25U) +#define FLASH_ISR_DBECCERR (1U << 26U) +#define FLASH_ISR_CRCEND (1U << 27U) +#define FLASH_ISR_CRCRDERR (1U << 28U) +#define FLASH_ISR_ERROR_READ (FLASH_ISR_RDSERR | FLASH_ISR_SNECCERR | FLASH_ISR_DBECCERR) +#define FLASH_ISR_ERROR_MASK \ (FLASH_ISR_WRPERR | FLASH_ISR_PGSERR | FLASH_ISR_STRBERR | FLASH_ISR_INCERR | FLASH_ISR_ERROR_READ) -#define FLASH_CR_LOCK (1U << 0U) -#define FLASH_CR_PG (1U << 1U) -#define FLASH_CR_SER (1U << 2U) -#define FLASH_CR_BER (1U << 3U) -#define FLASH_CR_FW (1U << 4U) -#define FLASH_CR_START (1U << 5U) -#define FLASH_CR_SSN_SHIFT 6U -#define FLASH_CR_CRC_EN (1U << 17U) -#define FLASH_CRCCR_ALL_BANK (1U << 7U) -#define FLASH_CRCCR_START_CRC (1U << 16U) -#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) -#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) - -#define STM32H7RS_FLASH_KEY1 0x45670123U -#define STM32H7RS_FLASH_KEY2 0xcdef89abU - -#define STM32H7RS_OPT_KEY1 0x08192a3bU -#define STM32H7RS_OPT_KEY2 0x4c5d6e7fU - -#define STM32H7RS_FLASH_SIZE 0x1ff1e880U -#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U -#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U -#define NUM_SECTOR_PER_BANK 8U -#define FLASH_SECTOR_SIZE 0x2000U +#define FLASH_CR_LOCK (1U << 0U) +#define FLASH_CR_PG (1U << 1U) +#define FLASH_CR_SER (1U << 2U) +#define FLASH_CR_BER (1U << 3U) +#define FLASH_CR_FW (1U << 4U) +#define FLASH_CR_START (1U << 5U) +#define FLASH_CR_SSN_SHIFT 6U +#define FLASH_CR_CRC_EN (1U << 17U) +#define FLASH_CRCCR_ALL_BANK (1U << 7U) +#define FLASH_CRCCR_START_CRC (1U << 16U) +#define FLASH_CRCCR_CLEAN_CRC (1U << 17U) +#define FLASH_CRCCR_CRC_BURST_3 (3U << 20U) + +#define STM32H7RS_FLASH_KEY1 0x45670123U +#define STM32H7RS_FLASH_KEY2 0xcdef89abU + +#define STM32H7RS_OPT_KEY1 0x08192a3bU +#define STM32H7RS_OPT_KEY2 0x4c5d6e7fU + +#define STM32H7RS_FLASH_SIZE 0x1ff1e880U +#define STM32H7RS_FLASH_BANK1_BASE 0x08000000U +#define STM32H7RS_FLASH_BANK_SIZE 0x00010000U +#define NUM_SECTOR_PER_BANK 8U +#define FLASH_SECTOR_SIZE 0x2000U /* WWDG base address and register map */ -#define STM32H7RS_WWDG_BASE 0x40002c00U -#define STM32H7RS_WWDG_CR (STM32H7RS_WWDG_BASE + 0x00) -#define STM32H7RS_WWDG_CR_RESET 0x0000007fU +#define STM32H7RS_WWDG_BASE 0x40002c00U +#define STM32H7RS_WWDG_CR (STM32H7RS_WWDG_BASE + 0x00) +#define STM32H7RS_WWDG_CR_RESET 0x0000007fU /* IWDG base address and register map */ -#define STM32H7RS_IWDG_BASE 0x58004800U -#define STM32H7RS_IWDG_KEY (STM32H7RS_IWDG_BASE + 0x00U) -#define STM32H7RS_IWDG_KEY_RESET 0x0000aaaaU +#define STM32H7RS_IWDG_BASE 0x58004800U +#define STM32H7RS_IWDG_KEY (STM32H7RS_IWDG_BASE + 0x00U) +#define STM32H7RS_IWDG_KEY_RESET 0x0000aaaaU /* * Access from processor address space. * Access via the APB-D is at 0xe00e1000 */ -#define DBGMCU_IDCODE 0x5c001000U -#define DBGMCU_IDC (DBGMCU_IDCODE + 0U) -#define DBGMCU_CR (DBGMCU_IDCODE + 4U) -#define DBGMCU_APB1FREEZE (DBGMCU_IDCODE + 0x03cU) -#define DBGMCU_APB4FREEZE (DBGMCU_IDCODE + 0x054U) -#define DBGSLEEP_D1 (1U << 0U) -#define DBGSTOP_D1 (1U << 1U) -#define DBGSTBY_D1 (1U << 2U) -#define DBGSTOP_D3 (1U << 7U) -#define DBGSTBY_D3 (1U << 8U) -#define D1DBGCKEN (1U << 21U) -#define D3DBGCKEN (1U << 22U) -#define DBGMCU_APB1FREEZE_WWDG1 (1U << 11U) -#define DBGMCU_APB4FREEZE_IWDG1 (1U << 18U) - -#define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU -#define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U - -#define ID_STM32H7RS 0x485U /* RM0477 */ +#define DBGMCU_IDCODE 0x5c001000U +#define DBGMCU_IDC (DBGMCU_IDCODE + 0U) +#define DBGMCU_CR (DBGMCU_IDCODE + 4U) +#define DBGMCU_APB1FREEZE (DBGMCU_IDCODE + 0x03cU) +#define DBGMCU_APB4FREEZE (DBGMCU_IDCODE + 0x054U) +#define DBGSLEEP_D1 (1U << 0U) +#define DBGSTOP_D1 (1U << 1U) +#define DBGSTBY_D1 (1U << 2U) +#define DBGSTOP_D3 (1U << 7U) +#define DBGSTBY_D3 (1U << 8U) +#define D1DBGCKEN (1U << 21U) +#define D3DBGCKEN (1U << 22U) +#define DBGMCU_APB1FREEZE_WWDG1 (1U << 11U) +#define DBGMCU_APB4FREEZE_IWDG1 (1U << 18U) + +#define STM32H7RS_DBGMCU_IDCODE_DEV_MASK 0x00000fffU +#define STM32H7RS_DBGMCU_IDCODE_REV_SHIFT 16U + +#define ID_STM32H7RS 0x485U /* RM0477 */ /* * Uncomment this to enable DBGMCU setup in attach() and detach() @@ -187,9 +187,9 @@ bool stm32h7rs_probe(target_s *target) const adiv5_access_port_s *const ap = cortex_ap(target); if (ap->partno != ID_STM32H7RS) return false; - + target->part_id = ap->partno; - + /* Save private storage */ stm32h7rs_priv_s *priv = calloc(1, sizeof(*priv)); if (!priv) { /* calloc failed: heap exhaustion */ @@ -198,13 +198,13 @@ bool stm32h7rs_probe(target_s *target) } target->target_storage = priv; priv->dbg_cr = target_mem32_read32(target, DBGMCU_CR); - + target->driver = "STM32H7R/S"; target->attach = stm32h7rs_attach; target->detach = stm32h7rs_detach; target->mass_erase = stm32h7rs_mass_erase; target_add_commands(target, stm32h7rs_cmd_list, target->driver); - + /* Now we have a stable debug environment, make sure the WDTs can't bonk the processor out from under us */ target_mem32_write32(target, DBGMCU_APB1FREEZE, DBGMCU_APB1FREEZE_WWDG1); target_mem32_write32(target, DBGMCU_APB4FREEZE, DBGMCU_APB4FREEZE_IWDG1); @@ -213,12 +213,10 @@ bool stm32h7rs_probe(target_s *target) * debugging through sleep, stop and standby states for domain D1 */ target_mem32_write32(target, DBGMCU_CR, - target_mem32_read32(target, DBGMCU_CR) | DBGSLEEP_D1 | - DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); + target_mem32_read32(target, DBGMCU_CR) | DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); target_mem32_write32(target, STM32H7RS_WWDG_CR, STM32H7RS_WWDG_CR_RESET); target_mem32_write32(target, STM32H7RS_IWDG_KEY, STM32H7RS_IWDG_KEY_RESET); - /* Build the RAM map */ switch (target->part_id) { case ID_STM32H7RS: { @@ -259,8 +257,7 @@ static bool stm32h7rs_attach(target_s *target) * Make sure that both domain D1 and D3 debugging are enabled and that we can keep * debugging through sleep, stop and standby states for domain D1 - this is duplicated as it's undone by detach. */ - target_mem32_write32(target, DBGMCU_CR, - DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); + target_mem32_write32(target, DBGMCU_CR, DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN); target_mem32_write32(target, STM32H7RS_WWDG_CR, STM32H7RS_WWDG_CR_RESET); target_mem32_write32(target, STM32H7RS_IWDG_KEY, STM32H7RS_IWDG_KEY_RESET); #endif @@ -274,8 +271,7 @@ static void stm32h7rs_detach(target_s *target) * undo DBGMCU setup done in attach() */ target_mem32_write32(target, DBGMCU_CR, - target_mem32_read32(target, DBGMCU_CR) & - ~(DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN)); + target_mem32_read32(target, DBGMCU_CR) & ~(DBGSLEEP_D1 | DBGSTOP_D1 | DBGSTBY_D1 | D1DBGCKEN | D3DBGCKEN)); #endif cortexm_detach(target); } @@ -297,8 +293,7 @@ static bool stm32h7rs_flash_wait_complete(target_s *const target, const uint32_t /* Now the operation's complete, we can check the error bits */ if (istatus & FLASH_ISR_ERROR_MASK) DEBUG_ERROR("%s: Flash error: %08" PRIx32 "\n", __func__, istatus); - target_mem32_write32(target, regbase + FLASH_ICR, - istatus & (FLASH_ISR_EOP | FLASH_ISR_ERROR_MASK)); + target_mem32_write32(target, regbase + FLASH_ICR, istatus & (FLASH_ISR_EOP | FLASH_ISR_ERROR_MASK)); /* Return whether any errors occured */ return !(istatus & FLASH_ISR_ERROR_MASK); } @@ -307,12 +302,11 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t regbas { /* clear any pending flash interrupts that could hurt us */ uint32_t istatus = target_mem32_read32(target, FPEC1_BASE + FLASH_ISR); - if (istatus & FLASH_ISR_ERROR_MASK) - { + if (istatus & FLASH_ISR_ERROR_MASK) { DEBUG_INFO("%s: FLASH_ISR %08" PRIx32 " - clearing\n", __func__, istatus); target_mem32_write32(target, FPEC1_BASE + FLASH_ICR, istatus & FLASH_ISR_ERROR_MASK); } - + /* Read out the Flash status and tend to any pending conditions */ const uint32_t status = target_mem32_read32(target, regbase + FLASH_SR); /* Start by checking if there are any pending ongoing operations */ @@ -321,7 +315,7 @@ static bool stm32h7rs_flash_unlock(target_s *const target, const uint32_t regbas if (!stm32h7rs_flash_wait_complete(target, regbase)) return false; } - + /* Unlock the device Flash if not already unlocked (it's an error to re-key the controller if it is) */ if (target_mem32_read32(target, regbase + FLASH_CR) & FLASH_CR_LOCK) { /* Enable Flash controller access */ @@ -352,7 +346,7 @@ static bool stm32h7rs_flash_done(target_flash_s *const target_flash) static bool stm32h7rs_flash_erase(target_flash_s *const target_flash, target_addr_t addr, const size_t len) { - (void) len; + (void)len; /* Erases are always done one sector at a time - the target Flash API guarantees this */ target_s *target = target_flash->t; const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; @@ -375,7 +369,7 @@ static bool stm32h7rs_flash_write( target_flash_s *const target_flash, const target_addr_t dest, const void *const src, const size_t len) { target_s *target = target_flash->t; - const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; + const stm32h7rs_flash_s *const flash = (stm32h7rs_flash_s *)target_flash; /* Prepare the Flash write operation */ const uint32_t ctrl_pg = FLASH_CR_PG; @@ -392,7 +386,7 @@ static bool stm32h7rs_flash_write( */ if (amount < 16U) target_mem32_write32(target, flash->regbase + FLASH_CR, ctrl_pg | FLASH_CR_FW); - + /* wait for QW bit to clear */ while (target_mem32_read32(target, flash->regbase + FLASH_SR) & FLASH_SR_QW) continue; @@ -402,8 +396,7 @@ static bool stm32h7rs_flash_write( return stm32h7rs_flash_wait_complete(target, flash->regbase); } -static bool stm32h7rs_erase_bank( - target_s *const target, const uint32_t reg_base) +static bool stm32h7rs_erase_bank(target_s *const target, const uint32_t reg_base) { if (!stm32h7rs_flash_unlock(target, reg_base)) { DEBUG_ERROR("Bank erase: Unlock bank failed\n"); @@ -416,7 +409,8 @@ static bool stm32h7rs_erase_bank( return true; } -static bool stm32h7rs_wait_erase_bank(target_s *const target, platform_timeout_s *const timeout, const uint32_t reg_base) +static bool stm32h7rs_wait_erase_bank( + target_s *const target, platform_timeout_s *const timeout, const uint32_t reg_base) { while (target_mem32_read32(target, reg_base + FLASH_SR) & FLASH_SR_QW) { if (target_check_error(target)) { @@ -465,8 +459,7 @@ static bool stm32h7rs_crc_bank(target_s *target) return false; target_mem32_write32(target, reg_base + FLASH_CR, FLASH_CR_CRC_EN); - const uint32_t crc_ctrl = - FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_ALL_BANK; + const uint32_t crc_ctrl = FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_CRC_BURST_3 | FLASH_CRCCR_ALL_BANK; target_mem32_write32(target, reg_base + FLASH_CRCCR, crc_ctrl | FLASH_CRCCR_START_CRC); uint32_t status = FLASH_SR_CRC_BUSY; while (status & FLASH_SR_CRC_BUSY) {