Porównaj commity

...

17 Commity

Autor SHA1 Wiadomość Data
nightwalker-87 7dcb1302d8 Fixes for STM32H7 & STM32G0B1 devices
- Fixed flash lock for STM32H7 dual bank devices
- Fixed flash erase issue on STM32G0B1 (Closes #1321)
2023-11-24 18:21:31 +01:00
nightwalker-87 509d60efe4
Merge pull request #1355 from marcelobarrosufu/develop
Fixed support for STM32U5 chips.
2023-11-23 20:16:22 +01:00
nightwalker-87 ed558c9ac7
Merge branch 'develop' into develop 2023-11-23 20:12:57 +01:00
nightwalker-87 e212349460
Merge pull request #1354 from rcubee/c0
Added support for STM32C0x1.
2023-11-23 20:10:31 +01:00
nightwalker-87 fb141d40d7
Merge pull request #1353 from mirkomatonti/mirko-otp_read_write
First Implementation of the OTP Read/Write function
2023-11-23 20:08:15 +01:00
Mirko Matonti 033007fd27 pr adjustment 2023-11-23 17:46:09 +00:00
rcubee cf840b5f3d fixed formatting 2023-11-14 17:38:12 +01:00
rcubee 3fd7140524 forgot to include these 2023-11-14 17:30:00 +01:00
Marcelo Barros de Almeida 5df53adb2c Missing swo and dualback flags in U6 chip models 2023-11-14 07:39:56 -03:00
Marcelo Barros de Almeida e286f243ef Fixing support for U5 chips (original U5x5.chip was not handling all U5 chips ) 2023-11-14 00:27:19 -03:00
rcubee 4a7b8cdb26 removed the patch file itself 2023-11-11 18:19:04 +01:00
rcubee eb083ae753 removed redundant lines 2023-11-11 17:40:28 +01:00
rcubee 99a2be4d28 initial commit 2023-11-11 17:27:05 +01:00
Mirko e122764f21 forgot to include this 2023-11-08 22:58:05 +00:00
Mirko 3cb15d7da2 final 2023-11-08 15:14:19 +00:00
Mirko b1d99a2fc2 cleaning ident 2023-11-08 15:04:10 +00:00
Mirko 2d21188cdc first commit 2023-11-08 14:51:19 +00:00
22 zmienionych plików z 427 dodań i 72 usunięć

Wyświetl plik

@ -0,0 +1,14 @@
# Chip-ID file for STM32C011xx device
#
dev_type STM32C011xx
ref_manual_id 0490
chip_id 0x453 // STM32_CHIPID_C011xx
flash_type C0
flash_size_reg 0x1fff75a0
flash_pagesize 0x800 // 2 KB
sram_size 0x1800 // 6 KB
bootrom_base 0x1fff0000
bootrom_size 0x1800 // 6 KB
option_base 0x1fff7800 // STM32_C0_OPTION_BYTES_BASE
option_size 0x80 // 128 B
flags none

Wyświetl plik

@ -0,0 +1,14 @@
# Chip-ID file for STM32C031xx device
#
dev_type STM32C031xx
ref_manual_id 0490
chip_id 0x453 // STM32_CHIPID_C031xx
flash_type C0
flash_size_reg 0x1fff75a0
flash_pagesize 0x800 // 2 KB
sram_size 0x3000 // 12 KB
bootrom_base 0x1fff0000
bootrom_size 0x1800 // 6 KB
option_base 0x1fff7800 // STM32_C0_OPTION_BYTES_BASE
option_size 0x80 // 128 B
flags none

Wyświetl plik

@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB
option_base 0x0
option_size 0x0
flags swo
otp_base 0x1fff7000
otp_size 0x400 // 1 KB

Wyświetl plik

@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB
option_base 0x1fff7800 // STM32_L4_OPTION_BYTES_BASE
option_size 0x4 // 4 B
flags swo
otp_base 0x1fff7000
otp_size 0x400 // 1 KB

Wyświetl plik

@ -0,0 +1,14 @@
# Chip-ID file for STM32U535 / STM32U545 device
#
dev_type STM32U535_U545
ref_manual_id 0456
chip_id 0x455 // STM32U535/545
flash_type L5_U5_H5
flash_size_reg 0x0bfa07a0
flash_pagesize 0x2000 // 8 KB
sram_size 0x44800 // 274 KB
bootrom_base 0x0bf90000
bootrom_size 0x8000 // 32 KB
option_base 0x0
option_size 0x0
flags swo dualbank

Wyświetl plik

@ -0,0 +1,14 @@
# Chip-ID file for STM32U5Fx / STM32U5Gx device
#
dev_type STM32U5Fx_U5Gx
ref_manual_id 0456
chip_id 0x476 // STM32U5Fx5/5Gx
flash_type L5_U5_H5
flash_size_reg 0x0bfa07a0
flash_pagesize 0x2000 // 8 KB
sram_size 0x2f4800 // 3026 KB
bootrom_base 0x0bf90000
bootrom_size 0x8000 // 32 KB
option_base 0x0
option_size 0x0
flags swo dualbank

Wyświetl plik

@ -1,8 +1,8 @@
# Chip-ID file for STM32U5x5 device
# Chip-ID file for STM32U575 / STM32U585 device
#
dev_type STM32U5x5
dev_type STM32U575_U585
ref_manual_id 0456
chip_id 0x482 // STM32_CHIPID_U5x5
chip_id 0x482 // STM32U575/585
flash_type L5_U5_H5
flash_size_reg 0x0bfa07a0
flash_pagesize 0x2000 // 8 KB
@ -11,4 +11,4 @@ bootrom_base 0x0bf90000
bootrom_size 0x10000 // 64 KB
option_base 0x0
option_size 0x0
flags none
flags swo dualbank

Wyświetl plik

@ -0,0 +1,14 @@
# Chip-ID file for STM32U59x / STM32U5Ax device
#
dev_type STM32U59x_U5Ax
ref_manual_id 0456
chip_id 0x481 // STM32U59x/5Ax
flash_type L5_U5_H5
flash_size_reg 0x0bfa07a0
flash_pagesize 0x2000 // 8 KB
sram_size 0x274800 // 2514 KB
bootrom_base 0x0bf90000
bootrom_size 0x8000 // 32 KB
option_base 0x0
option_size 0x0
flags swo dualbank

Wyświetl plik

@ -6,6 +6,7 @@ More commonly these are:
| Product-Family | ARM Cortex Core | Product Line |
| -------------- | --------------- | ---------------------------------------------------------- |
| STM32F0 | M0 | |
| STM32C0 | M0+ | |
| STM32G0 | M0+ | |
| STM32L0 | M0+ | |
| STM32F10**0** | M3 | Value line |

Wyświetl plik

@ -232,6 +232,9 @@ struct _stlink {
uint32_t chip_flags; // stlink_chipid_params.flags, set by stlink_load_device_params(), values: CHIP_F_xxx
uint32_t max_trace_freq; // set by stlink_open_usb()
uint32_t otp_base;
uint32_t otp_size;
};
/* Functions defined in common.c */

Wyświetl plik

@ -51,17 +51,18 @@ enum stm32_core_id {
/* STM32 flash types */
enum stm32_flash_type {
STM32_FLASH_TYPE_UNKNOWN = 0,
STM32_FLASH_TYPE_F0_F1_F3 = 1,
STM32_FLASH_TYPE_F1_XL = 2,
STM32_FLASH_TYPE_F2_F4 = 3,
STM32_FLASH_TYPE_F7 = 4,
STM32_FLASH_TYPE_G0 = 5,
STM32_FLASH_TYPE_G4 = 6,
STM32_FLASH_TYPE_H7 = 7,
STM32_FLASH_TYPE_L0_L1 = 8,
STM32_FLASH_TYPE_L4 = 9,
STM32_FLASH_TYPE_L5_U5_H5 = 10,
STM32_FLASH_TYPE_WB_WL = 11,
STM32_FLASH_TYPE_C0 = 1,
STM32_FLASH_TYPE_F0_F1_F3 = 2,
STM32_FLASH_TYPE_F1_XL = 3,
STM32_FLASH_TYPE_F2_F4 = 4,
STM32_FLASH_TYPE_F7 = 5,
STM32_FLASH_TYPE_G0 = 6,
STM32_FLASH_TYPE_G4 = 7,
STM32_FLASH_TYPE_H7 = 8,
STM32_FLASH_TYPE_L0_L1 = 9,
STM32_FLASH_TYPE_L4 = 10,
STM32_FLASH_TYPE_L5_U5_H5 = 11,
STM32_FLASH_TYPE_WB_WL = 12,
};
/* STM32 chip-ids */
@ -102,6 +103,7 @@ enum stm32_chipids {
STM32_CHIPID_F0 = 0x440,
STM32_CHIPID_F412 = 0x441,
STM32_CHIPID_F09x = 0x442,
STM32_CHIPID_C011xx = 0x443, /* RM0490 (revision 3), section 26.10.1 "DBG device ID code register (DBG_IDCODE)" */
STM32_CHIPID_F0xx_SMALL = 0x444,
STM32_CHIPID_F04 = 0x445,
STM32_CHIPID_F303_HD = 0x446, /* high density */
@ -111,6 +113,8 @@ enum stm32_chipids {
STM32_CHIPID_H74xxx = 0x450, /* RM0433, p.3189 */
STM32_CHIPID_F76xxx = 0x451,
STM32_CHIPID_F72xxx = 0x452, /* Nucleo F722ZE board */
STM32_CHIPID_C031xx = 0x453, /* RM0490 (revision 3), section 26.10.1 "DBG device ID code register (DBG_IDCODE)" */
STM32_CHIPID_U535_U545 = 0x455, /* RM0456, p.3604 */
STM32_CHIPID_G0_CAT4 = 0x456, /* G051/G061 */
STM32_CHIPID_L0_CAT1 = 0x457,
STM32_CHIPID_F410 = 0x458,
@ -126,9 +130,11 @@ enum stm32_chipids {
STM32_CHIPID_L4Rx = 0x470, /* RM0432, p.2247, found on the STM32L4R9I-DISCO board */
STM32_CHIPID_L4PX = 0x471, /* RM0432, p.2247 */
STM32_CHIPID_L5x2xx = 0x472, /* RM0438, p.2157 */
STM32_CHIPID_U5Fx_U5Gx = 0x476, /* RM0456, p.3604 */
STM32_CHIPID_G4_CAT4 = 0x479,
STM32_CHIPID_H7Ax = 0x480, /* RM0455, p.2863 */
STM32_CHIPID_U5x5 = 0x482, /* RM0456, p.2991 */
STM32_CHIPID_U59x_U5Ax = 0x481, /* RM0456, p.3604 */
STM32_CHIPID_U575_U585 = 0x482, /* RM0456, p.3604 */
STM32_CHIPID_H72x = 0x483, /* RM0468, p.3199 */
STM32_CHIPID_H5xx = 0x484, /* RM0481, p.3085 */
STM32_CHIPID_WB55 = 0x495,
@ -136,6 +142,8 @@ enum stm32_chipids {
};
/* Constant STM32 option bytes base memory address */
#define STM32_C0_OPTION_BYTES_BASE ((uint32_t)0x1fff7800)
#define STM32_F4_OPTION_BYTES_BASE ((uint32_t)0x40023c14)
#define STM32_H7_OPTION_BYTES_BASE ((uint32_t)0x5200201c)
@ -189,6 +197,9 @@ enum stm32_chipids {
#define STM32WB_DBGMCU_APB1FZR1_WWDG_STOP 11
#define STM32WB_DBGMCU_APB1FZR1_IWDG_STOP 12
#define STM32C0_RCC_AHBENR 0x40021038 // RM0490 (revision 3), section 5.4.25 "RCC register map"
#define STM32C0_RCC_DMAEN 0x00000001 // DMAEN // RM0490 (revision 3), section 5.4.25 "RCC register map"
#define STM32F1_RCC_AHBENR 0x40021014
#define STM32F1_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN

Wyświetl plik

@ -58,6 +58,30 @@
#define FLASH_OBR_OFF ((uint32_t)0x1c)
#define FLASH_WRPR_OFF ((uint32_t)0x20)
// == STM32C0 == (RM0490)
// C0 Flash registers
#define FLASH_C0_REGS_ADDR ((uint32_t)0x40022000)
#define FLASH_C0_KEYR (FLASH_C0_REGS_ADDR + 0x08)
#define FLASH_C0_OPT_KEYR (FLASH_C0_REGS_ADDR + 0x0C)
#define FLASH_C0_SR (FLASH_C0_REGS_ADDR + 0x10)
#define FLASH_C0_CR (FLASH_C0_REGS_ADDR + 0x14)
#define FLASH_C0_OPTR (FLASH_C0_REGS_ADDR + 0x20)
// C0 Flash control register
#define FLASH_C0_CR_PNB 3
#define FLASH_C0_CR_STRT 16
#define FLASH_C0_CR_OPTSTRT 17
#define FLASH_C0_CR_OBL_LAUNCH 27
#define FLASH_C0_CR_OPTLOCK 30
#define FLASH_C0_CR_LOCK 31
// C0 Flash status register
#define FLASH_C0_SR_ERROR_MASK 0xC3F8 // [15:14], [9:3]
#define FLASH_C0_SR_PROGERR 3
#define FLASH_C0_SR_WRPERR 4
#define FLASH_C0_SR_PGAERR 5
#define FLASH_C0_SR_BSY 16
// == STM32F0 ==
#define FLASH_F0_OPTKEY1 0x45670123
#define FLASH_F0_OPTKEY2 0xcdef89ab

Wyświetl plik

@ -61,6 +61,8 @@ static void usage(void) {
puts("example write option control register1 byte: ./st-flash --area=optcr write 0xXXXXXXXX");
puts("example read option control register1 byte: ./st-flash --area=optcr1 read");
puts("example write option control register1 byte: ./st-flash --area=optcr1 write 0xXXXXXXXX");
puts("example read OTP area: ./st-flash --area=otp read [path]");
puts("example write OTP area: ./st-flash --area=otp write [path] 0xXXXXXXXX");
}
int32_t main(int32_t ac, char** av) {
@ -180,6 +182,18 @@ int32_t main(int32_t ac, char** av) {
DLOG("@@@@ Write %d (%0#10x) to option bytes boot address\n", o.val, o.val);
err = stlink_write_option_bytes_boot_add32(sl, o.val);
} else if (o.area == FLASH_OTP) {
if(sl->otp_base == 0) {
err = -1;
printf("OTP Write NOT implemented\n");
goto on_error;
}
err = stlink_fwrite_flash(sl, o.filename, o.addr);
if (err == -1) {
printf("stlink_fwrite_flash() == -1\n");
goto on_error;
}
} else {
err = -1;
printf("Unknown memory region\n");
@ -284,6 +298,17 @@ int32_t main(int32_t ac, char** av) {
} else {
printf("%08x\n",option_byte);
}
} else if (o.area == FLASH_OTP) {
if(sl->otp_base == 0) {
err = -1;
printf("OTP Read NOT implemented\n");
goto on_error;
}
err = stlink_fread(sl, o.filename, 0, sl->otp_base, sl->otp_size);
if (err == -1) {
printf("could not read OTP area (%d)\n", err);
goto on_error;
}
}
}

Wyświetl plik

@ -288,8 +288,7 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) {
break;
} else if (o->area == FLASH_OTP) {
return bad_arg("TODO: otp not implemented yet");
if (ac > 1) { return invalid_args("otp read: [path]"); }
if (ac > 1 || ac ==0 ) { return invalid_args("otp read: [path]"); }
if (ac > 0) { o->filename = av[0]; }
break;
} else if (o->area == FLASH_OPTION_BYTES) {

Wyświetl plik

@ -66,7 +66,7 @@ uint32_t calculate_L4_page(stlink_t *sl, uint32_t flashaddr) {
if (sl->chip_id == STM32_CHIPID_L4 ||
sl->chip_id == STM32_CHIPID_L496x_L4A6x ||
sl->chip_id == STM32_CHIPID_L4Rx) {
// this chip use dual banked flash
// these chips use dual bank flash
if (flashopt & (uint32_t)(1lu << FLASH_L4_OPTR_DUALBANK)) {
uint32_t banksize = sl->flash_size / 2;

Wyświetl plik

@ -34,6 +34,8 @@ void dump_a_chip(struct stlink_chipid_params *dev) {
DLOG("option_base 0x%x\n", dev->option_base);
DLOG("option_size 0x%x\n", dev->option_size);
DLOG("flags %d\n\n", dev->flags);
DLOG("otp_base %d\n\n", dev->otp_base);
DLOG("otp_size %d\n\n", dev->otp_size);
}
struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chip_id) {
@ -97,7 +99,9 @@ void process_chipfile(char *fname) {
buf[strlen(buf) - 1] = 0; // chomp newline
sscanf(buf, "%*s %n", &nc);
// Match human readable flash_type with enum stm32_flash_type { }.
if (strcmp(value, "F0_F1_F3") == 0) {
if(strcmp(value, "C0") == 0) {
ts->flash_type = STM32_FLASH_TYPE_C0;
} else if (strcmp(value, "F0_F1_F3") == 0) {
ts->flash_type = STM32_FLASH_TYPE_F0_F1_F3;
} else if (strcmp(value, "F1_XL") == 0) {
ts->flash_type = STM32_FLASH_TYPE_F1_XL;
@ -182,6 +186,18 @@ void process_chipfile(char *fname) {
}
sscanf(value, "%x", &ts->flags);
} else if (strcmp(word, "otp_base") == 0) {
buf[strlen(buf) - 1] = 0; // chomp newline
sscanf(buf, "%*s %n", &nc);
if (sscanf(value, "%i", &ts->otp_base) < 1) {
fprintf(stderr, "Failed to parse option size\n");
}
} else if (strcmp(word, "otp_size") == 0) {
buf[strlen(buf) - 1] = 0; // chomp newline
sscanf(buf, "%*s %n", &nc);
if (sscanf(value, "%i", &ts->otp_size) < 1) {
fprintf(stderr, "Failed to parse option size\n");
}
} else {
fprintf(stderr, "Unknown keyword in %s: %s\n", fname, word);
}

Wyświetl plik

@ -21,6 +21,8 @@ struct stlink_chipid_params {
uint32_t option_base;
uint32_t option_size;
uint32_t flags;
uint32_t otp_base;
uint32_t otp_size;
struct stlink_chipid_params *next;
};

Wyświetl plik

@ -290,6 +290,8 @@ int32_t stlink_load_device_params(stlink_t *sl) {
sl->option_base = params->option_base;
sl->option_size = params->option_size;
sl->chip_flags = params->flags;
sl->otp_base = params->otp_base;
sl->otp_size = params->otp_size;
// medium and low devices have the same chipid. ram size depends on flash
// size. STM32F100xx datasheet Doc ID 16455 Table 2

Wyświetl plik

@ -46,7 +46,9 @@ uint32_t get_stm32l0_flash_base(stlink_t *sl) {
uint32_t read_flash_cr(stlink_t *sl, uint32_t bank) {
uint32_t reg, res;
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
reg = FLASH_F4_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
reg = FLASH_F7_CR;
@ -77,7 +79,10 @@ void lock_flash(stlink_t *sl) {
uint32_t cr_lock_shift = 0, cr_reg = 0, n = 0, cr2_reg = 0;
uint32_t cr_mask = 0xffffffffu;
if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_lock_shift = FLASH_C0_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
cr_reg = FLASH_CR;
cr_lock_shift = FLASH_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
@ -96,6 +101,11 @@ void lock_flash(stlink_t *sl) {
cr_lock_shift = FLASH_Gx_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_H7) {
cr_reg = FLASH_H7_CR1;
if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) {
cr2_reg = FLASH_H7_CR2;
}
cr_lock_shift = FLASH_H7_CR_LOCK;
cr_mask = ~(1u << FLASH_H7_CR_SER);
} else if (sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
cr_reg = get_stm32l0_flash_base(sl) + FLASH_PECR_OFF;
cr_lock_shift = FLASH_L0_PELOCK;
@ -108,11 +118,6 @@ void lock_flash(stlink_t *sl) {
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL) {
cr_reg = FLASH_WB_CR;
cr_lock_shift = FLASH_WB_CR_LOCK;
if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) {
cr2_reg = FLASH_H7_CR2;
}
cr_lock_shift = FLASH_H7_CR_LOCK;
cr_mask = ~(1u << FLASH_H7_CR_SER);
} else {
ELOG("unsupported flash method, abort\n");
return;
@ -132,8 +137,10 @@ void lock_flash(stlink_t *sl) {
static inline int32_t write_flash_sr(stlink_t *sl, uint32_t bank, uint32_t val) {
uint32_t sr_reg;
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_reg = FLASH_C0_SR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_reg = FLASH_F4_SR;
@ -162,6 +169,9 @@ static inline int32_t write_flash_sr(stlink_t *sl, uint32_t bank, uint32_t val)
void clear_flash_error(stlink_t *sl) {
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
write_flash_sr(sl, BANK_1, FLASH_C0_SR_ERROR_MASK);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
write_flash_sr(sl, BANK_1, FLASH_SR_ERROR_MASK);
break;
@ -205,8 +215,10 @@ void clear_flash_error(stlink_t *sl) {
uint32_t read_flash_sr(stlink_t *sl, uint32_t bank) {
uint32_t res, sr_reg;
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_reg = FLASH_C0_SR;
} else if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_reg = FLASH_F4_SR;
@ -238,9 +250,11 @@ uint32_t is_flash_busy(stlink_t *sl) {
uint32_t sr_busy_shift;
uint32_t res;
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL) ||
(sl->flash_type == STM32_FLASH_TYPE_L0_L1)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_busy_shift = FLASH_C0_SR_BSY;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL ||
sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
sr_busy_shift = FLASH_SR_BSY;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_busy_shift = FLASH_F4_SR_BSY;
@ -286,6 +300,12 @@ int32_t check_flash_error(stlink_t *sl) {
WRPERR = PROGERR = PGAERR = 0;
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
res = read_flash_sr(sl, BANK_1) & FLASH_C0_SR_ERROR_MASK;
WRPERR = (1 << FLASH_C0_SR_WRPERR);
PROGERR = (1 << FLASH_C0_SR_PROGERR);
PGAERR = (1 << FLASH_C0_SR_PGAERR);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
res = read_flash_sr(sl, BANK_1) & FLASH_SR_ERROR_MASK;
@ -382,8 +402,11 @@ static inline uint32_t is_flash_locked(stlink_t *sl) {
uint32_t cr_reg;
uint32_t n;
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_lock_shift = FLASH_C0_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
cr_reg = FLASH_CR;
cr_lock_shift = FLASH_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
@ -429,7 +452,9 @@ static void unlock_flash(stlink_t *sl) {
* definitive lock of the FPEC block until next reset.
*/
if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
key_reg = FLASH_C0_KEYR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
key_reg = FLASH_KEYR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
key_reg = FLASH_KEYR;
@ -497,6 +522,10 @@ int32_t lock_flash_option(stlink_t *sl) {
int32_t active_bit_level = 1;
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optcr_reg = FLASH_C0_CR;
optlock_shift = FLASH_C0_CR_OPTLOCK;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optcr_reg = FLASH_CR;
@ -574,6 +603,10 @@ static bool is_flash_option_locked(stlink_t *sl) {
uint32_t n;
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optcr_reg = FLASH_C0_CR;
optlock_shift = FLASH_C0_CR_OPTLOCK;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optcr_reg = FLASH_CR;
@ -633,6 +666,9 @@ static int32_t unlock_flash_option(stlink_t *sl) {
uint32_t optkey2 = FLASH_OPTKEY2;
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optkey_reg = FLASH_C0_OPT_KEYR;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optkey_reg = FLASH_OPTKEYR;
@ -726,7 +762,9 @@ void clear_flash_cr_pg(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg, n;
uint32_t bit = FLASH_CR_PG;
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
cr_reg = FLASH_F7_CR;
@ -802,8 +840,10 @@ static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n, uint32_t bank) {
static void set_flash_cr_per(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg, val;
if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
cr_reg = FLASH_Gx_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
cr_reg = FLASH_L5_NSCR;
@ -821,8 +861,10 @@ static void set_flash_cr_per(stlink_t *sl, uint32_t bank) {
static void clear_flash_cr_per(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg;
if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
cr_reg = FLASH_Gx_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
cr_reg = FLASH_L5_NSCR;
@ -855,7 +897,10 @@ static inline void write_flash_cr_bker_pnb(stlink_t *sl, uint32_t n) {
static void set_flash_cr_strt(stlink_t *sl, uint32_t bank) {
uint32_t val, cr_reg, cr_strt;
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_strt = 1 << FLASH_C0_CR_STRT;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
cr_strt = 1 << FLASH_F4_CR_STRT;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
@ -890,7 +935,11 @@ static void set_flash_cr_strt(stlink_t *sl, uint32_t bank) {
static void set_flash_cr_mer(stlink_t *sl, bool v, uint32_t bank) {
uint32_t val, cr_reg, cr_mer, cr_pg;
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_mer = 1 << FLASH_CR_MER;
cr_pg = 1 << FLASH_CR_PG;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
cr_mer = 1 << FLASH_CR_MER;
cr_pg = 1 << FLASH_CR_PG;
@ -965,11 +1014,7 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
unlock_flash_if(sl);
// select the page to erase
if ((sl->chip_id == STM32_CHIPID_L4) ||
(sl->chip_id == STM32_CHIPID_L43x_L44x) ||
(sl->chip_id == STM32_CHIPID_L45x_L46x) ||
(sl->chip_id == STM32_CHIPID_L496x_L4A6x) ||
(sl->chip_id == STM32_CHIPID_L4Rx)) {
if (sl->flash_type == STM32_FLASH_TYPE_L4) {
// calculate the actual bank+page from the address
uint32_t page = calculate_L4_page(sl, flashaddr);
@ -1062,7 +1107,8 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4 ||
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5 ||
sl->flash_type == STM32_FLASH_TYPE_WB_WL) {
sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
sl->flash_type == STM32_FLASH_TYPE_C0) {
uint32_t val;
unlock_flash_if(sl);
set_flash_cr_per(sl, BANK_1); // set the 'enable Flash erase' bit
@ -1071,21 +1117,23 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
if (sl->flash_type == STM32_FLASH_TYPE_G0) {
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
stlink_read_debug32(sl, FLASH_Gx_CR, &val);
// sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2.
val &= ~(0x3F << 3);
val |= ((flash_page & 0x3F) << 3) | (1 << FLASH_CR_PER);
// sec 3.7.5 - PNB[9:0] is offset by 3. PER is 0x2.
val &= ~(0x3FF << 3);
val |= ((flash_page & 0x3FF) << 3) | (1 << FLASH_CR_PER);
stlink_write_debug32(sl, FLASH_Gx_CR, val);
} else if (sl->flash_type == STM32_FLASH_TYPE_G4) {
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
stlink_read_debug32(sl, FLASH_Gx_CR, &val);
// sec 3.7.5 - PNB[6:0] is offset by 3. PER is 0x2.
val &= ~(0x7F << 3);
val |= ((flash_page & 0x7F) << 3) | (1 << FLASH_CR_PER);
// sec 3.7.5 - PNB[9:0] is offset by 3. PER is 0x2.
val &= ~(0x7FF << 3);
val |= ((flash_page & 0x7FF) << 3) | (1 << FLASH_CR_PER);
stlink_write_debug32(sl, FLASH_Gx_CR, val);
// STM32L5x2xx has two banks with 2k pages or single with 4k pages
// STM32H5xx, STM32U535, STM32U545, STM32U575 or STM32U585 have 2 banks with 8k pages
} else if (sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
uint32_t flash_page;
stlink_read_debug32(sl, FLASH_L5_NSCR, &val);
if (sl->flash_pgsz == 0x800 && (flashaddr - STM32_FLASH_BASE) >= sl->flash_size/2) {
if ((sl->flash_pgsz == 0x800 || sl->flash_pgsz == 0x2000) && (flashaddr - STM32_FLASH_BASE) >= sl->flash_size/2) {
flash_page = (flashaddr - STM32_FLASH_BASE - sl->flash_size/2) / sl->flash_pgsz;
// set bank 2 for erasure
val |= (1 << FLASH_L5_NSCR_NSBKER);
@ -1094,9 +1142,11 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
// set bank 1 for erasure
val &= ~(1 << FLASH_L5_NSCR_NSBKER);
}
// sec 6.9.9
val &= ~(0x7F << 3);
val |= ((flash_page & 0x7F) << 3) | (1 << FLASH_CR_PER);
// sec 7.9.9 for U5, 6.9.9 for L5 (for L7 we have 7 bits instead 8 bits for U5 but
// the bit position for 8th bit reserved.
// Maybe the best solution is to handle each one separately.
val &= ~(0xFF << 3);
val |= ((flash_page & 0xFF) << 3) | (1 << FLASH_CR_PER);
stlink_write_debug32(sl, FLASH_L5_NSCR, val);
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL) {
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
@ -1107,6 +1157,14 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
val |= ((flash_page & 0xFF) << 3);
stlink_write_debug32(sl, FLASH_WB_CR, val);
} else if (sl->flash_type == STM32_FLASH_TYPE_C0) {
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
stlink_read_debug32(sl, FLASH_C0_CR, &val);
val &= ~(0xF << FLASH_C0_CR_PNB);
val |= ((flash_page & 0xF) << FLASH_C0_CR_PNB);
stlink_write_debug32(sl, FLASH_C0_CR, val);
}
set_flash_cr_strt(sl, BANK_1); // set the 'start operation' bit
@ -1310,9 +1368,16 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) {
* If the file is identified to be all-empty and four-bytes aligned,
* still flash the whole file even if ignoring message is printed.
*/
err = stlink_write_flash(sl, addr, mf.base,
/* In case the address is within the OTP area we use a different flash method */
if(addr >= sl->otp_base && addr < sl->otp_base + sl->otp_size) {
err = stlink_write_otp(sl, addr, mf.base,
(num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty);
} else {
err = stlink_write_flash(sl, addr, mf.base,
(num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty,
num_empty == mf.len);
}
stlink_fwrite_finalize(sl, addr);
unmap_file(&mf);
return (err);
@ -1389,6 +1454,22 @@ int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uin
return 0;
}
// Check if an address and size are within the flash (otp area)
int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size) {
uint32_t logvar;
if (addr < sl->otp_base || addr >= (sl->otp_base + sl->otp_size)) {
logvar = sl->otp_base + sl->otp_size - 1;
ELOG("Invalid address, it should be within 0x%08x - 0x%08x\n", sl->otp_base, logvar);
return (-1);
}
if ((addr + size) >= (sl->otp_base + sl->otp_size)) {
logvar = sl->otp_base + sl->otp_size - addr;
ELOG("The size exceeds the size of the OTP Area (0x%08x bytes available)\n", logvar);
return (-1);
}
return 0;
}
// Check if an address is aligned with the beginning of a page
int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr) {
stm32_addr_t page = sl->flash_base;
@ -1408,6 +1489,7 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3
int32_t ret;
flash_loader_t fl;
ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr);
// check addr range is inside the flash
stlink_calculate_pagesize(sl, addr);
@ -1437,7 +1519,33 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3
if (eraseonly) {
return (0);
}
ret = stlink_flashloader_start(sl, &fl);
if (ret)
return ret;
ret = stlink_flashloader_write(sl, &fl, addr, base, len);
if (ret)
return ret;
ret = stlink_flashloader_stop(sl, &fl);
if (ret)
return ret;
return (stlink_verify_write_flash(sl, addr, base, len));
}
int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) {
int32_t ret;
flash_loader_t fl;
ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr);
// Check the address and size validity
if (stlink_check_address_range_validity_otp(sl, addr, len) < 0) {
return (-1);
}
// make sure we've loaded the context with the chip details
stlink_core_id(sl);
ret = stlink_flashloader_start(sl, &fl);
if (ret)
return ret;

Wyświetl plik

@ -44,8 +44,10 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr);
int32_t stlink_fcheck_flash(stlink_t *sl, const char *path, stm32_addr_t addr);
int32_t stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length);
int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uint32_t size);
int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size);
int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr);
int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len, uint8_t eraseonly);
int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len);
void stlink_fwrite_finalize(stlink_t *, stm32_addr_t);
#endif // COMMON_FLASH_H

Wyświetl plik

@ -491,12 +491,15 @@ static void set_flash_cr_pg(stlink_t *sl, uint32_t bank) {
x = read_flash_cr(sl, bank);
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
x |= (1 << FLASH_CR_PG);
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
x |= 1 << FLASH_CR_PG;
x |= (1 << FLASH_CR_PG);
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
cr_reg = FLASH_F7_CR;
x |= 1 << FLASH_CR_PG;
x |= (1 << FLASH_CR_PG);
} else if (sl->flash_type == STM32_FLASH_TYPE_L4) {
cr_reg = FLASH_L4_CR;
x &= ~FLASH_L4_CR_OPBITS;
@ -528,6 +531,10 @@ static void set_dma_state(stlink_t *sl, flash_loader_t *fl, int32_t bckpRstr) {
rcc = rcc_dma_mask = value = 0;
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
rcc = STM32C0_RCC_AHBENR;
rcc_dma_mask = STM32C0_RCC_DMAEN;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
rcc = STM32F1_RCC_AHBENR;
@ -639,8 +646,9 @@ int32_t stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl) {
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4 ||
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
ILOG("Starting Flash write for WB/G0/G4/L5/U5/H5\n");
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5 ||
sl->flash_type == STM32_FLASH_TYPE_C0) {
ILOG("Starting Flash write for WB/G0/G4/L5/U5/H5/C0\n");
unlock_flash_if(sl); // unlock flash if necessary
set_flash_cr_pg(sl, BANK_1); // set PG 'allow programming' bit
@ -720,6 +728,7 @@ int32_t stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl) {
int32_t stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, uint8_t *base, uint32_t len) {
uint32_t off;
if ((sl->flash_type == STM32_FLASH_TYPE_F2_F4) ||
(sl->flash_type == STM32_FLASH_TYPE_F7) ||
(sl->flash_type == STM32_FLASH_TYPE_L4)) {
@ -737,13 +746,14 @@ int32_t stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4 ||
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5 ||
sl->flash_type == STM32_FLASH_TYPE_C0) {
DLOG("Starting %3u page write\n", len / sl->flash_pgsz);
for (off = 0; off < len; off += sizeof(uint32_t)) {
uint32_t data;
if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) {
fprintf(stdout, "\r%3u/%3u pages written", (off / sl->flash_pgsz + 1), (len / sl->flash_pgsz));
fprintf(stdout, "\r%3u/%-3u pages written", (off / sl->flash_pgsz + 1), (len / sl->flash_pgsz));
fflush(stdout);
}
@ -782,7 +792,7 @@ int32_t stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t
uint32_t data;
if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) {
fprintf(stdout, "\r%3u/%3u pages written", (off / sl->flash_pgsz + 1), (len / sl->flash_pgsz));
fprintf(stdout, "\r%3u/%-3u pages written", (off / sl->flash_pgsz + 1), (len / sl->flash_pgsz));
fflush(stdout);
}
@ -819,7 +829,7 @@ int32_t stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t
if (sl->verbose >= 1) {
// show progress; writing procedure is slow and previous errors are
// misleading
fprintf(stdout, "\r%3u/%3u pages written", ++write_block_count,
fprintf(stdout, "\r%3u/%-3u pages written", ++write_block_count,
(len + sl->flash_pgsz - 1) / sl->flash_pgsz);
fflush(stdout);
}
@ -856,7 +866,8 @@ int32_t stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t
int32_t stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl) {
uint32_t dhcsr;
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
if ((sl->flash_type == STM32_FLASH_TYPE_C0) ||
(sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL) ||
(sl->flash_type == STM32_FLASH_TYPE_F2_F4) ||
(sl->flash_type == STM32_FLASH_TYPE_F7) ||

Wyświetl plik

@ -18,6 +18,73 @@
#include "md5.h"
#include "read_write.h"
/**
* Read option control register C0
* @param sl
* @param option_byte
* @return 0 on success, -ve on failure.
*/
static int32_t stlink_read_option_control_register_c0(stlink_t *sl, uint32_t *option_byte) {
return stlink_read_debug32(sl, FLASH_C0_OPTR, option_byte);
}
/**
* Read option bytes C0
* @param sl
* @param option_byte
* @return 0 on success, -ve on failure.
*/
static int32_t stlink_read_option_bytes_c0(stlink_t *sl, uint32_t *option_byte) {
return stlink_read_option_control_register_c0(sl, option_byte);
}
/**
* Write option control register C0
* @param sl
* @param option_cr
* @return 0 on success, -ve on failure.
*/
static int32_t stlink_write_option_control_register_c0(stlink_t *sl, uint32_t option_cr) {
int32_t ret = 0;
clear_flash_error(sl);
if ((ret = stlink_write_debug32(sl, FLASH_C0_OPTR, option_cr)))
return ret;
wait_flash_busy(sl);
uint32_t cr_reg = (1 << FLASH_C0_CR_OPTSTRT);
if ((ret = stlink_write_debug32(sl, FLASH_C0_CR, cr_reg)))
return ret;
wait_flash_busy(sl);
if ((ret = check_flash_error(sl)))
return ret;
// trigger the load of option bytes into option registers
cr_reg = (1 << FLASH_C0_CR_OBL_LAUNCH);
stlink_write_debug32(sl, FLASH_C0_CR, cr_reg);
return ret;
}
/**
* Write option bytes C0
* @param sl
* @param addr of the memory mapped option bytes
* @param base option bytes
* @param len of option bytes
* @return 0 on success, -ve on failure.
*/
static int32_t stlink_write_option_bytes_c0(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) {
(void)addr;
(void)len;
return stlink_write_option_control_register_c0(sl, *(uint32_t*)base);
}
/**
* Read option control register F0
* @param sl
@ -745,7 +812,6 @@ int32_t stlink_read_option_bytes_generic(stlink_t *sl, uint32_t *option_byte) {
return stlink_read_debug32(sl, sl->option_base, option_byte);
}
/**
* Write option bytes
* @param sl
@ -785,6 +851,9 @@ int32_t stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t *base
}
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
ret = stlink_write_option_bytes_c0(sl, addr, base, len);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
ret = stlink_write_option_bytes_f0(sl, addr, base, len);
@ -870,6 +939,8 @@ int32_t stlink_read_option_control_register32(stlink_t *sl, uint32_t *option_byt
}
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
return stlink_read_option_control_register_c0(sl, option_byte);
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
return stlink_read_option_control_register_f0(sl, option_byte);
@ -904,6 +975,9 @@ int32_t stlink_write_option_control_register32(stlink_t *sl, uint32_t option_cr)
}
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
ret = stlink_write_option_control_register_c0(sl, option_cr);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
ret = stlink_write_option_control_register_f0(sl, option_cr);
@ -1009,6 +1083,9 @@ int32_t stlink_read_option_bytes32(stlink_t *sl, uint32_t *option_byte) {
}
switch (sl->chip_id) {
case STM32_CHIPID_C011xx:
case STM32_CHIPID_C031xx:
return stlink_read_option_bytes_c0(sl, option_byte);
case STM32_CHIPID_F2:
return stlink_read_option_bytes_f2(sl, option_byte);
case STM32_CHIPID_F4: