Skip to content

Commit b8fd9ae

Browse files
tarek-bochkatitom-van
authored andcommitted
stm32l4x: add OTP support for STM32 G0/G4/L4/L4+/L5/WB/WL devices
this is a rework of #5320 started by Andreas then abandoned. same syntax as in stm32f2x driver: enable OTP for writing > stm32l4x otp 1 enable write to OTP > flash write_bank 1 foo.bin 0 > flash filld 0x1FFF7000 0xDeadBeafBaadF00d 1 read OTP > mdw 0x1FFF7000 4 disable OTP > stm32l4x otp 1 disable Change-Id: Id7d7c163b35d7a3f406dc200d7e2fc293b0675c2 Signed-off-by: Andreas Bolsch <[email protected]> Signed-off-by: Tarek BOCHKATI <[email protected]> Reviewed-on: http://openocd.zylin.com/5537 Tested-by: jenkins Reviewed-by: Tomas Vanek <[email protected]>
1 parent f13bb10 commit b8fd9ae

File tree

8 files changed

+182
-12
lines changed

8 files changed

+182
-12
lines changed

doc/openocd.texi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7179,6 +7179,17 @@ the chip identification register, and autoconfigures itself.
71797179
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
71807180
@end example
71817181

7182+
If you use OTP (One-Time Programmable) memory define it as a second bank
7183+
as per the following example.
7184+
@example
7185+
flash bank $_FLASHNAME stm32l4x 0x1FFF7000 0 0 0 $_TARGETNAME
7186+
@end example
7187+
7188+
@deffn Command {stm32l4x otp} num (@option{enable}|@option{disable}|@option{show})
7189+
Enables or disables OTP write commands for bank @var{num}.
7190+
The @var{num} parameter is a value shown by @command{flash banks}.
7191+
@end deffn
7192+
71827193
Note that some devices have been found that have a flash size register that contains
71837194
an invalid value, to workaround this issue you can override the probed value used by
71847195
the flash driver. However, specifying a wrong value might lead to a completely

src/flash/nor/stm32l4x.c

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ struct stm32l4_part_info {
171171
const uint32_t flash_regs_base;
172172
const uint32_t *default_flash_regs;
173173
const uint32_t fsize_addr;
174+
const uint32_t otp_base;
175+
const uint32_t otp_size;
174176
};
175177

176178
struct stm32l4_flash_bank {
@@ -183,6 +185,7 @@ struct stm32l4_flash_bank {
183185
uint32_t wrpxxr_mask;
184186
const struct stm32l4_part_info *part_info;
185187
const uint32_t *flash_regs;
188+
bool otp_enabled;
186189
};
187190

188191
/* human readable list of families this drivers supports (sorted alphabetically) */
@@ -263,6 +266,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
263266
.flash_regs_base = 0x40022000,
264267
.default_flash_regs = stm32l4_flash_regs,
265268
.fsize_addr = 0x1FFF75E0,
269+
.otp_base = 0x1FFF7000,
270+
.otp_size = 1024,
266271
},
267272
{
268273
.id = 0x435,
@@ -274,6 +279,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
274279
.flash_regs_base = 0x40022000,
275280
.default_flash_regs = stm32l4_flash_regs,
276281
.fsize_addr = 0x1FFF75E0,
282+
.otp_base = 0x1FFF7000,
283+
.otp_size = 1024,
277284
},
278285
{
279286
.id = 0x460,
@@ -285,6 +292,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
285292
.flash_regs_base = 0x40022000,
286293
.default_flash_regs = stm32l4_flash_regs,
287294
.fsize_addr = 0x1FFF75E0,
295+
.otp_base = 0x1FFF7000,
296+
.otp_size = 1024,
288297
},
289298
{
290299
.id = 0x461,
@@ -296,6 +305,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
296305
.flash_regs_base = 0x40022000,
297306
.default_flash_regs = stm32l4_flash_regs,
298307
.fsize_addr = 0x1FFF75E0,
308+
.otp_base = 0x1FFF7000,
309+
.otp_size = 1024,
299310
},
300311
{
301312
.id = 0x462,
@@ -307,6 +318,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
307318
.flash_regs_base = 0x40022000,
308319
.default_flash_regs = stm32l4_flash_regs,
309320
.fsize_addr = 0x1FFF75E0,
321+
.otp_base = 0x1FFF7000,
322+
.otp_size = 1024,
310323
},
311324
{
312325
.id = 0x464,
@@ -318,6 +331,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
318331
.flash_regs_base = 0x40022000,
319332
.default_flash_regs = stm32l4_flash_regs,
320333
.fsize_addr = 0x1FFF75E0,
334+
.otp_base = 0x1FFF7000,
335+
.otp_size = 1024,
321336
},
322337
{
323338
.id = 0x466,
@@ -329,6 +344,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
329344
.flash_regs_base = 0x40022000,
330345
.default_flash_regs = stm32l4_flash_regs,
331346
.fsize_addr = 0x1FFF75E0,
347+
.otp_base = 0x1FFF7000,
348+
.otp_size = 1024,
332349
},
333350
{
334351
.id = 0x468,
@@ -340,6 +357,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
340357
.flash_regs_base = 0x40022000,
341358
.default_flash_regs = stm32l4_flash_regs,
342359
.fsize_addr = 0x1FFF75E0,
360+
.otp_base = 0x1FFF7000,
361+
.otp_size = 1024,
343362
},
344363
{
345364
.id = 0x469,
@@ -351,6 +370,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
351370
.flash_regs_base = 0x40022000,
352371
.default_flash_regs = stm32l4_flash_regs,
353372
.fsize_addr = 0x1FFF75E0,
373+
.otp_base = 0x1FFF7000,
374+
.otp_size = 1024,
354375
},
355376
{
356377
.id = 0x470,
@@ -362,6 +383,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
362383
.flash_regs_base = 0x40022000,
363384
.default_flash_regs = stm32l4_flash_regs,
364385
.fsize_addr = 0x1FFF75E0,
386+
.otp_base = 0x1FFF7000,
387+
.otp_size = 1024,
365388
},
366389
{
367390
.id = 0x471,
@@ -373,6 +396,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
373396
.flash_regs_base = 0x40022000,
374397
.default_flash_regs = stm32l4_flash_regs,
375398
.fsize_addr = 0x1FFF75E0,
399+
.otp_base = 0x1FFF7000,
400+
.otp_size = 1024,
376401
},
377402
{
378403
.id = 0x472,
@@ -384,6 +409,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
384409
.flash_regs_base = 0x40022000,
385410
.default_flash_regs = stm32l5_ns_flash_regs,
386411
.fsize_addr = 0x0BFA05E0,
412+
.otp_base = 0x0BFA0000,
413+
.otp_size = 512,
387414
},
388415
{
389416
.id = 0x479,
@@ -395,6 +422,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
395422
.flash_regs_base = 0x40022000,
396423
.default_flash_regs = stm32l4_flash_regs,
397424
.fsize_addr = 0x1FFF75E0,
425+
.otp_base = 0x1FFF7000,
426+
.otp_size = 1024,
398427
},
399428
{
400429
.id = 0x495,
@@ -406,6 +435,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
406435
.flash_regs_base = 0x58004000,
407436
.default_flash_regs = stm32l4_flash_regs,
408437
.fsize_addr = 0x1FFF75E0,
438+
.otp_base = 0x1FFF7000,
439+
.otp_size = 1024,
409440
},
410441
{
411442
.id = 0x496,
@@ -417,6 +448,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
417448
.flash_regs_base = 0x58004000,
418449
.default_flash_regs = stm32l4_flash_regs,
419450
.fsize_addr = 0x1FFF75E0,
451+
.otp_base = 0x1FFF7000,
452+
.otp_size = 1024,
420453
},
421454
{
422455
.id = 0x497,
@@ -428,6 +461,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
428461
.flash_regs_base = 0x58004000,
429462
.default_flash_regs = stm32l4_flash_regs,
430463
.fsize_addr = 0x1FFF75E0,
464+
.otp_base = 0x1FFF7000,
465+
.otp_size = 1024,
431466
},
432467
};
433468

@@ -439,6 +474,10 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
439474
if (CMD_ARGC < 6)
440475
return ERROR_COMMAND_SYNTAX_ERROR;
441476

477+
/* fix-up bank base address: 0 is used for normal flash memory */
478+
if (bank->base == 0)
479+
bank->base = STM32_FLASH_BANK_BASE;
480+
442481
stm32l4_info = calloc(1, sizeof(struct stm32l4_flash_bank));
443482
if (!stm32l4_info)
444483
return ERROR_FAIL; /* Checkme: What better error to use?*/
@@ -449,11 +488,43 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
449488
bank->write_start_alignment = bank->write_end_alignment = 8;
450489

451490
stm32l4_info->probed = false;
491+
stm32l4_info->otp_enabled = false;
452492
stm32l4_info->user_bank_size = bank->size;
453493

454494
return ERROR_OK;
455495
}
456496

497+
static inline bool stm32l4_is_otp(struct flash_bank *bank)
498+
{
499+
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
500+
return bank->base == stm32l4_info->part_info->otp_base;
501+
}
502+
503+
static int stm32l4_otp_enable(struct flash_bank *bank, bool enable)
504+
{
505+
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
506+
507+
if (!stm32l4_is_otp(bank))
508+
return ERROR_FAIL;
509+
510+
char *op_str = enable ? "enabled" : "disabled";
511+
512+
LOG_INFO("OTP memory (bank #%d) is %s%s for write commands",
513+
bank->bank_number,
514+
stm32l4_info->otp_enabled == enable ? "already " : "",
515+
op_str);
516+
517+
stm32l4_info->otp_enabled = enable;
518+
519+
return ERROR_OK;
520+
}
521+
522+
static inline bool stm32l4_otp_is_enabled(struct flash_bank *bank)
523+
{
524+
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
525+
return stm32l4_info->otp_enabled;
526+
}
527+
457528
static inline uint32_t stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
458529
{
459530
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
@@ -693,6 +764,11 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first,
693764

694765
assert((first <= last) && (last < bank->num_sectors));
695766

767+
if (stm32l4_is_otp(bank)) {
768+
LOG_ERROR("cannot erase OTP memory");
769+
return ERROR_FLASH_OPER_UNSUPPORTED;
770+
}
771+
696772
if (bank->target->state != TARGET_HALTED) {
697773
LOG_ERROR("Target not halted");
698774
return ERROR_TARGET_NOT_HALTED;
@@ -749,6 +825,11 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first,
749825
struct target *target = bank->target;
750826
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
751827

828+
if (stm32l4_is_otp(bank)) {
829+
LOG_ERROR("cannot protect/unprotect OTP memory");
830+
return ERROR_FLASH_OPER_UNSUPPORTED;
831+
}
832+
752833
if (target->state != TARGET_HALTED) {
753834
LOG_ERROR("Target not halted");
754835
return ERROR_TARGET_NOT_HALTED;
@@ -883,6 +964,11 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
883964
{
884965
int retval = ERROR_OK, retval2;
885966

967+
if (stm32l4_is_otp(bank) && !stm32l4_otp_is_enabled(bank)) {
968+
LOG_ERROR("OTP memory is disabled for write commands");
969+
return ERROR_FAIL;
970+
}
971+
886972
if (bank->target->state != TARGET_HALTED) {
887973
LOG_ERROR("Target not halted");
888974
return ERROR_TARGET_NOT_HALTED;
@@ -1001,6 +1087,29 @@ static int stm32l4_probe(struct flash_bank *bank)
10011087

10021088
LOG_INFO("device idcode = 0x%08" PRIx32 " (%s)", stm32l4_info->idcode, device_info);
10031089

1090+
if (stm32l4_is_otp(bank)) {
1091+
bank->size = part_info->otp_size;
1092+
1093+
LOG_INFO("OTP size is %d bytes, base address is " TARGET_ADDR_FMT, bank->size, bank->base);
1094+
1095+
/* OTP memory is considered as one sector */
1096+
free(bank->sectors);
1097+
bank->num_sectors = 1;
1098+
bank->sectors = alloc_block_array(0, part_info->otp_size, 1);
1099+
1100+
if (!bank->sectors) {
1101+
LOG_ERROR("failed to allocate bank sectors");
1102+
return ERROR_FAIL;
1103+
}
1104+
1105+
1106+
stm32l4_info->probed = true;
1107+
return ERROR_OK;
1108+
} else if (bank->base != STM32_FLASH_BANK_BASE) {
1109+
LOG_ERROR("invalid bank base address");
1110+
return ERROR_FAIL;
1111+
}
1112+
10041113
/* get flash size from target. */
10051114
retval = target_read_u16(target, part_info->fsize_addr, &flash_size_kb);
10061115

@@ -1175,7 +1284,6 @@ static int stm32l4_probe(struct flash_bank *bank)
11751284
free(bank->sectors);
11761285

11771286
bank->size = (flash_size_kb + gap_size_kb) * 1024;
1178-
bank->base = STM32_FLASH_BANK_BASE;
11791287
bank->num_sectors = num_pages;
11801288
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
11811289
if (bank->sectors == NULL) {
@@ -1227,6 +1335,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
12271335

12281336
if (stm32l4_info->probed)
12291337
snprintf(buf + buf_len, buf_size - buf_len, " - %s-bank",
1338+
stm32l4_is_otp(bank) ? "OTP" :
12301339
stm32l4_info->dual_bank_mode ? "Flash dual" : "Flash single");
12311340

12321341
return ERROR_OK;
@@ -1244,6 +1353,11 @@ static int stm32l4_mass_erase(struct flash_bank *bank)
12441353
struct target *target = bank->target;
12451354
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
12461355

1356+
if (stm32l4_is_otp(bank)) {
1357+
LOG_ERROR("cannot erase OTP memory");
1358+
return ERROR_FLASH_OPER_UNSUPPORTED;
1359+
}
1360+
12471361
uint32_t action = FLASH_MER1;
12481362

12491363
if (stm32l4_info->part_info->has_dual_bank)
@@ -1410,6 +1524,11 @@ COMMAND_HANDLER(stm32l4_handle_lock_command)
14101524
if (ERROR_OK != retval)
14111525
return retval;
14121526

1527+
if (stm32l4_is_otp(bank)) {
1528+
LOG_ERROR("cannot lock/unlock OTP memory");
1529+
return ERROR_FLASH_OPER_UNSUPPORTED;
1530+
}
1531+
14131532
target = bank->target;
14141533

14151534
if (target->state != TARGET_HALTED) {
@@ -1439,6 +1558,11 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command)
14391558
if (ERROR_OK != retval)
14401559
return retval;
14411560

1561+
if (stm32l4_is_otp(bank)) {
1562+
LOG_ERROR("cannot lock/unlock OTP memory");
1563+
return ERROR_FLASH_OPER_UNSUPPORTED;
1564+
}
1565+
14421566
target = bank->target;
14431567

14441568
if (target->state != TARGET_HALTED) {
@@ -1456,6 +1580,33 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command)
14561580
return ERROR_OK;
14571581
}
14581582

1583+
COMMAND_HANDLER(stm32l4_handle_otp_command)
1584+
{
1585+
if (CMD_ARGC < 2)
1586+
return ERROR_COMMAND_SYNTAX_ERROR;
1587+
1588+
struct flash_bank *bank;
1589+
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1590+
if (ERROR_OK != retval)
1591+
return retval;
1592+
1593+
if (!stm32l4_is_otp(bank)) {
1594+
command_print(CMD, "the specified bank is not an OTP memory");
1595+
return ERROR_FAIL;
1596+
}
1597+
if (strcmp(CMD_ARGV[1], "enable") == 0)
1598+
stm32l4_otp_enable(bank, true);
1599+
else if (strcmp(CMD_ARGV[1], "disable") == 0)
1600+
stm32l4_otp_enable(bank, false);
1601+
else if (strcmp(CMD_ARGV[1], "show") == 0)
1602+
command_print(CMD, "OTP memory bank #%d is %s for write commands.",
1603+
bank->bank_number, stm32l4_otp_is_enabled(bank) ? "enabled" : "disabled");
1604+
else
1605+
return ERROR_COMMAND_SYNTAX_ERROR;
1606+
1607+
return ERROR_OK;
1608+
}
1609+
14591610
static const struct command_registration stm32l4_exec_command_handlers[] = {
14601611
{
14611612
.name = "lock",
@@ -1499,6 +1650,13 @@ static const struct command_registration stm32l4_exec_command_handlers[] = {
14991650
.usage = "bank_id",
15001651
.help = "Force re-load of device options (will cause device reset).",
15011652
},
1653+
{
1654+
.name = "otp",
1655+
.handler = stm32l4_handle_otp_command,
1656+
.mode = COMMAND_EXEC,
1657+
.usage = "<bank_id> <enable|disable|show>",
1658+
.help = "OTP (One Time Programmable) memory write enable/disable",
1659+
},
15021660
COMMAND_REGISTRATION_DONE
15031661
};
15041662

0 commit comments

Comments
 (0)