flash/stm32h7x: support STM32H7R/H7Sx

The STM32H7R/H7Sx has a flash size up to 64 Kb
Change-Id: I2e9d80758d1bc88defdd6bbd1787026373b39fa4
Signed-off-by: HAOUES Ahmed <ahmed.haoues@st.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8890
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Tested-by: jenkins
This commit is contained in:
HAOUES Ahmed
2025-07-23 14:57:11 +01:00
committed by Tomas Vanek
parent b8dc15f43b
commit 03b79387cc
4 changed files with 310 additions and 20 deletions

View File

@@ -18,14 +18,21 @@
#define FLASH_WRITE_TIMEOUT 5
#define MASS_ERASE_TIMEOUT 30000
static const uint8_t stm32h7_flash_write_code[] = {
#include "../../../contrib/loaders/flash/stm32/stm32h7x.inc"
};
static const uint8_t stm32h7rs_flash_write_code[] = {
#include "../../../contrib/loaders/flash/stm32/stm32h7rx.inc"
};
enum stm32h7_flash_reg_index {
STM32_FLASH_ACR_INDEX,
STM32_FLASH_KEYR_INDEX,
STM32_FLASH_OPTKEYR_INDEX,
STM32_FLASH_SR_INDEX,
STM32_FLASH_CR_INDEX,
STM32_FLASH_ICR_INDEX,
STM32_FLASH_CCR_INDEX,
STM32_FLASH_ICR_CCR_INDEX,
STM32_FLASH_OPTCR_INDEX,
STM32_FLASH_OPTSR_INDEX,
STM32_FLASH_OPTSR_CUR_INDEX,
@@ -46,7 +53,7 @@ static const uint32_t stm32h7_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
[STM32_FLASH_OPTKEYR_INDEX] = 0x08,
[STM32_FLASH_SR_INDEX] = 0x10,
[STM32_FLASH_CR_INDEX] = 0x0C,
[STM32_FLASH_CCR_INDEX] = 0x14,
[STM32_FLASH_ICR_CCR_INDEX] = 0x14,
[STM32_FLASH_OPTCR_INDEX] = 0x18,
[STM32_FLASH_OPTSR_CUR_INDEX] = 0x1C,
[STM32_FLASH_OPTSR_PRG_INDEX] = 0x20,
@@ -55,6 +62,18 @@ static const uint32_t stm32h7_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
[STM32_FLASH_WPSN_PRG_INDEX] = 0x3C
};
static const uint32_t stm32h7rs_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
[STM32_FLASH_ACR_INDEX] = 0x00,
[STM32_FLASH_KEYR_INDEX] = 0x04,
[STM32_FLASH_OPTKEYR_INDEX] = 0x100,
[STM32_FLASH_SR_INDEX] = 0x14,
[STM32_FLASH_CR_INDEX] = 0x10,
[STM32_FLASH_ICR_CCR_INDEX] = 0x28,
[STM32_FLASH_OPTCR_INDEX] = 0x104,
[STM32_FLASH_OPTSR_INDEX] = 0x10C,
[STM32_FLASH_ISR_INDEX] = 0x24,
};
/* FLASH_CR register bits */
#define FLASH_LOCK BIT(0)
#define FLASH_PG BIT(1)
@@ -67,6 +86,19 @@ static const uint32_t stm32h7_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
#define FLASH_FW BIT(6)
#define FLASH_START BIT(7)
/* FLASH_ISR register bits for H7RS */
#define FLASH_CRCRDERRF BIT(28) /* CRC read error flag */
#define FLASH_CRCENDF BIT(27) /* CRC end flag */
#define FLASH_DBECCERRF BIT(26) /* ECC double error flag */
#define FLASH_SNECCERRF BIT(25) /* ECC single error flag */
#define FLASH_RDSERRF BIT(24) /* Read security error flag */
#define FLASH_INCERRF BIT(21) /* Inconsistency error flag */
#define FLASH_OBLERRF BIT(20) /* Option byte loading error flag */
#define FLASH_STRBERRF BIT(19) /* Strobe error flag */
#define FLASH_PGSERRF BIT(18) /* Programming sequence error flag */
#define FLASH_WRPERRF BIT(17) /* Write protection error flag */
#define FLASH_EOPF BIT(16) /* End-of-program flag */
/* FLASH_SR register bits */
#define FLASH_BSY BIT(0) /* Operation in progress */
#define FLASH_QW BIT(2) /* Operation queue in progress */
@@ -82,6 +114,9 @@ static const uint32_t stm32h7_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
#define FLASH_ERROR (FLASH_WRPERR | FLASH_PGSERR | FLASH_STRBERR | FLASH_INCERR | FLASH_OPERR | \
FLASH_RDPERR | FLASH_RDSERR | FLASH_SNECCERR | FLASH_DBECCERR)
/* Possible errors for H7RS */
#define FLASH_ERROR_H7RS (FLASH_CRCRDERRF | FLASH_CRCENDF | FLASH_DBECCERRF | FLASH_SNECCERRF | FLASH_RDSERRF | \
FLASH_INCERRF | FLASH_OBLERRF | FLASH_STRBERRF | FLASH_PGSERRF | FLASH_WRPERRF | FLASH_EOPF)
/* FLASH_OPTCR register bits */
#define OPT_LOCK BIT(0)
@@ -114,6 +149,7 @@ static const uint32_t stm32h7_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
#define DEVID_STM32H74_H75XX 0x450
#define DEVID_STM32H7A_H7BXX 0x480
#define DEVID_STM32H72_H73XX 0x483
#define DEVID_STM32H7R_H7SXX 0x485
struct stm32h7_rev {
uint16_t rev;
@@ -139,6 +175,9 @@ struct stm32h7_part_info {
/* function to compute flash_cr register values */
uint32_t (*compute_flash_cr)(uint32_t cmd, int snb);
int (*get_flash_error_status)(struct flash_bank *bank, uint32_t *status);
uint32_t flash_error;
const uint8_t *write_code;
size_t write_code_size;
};
struct stm32h7_flash_bank {
@@ -168,12 +207,16 @@ static const struct stm32h7_rev stm32h72_h73xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" },
};
static const struct stm32h7_rev stm32h7r_h7sxx_revs[] = {
{ 0x1000, "A" }, { 0x2000, "B" },
};
static uint32_t stm32h74_h75xx_compute_flash_cr(uint32_t cmd, int snb)
{
return cmd | (snb << 8);
}
static uint32_t stm32h7a_h7bxx_compute_flash_cr(uint32_t cmd, int snb)
static uint32_t stm32h7a_h7b_h7r_h7sxx_compute_flash_cr(uint32_t cmd, int snb)
{
/* save FW and START bits, to be right shifted by 2 bits later */
const uint32_t tmp = cmd & (FLASH_FW | FLASH_START);
@@ -185,6 +228,7 @@ static uint32_t stm32h7a_h7bxx_compute_flash_cr(uint32_t cmd, int snb)
}
static int stm32h7_get_flash_status(struct flash_bank *bank, uint32_t *status);
static int stm32h7rs_get_flash_status(struct flash_bank *bank, uint32_t *status);
static const struct stm32h7_part_info stm32h7_parts[] = {
{
@@ -202,6 +246,9 @@ static const struct stm32h7_part_info stm32h7_parts[] = {
.wps_mask = 0xFF,
.compute_flash_cr = stm32h74_h75xx_compute_flash_cr,
.get_flash_error_status = stm32h7_get_flash_status,
.flash_error = FLASH_ERROR,
.write_code = stm32h7_flash_write_code,
.write_code_size = sizeof(stm32h7_flash_write_code),
},
{
.id = DEVID_STM32H7A_H7BXX,
@@ -216,8 +263,11 @@ static const struct stm32h7_part_info stm32h7_parts[] = {
.fsize_addr = 0x08FFF80C,
.wps_group_size = 4,
.wps_mask = 0xFFFFFFFF,
.compute_flash_cr = stm32h7a_h7bxx_compute_flash_cr,
.compute_flash_cr = stm32h7a_h7b_h7r_h7sxx_compute_flash_cr,
.get_flash_error_status = stm32h7_get_flash_status,
.flash_error = FLASH_ERROR,
.write_code = stm32h7_flash_write_code,
.write_code_size = sizeof(stm32h7_flash_write_code),
},
{
.id = DEVID_STM32H72_H73XX,
@@ -234,6 +284,28 @@ static const struct stm32h7_part_info stm32h7_parts[] = {
.wps_mask = 0xFF,
.compute_flash_cr = stm32h74_h75xx_compute_flash_cr,
.get_flash_error_status = stm32h7_get_flash_status,
.flash_error = FLASH_ERROR,
.write_code = stm32h7_flash_write_code,
.write_code_size = sizeof(stm32h7_flash_write_code),
},
{
.id = DEVID_STM32H7R_H7SXX,
.revs = stm32h7r_h7sxx_revs,
.num_revs = ARRAY_SIZE(stm32h7r_h7sxx_revs),
.device_str = "STM32H7Rx/7Sx",
.page_size_kb = 8,
.block_size = 16,
.max_flash_size_kb = 64,
.max_bank_size_kb = 64,
.has_dual_bank = false,
.fsize_addr = 0x08FFF80C,
.wps_group_size = 1,
.wps_mask = 0xFF,
.compute_flash_cr = stm32h7a_h7b_h7r_h7sxx_compute_flash_cr,
.get_flash_error_status = stm32h7rs_get_flash_status,
.flash_error = FLASH_ERROR_H7RS,
.write_code = stm32h7rs_flash_write_code,
.write_code_size = sizeof(stm32h7rs_flash_write_code),
},
};
@@ -302,10 +374,16 @@ static int stm32h7_get_flash_status(struct flash_bank *bank, uint32_t *status)
return stm32h7_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, status);
}
static int stm32h7rs_get_flash_status(struct flash_bank *bank, uint32_t *status)
{
return stm32h7_read_flash_reg_by_index(bank, STM32_FLASH_ISR_INDEX, status);
}
static int stm32h7_wait_flash_op_queue(struct flash_bank *bank, int timeout)
{
uint32_t status;
int retval;
struct stm32h7_flash_bank *stm32h7_info = bank->driver_priv;
/* wait for flash operations completion */
for (;;) {
@@ -324,16 +402,16 @@ static int stm32h7_wait_flash_op_queue(struct flash_bank *bank, int timeout)
}
if (status & FLASH_WRPERR) {
LOG_ERROR("wait_flash_op_queue, WRPERR detected");
LOG_ERROR("wait_flash_op_queue, write protection error");
retval = ERROR_FAIL;
}
/* Clear error + EOP flags but report errors */
if (status & FLASH_ERROR) {
if (status & stm32h7_info->part_info->flash_error) {
if (retval == ERROR_OK)
retval = ERROR_FAIL;
/* If this operation fails, we ignore it and report the original retval */
stm32h7_write_flash_reg_by_index(bank, STM32_FLASH_CCR_INDEX, status);
stm32h7_write_flash_reg_by_index(bank, STM32_FLASH_ICR_CCR_INDEX, status);
}
return retval;
}
@@ -611,24 +689,21 @@ static int stm32h7_write_block(struct flash_bank *bank, const uint8_t *buffer,
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
static const uint8_t stm32h7_flash_write_code[] = {
#include "../../../contrib/loaders/flash/stm32/stm32h7x.inc"
};
if (target_alloc_working_area(target, sizeof(stm32h7_flash_write_code),
if (target_alloc_working_area(target, stm32h7_info->part_info->write_code_size,
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
retval = target_write_buffer(target, write_algorithm->address,
sizeof(stm32h7_flash_write_code),
stm32h7_flash_write_code);
stm32h7_info->part_info->write_code_size,
stm32h7_info->part_info->write_code);
if (retval != ERROR_OK) {
target_free_working_area(target, write_algorithm);
return retval;
}
/* memory buffer */
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
data_size /= 2;
@@ -680,10 +755,10 @@ static int stm32h7_write_block(struct flash_bank *bank, const uint8_t *buffer,
if (flash_sr & FLASH_WRPERR)
LOG_ERROR("flash memory write protected");
if ((flash_sr & FLASH_ERROR) != 0) {
LOG_ERROR("flash write failed, FLASH_SR = 0x%08" PRIx32, flash_sr);
if ((flash_sr & stm32h7_info->part_info->flash_error) != 0) {
LOG_ERROR("flash write failed, status = 0x%08" PRIx32, flash_sr);
/* Clear error + EOP flags but report errors */
stm32h7_write_flash_reg_by_index(bank, STM32_FLASH_CCR_INDEX, flash_sr);
stm32h7_write_flash_reg_by_index(bank, STM32_FLASH_ICR_CCR_INDEX, flash_sr);
retval = ERROR_FAIL;
}
}
@@ -810,8 +885,11 @@ static int stm32h7_probe(struct flash_bank *bank)
LOG_DEBUG("device id = 0x%08" PRIx32, stm32h7_info->idcode);
device_id = stm32h7_info->idcode & 0xfff;
stm32h7_info->flash_regs = stm32h7_flash_regs;
if (device_id == DEVID_STM32H7R_H7SXX) {
stm32h7_info->flash_regs = stm32h7rs_flash_regs;
} else {
stm32h7_info->flash_regs = stm32h7_flash_regs;
}
for (unsigned int n = 0; n < ARRAY_SIZE(stm32h7_parts); n++) {
if (device_id == stm32h7_parts[n].id)
@@ -872,6 +950,7 @@ static int stm32h7_probe(struct flash_bank *bank)
flash_size_in_kb /= 2;
break;
case DEVID_STM32H72_H73XX:
case DEVID_STM32H7R_H7SXX:
break;
default:
LOG_ERROR("unsupported device");