#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
-#include <target/armv7m.h>
+#include <target/cortex_m.h>
/* Erase time can be as high as 1000ms, 10x this and it's toast... */
#define FLASH_REG_BASE_B0 0x52002000
#define FLASH_REG_BASE_B1 0x52002100
+/* Supported device IDs */
+#define DEVID_STM32H74_H75XX 0x450
+#define DEVID_STM32H7A_H7BXX 0x480
+#define DEVID_STM32H72_H73XX 0x483
+
struct stm32h7x_rev {
uint16_t rev;
const char *str;
OPT_RDP_L2 = 0xcc
};
-static const struct stm32h7x_rev stm32_450_revs[] = {
+static const struct stm32h7x_rev stm32h74_h75xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2001, "X" }, { 0x2003, "V" },
};
-static const struct stm32h7x_rev stm32_480_revs[] = {
+static const struct stm32h7x_rev stm32h7a_h7bxx_revs[] = {
{ 0x1000, "A"},
};
-static const struct stm32h7x_rev stm32_483_revs[] = {
+static const struct stm32h7x_rev stm32h72_h73xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" },
};
-static uint32_t stm32x_compute_flash_cr_450_483(uint32_t cmd, int snb)
+static uint32_t stm32h74_h75xx_compute_flash_cr(uint32_t cmd, int snb)
{
return cmd | (snb << 8);
}
-static uint32_t stm32x_compute_flash_cr_480(uint32_t cmd, int snb)
+static uint32_t stm32h7a_h7bxx_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);
static const struct stm32h7x_part_info stm32h7x_parts[] = {
{
- .id = 0x450,
- .revs = stm32_450_revs,
- .num_revs = ARRAY_SIZE(stm32_450_revs),
+ .id = DEVID_STM32H74_H75XX,
+ .revs = stm32h74_h75xx_revs,
+ .num_revs = ARRAY_SIZE(stm32h74_h75xx_revs),
.device_str = "STM32H74x/75x",
.page_size_kb = 128,
.block_size = 32,
.fsize_addr = 0x1FF1E880,
.wps_group_size = 1,
.wps_mask = 0xFF,
- .compute_flash_cr = stm32x_compute_flash_cr_450_483,
+ .compute_flash_cr = stm32h74_h75xx_compute_flash_cr,
},
{
- .id = 0x480,
- .revs = stm32_480_revs,
- .num_revs = ARRAY_SIZE(stm32_480_revs),
+ .id = DEVID_STM32H7A_H7BXX,
+ .revs = stm32h7a_h7bxx_revs,
+ .num_revs = ARRAY_SIZE(stm32h7a_h7bxx_revs),
.device_str = "STM32H7Ax/7Bx",
.page_size_kb = 8,
.block_size = 16,
.fsize_addr = 0x08FFF80C,
.wps_group_size = 4,
.wps_mask = 0xFFFFFFFF,
- .compute_flash_cr = stm32x_compute_flash_cr_480,
+ .compute_flash_cr = stm32h7a_h7bxx_compute_flash_cr,
},
{
- .id = 0x483,
- .revs = stm32_483_revs,
- .num_revs = ARRAY_SIZE(stm32_483_revs),
+ .id = DEVID_STM32H72_H73XX,
+ .revs = stm32h72_h73xx_revs,
+ .num_revs = ARRAY_SIZE(stm32h72_h73xx_revs),
.device_str = "STM32H72x/73x",
.page_size_kb = 128,
.block_size = 32,
.fsize_addr = 0x1FF1E880,
.wps_group_size = 1,
.wps_mask = 0xFF,
- .compute_flash_cr = stm32x_compute_flash_cr_450_483,
+ .compute_flash_cr = stm32h74_h75xx_compute_flash_cr,
},
};
LOG_ERROR("erase time-out or operation error sector %u", i);
goto flash_lock;
}
- bank->sectors[i].is_erased = 1;
}
flash_lock:
stm32x_info->probed = false;
stm32x_info->part_info = NULL;
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
int retval = stm32x_read_id_code(bank, &stm32x_info->idcode);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("flash_regs_base: 0x%" PRIx32, stm32x_info->flash_regs_base);
/* get flash size from target */
- retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb);
+ /* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */
+ retval = ERROR_FAIL;
+ if (device_id == DEVID_STM32H74_H75XX
+ && cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO)
+ LOG_WARNING("%s cannot read the flash size register", target_name(target));
+ else
+ retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb);
+
if (retval != ERROR_OK) {
/* read error when device has invalid value, set max flash size */
flash_size_in_kb = stm32x_info->part_info->max_flash_size_kb;
+ LOG_INFO("assuming %" PRIu16 "k flash", flash_size_in_kb);
} else
- LOG_INFO("flash size probed value %" PRIu16, flash_size_in_kb);
-
-
-
+ LOG_INFO("flash size probed value %" PRIu16 "k", flash_size_in_kb);
/* setup bank size */
const uint32_t bank1_base = FLASH_BANK0_ADDRESS;
bool has_dual_bank = stm32x_info->part_info->has_dual_bank;
switch (device_id) {
- case 0x450:
- case 0x480:
+ case DEVID_STM32H74_H75XX:
+ case DEVID_STM32H7A_H7BXX:
/* For STM32H74x/75x and STM32H7Ax/Bx
* - STM32H7xxxI devices contains dual bank, 1 Mbyte each
* - STM32H7xxxG devices contains dual bank, 512 Kbyte each
/* flash size is 2M or 1M */
flash_size_in_kb /= 2;
break;
- case 0x483:
+ case DEVID_STM32H72_H73XX:
break;
default:
LOG_ERROR("unsupported device");
bank->sectors = alloc_block_array(0, stm32x_info->part_info->page_size_kb * 1024,
bank->num_sectors);
- if (bank->sectors == NULL) {
+ if (!bank->sectors) {
LOG_ERROR("failed to allocate bank sectors");
return ERROR_FAIL;
}
bank->prot_blocks = alloc_block_array(0, stm32x_info->part_info->page_size_kb * wpsn * 1024,
bank->num_prot_blocks);
- if (bank->prot_blocks == NULL) {
+ if (!bank->prot_blocks) {
LOG_ERROR("failed to allocate bank prot_block");
return ERROR_FAIL;
}
if (rev_id == info->revs[i].rev)
rev_str = info->revs[i].str;
- if (rev_str != NULL) {
+ if (rev_str) {
command_print_sameline(cmd, "%s - Rev: %s",
stm32x_info->part_info->device_str, rev_str);
} else {
return retval;
retval = stm32x_mass_erase(bank);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (unsigned int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
+ if (retval == ERROR_OK)
command_print(CMD, "stm32h7x mass erase complete");
- } else {
+ else
command_print(CMD, "stm32h7x mass erase failed");
- }
return retval;
}
return stm32x_modify_option(bank, reg_offset, value, mask);
}
-static const struct command_registration stm32x_exec_command_handlers[] = {
+static const struct command_registration stm32h7x_exec_command_handlers[] = {
{
.name = "lock",
.handler = stm32x_handle_lock_command,
COMMAND_REGISTRATION_DONE
};
-static const struct command_registration stm32x_command_handlers[] = {
+static const struct command_registration stm32h7x_command_handlers[] = {
{
.name = "stm32h7x",
.mode = COMMAND_ANY,
.help = "stm32h7x flash command group",
.usage = "",
- .chain = stm32x_exec_command_handlers,
+ .chain = stm32h7x_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
const struct flash_driver stm32h7x_flash = {
.name = "stm32h7x",
- .commands = stm32x_command_handlers,
+ .commands = stm32h7x_command_handlers,
.flash_bank_command = stm32x_flash_bank_command,
.erase = stm32x_erase,
.protect = stm32x_protect,