Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Read/Write command for Option-Bytes on STM32F2 series #836

Merged
merged 2 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/stlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ typedef struct flash_loader {
int stlink_mwrite_flash(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr);
int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr);
int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr);
int stlink_fwrite_option_bytes_32bit(stlink_t *sl,uint32_t val);
int stlink_mwrite_sram(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_t addr);
int stlink_fwrite_sram(stlink_t *sl, const char* path, stm32_addr_t addr);
int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length);
Expand All @@ -221,6 +222,7 @@ typedef struct flash_loader {
int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size);
int stlink_fread(stlink_t* sl, const char* path, bool is_ihex, stm32_addr_t addr, size_t size);
int stlink_load_device_params(stlink_t *sl);
int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte);

#include "stlink/sg.h"
#include "stlink/usb.h"
Expand Down
5 changes: 4 additions & 1 deletion include/stlink/tools/flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

enum flash_cmd {FLASH_CMD_NONE = 0, FLASH_CMD_WRITE = 1, FLASH_CMD_READ = 2, FLASH_CMD_ERASE = 3, CMD_RESET = 4};
enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1};
enum flash_area {FLASH_MAIN_MEMORY = 0, FLASH_SYSTEM_MEMORY = 1,FLASH_OTP = 2, FLASH_OPTION_BYTES = 3};
struct flash_opts
{
enum flash_cmd cmd;
Expand All @@ -20,10 +21,12 @@ struct flash_opts
int reset;
int log_level;
enum flash_format format;
enum flash_area area;
uint32_t val;
size_t flash_size; /* --flash=n[k][m] */
};

#define FLASH_OPTS_INITIALIZER {0, NULL, { 0 }, NULL, 0, 0, 0, 0, 0, 0 }
#define FLASH_OPTS_INITIALIZER {0, NULL, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0 }

int flash_get_opts(struct flash_opts* o, int ac, char** av);

Expand Down
2 changes: 1 addition & 1 deletion include/stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
#define STM32_SRAM_BASE ((uint32_t)0x20000000)
#define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800)
#define STM32_L0_CAT2_OPTION_BYTES_BASE ((uint32_t)0x1FF80000)

#define STM32_F2_OPTION_BYTES_BASE ((uint32_t)0x1FFFC000)
#endif /* STM32_H */
120 changes: 119 additions & 1 deletion src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@
#define FLASH_F4_CR_SNB_MASK 0xf8
#define FLASH_F4_SR_BSY 16

//STM32F2
#define FLASH_F2_REGS_ADDR ((uint32_t)0x40023c00)
#define FLASH_F2_KEYR (FLASH_F2_REGS_ADDR + 0x04)
#define FLASH_F2_OPT_KEYR (FLASH_F2_REGS_ADDR + 0x08)
#define FLASH_F2_SR (FLASH_F2_REGS_ADDR + 0x0c)
#define FLASH_F2_CR (FLASH_F2_REGS_ADDR + 0x10)
#define FLASH_F2_OPT_CR (FLASH_F2_REGS_ADDR + 0x14)
#define FLASH_F2_OPT_LOCK_BIT (1u << 0)
#define FLASH_F2_CR_STRT 16
#define FLASH_F2_CR_LOCK 31

#define FLASH_F2_CR_SER 1
#define FLASH_F2_CR_SNB 3
#define FLASH_F2_CR_SNB_MASK 0x78
#define FLASH_F2_SR_BSY 16


#define L1_WRITE_BLOCK_SIZE 0x80
#define L0_WRITE_BLOCK_SIZE 0x40

Expand Down Expand Up @@ -2642,6 +2659,89 @@ static int stlink_write_option_bytes_l0_cat2(stlink_t *sl, uint8_t* base, uint32
return 0;
}

/**
* Write option bytes
* @param sl
* @param option_byte value to write
* @return 0 on success, -ve on failure.
*/
static int stlink_write_option_bytes_f2(stlink_t *sl, uint32_t option_byte) {
uint32_t val;

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
if (val & FLASH_F2_OPT_LOCK_BIT) {
WLOG("Unlocking option flash\n");
//Unlock the FLASH_OPT_CR register (FLASH Programming manual page 15)
//https://www.st.com/resource/en/programming_manual/cd00233952.pdf
stlink_write_debug32(sl, FLASH_F2_OPT_KEYR, 0x08192A3B);
stlink_write_debug32(sl, FLASH_F2_OPT_KEYR, 0x4C5D6E7F);

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
if (val & FLASH_F2_OPT_LOCK_BIT) {
ELOG("Option flash unlock failed! System reset required to be able to unlock it again!\n");
return -1;
}
}

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
WLOG("option bytes CR = %x\n",val);

stlink_write_debug32(sl, FLASH_F2_OPT_CR, option_byte & 0x0FFFFFFC);

stlink_write_debug32(sl, FLASH_F2_OPT_CR, (option_byte & 0x0FFFFFFC)|0x00000002);


stlink_read_debug32(sl, FLASH_F2_SR, &val);
WLOG("wait BSY flag to be 0\n");

while(val & 0x00010000){
stlink_read_debug32(sl, FLASH_F2_SR, &val);
}
WLOG("BSY flag is 0\n");

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
WLOG("option bytes CR = %x\n",val);
WLOG("Option flash re-lock\n");
stlink_write_debug32(sl, FLASH_F2_OPT_CR, val | 0x00000001);

DLOG("STM32 F2 option bytes are written\n");

return 0;
}

/**
* Read option bytes
* @param sl
* @param option_byte value to write
* @return 0 on success, -ve on failure.
*/
int stlink_read_option_bytes_f2(stlink_t *sl, uint32_t* option_byte) {
uint32_t val;

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
if (val & FLASH_F2_OPT_LOCK_BIT) {
WLOG("Unlocking option flash\n");
//Unlock the FLASH_OPT_CR register (FLASH Programming manual page 15)
//https://www.st.com/resource/en/programming_manual/cd00233952.pdf
stlink_write_debug32(sl, FLASH_F2_OPT_KEYR, 0x08192A3B);
stlink_write_debug32(sl, FLASH_F2_OPT_KEYR, 0x4C5D6E7F);

stlink_read_debug32(sl, FLASH_F2_OPT_CR, &val);
if (val & FLASH_F2_OPT_LOCK_BIT) {
ELOG("Option flash unlock failed! System reset required to be able to unlock it again!\n");
return -1;
}
}

stlink_read_debug32(sl, FLASH_F2_OPT_CR, option_byte);
WLOG("option bytes CR = %x\n",option_byte);

WLOG("Option flash re-lock\n");
stlink_write_debug32(sl, FLASH_F2_OPT_CR, val | 0x00000001);

return 0;
}

/**
* Write option bytes
* @param sl
Expand All @@ -2662,7 +2762,7 @@ int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, ui
return stlink_write_option_bytes_l0_cat2(sl, base, len);
}
else {
ELOG("Option bytes writing is currently only supported for the STM32G0 and STM32L0\n");
ELOG("Option bytes writing is currently only supported for the STM32F2, STM32G0 and STM32L0\n");
return -1;
}

Expand Down Expand Up @@ -2690,3 +2790,21 @@ int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr
unmap_file(&mf);
return err;
}

/**
* Write the given 32-bit value with option byte
* @param sl
* @param option_byte value to write
* @return 0 on success, -ve on failure.
*/
int stlink_fwrite_option_bytes_32bit(stlink_t *sl, uint32_t val) {

if(sl->chip_id == STLINK_CHIPID_STM32_F2){
return stlink_write_option_bytes_f2(sl, val);
}
else
{
ELOG("Option bytes writing is currently only supported for the STM32F2, STM32G0 and STM32L0\n");
return -1;
}
}
34 changes: 27 additions & 7 deletions src/tools/flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ static void usage(void)
puts(" fsize: Use decimal, octal or hex by prefix 0xXXX for hex, optionally followed by k=KB, or m=MB (eg. --flash=128k)");
puts(" Format may be 'binary' (default) or 'ihex', although <addr> must be specified for binary format only.");
puts(" ./st-flash [--version]");
puts("example write option byte: ./st-flash --debug --reset --area=option write 0xXXXXXXXX");
puts("example read option byte: ./st-flash --debug --reset --area=option read > option_byte");
}

int main(int ac, char** av)
Expand Down Expand Up @@ -131,15 +133,13 @@ int main(int ac, char** av)
if (o.cmd == FLASH_CMD_WRITE) /* write */
{
size_t size = 0;

if(o.format == FLASH_FORMAT_IHEX) {
err = stlink_parse_ihex(o.filename, stlink_get_erased_pattern(sl), &mem, &size, &o.addr);
if (err == -1) {
printf("Cannot parse %s as Intel-HEX file\n", o.filename);
goto on_error;
}
}

if ((o.addr >= sl->flash_base) &&
(o.addr < sl->flash_base + sl->flash_size)) {
if(o.format == FLASH_FORMAT_IHEX)
Expand All @@ -164,14 +164,22 @@ int main(int ac, char** av)
goto on_error;
}
}
else if (o.addr == STM32_G0_OPTION_BYTES_BASE || o.addr == STM32_L0_CAT2_OPTION_BYTES_BASE) {
else if (o.addr == STM32_G0_OPTION_BYTES_BASE || o.addr == STM32_L0_CAT2_OPTION_BYTES_BASE){
err = stlink_fwrite_option_bytes(sl, o.filename, o.addr);
if (err == -1)
{
printf("stlink_fwrite_option_bytes() == -1\n");
goto on_error;
}
}
else if (o.area == FLASH_OPTION_BYTES){
err = stlink_fwrite_option_bytes_32bit(sl, o.val);
if (err == -1)
{
printf("stlink_fwrite_option_bytes() == -1\n");
goto on_error;
}
}
else {
err = -1;
printf("Unknown memory region\n");
Expand Down Expand Up @@ -201,13 +209,25 @@ int main(int ac, char** av)
}
else /* read */
{
if ((o.addr >= sl->flash_base) && (o.size == 0) &&
(o.addr < sl->flash_base + sl->flash_size))
if(o.area == FLASH_OPTION_BYTES){
if(sl->chip_id == STLINK_CHIPID_STM32_F2){
uint32_t option_byte = 0;
err = stlink_read_option_bytes_f2(sl,&option_byte);
printf("%x\n",option_byte);
}else{
printf("This format is available for STM32F2 Only\n");
}
}
else if ((o.addr >= sl->flash_base) && (o.size == 0) &&
(o.addr < sl->flash_base + sl->flash_size)){
o.size = sl->flash_size;
err = stlink_fread(sl, o.filename, o.format == FLASH_FORMAT_IHEX, o.addr, o.size);
Nightwalker-87 marked this conversation as resolved.
Show resolved Hide resolved
}
else if ((o.addr >= sl->sram_base) && (o.size == 0) &&
(o.addr < sl->sram_base + sl->sram_size))
(o.addr < sl->sram_base + sl->sram_size)){
o.size = sl->sram_size;
err = stlink_fread(sl, o.filename, o.format == FLASH_FORMAT_IHEX, o.addr, o.size);
err = stlink_fread(sl, o.filename, o.format == FLASH_FORMAT_IHEX, o.addr, o.size);
Nightwalker-87 marked this conversation as resolved.
Show resolved Hide resolved
}
if (err == -1)
{
printf("stlink_fread() == -1\n");
Expand Down
31 changes: 30 additions & 1 deletion src/tools/flash_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av)

serial_specified = true;
}
else if (strcmp(av[0], "--area") == 0 || starts_with(av[0], "--area=")) {
const char * area;
if(strcmp(av[0], "--area") == 0) {
ac--;
av++;
if (ac < 1) return -1;
area = av[0];
}
else {
area = av[0] + strlen("--area=");
}
if (strcmp(area, "main") == 0)
o->area = FLASH_MAIN_MEMORY;
else if (strcmp(area, "system") == 0)
o->area = FLASH_SYSTEM_MEMORY;
else if (strcmp(area, "otp") == 0)
o->area = FLASH_OTP;
else if (strcmp(area, "option") == 0)
o->area = FLASH_OPTION_BYTES;
else
return -1;

}
else if (strcmp(av[0], "--format") == 0 || starts_with(av[0], "--format=")) {
const char * format;
if(strcmp(av[0], "--format") == 0) {
Expand Down Expand Up @@ -149,6 +172,7 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av)
break;

case FLASH_CMD_READ: // expect filename, addr and size
if((o->area == FLASH_OPTION_BYTES) &&(ac == 0)) break;
if (ac != 3) return -1;

o->filename = av[0];
Expand All @@ -161,7 +185,12 @@ int flash_get_opts(struct flash_opts* o, int ac, char** av)
break;

case FLASH_CMD_WRITE:
if(o->format == FLASH_FORMAT_BINARY) { // expect filename and addr
if(o->area == FLASH_OPTION_BYTES){
if(ac != 1) return -1;

o->val = (uint32_t)strtoul(av[0], &tail, 16);
}
else if(o->format == FLASH_FORMAT_BINARY) { // expect filename and addr
if (ac != 2) return -1;

o->filename = av[0];
Expand Down