Skip to content

Commit fb141d4

Browse files
Merge pull request #1353 from mirkomatonti/mirko-otp_read_write
First Implementation of the OTP Read/Write function
2 parents 0d16dba + 033007f commit fb141d4

File tree

10 files changed

+104
-3
lines changed

10 files changed

+104
-3
lines changed

config/chips/L45x_L46x.chip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB
1212
option_base 0x0
1313
option_size 0x0
1414
flags swo
15+
otp_base 0x1fff7000
16+
otp_size 0x400 // 1 KB

config/chips/L496x_L4A6x.chip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB
1212
option_base 0x1fff7800 // STM32_L4_OPTION_BYTES_BASE
1313
option_size 0x4 // 4 B
1414
flags swo
15+
otp_base 0x1fff7000
16+
otp_size 0x400 // 1 KB

inc/stlink.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ struct _stlink {
232232
uint32_t chip_flags; // stlink_chipid_params.flags, set by stlink_load_device_params(), values: CHIP_F_xxx
233233

234234
uint32_t max_trace_freq; // set by stlink_open_usb()
235+
236+
uint32_t otp_base;
237+
uint32_t otp_size;
235238
};
236239

237240
/* Functions defined in common.c */

src/st-flash/flash.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static void usage(void) {
6161
puts("example write option control register1 byte: ./st-flash --area=optcr write 0xXXXXXXXX");
6262
puts("example read option control register1 byte: ./st-flash --area=optcr1 read");
6363
puts("example write option control register1 byte: ./st-flash --area=optcr1 write 0xXXXXXXXX");
64+
puts("example read OTP area: ./st-flash --area=otp read [path]");
65+
puts("example write OTP area: ./st-flash --area=otp write [path] 0xXXXXXXXX");
6466
}
6567

6668
int32_t main(int32_t ac, char** av) {
@@ -180,6 +182,18 @@ int32_t main(int32_t ac, char** av) {
180182
DLOG("@@@@ Write %d (%0#10x) to option bytes boot address\n", o.val, o.val);
181183

182184
err = stlink_write_option_bytes_boot_add32(sl, o.val);
185+
} else if (o.area == FLASH_OTP) {
186+
if(sl->otp_base == 0) {
187+
err = -1;
188+
printf("OTP Write NOT implemented\n");
189+
goto on_error;
190+
}
191+
err = stlink_fwrite_flash(sl, o.filename, o.addr);
192+
193+
if (err == -1) {
194+
printf("stlink_fwrite_flash() == -1\n");
195+
goto on_error;
196+
}
183197
} else {
184198
err = -1;
185199
printf("Unknown memory region\n");
@@ -284,6 +298,17 @@ int32_t main(int32_t ac, char** av) {
284298
} else {
285299
printf("%08x\n",option_byte);
286300
}
301+
} else if (o.area == FLASH_OTP) {
302+
if(sl->otp_base == 0) {
303+
err = -1;
304+
printf("OTP Read NOT implemented\n");
305+
goto on_error;
306+
}
307+
err = stlink_fread(sl, o.filename, 0, sl->otp_base, sl->otp_size);
308+
if (err == -1) {
309+
printf("could not read OTP area (%d)\n", err);
310+
goto on_error;
311+
}
287312
}
288313
}
289314

src/st-flash/flash_opts.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,7 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) {
288288

289289
break;
290290
} else if (o->area == FLASH_OTP) {
291-
return bad_arg("TODO: otp not implemented yet");
292-
if (ac > 1) { return invalid_args("otp read: [path]"); }
291+
if (ac > 1 || ac ==0 ) { return invalid_args("otp read: [path]"); }
293292
if (ac > 0) { o->filename = av[0]; }
294293
break;
295294
} else if (o->area == FLASH_OPTION_BYTES) {

src/stlink-lib/chipid.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ void dump_a_chip(struct stlink_chipid_params *dev) {
3434
DLOG("option_base 0x%x\n", dev->option_base);
3535
DLOG("option_size 0x%x\n", dev->option_size);
3636
DLOG("flags %d\n\n", dev->flags);
37+
DLOG("otp_base %d\n\n", dev->otp_base);
38+
DLOG("otp_size %d\n\n", dev->otp_size);
3739
}
3840

3941
struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chip_id) {
@@ -182,6 +184,18 @@ void process_chipfile(char *fname) {
182184
}
183185

184186
sscanf(value, "%x", &ts->flags);
187+
} else if (strcmp(word, "otp_base") == 0) {
188+
buf[strlen(buf) - 1] = 0; // chomp newline
189+
sscanf(buf, "%*s %n", &nc);
190+
if (sscanf(value, "%i", &ts->otp_base) < 1) {
191+
fprintf(stderr, "Failed to parse option size\n");
192+
}
193+
} else if (strcmp(word, "otp_size") == 0) {
194+
buf[strlen(buf) - 1] = 0; // chomp newline
195+
sscanf(buf, "%*s %n", &nc);
196+
if (sscanf(value, "%i", &ts->otp_size) < 1) {
197+
fprintf(stderr, "Failed to parse option size\n");
198+
}
185199
} else {
186200
fprintf(stderr, "Unknown keyword in %s: %s\n", fname, word);
187201
}

src/stlink-lib/chipid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ struct stlink_chipid_params {
2121
uint32_t option_base;
2222
uint32_t option_size;
2323
uint32_t flags;
24+
uint32_t otp_base;
25+
uint32_t otp_size;
2426
struct stlink_chipid_params *next;
2527
};
2628

src/stlink-lib/common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ int32_t stlink_load_device_params(stlink_t *sl) {
290290
sl->option_base = params->option_base;
291291
sl->option_size = params->option_size;
292292
sl->chip_flags = params->flags;
293+
sl->otp_base = params->otp_base;
294+
sl->otp_size = params->otp_size;
293295

294296
// medium and low devices have the same chipid. ram size depends on flash
295297
// size. STM32F100xx datasheet Doc ID 16455 Table 2

src/stlink-lib/common_flash.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,9 +1310,16 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) {
13101310
* If the file is identified to be all-empty and four-bytes aligned,
13111311
* still flash the whole file even if ignoring message is printed.
13121312
*/
1313-
err = stlink_write_flash(sl, addr, mf.base,
1313+
1314+
/* In case the address is within the OTP area we use a different flash method */
1315+
if(addr >= sl->otp_base && addr < sl->otp_base + sl->otp_size) {
1316+
err = stlink_write_otp(sl, addr, mf.base,
1317+
(num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty);
1318+
} else {
1319+
err = stlink_write_flash(sl, addr, mf.base,
13141320
(num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty,
13151321
num_empty == mf.len);
1322+
}
13161323
stlink_fwrite_finalize(sl, addr);
13171324
unmap_file(&mf);
13181325
return (err);
@@ -1389,6 +1396,22 @@ int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uin
13891396
return 0;
13901397
}
13911398

1399+
// Check if an address and size are within the flash (otp area)
1400+
int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size) {
1401+
uint32_t logvar;
1402+
if (addr < sl->otp_base || addr >= (sl->otp_base + sl->otp_size)) {
1403+
logvar = sl->otp_base + sl->otp_size - 1;
1404+
ELOG("Invalid address, it should be within 0x%08x - 0x%08x\n", sl->otp_base, logvar);
1405+
return (-1);
1406+
}
1407+
if ((addr + size) >= (sl->otp_base + sl->otp_size)) {
1408+
logvar = sl->otp_base + sl->otp_size - addr;
1409+
ELOG("The size exceeds the size of the OTP Area (0x%08x bytes available)\n", logvar);
1410+
return (-1);
1411+
}
1412+
return 0;
1413+
}
1414+
13921415
// Check if an address is aligned with the beginning of a page
13931416
int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr) {
13941417
stm32_addr_t page = sl->flash_base;
@@ -1408,6 +1431,7 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3
14081431
int32_t ret;
14091432
flash_loader_t fl;
14101433
ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr);
1434+
14111435
// check addr range is inside the flash
14121436
stlink_calculate_pagesize(sl, addr);
14131437

@@ -1437,7 +1461,33 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3
14371461
if (eraseonly) {
14381462
return (0);
14391463
}
1464+
1465+
ret = stlink_flashloader_start(sl, &fl);
1466+
if (ret)
1467+
return ret;
1468+
ret = stlink_flashloader_write(sl, &fl, addr, base, len);
1469+
if (ret)
1470+
return ret;
1471+
ret = stlink_flashloader_stop(sl, &fl);
1472+
if (ret)
1473+
return ret;
1474+
1475+
return (stlink_verify_write_flash(sl, addr, base, len));
1476+
}
1477+
1478+
int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) {
1479+
int32_t ret;
1480+
flash_loader_t fl;
1481+
ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr);
1482+
1483+
// Check the address and size validity
1484+
if (stlink_check_address_range_validity_otp(sl, addr, len) < 0) {
1485+
return (-1);
1486+
}
14401487

1488+
// make sure we've loaded the context with the chip details
1489+
stlink_core_id(sl);
1490+
14411491
ret = stlink_flashloader_start(sl, &fl);
14421492
if (ret)
14431493
return ret;

src/stlink-lib/common_flash.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr);
4444
int32_t stlink_fcheck_flash(stlink_t *sl, const char *path, stm32_addr_t addr);
4545
int32_t stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length);
4646
int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uint32_t size);
47+
int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size);
4748
int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr);
4849
int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len, uint8_t eraseonly);
50+
int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len);
4951
void stlink_fwrite_finalize(stlink_t *, stm32_addr_t);
5052

5153
#endif // COMMON_FLASH_H

0 commit comments

Comments
 (0)