Skip to content

Commit

Permalink
Merge pull request #1353 from mirkomatonti/mirko-otp_read_write
Browse files Browse the repository at this point in the history
First Implementation of the OTP Read/Write function
  • Loading branch information
Nightwalker-87 committed Nov 23, 2023
2 parents 0d16dba + 033007f commit fb141d4
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 3 deletions.
2 changes: 2 additions & 0 deletions config/chips/L45x_L46x.chip
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions config/chips/L496x_L4A6x.chip
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions inc/stlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
25 changes: 25 additions & 0 deletions src/st-flash/flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/st-flash/flash_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions src/stlink-lib/chipid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -182,6 +184,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);
}
Expand Down
2 changes: 2 additions & 0 deletions src/stlink-lib/chipid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
2 changes: 2 additions & 0 deletions src/stlink-lib/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 51 additions & 1 deletion src/stlink-lib/common_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1310,9 +1310,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);
Expand Down Expand Up @@ -1389,6 +1396,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;
Expand All @@ -1408,6 +1431,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);

Expand Down Expand Up @@ -1437,7 +1461,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;
Expand Down
2 changes: 2 additions & 0 deletions src/stlink-lib/common_flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit fb141d4

Please sign in to comment.