From 259e400276e939f7c8503068312e940dc25bdf46 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Wed, 18 Aug 2021 18:41:49 +0100 Subject: [PATCH 01/56] server/telnet: simplify telnet_input function running complexity on this file tells that: NOTE: proc telnet_input in file telnet_server.c line 576 nesting depth reached level 8 ==> *seriously consider rewriting the procedure*. Complexity Scores Score | ln-ct | nc-lns| file-name(line): proc-name 319 272 226 src/server/telnet_server.c(576): telnet_input total nc-lns 226 so try to reduce the complexity score of telnet_input function Change-Id: I64ecb0c54da83c27a343f2a1df99fc8f9484572a Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6440 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/server/telnet_server.c | 299 +++++++++++++++++++++---------------- 1 file changed, 168 insertions(+), 131 deletions(-) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 36b017c58..13fbc3fda 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -320,6 +320,32 @@ static void telnet_history_down(struct connection *connection) telnet_history_go(connection, next_history); } +static void telnet_history_add(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + + /* save only non-blank not repeating lines in the history */ + char *prev_line = t_con->history[(t_con->current_history > 0) ? + t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1]; + + if (*t_con->line && (!prev_line || strcmp(t_con->line, prev_line))) { + /* if the history slot is already taken, free it */ + free(t_con->history[t_con->next_history]); + + /* add line to history */ + t_con->history[t_con->next_history] = strdup(t_con->line); + + /* wrap history at TELNET_LINE_HISTORY_SIZE */ + t_con->next_history = (t_con->next_history + 1) % TELNET_LINE_HISTORY_SIZE; + + /* current history line starts at the new entry */ + t_con->current_history = t_con->next_history; + + free(t_con->history[t_con->current_history]); + t_con->history[t_con->current_history] = strdup(""); + } +} + static int telnet_history_print(struct connection *connection) { struct telnet_connection *tc; @@ -423,6 +449,137 @@ static bool telnet_insert(struct connection *connection, const void *data, size_ return true; } +static void telnet_delete_character(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + + if (t_con->line_cursor == 0) + return; + + if (t_con->line_cursor != t_con->line_size) { + size_t i; + telnet_write(connection, "\b", 1); + t_con->line_cursor--; + t_con->line_size--; + memmove(t_con->line + t_con->line_cursor, + t_con->line + t_con->line_cursor + 1, + t_con->line_size - + t_con->line_cursor); + + telnet_write(connection, + t_con->line + t_con->line_cursor, + t_con->line_size - + t_con->line_cursor); + telnet_write(connection, " \b", 2); + for (i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, "\b", 1); + } else { + t_con->line_size--; + t_con->line_cursor--; + /* back space: move the 'printer' head one char + * back, overwrite with space, move back again */ + telnet_write(connection, "\b \b", 3); + } +} + +static void telnet_remove_character(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + + if (t_con->line_cursor < t_con->line_size) { + size_t i; + t_con->line_size--; + /* remove char from line buffer */ + memmove(t_con->line + t_con->line_cursor, + t_con->line + t_con->line_cursor + 1, + t_con->line_size - t_con->line_cursor); + + /* print remainder of buffer */ + telnet_write(connection, t_con->line + t_con->line_cursor, + t_con->line_size - t_con->line_cursor); + /* overwrite last char with whitespace */ + telnet_write(connection, " \b", 2); + + /* move back to cursor position*/ + for (i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, "\b", 1); + } +} + +static int telnet_exec_line(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + struct command_context *command_context = connection->cmd_ctx; + int retval; + + telnet_write(connection, "\r\n\x00", 3); + + if (strcmp(t_con->line, "history") == 0) { + retval = telnet_history_print(connection); + + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; + } + + telnet_history_add(connection); + + t_con->line_size = 0; + + /* to suppress prompt in log callback during command execution */ + t_con->prompt_visible = false; + + if (strcmp(t_con->line, "shutdown") == 0) + telnet_save_history(t_con); + + retval = command_run_line(command_context, t_con->line); + + t_con->line_cursor = 0; + t_con->prompt_visible = true; + + if (retval == ERROR_COMMAND_CLOSE_CONNECTION) + return ERROR_SERVER_REMOTE_CLOSED; + + /* the prompt is always placed at the line beginning */ + telnet_write(connection, "\r", 1); + + retval = telnet_prompt(connection); + if (retval == ERROR_SERVER_REMOTE_CLOSED) + return ERROR_SERVER_REMOTE_CLOSED; + + return ERROR_OK; +} + +static void telnet_cut_line_to_end(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + + /* FIXME: currently this function does not save to clipboard */ + + if (t_con->line_cursor < t_con->line_size) { + /* overwrite with space, until end of line, move back */ + for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, " ", 1); + for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) + telnet_write(connection, "\b", 1); + t_con->line[t_con->line_cursor] = '\0'; + t_con->line_size = t_con->line_cursor; + } +} + +static void telnet_interrupt(struct connection *connection) +{ + struct telnet_connection *t_con = connection->priv; + + /* print '^C' at line end, and display a new command prompt */ + telnet_move_cursor(connection, t_con->line_size); + telnet_write(connection, "^C\n\r", 4); + t_con->line_cursor = 0; + t_con->line_size = 0; + telnet_prompt(connection); +} + static void telnet_auto_complete(struct connection *connection) { struct telnet_connection *t_con = connection->priv; @@ -591,7 +748,6 @@ static int telnet_input(struct connection *connection) unsigned char buffer[TELNET_BUFFER_SIZE]; unsigned char *buf_p; struct telnet_connection *t_con = connection->priv; - struct command_context *command_context = connection->cmd_ctx; bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE); @@ -630,108 +786,20 @@ static int telnet_input(struct connection *connection) } t_con->line[t_con->line_size] = 0; - telnet_write(connection, "\r\n\x00", 3); - - if (strcmp(t_con->line, "history") == 0) { - retval = telnet_history_print(connection); - - if (retval != ERROR_OK) - return retval; - - continue; - } - - /* save only non-blank not repeating lines in the history */ - char *prev_line = t_con->history[(t_con->current_history > 0) ? - t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1]; - if (*t_con->line && (!prev_line || - strcmp(t_con->line, prev_line))) { - /* if the history slot is already taken, free it */ - free(t_con->history[t_con->next_history]); - - /* add line to history */ - t_con->history[t_con->next_history] = strdup(t_con->line); - - /* wrap history at TELNET_LINE_HISTORY_SIZE */ - t_con->next_history = (t_con->next_history + 1) % - TELNET_LINE_HISTORY_SIZE; - - /* current history line starts at the new entry */ - t_con->current_history = - t_con->next_history; - - free(t_con->history[t_con->current_history]); - t_con->history[t_con->current_history] = strdup(""); - } - - t_con->line_size = 0; - - /* to suppress prompt in log callback during command execution */ - t_con->prompt_visible = false; - - if (strcmp(t_con->line, "shutdown") == 0) - telnet_save_history(t_con); - - retval = command_run_line(command_context, t_con->line); - - t_con->line_cursor = 0; - t_con->prompt_visible = true; - - if (retval == ERROR_COMMAND_CLOSE_CONNECTION) - return ERROR_SERVER_REMOTE_CLOSED; - - /* the prompt is always * placed at the line beginning */ - telnet_write(connection, "\r", 1); - - retval = telnet_prompt(connection); - if (retval == ERROR_SERVER_REMOTE_CLOSED) - return ERROR_SERVER_REMOTE_CLOSED; - + retval = telnet_exec_line(connection); + if (retval != ERROR_OK) + return retval; } else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) { /* delete character */ - if (t_con->line_cursor > 0) { - if (t_con->line_cursor != t_con->line_size) { - size_t i; - telnet_write(connection, "\b", 1); - t_con->line_cursor--; - t_con->line_size--; - memmove(t_con->line + t_con->line_cursor, - t_con->line + t_con->line_cursor + 1, - t_con->line_size - - t_con->line_cursor); - - telnet_write(connection, - t_con->line + t_con->line_cursor, - t_con->line_size - - t_con->line_cursor); - telnet_write(connection, " \b", 2); - for (i = t_con->line_cursor; i < t_con->line_size; i++) - telnet_write(connection, "\b", 1); - } else { - t_con->line_size--; - t_con->line_cursor--; - /* back space: move the 'printer' head one char - * back, overwrite with space, move back again */ - telnet_write(connection, "\b \b", 3); - } - } + telnet_delete_character(connection); } else if (*buf_p == 0x15) { /* clear line */ telnet_clear_line(connection, t_con); } else if (*buf_p == CTRL('B')) { /* cursor left */ - if (t_con->line_cursor > 0) { - telnet_write(connection, "\b", 1); - t_con->line_cursor--; - } + telnet_move_cursor(connection, t_con->line_cursor - 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('C')) { /* interrupt */ - /* print '^C' at line end, and display a new command prompt */ - telnet_move_cursor(connection, t_con->line_size); - telnet_write(connection, "^C\n\r", 4); - t_con->line_cursor = 0; - t_con->line_size = 0; - telnet_prompt(connection); + telnet_interrupt(connection); } else if (*buf_p == CTRL('F')) { /* cursor right */ - if (t_con->line_cursor < t_con->line_size) - telnet_write(connection, t_con->line + t_con->line_cursor++, 1); + telnet_move_cursor(connection, t_con->line_cursor + 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == CTRL('P')) { /* cursor up */ telnet_history_up(connection); @@ -742,15 +810,7 @@ static int telnet_input(struct connection *connection) } else if (*buf_p == CTRL('E')) { /* move the cursor to the end of the line */ telnet_move_cursor(connection, t_con->line_size); } else if (*buf_p == CTRL('K')) { /* kill line to end */ - if (t_con->line_cursor < t_con->line_size) { - /* overwrite with space, until end of line, move back */ - for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) - telnet_write(connection, " ", 1); - for (size_t i = t_con->line_cursor; i < t_con->line_size; i++) - telnet_write(connection, "\b", 1); - t_con->line[t_con->line_cursor] = '\0'; - t_con->line_size = t_con->line_cursor; - } + telnet_cut_line_to_end(connection); } else if (*buf_p == '\t') { telnet_auto_complete(connection); } else { @@ -788,15 +848,10 @@ static int telnet_input(struct connection *connection) case TELNET_STATE_ESCAPE: if (t_con->last_escape == '[') { if (*buf_p == 'D') { /* cursor left */ - if (t_con->line_cursor > 0) { - telnet_write(connection, "\b", 1); - t_con->line_cursor--; - } + telnet_move_cursor(connection, t_con->line_cursor - 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'C') { /* cursor right */ - if (t_con->line_cursor < t_con->line_size) - telnet_write(connection, - t_con->line + t_con->line_cursor++, 1); + telnet_move_cursor(connection, t_con->line_cursor + 1); t_con->state = TELNET_STATE_DATA; } else if (*buf_p == 'A') { /* cursor up */ telnet_history_up(connection); @@ -816,25 +871,7 @@ static int telnet_input(struct connection *connection) } else if (t_con->last_escape == '3') { /* Remove character */ if (*buf_p == '~') { - if (t_con->line_cursor < t_con->line_size) { - size_t i; - t_con->line_size--; - /* remove char from line buffer */ - memmove(t_con->line + t_con->line_cursor, - t_con->line + t_con->line_cursor + 1, - t_con->line_size - t_con->line_cursor); - - /* print remainder of buffer */ - telnet_write(connection, t_con->line + t_con->line_cursor, - t_con->line_size - t_con->line_cursor); - /* overwrite last char with whitespace */ - telnet_write(connection, " \b", 2); - - /* move back to cursor position*/ - for (i = t_con->line_cursor; i < t_con->line_size; i++) - telnet_write(connection, "\b", 1); - } - + telnet_remove_character(connection); t_con->state = TELNET_STATE_DATA; } else t_con->state = TELNET_STATE_DATA; From a098816a6557e5882bf088ab12a06b94934f30ce Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 19 Aug 2021 01:30:38 +0100 Subject: [PATCH 02/56] server/telnet: add variables auto-completion Change-Id: Ie690afad18065cde8d754c8af50dacd9f467c8e5 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6442 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/server/telnet_server.c | 53 ++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 13fbc3fda..2ebcff163 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -592,16 +592,30 @@ static void telnet_auto_complete(struct connection *connection) LIST_HEAD(matches); - /* user command sequence, either at line beginning - * or we start over after these characters ';', '[', '{' */ + /* - user command sequence, either at line beginning + * or we start over after these characters ';', '[', '{' + * - user variable sequence, start after the character '$' + * and do not contain white spaces */ + bool is_variable_auto_completion = false; + bool have_spaces = false; size_t seq_start = (t_con->line_cursor == 0) ? 0 : (t_con->line_cursor - 1); - while (seq_start > 0) { + while (1) { char c = t_con->line[seq_start]; + if (c == ';' || c == '[' || c == '{') { seq_start++; break; + } else if (c == ' ') { + have_spaces = true; + } else if (c == '$' && !have_spaces) { + is_variable_auto_completion = true; + seq_start++; + break; } + if (seq_start == 0) + break; + seq_start--; } @@ -631,7 +645,12 @@ static void telnet_auto_complete(struct connection *connection) query[usr_cmd_len] = '\0'; /* filter commands */ - char *query_cmd = alloc_printf("_telnet_autocomplete_helper {%s*}", query); + char *query_cmd; + + if (is_variable_auto_completion) + query_cmd = alloc_printf("lsort [info vars {%s*}]", query); + else + query_cmd = alloc_printf("_telnet_autocomplete_helper {%s*}", query); if (!query_cmd) { LOG_ERROR("Out of memory"); @@ -659,20 +678,22 @@ static void telnet_auto_complete(struct connection *connection) /* validate the command */ bool ignore_cmd = false; - Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE); + if (!is_variable_auto_completion) { + Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE); - if (!jim_cmd) { - /* Why we are here? Let's ignore it! */ - ignore_cmd = true; - } else if (jimcmd_is_oocd_command(jim_cmd)) { - struct command *cmd = jimcmd_privdata(jim_cmd); + if (!jim_cmd) { + /* Why we are here? Let's ignore it! */ + ignore_cmd = true; + } else if (jimcmd_is_oocd_command(jim_cmd)) { + struct command *cmd = jimcmd_privdata(jim_cmd); - if (cmd && !cmd->handler && !cmd->jim_handler) { - /* Initial part of a multi-word command. Ignore it! */ - ignore_cmd = true; - } else if (cmd && cmd->mode == COMMAND_CONFIG) { - /* Not executable after config phase. Ignore it! */ - ignore_cmd = true; + if (cmd && !cmd->handler && !cmd->jim_handler) { + /* Initial part of a multi-word command. Ignore it! */ + ignore_cmd = true; + } else if (cmd && cmd->mode == COMMAND_CONFIG) { + /* Not executable after config phase. Ignore it! */ + ignore_cmd = true; + } } } From 385eedfc6f0b82c5d6715c740ee40bdce983ef04 Mon Sep 17 00:00:00 2001 From: Wealian Liao Date: Thu, 26 Nov 2020 10:25:09 +0800 Subject: [PATCH 03/56] flash/nor: add support for Nuvoton NPCX series flash Added NPCX flash driver to support the Nuvoton NPCX series microcontrollers. Add config file for NPCX series. Change-Id: Ia10b019a3521f59ad1e10ccdc56827ba30c3eac8 Signed-off-by: Wealian Liao Signed-off-by: Mulin Chao Reviewed-on: https://review.openocd.org/c/openocd/+/5950 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- contrib/loaders/flash/npcx/Makefile | 65 +++ contrib/loaders/flash/npcx/npcx_algo.inc | 60 ++ contrib/loaders/flash/npcx/npcx_flash.c | 342 ++++++++++++ contrib/loaders/flash/npcx/npcx_flash.h | 179 ++++++ contrib/loaders/flash/npcx/npcx_flash.lds | 58 ++ .../loaders/flash/npcx/npcx_flash_config.h | 31 ++ doc/openocd.texi | 11 + src/flash/nor/Makefile.am | 1 + src/flash/nor/drivers.c | 2 + src/flash/nor/npcx.c | 524 ++++++++++++++++++ tcl/board/npcx_evb.cfg | 8 + tcl/target/npcx.cfg | 51 ++ 12 files changed, 1332 insertions(+) create mode 100644 contrib/loaders/flash/npcx/Makefile create mode 100644 contrib/loaders/flash/npcx/npcx_algo.inc create mode 100644 contrib/loaders/flash/npcx/npcx_flash.c create mode 100644 contrib/loaders/flash/npcx/npcx_flash.h create mode 100644 contrib/loaders/flash/npcx/npcx_flash.lds create mode 100644 contrib/loaders/flash/npcx/npcx_flash_config.h create mode 100644 src/flash/nor/npcx.c create mode 100644 tcl/board/npcx_evb.cfg create mode 100644 tcl/target/npcx.cfg diff --git a/contrib/loaders/flash/npcx/Makefile b/contrib/loaders/flash/npcx/Makefile new file mode 100644 index 000000000..293bd02da --- /dev/null +++ b/contrib/loaders/flash/npcx/Makefile @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +BIN2C = ../../../../src/helper/bin2char.sh + +# Toolchain used in makefile +CROSS_COMPILE ?= arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +CPLUS = $(CROSS_COMPILE)g++ +CPP = $(CROSS_COMPILE)cpp +LD = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +OBJSIZE = $(CROSS_COMPILE)size + +TARGET = npcx_algo +OBJS := npcx_flash.o +FLAGS = -mthumb -Os -ffunction-sections -fdata-sections -g -gdwarf-3 --specs=nano.specs +FLAGS += -gstrict-dwarf -Wall -fno-strict-aliasing --asm + +CFLAGS = -c -I. -mcpu=cortex-m4 -fpack-struct + +PRE_LD_FILE = npcx_flash.lds +LD_FILE = npcx_flash_generated.lds +LDFLAGS = -Wl,-Map,lfw.map -Wl,-T$(LD_FILE) -nostartfiles + +all: $(TARGET).inc + +# Implicit rules +%.o: %.c + -@ echo CC $@ from $< + @$(CC) $< $(FLAGS) $(CFLAGS) -o $@ + + $(LD_FILE): $(PRE_LD_FILE) + -@ echo Generate $@ from $< + -@$(CPP) $(PRE_LD_FILE) | grep -v '^#' >>$(LD_FILE) + +$(TARGET).elf: $(OBJS) $(LD_FILE) + -@ echo LD $@ from $< + @$(LD) -o $@ $< $(FLAGS) $(LDFLAGS) + +%.bin: %.elf + -@ echo OBJCOPY $@ from $< + -@ $(OBJCOPY) $< -O binary $@ + -@ $(OBJSIZE) $< --format=berkeley + +%.inc: %.bin + @echo 'Building target: $@' + @echo 'Invoking Bin2Char Script' + $(BIN2C) < $< > $@ + rm $< $*.elf + @echo 'Finished building target: $@' + @echo ' ' + +clean: + @echo 'Cleaning Targets and Build Artifacts' + rm -rf *.inc *.bin *.elf *.map + rm -rf *.o *.d + rm -rf $(LD_FILE) + @echo 'Finished clean' + @echo ' ' + +.PRECIOUS: %.bin + +.PHONY: all clean diff --git a/contrib/loaders/flash/npcx/npcx_algo.inc b/contrib/loaders/flash/npcx/npcx_algo.inc new file mode 100644 index 000000000..4312fdb1b --- /dev/null +++ b/contrib/loaders/flash/npcx/npcx_algo.inc @@ -0,0 +1,60 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x2f,0xf9,0x00,0x00,0x48,0x15,0x0c,0x20, +0x03,0x4b,0x18,0x70,0x19,0x72,0x08,0x33,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47, +0x16,0x00,0x02,0x40,0x70,0xb5,0x11,0x4c,0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70, +0xc0,0x21,0x05,0x20,0xff,0xf7,0xec,0xff,0x0d,0x4a,0x0e,0x49,0x6f,0xf0,0x7f,0x43, +0x6f,0xf0,0x2e,0x05,0x10,0x46,0x15,0x70,0x06,0x78,0xf6,0x09,0xfc,0xd1,0x0e,0x78, +0xf6,0x07,0x01,0xd5,0x01,0x3b,0xf6,0xd1,0x22,0x78,0x42,0xf0,0x02,0x02,0x00,0x2b, +0x22,0x70,0x0c,0xbf,0x03,0x20,0x00,0x20,0x70,0xbd,0x00,0xbf,0x1f,0x00,0x02,0x40, +0x1e,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x08,0xb5,0xc0,0x21,0x06,0x20,0xff,0xf7, +0xc7,0xff,0xff,0xf7,0xcf,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f, +0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0xf8,0xb5,0x12,0x4c, +0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,0x10,0x4b,0x17,0x46,0xc0,0xf3,0x07,0x42, +0x1a,0x70,0xc0,0xf3,0x07,0x22,0xc0,0xb2,0x03,0xf8,0x01,0x2c,0x0e,0x46,0x03,0xf8, +0x02,0x0c,0xe8,0x21,0x02,0x20,0xff,0xf7,0xa3,0xff,0x00,0x25,0xae,0x42,0x04,0xd8, +0x23,0x78,0x43,0xf0,0x02,0x03,0x23,0x70,0xf8,0xbd,0x78,0x5d,0xe0,0x21,0xff,0xf7, +0x97,0xff,0x01,0x35,0xf2,0xe7,0x00,0xbf,0x1f,0x00,0x02,0x40,0x19,0x00,0x02,0x40, +0x70,0x47,0x2d,0xe9,0xf0,0x41,0x00,0xf1,0xff,0x06,0x26,0xf0,0xff,0x06,0x34,0x1a, +0x8c,0x42,0x28,0xbf,0x0c,0x46,0x80,0x46,0x0d,0x46,0x17,0x46,0x5c,0xb1,0xff,0xf7, +0xb3,0xff,0x58,0xb9,0x3a,0x46,0xa1,0xb2,0x40,0x46,0xff,0xf7,0xbf,0xff,0xff,0xf7, +0x81,0xff,0x18,0xb9,0x27,0x44,0x2c,0x1b,0x14,0xb9,0x20,0x46,0xbd,0xe8,0xf0,0x81, +0xb4,0xf5,0x80,0x7f,0x25,0x46,0x28,0xbf,0x4f,0xf4,0x80,0x75,0xff,0xf7,0x9c,0xff, +0x00,0x28,0xf3,0xd1,0x3a,0x46,0xa9,0xb2,0x30,0x46,0xff,0xf7,0xa7,0xff,0xff,0xf7, +0x69,0xff,0x00,0x28,0xea,0xd1,0x2f,0x44,0x2e,0x44,0x64,0x1b,0xe4,0xe7,0x00,0x00, +0x2d,0xe9,0xf0,0x47,0x14,0x4e,0x15,0x4f,0xdf,0xf8,0x54,0x80,0x05,0x46,0x0c,0x46, +0x8a,0x46,0x05,0xeb,0x04,0x09,0xa9,0xeb,0x0a,0x09,0xba,0xf1,0x00,0x0f,0x02,0xd1, +0x50,0x46,0xbd,0xe8,0xf0,0x87,0xff,0xf7,0x77,0xff,0x00,0x28,0xf9,0xd1,0xc9,0xf3, +0x07,0x43,0x33,0x70,0xc9,0xf3,0x07,0x23,0x5f,0xfa,0x89,0xf9,0x3b,0x70,0xc8,0x21, +0x20,0x20,0x88,0xf8,0x00,0x90,0xff,0xf7,0x33,0xff,0xff,0xf7,0x3b,0xff,0x00,0x28, +0xe7,0xd1,0xaa,0xf5,0x80,0x5a,0xdc,0xe7,0x19,0x00,0x02,0x40,0x18,0x00,0x02,0x40, +0x17,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7,0x57,0xff,0x38,0xb9,0xc0,0x21,0xc7,0x20, +0xff,0xf7,0x1e,0xff,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x24,0xbf,0x08,0xbd,0x00,0x00, +0x38,0xb5,0xff,0xf7,0x49,0xff,0x04,0x46,0xc0,0xb9,0x0d,0x4b,0x0d,0x4d,0xf2,0x21, +0x28,0x70,0x18,0x70,0x01,0x20,0xff,0xf7,0x0b,0xff,0xff,0xf7,0x13,0xff,0x04,0x46, +0x60,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7,0x03,0xff,0x2b,0x78,0x2b,0xb9,0xc1,0x21, +0x35,0x20,0xff,0xf7,0xfd,0xfe,0x2b,0x78,0x03,0xb1,0x02,0x24,0x20,0x46,0x38,0xbd, +0x1b,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x10,0xb5,0xc3,0x21,0x04,0x46,0x9f,0x20, +0xff,0xf7,0xee,0xfe,0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78, +0x12,0x78,0x1b,0x02,0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf, +0x1a,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0x10,0x22,0x00,0x21,0x00,0xf0, +0x4d,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0x73,0xb5,0x21,0x48,0x20,0x4c,0xff,0xf7, +0xf3,0xff,0x20,0x4a,0x13,0x78,0x43,0xf0,0x80,0x03,0x13,0x70,0xff,0xf7,0xb0,0xff, +0x05,0x46,0x58,0xb9,0x1c,0x4e,0xe3,0x68,0x00,0x2b,0xfc,0xd0,0xa3,0x68,0x01,0x3b, +0x03,0x2b,0x2a,0xd8,0xdf,0xe8,0x03,0xf0,0x04,0x18,0x20,0x23,0xe5,0x60,0xfd,0xe7, +0x01,0xa8,0xff,0xf7,0xc1,0xff,0xa8,0xb9,0x01,0x9b,0x33,0x70,0x1a,0x0a,0x1b,0x0c, +0x72,0x70,0xb3,0x70,0xf0,0x70,0x23,0x7b,0x25,0x73,0x63,0x7b,0x65,0x73,0xa3,0x7b, +0xa5,0x73,0xe3,0x7b,0xe5,0x73,0xde,0xe7,0x20,0x68,0x61,0x68,0xff,0xf7,0x48,0xff, +0x00,0x28,0xf0,0xd0,0xe0,0x60,0xfe,0xe7,0xff,0xf7,0x74,0xff,0xf8,0xe7,0x20,0x68, +0x61,0x68,0x32,0x46,0xff,0xf7,0x05,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0xbf, +0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x10,0x00,0x0c,0x20,0xf0,0xb5,0x05,0x00, +0x83,0x07,0x4e,0xd0,0x54,0x1e,0x00,0x2a,0x46,0xd0,0x0a,0x06,0x12,0x0e,0x03,0x00, +0x03,0x26,0x02,0xe0,0x01,0x35,0x01,0x3c,0x3e,0xd3,0x01,0x33,0x2a,0x70,0x33,0x42, +0xf8,0xd1,0x03,0x2c,0x2f,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43,0x2a,0x04, +0x15,0x43,0x0f,0x2c,0x38,0xd9,0x27,0x00,0x10,0x3f,0x3f,0x09,0x3e,0x01,0xb4,0x46, +0x1e,0x00,0x1a,0x00,0x10,0x36,0x66,0x44,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60, +0x10,0x32,0xb2,0x42,0xf8,0xd1,0x0f,0x26,0x0c,0x22,0x01,0x37,0x3f,0x01,0x26,0x40, +0xdb,0x19,0x37,0x00,0x22,0x42,0x1a,0xd0,0x3e,0x1f,0xb6,0x08,0xb4,0x00,0xa4,0x46, +0x1a,0x00,0x1c,0x1d,0x64,0x44,0x20,0xc2,0xa2,0x42,0xfc,0xd1,0x03,0x24,0x01,0x36, +0xb6,0x00,0x9b,0x19,0x3c,0x40,0x00,0x2c,0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e, +0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1,0xf0,0xbc,0x02,0xbc,0x08,0x47,0x34,0x00, +0xf1,0xe7,0x14,0x00,0x03,0x00,0xbc,0xe7,0x27,0x00,0xdd,0xe7, diff --git a/contrib/loaders/flash/npcx/npcx_flash.c b/contrib/loaders/flash/npcx/npcx_flash.c new file mode 100644 index 000000000..d60624ae8 --- /dev/null +++ b/contrib/loaders/flash/npcx/npcx_flash.c @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2020 by Nuvoton Technology Corporation + * Mulin Chao + * Wealian Liao + */ + +#include +#include +#include "npcx_flash.h" + +/*---------------------------------------------------------------------------- + * NPCX flash driver + *----------------------------------------------------------------------------*/ +static void flash_execute_cmd(uint8_t code, uint8_t cts) +{ + /* Set UMA code */ + NPCX_UMA_CODE = code; + /* Execute UMA flash transaction by CTS setting */ + NPCX_UMA_CTS = cts; + /* Wait for transaction completed */ + while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) + ; +} + +static void flash_cs_level(uint8_t level) +{ + /* Program chip select pin to high/low level */ + if (level) + NPCX_SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1); + else + NPCX_CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1); +} + +static void flash_set_address(uint32_t dest_addr) +{ + uint8_t *addr = (uint8_t *)&dest_addr; + + /* Set target flash address */ + NPCX_UMA_AB2 = addr[2]; + NPCX_UMA_AB1 = addr[1]; + NPCX_UMA_AB0 = addr[0]; +} + +void delay(uint32_t i) +{ + while (i--) + ; +} + +static int flash_wait_ready(uint32_t timeout) +{ + /* Chip Select down. -- Burst mode */ + flash_cs_level(0); + + /* Command for Read status register */ + flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_ONLY); + while (timeout > 0) { + /* Read status register */ + NPCX_UMA_CTS = NPCX_MASK_RD_1BYTE; + while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) + ; + + if (!(NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_BUSY)) + break; + + if (--timeout > 0) + delay(100); + + }; /* Wait for Busy clear */ + + /* Chip Select high. */ + flash_cs_level(1); + + if (timeout == 0) + return NPCX_FLASH_STATUS_FAILED_TIMEOUT; + + return NPCX_FLASH_STATUS_OK; +} + +static int flash_write_enable(void) +{ + /* Write enable command */ + flash_execute_cmd(NPCX_CMD_WRITE_EN, NPCX_MASK_CMD_ONLY); + + /* Wait for flash is not busy */ + int status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + if (NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_WEL) + return NPCX_FLASH_STATUS_OK; + else + return NPCX_FLASH_STATUS_FAILED; +} + +static void flash_burst_write(uint32_t dest_addr, uint16_t bytes, + const uint8_t *data) +{ + /* Chip Select down -- Burst mode */ + flash_cs_level(0); + + /* Set write address */ + flash_set_address(dest_addr); + /* Start programming */ + flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_ADR); + for (uint32_t i = 0; i < bytes; i++) { + flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY); + data++; + } + + /* Chip Select up */ + flash_cs_level(1); +} + +/* The data to write cannot cross 256 Bytes boundary */ +static int flash_program_write(uint32_t addr, uint32_t size, + const uint8_t *data) +{ + int status = flash_write_enable(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + flash_burst_write(addr, size, data); + return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); +} + +int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data) +{ + int status; + uint32_t trunk_start = (offset + 0xff) & ~0xff; + + /* write head */ + uint32_t dest_addr = offset; + uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset); + + if (write_len) { + status = flash_program_write(dest_addr, write_len, data); + if (status != NPCX_FLASH_STATUS_OK) + return status; + data += write_len; + } + + dest_addr = trunk_start; + size -= write_len; + + /* write remaining data*/ + while (size > 0) { + write_len = (size > NPCX_FLASH_WRITE_SIZE) ? + NPCX_FLASH_WRITE_SIZE : size; + + status = flash_program_write(dest_addr, write_len, data); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + data += write_len; + dest_addr += write_len; + size -= write_len; + } + + return NPCX_FLASH_STATUS_OK; +} + +int flash_physical_erase(uint32_t offset, uint32_t size) +{ + /* Alignment has been checked in upper layer */ + for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE, + offset += NPCX_FLASH_ERASE_SIZE) { + /* Enable write */ + int status = flash_write_enable(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + /* Set erase address */ + flash_set_address(offset); + /* Start erase */ + flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_ADR); + /* Wait erase completed */ + status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + if (status != NPCX_FLASH_STATUS_OK) + return status; + } + + return NPCX_FLASH_STATUS_OK; +} + +int flash_physical_erase_all(void) +{ + /* Enable write */ + int status = flash_write_enable(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + /* Start erase */ + flash_execute_cmd(NPCX_CMD_CHIP_ERASE, NPCX_MASK_CMD_ONLY); + + /* Wait erase completed */ + status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + return NPCX_FLASH_STATUS_OK; +} + +int flash_physical_clear_stsreg(void) +{ + /* Enable write */ + int status = flash_write_enable(); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + NPCX_UMA_DB0 = 0x0; + NPCX_UMA_DB1 = 0x0; + + /* Write status register 1/2 */ + flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE); + + /* Wait writing completed */ + status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT); + if (status != NPCX_FLASH_STATUS_OK) + return status; + + /* Read status register 1/2 for checking */ + flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE); + if (NPCX_UMA_DB0 != 0x00) + return NPCX_FLASH_STATUS_FAILED; + flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE); + if (NPCX_UMA_DB0 != 0x00) + return NPCX_FLASH_STATUS_FAILED; + + return NPCX_FLASH_STATUS_OK; +} + +int flash_get_id(uint32_t *id) +{ + flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE); + *id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2; + + return NPCX_FLASH_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * flash loader function + *----------------------------------------------------------------------------*/ +uint32_t flashloader_init(struct npcx_flash_params *params) +{ + /* Initialize params buffers */ + memset(params, 0, sizeof(struct npcx_flash_params)); + + return NPCX_FLASH_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ +/* flashloader parameter structure */ +__attribute__ ((section(".buffers.g_cfg"))) +volatile struct npcx_flash_params g_cfg; +/* data buffer */ +__attribute__ ((section(".buffers.g_buf"))) +uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE]; + +int main(void) +{ + uint32_t id; + + /* set buffer */ + flashloader_init((struct npcx_flash_params *)&g_cfg); + + /* Avoid F_CS0 toggles while programming the internal flash. */ + NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI); + + /* clear flash status registers */ + int status = flash_physical_clear_stsreg(); + if (status != NPCX_FLASH_STATUS_OK) { + while (1) + g_cfg.sync = status; + } + + while (1) { + /* wait command*/ + while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT) + ; + + /* command handler */ + switch (g_cfg.cmd) { + case NPCX_FLASH_CMD_GET_FLASH_ID: + status = flash_get_id(&id); + if (status == NPCX_FLASH_STATUS_OK) { + g_buf[0] = id & 0xff; + g_buf[1] = (id >> 8) & 0xff; + g_buf[2] = (id >> 16) & 0xff; + g_buf[3] = 0x00; + } + break; + case NPCX_FLASH_CMD_ERASE_SECTORS: + status = flash_physical_erase(g_cfg.addr, g_cfg.len); + break; + case NPCX_FLASH_CMD_ERASE_ALL: + status = flash_physical_erase_all(); + break; + case NPCX_FLASH_CMD_PROGRAM: + status = flash_physical_write(g_cfg.addr, + g_cfg.len, + g_buf); + break; + default: + status = NPCX_FLASH_STATUS_FAILED_UNKNOWN_COMMAND; + break; + } + + /* clear & set result for next command */ + if (status != NPCX_FLASH_STATUS_OK) { + g_cfg.sync = status; + while (1) + ; + } else { + g_cfg.sync = NPCX_FLASH_LOADER_WAIT; + } + } + + return 0; +} + +__attribute__ ((section(".stack"))) +__attribute__ ((used)) +static uint32_t stack[NPCX_FLASH_LOADER_STACK_SIZE / 4]; +extern uint32_t _estack; +extern uint32_t _bss; +extern uint32_t _ebss; + +__attribute__ ((section(".entry"))) +void entry(void) +{ + /* set sp from end of stack */ + __asm(" ldr sp, =_estack - 4"); + + main(); + + __asm(" bkpt #0x00"); +} diff --git a/contrib/loaders/flash/npcx/npcx_flash.h b/contrib/loaders/flash/npcx/npcx_flash.h new file mode 100644 index 000000000..cc4f1ad50 --- /dev/null +++ b/contrib/loaders/flash/npcx/npcx_flash.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2020 by Nuvoton Technology Corporation + * Mulin Chao + * Wealian Liao + */ + +#ifndef OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H +#define OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H + +#include "npcx_flash_config.h" + +/* Bit functions */ +#define NPCX_SET_BIT(reg, bit) ((reg) |= (0x1 << (bit))) +#define NPCX_CLEAR_BIT(reg, bit) ((reg) &= (~(0x1 << (bit)))) +#define NPCX_IS_BIT_SET(reg, bit) (((reg) >> (bit)) & (0x1)) + +/* Field functions */ +#define NPCX_GET_POS_FIELD(pos, size) (pos) +#define NPCX_GET_SIZE_FIELD(pos, size) (size) +#define NPCX_FIELD_POS(field) NPCX_GET_POS_##field +#define NPCX_FIELD_SIZE(field) NPCX_GET_SIZE_##field +/* Read field functions */ +#define NPCX_GET_FIELD(reg, field) \ + _NPCX_GET_FIELD_((reg), NPCX_FIELD_POS(field), NPCX_FIELD_SIZE(field)) +#define _NPCX_GET_FIELD_(reg, f_pos, f_size) \ + (((reg) >> (f_pos)) & ((1 << (f_size)) - 1)) +/* Write field functions */ +#define NPCX_SET_FIELD(reg, field, value) \ + _NPCX_SET_FIELD_((reg), NPCX_FIELD_POS(field), NPCX_FIELD_SIZE(field), (value)) +#define _NPCX_SET_FIELD_(reg, f_pos, f_size, value) \ + ((reg) = ((reg) & (~(((1 << (f_size)) - 1) << (f_pos)))) | ((value) << (f_pos))) + +/* Register definitions */ +#define NPCX_REG32_ADDR(addr) ((volatile uint32_t *)(addr)) +#define NPCX_REG16_ADDR(addr) ((volatile uint16_t *)(addr)) +#define NPCX_REG8_ADDR(addr) ((volatile uint8_t *)(addr)) + +#define NPCX_HW_BYTE(addr) (*NPCX_REG8_ADDR(addr)) +#define NPCX_HW_WORD(addr) (*NPCX_REG16_ADDR(addr)) +#define NPCX_HW_DWORD(addr) (*NPCX_REG32_ADDR(addr)) + +/* Devalt */ +#define NPCX_SCFG_BASE_ADDR 0x400C3000 +#define NPCX_DEVCNT NPCX_HW_BYTE(NPCX_SCFG_BASE_ADDR + 0x000) +#define NPCX_DEVALT(n) NPCX_HW_BYTE(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) + +#define NPCX_DEVCNT_HIF_TYP_SEL_FIELD FIELD(2, 2) +#define NPCX_DEVCNT_JEN0_HEN 4 +#define NPCX_DEVCNT_JEN1_HEN 5 +#define NPCX_DEVCNT_F_SPI_TRIS 6 + +/* Pin-mux for SPI/FIU */ +#define NPCX_DEVALT0_SPIP_SL 0 +#define NPCX_DEVALT0_GPIO_NO_SPIP 3 +#define NPCX_DEVALT0_F_SPI_CS1_2 4 +#define NPCX_DEVALT0_F_SPI_CS1_1 5 +#define NPCX_DEVALT0_F_SPI_QUAD 6 +#define NPCX_DEVALT0_NO_F_SPI 7 + +/* Flash Interface Unit (FIU) registers */ +#define NPCX_FIU_BASE_ADDR 0x40020000 +#define NPCX_FIU_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x000) +#define NPCX_BURST_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x001) +#define NPCX_RESP_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x002) +#define NPCX_SPI_FL_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x014) +#define NPCX_UMA_CODE NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x016) +#define NPCX_UMA_AB0 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x017) +#define NPCX_UMA_AB1 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x018) +#define NPCX_UMA_AB2 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x019) +#define NPCX_UMA_DB0 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01A) +#define NPCX_UMA_DB1 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01B) +#define NPCX_UMA_DB2 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01C) +#define NPCX_UMA_DB3 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01D) +#define NPCX_UMA_CTS NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01E) +#define NPCX_UMA_ECTS NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01F) +#define NPCX_UMA_DB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x020) +#define NPCX_FIU_RD_CMD NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x030) +#define NPCX_FIU_DMM_CYC NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x032) +#define NPCX_FIU_EXT_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x033) +#define NPCX_FIU_UMA_AB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x034) + +/* FIU register fields */ +#define NPCX_RESP_CFG_IAD_EN 0 +#define NPCX_RESP_CFG_DEV_SIZE_EX 2 +#define NPCX_UMA_CTS_A_SIZE 3 +#define NPCX_UMA_CTS_C_SIZE 4 +#define NPCX_UMA_CTS_RD_WR 5 +#define NPCX_UMA_CTS_DEV_NUM 6 +#define NPCX_UMA_CTS_EXEC_DONE 7 +#define NPCX_UMA_ECTS_SW_CS0 0 +#define NPCX_UMA_ECTS_SW_CS1 1 +#define NPCX_UMA_ECTS_SEC_CS 2 +#define NPCX_UMA_ECTS_UMA_LOCK 3 + +/* Flash UMA commands for npcx internal SPI flash */ +#define NPCX_CMD_READ_ID 0x9F +#define NPCX_CMD_READ_MAN_DEV_ID 0x90 +#define NPCX_CMD_WRITE_EN 0x06 +#define NPCX_CMD_WRITE_STATUS 0x50 +#define NPCX_CMD_READ_STATUS_REG 0x05 +#define NPCX_CMD_READ_STATUS_REG2 0x35 +#define NPCX_CMD_WRITE_STATUS_REG 0x01 +#define NPCX_CMD_FLASH_PROGRAM 0x02 +#define NPCX_CMD_SECTOR_ERASE 0x20 +#define NPCX_CMD_PROGRAM_UINT_SIZE 0x08 +#define NPCX_CMD_PAGE_SIZE 0x00 +#define NPCX_CMD_READ_ID_TYPE 0x47 +#define NPCX_CMD_FAST_READ 0x0B +#define NPCX_CMD_CHIP_ERASE 0xC7 + +/* + * Status registers for SPI flash + */ +#define NPCX_SPI_FLASH_SR2_SUS (1 << 7) +#define NPCX_SPI_FLASH_SR2_CMP (1 << 6) +#define NPCX_SPI_FLASH_SR2_LB3 (1 << 5) +#define NPCX_SPI_FLASH_SR2_LB2 (1 << 4) +#define NPCX_SPI_FLASH_SR2_LB1 (1 << 3) +#define NPCX_SPI_FLASH_SR2_QE (1 << 1) +#define NPCX_SPI_FLASH_SR2_SRP1 (1 << 0) +#define NPCX_SPI_FLASH_SR1_SRP0 (1 << 7) +#define NPCX_SPI_FLASH_SR1_SEC (1 << 6) +#define NPCX_SPI_FLASH_SR1_TB (1 << 5) +#define NPCX_SPI_FLASH_SR1_BP2 (1 << 4) +#define NPCX_SPI_FLASH_SR1_BP1 (1 << 3) +#define NPCX_SPI_FLASH_SR1_BP0 (1 << 2) +#define NPCX_SPI_FLASH_SR1_WEL (1 << 1) +#define NPCX_SPI_FLASH_SR1_BUSY (1 << 0) + +#define NPCX_MASK_CMD_ONLY (0xC0) +#define NPCX_MASK_CMD_ADR (0xC0 | 0x08) +#define NPCX_MASK_CMD_ADR_WR (0xC0 | 0x20 | 0x08 | 0x01) +#define NPCX_MASK_RD_1BYTE (0xC0 | 0x10 | 0x01) +#define NPCX_MASK_RD_2BYTE (0xC0 | 0x10 | 0x02) +#define NPCX_MASK_RD_3BYTE (0xC0 | 0x10 | 0x03) +#define NPCX_MASK_RD_4BYTE (0xC0 | 0x10 | 0x04) +#define NPCX_MASK_CMD_RD_1BYTE (0xC0 | 0x01) +#define NPCX_MASK_CMD_RD_2BYTE (0xC0 | 0x02) +#define NPCX_MASK_CMD_RD_3BYTE (0xC0 | 0x03) +#define NPCX_MASK_CMD_RD_4BYTE (0xC0 | 0x04) +#define NPCX_MASK_CMD_WR_ONLY (0xC0 | 0x20) +#define NPCX_MASK_CMD_WR_1BYTE (0xC0 | 0x20 | 0x10 | 0x01) +#define NPCX_MASK_CMD_WR_2BYTE (0xC0 | 0x20 | 0x10 | 0x02) +#define NPCX_MASK_CMD_WR_ADR (0xC0 | 0x20 | 0x08) + +/* Flash loader parameters */ +struct __attribute__((__packed__)) npcx_flash_params { + uint32_t addr; /* Address in flash */ + uint32_t len; /* Number of bytes */ + uint32_t cmd; /* Command */ + uint32_t sync; /* Handshake signal */ +}; + +/* Flash trigger signal */ +enum npcx_flash_handshake { + NPCX_FLASH_LOADER_WAIT = 0x0, /* Idle */ + NPCX_FLASH_LOADER_EXECUTE = 0xFFFFFFFF /* Execute Command */ +}; + +/* Flash loader command */ +enum npcx_flash_commands { + NPCX_FLASH_CMD_NO_ACTION = 0, /* No action, default value */ + NPCX_FLASH_CMD_GET_FLASH_ID, /* Get the internal flash ID */ + NPCX_FLASH_CMD_ERASE_SECTORS, /* Erase unprotected sectors */ + NPCX_FLASH_CMD_ERASE_ALL, /* Erase all */ + NPCX_FLASH_CMD_PROGRAM, /* Program data */ +}; + +/* Status */ +enum npcx_flash_status { + NPCX_FLASH_STATUS_OK = 0, + NPCX_FLASH_STATUS_FAILED_UNKNOWN_COMMAND, + NPCX_FLASH_STATUS_FAILED, + NPCX_FLASH_STATUS_FAILED_TIMEOUT, +}; + +#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H */ diff --git a/contrib/loaders/flash/npcx/npcx_flash.lds b/contrib/loaders/flash/npcx/npcx_flash.lds new file mode 100644 index 000000000..0d782523a --- /dev/null +++ b/contrib/loaders/flash/npcx/npcx_flash.lds @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "npcx_flash_config.h" + +/* Application memory map */ +MEMORY { + /* buffer + parameters */ + BUFFER (RWX) : ORIGIN = NPCX_FLASH_LOADER_PARAMS_ADDR, + LENGTH = NPCX_FLASH_LOADER_PARAMS_SIZE + NPCX_FLASH_LOADER_BUFFER_SIZE + + PROGRAM (RWX) : ORIGIN = NPCX_FLASH_LOADER_PROGRAM_ADDR, + LENGTH = NPCX_FLASH_LOADER_PROGRAM_SIZE +} + +/* Sections used for flashing */ +SECTIONS +{ + .buffers (NOLOAD) : + { + _buffers = .; + *(.buffers.g_cfg) + *(.buffers.g_buf) + *(.buffers*) + _ebuffers = .; + } > BUFFER + + .text : + { + _text = .; + *(.entry*) + *(.text*) + _etext = .; + } > PROGRAM + + .data : + { _data = .; + *(.rodata*) + *(.data*) + _edata = .; + } > PROGRAM + + .bss : + { + __bss_start__ = .; + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + __bss_end__ = .; + } > PROGRAM + + .stack (NOLOAD) : + { + _stack = .; + *(.stack*) + _estack = .; + } > PROGRAM +} diff --git a/contrib/loaders/flash/npcx/npcx_flash_config.h b/contrib/loaders/flash/npcx/npcx_flash_config.h new file mode 100644 index 000000000..9ec1c5e33 --- /dev/null +++ b/contrib/loaders/flash/npcx/npcx_flash_config.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2021 by Nuvoton Technology Corporation + * Mulin Chao + * Wealian Liao + */ + +#ifndef OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H +#define OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H + +#define NPCX_FLASH_ABORT_TIMEOUT 0xFFFFFF + +/* NPCX chip information */ +#define NPCX_FLASH_WRITE_SIZE 256L /* One page size for write */ +#define NPCX_FLASH_ERASE_SIZE 0x1000 + +/* NPCX flash loader information */ +#define NPCX_FLASH_LOADER_WORKING_ADDR 0x200C0000 +#define NPCX_FLASH_LOADER_PARAMS_ADDR NPCX_FLASH_LOADER_WORKING_ADDR +#define NPCX_FLASH_LOADER_PARAMS_SIZE 16 +#define NPCX_FLASH_LOADER_BUFFER_ADDR (NPCX_FLASH_LOADER_PARAMS_ADDR + NPCX_FLASH_LOADER_PARAMS_SIZE) +#define NPCX_FLASH_LOADER_BUFFER_SIZE NPCX_FLASH_ERASE_SIZE +#define NPCX_FLASH_LOADER_PROGRAM_ADDR (NPCX_FLASH_LOADER_BUFFER_ADDR + NPCX_FLASH_LOADER_BUFFER_SIZE) +#define NPCX_FLASH_LOADER_PROGRAM_SIZE 0x1000 + +/* Stack size in byte. 4 byte size alignment */ +#define NPCX_FLASH_LOADER_STACK_SIZE 400 + + +#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H */ diff --git a/doc/openocd.texi b/doc/openocd.texi index 2759a39d3..9c94c7168 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6777,6 +6777,17 @@ Show information about flash driver. @end deffn +@deffn {Flash Driver} {npcx} +All versions of the NPCX microcontroller families from Nuvoton include internal +flash. The NPCX flash driver supports the NPCX family of devices. The driver +automatically recognizes the specific version's flash parameters and +autoconfigures itself. The flash bank starts at address 0x64000000. + +@example +flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME +@end example +@end deffn + @deffn {Flash Driver} {nrf5} All members of the nRF51 microcontroller families from Nordic Semiconductor include internal flash and use ARM Cortex-M0 core. diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 532670436..a5ef42210 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -44,6 +44,7 @@ NOR_DRIVERS = \ %D%/mrvlqspi.c \ %D%/niietcm4.c \ %D%/non_cfi.c \ + %D%/npcx.c \ %D%/nrf5.c \ %D%/numicro.c \ %D%/ocl.c \ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 6eadc756b..3e35c0954 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -56,6 +56,7 @@ extern const struct flash_driver mdr_flash; extern const struct flash_driver mrvlqspi_flash; extern const struct flash_driver msp432_flash; extern const struct flash_driver niietcm4_flash; +extern const struct flash_driver npcx_flash; extern const struct flash_driver nrf5_flash; extern const struct flash_driver nrf51_flash; extern const struct flash_driver numicro_flash; @@ -130,6 +131,7 @@ static const struct flash_driver * const flash_drivers[] = { &mrvlqspi_flash, &msp432_flash, &niietcm4_flash, + &npcx_flash, &nrf5_flash, &nrf51_flash, &numicro_flash, diff --git a/src/flash/nor/npcx.c b/src/flash/nor/npcx.c new file mode 100644 index 000000000..af623e577 --- /dev/null +++ b/src/flash/nor/npcx.c @@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2020 by Nuvoton Technology Corporation + * Mulin Chao + * Wealian Liao + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include +#include +#include +#include "../../../contrib/loaders/flash/npcx/npcx_flash.h" + +/* NPCX flash loader */ +const uint8_t npcx_algo[] = { +#include "../../../contrib/loaders/flash/npcx/npcx_algo.inc" +}; + +#define NPCX_FLASH_TIMEOUT_MS 8000 +#define NPCX_FLASH_BASE_ADDR 0x64000000 + +/* flash list */ +enum npcx_flash_device_index { + NPCX_FLASH_256KB = 0, + NPCX_FLASH_512KB = 1, + NPCX_FLASH_1MB = 2, + NPCX_FLASH_UNKNOWN, +}; + +struct npcx_flash_bank { + const char *family_name; + uint32_t sector_length; + bool probed; + enum npcx_flash_device_index flash; + struct working_area *working_area; + struct armv7m_algorithm armv7m_info; + const uint8_t *algo_code; + uint32_t algo_size; + uint32_t algo_working_size; + uint32_t buffer_addr; + uint32_t params_addr; +}; + +struct npcx_flash_info { + char *name; + uint32_t id; + uint32_t size; +}; + +static const struct npcx_flash_info flash_info[] = { + [NPCX_FLASH_256KB] = { + .name = "256KB Flash", + .id = 0xEF4012, + .size = 256 * 1024, + }, + [NPCX_FLASH_512KB] = { + .name = "512KB Flash", + .id = 0xEF4013, + .size = 512 * 1024, + }, + [NPCX_FLASH_1MB] = { + .name = "1MB Flash", + .id = 0xEF4014, + .size = 1024 * 1024, + }, + [NPCX_FLASH_UNKNOWN] = { + .name = "Unknown Flash", + .size = 0xFFFFFFFF, + }, +}; + +static int npcx_init(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + + /* Check for working area to use for flash helper algorithm */ + if (npcx_bank->working_area) { + target_free_working_area(target, npcx_bank->working_area); + npcx_bank->working_area = NULL; + } + + int retval = target_alloc_working_area(target, npcx_bank->algo_working_size, + &npcx_bank->working_area); + if (retval != ERROR_OK) + return retval; + + /* Confirm the defined working address is the area we need to use */ + if (npcx_bank->working_area->address != NPCX_FLASH_LOADER_WORKING_ADDR) { + LOG_ERROR("%s: Invalid working address", npcx_bank->family_name); + LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32 "' in your target configuration", + NPCX_FLASH_LOADER_WORKING_ADDR); + target_free_working_area(target, npcx_bank->working_area); + npcx_bank->working_area = NULL; + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + /* Write flash helper algorithm into target memory */ + retval = target_write_buffer(target, NPCX_FLASH_LOADER_PROGRAM_ADDR, + npcx_bank->algo_size, npcx_bank->algo_code); + if (retval != ERROR_OK) { + LOG_ERROR("%s: Failed to load flash helper algorithm", + npcx_bank->family_name); + target_free_working_area(target, npcx_bank->working_area); + npcx_bank->working_area = NULL; + return retval; + } + + /* Initialize the ARMv7 specific info to run the algorithm */ + npcx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + npcx_bank->armv7m_info.core_mode = ARM_MODE_THREAD; + + /* Begin executing the flash helper algorithm */ + retval = target_start_algorithm(target, 0, NULL, 0, NULL, + NPCX_FLASH_LOADER_PROGRAM_ADDR, 0, + &npcx_bank->armv7m_info); + if (retval != ERROR_OK) { + LOG_ERROR("%s: Failed to start flash helper algorithm", + npcx_bank->family_name); + target_free_working_area(target, npcx_bank->working_area); + npcx_bank->working_area = NULL; + return retval; + } + + /* + * At this point, the algorithm is running on the target and + * ready to receive commands and data to flash the target + */ + + return retval; +} + +static int npcx_quit(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + + /* Regardless of the algo's status, attempt to halt the target */ + (void)target_halt(target); + + /* Now confirm target halted and clean up from flash helper algorithm */ + int retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, + NPCX_FLASH_TIMEOUT_MS, &npcx_bank->armv7m_info); + + target_free_working_area(target, npcx_bank->working_area); + npcx_bank->working_area = NULL; + + return retval; +} + +static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + uint32_t status_addr = params_addr + offsetof(struct npcx_flash_params, sync); + uint32_t status; + int64_t start_ms = timeval_ms(); + + do { + int retval = target_read_u32(target, status_addr, &status); + if (retval != ERROR_OK) + return retval; + + keep_alive(); + + int64_t elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > NPCX_FLASH_TIMEOUT_MS) + break; + } while (status == NPCX_FLASH_LOADER_EXECUTE); + + if (status != NPCX_FLASH_LOADER_WAIT) { + LOG_ERROR("%s: Flash operation failed, status=0x%" PRIx32, + npcx_bank->family_name, + status); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static enum npcx_flash_device_index npcx_get_flash_id(struct flash_bank *bank, uint32_t *flash_id) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + struct npcx_flash_params algo_params; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + int retval = npcx_init(bank); + if (retval != ERROR_OK) + return retval; + + /* Set up algorithm parameters for get flash ID command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_GET_FLASH_ID); + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); + + /* Issue flash helper algorithm parameters for get flash ID */ + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + if (retval != ERROR_OK) { + (void)npcx_quit(bank); + return retval; + } + + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_EXECUTE); + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + + /* If no error, wait for finishing */ + if (retval == ERROR_OK) { + retval = npcx_wait_algo_done(bank, npcx_bank->params_addr); + if (retval == ERROR_OK) + target_read_u32(target, NPCX_FLASH_LOADER_BUFFER_ADDR, flash_id); + } + + /* Regardless of errors, try to close down algo */ + (void)npcx_quit(bank); + + return retval; +} + +static int npcx_get_flash(uint32_t flash_id) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(flash_info) - 1; i++) { + if (flash_info[i].id == flash_id) + return i; + } + + return NPCX_FLASH_UNKNOWN; +} + +static int npcx_probe(struct flash_bank *bank) +{ + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + uint32_t sector_length = NPCX_FLASH_ERASE_SIZE; + uint32_t flash_id; + + /* Set up appropriate flash helper algorithm */ + npcx_bank->algo_code = npcx_algo; + npcx_bank->algo_size = sizeof(npcx_algo); + npcx_bank->algo_working_size = NPCX_FLASH_LOADER_PARAMS_SIZE + + NPCX_FLASH_LOADER_BUFFER_SIZE + + NPCX_FLASH_LOADER_PROGRAM_SIZE; + npcx_bank->buffer_addr = NPCX_FLASH_LOADER_BUFFER_ADDR; + npcx_bank->params_addr = NPCX_FLASH_LOADER_PARAMS_ADDR; + + int retval = npcx_get_flash_id(bank, &flash_id); + if (retval != ERROR_OK) + return retval; + + npcx_bank->flash = npcx_get_flash(flash_id); + + unsigned int num_sectors = flash_info[npcx_bank->flash].size / sector_length; + + bank->sectors = calloc(num_sectors, sizeof(struct flash_sector)); + if (!bank->sectors) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + bank->base = NPCX_FLASH_BASE_ADDR; + bank->num_sectors = num_sectors; + bank->size = num_sectors * sector_length; + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + npcx_bank->sector_length = sector_length; + + for (unsigned int i = 0; i < num_sectors; i++) { + bank->sectors[i].offset = i * sector_length; + bank->sectors[i].size = sector_length; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } + + /* We've successfully determined the stats on the flash bank */ + npcx_bank->probed = true; + + /* If we fall through to here, then all went well */ + return ERROR_OK; +} + +static int npcx_auto_probe(struct flash_bank *bank) +{ + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + int retval = ERROR_OK; + + if (!npcx_bank->probed) + retval = npcx_probe(bank); + + return retval; +} + +FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command) +{ + struct npcx_flash_bank *npcx_bank; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + npcx_bank = calloc(1, sizeof(struct npcx_flash_bank)); + if (!npcx_bank) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + /* Initialize private flash information */ + npcx_bank->family_name = "npcx"; + npcx_bank->sector_length = NPCX_FLASH_ERASE_SIZE; + + /* Finish initialization of bank */ + bank->driver_priv = npcx_bank; + bank->next = NULL; + + return ERROR_OK; +} + +static int npcx_chip_erase(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + struct npcx_flash_params algo_params; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Make sure we've probed the flash to get the device and size */ + int retval = npcx_auto_probe(bank); + if (retval != ERROR_OK) + return retval; + + retval = npcx_init(bank); + if (retval != ERROR_OK) + return retval; + + /* Set up algorithm parameters for chip erase command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_ALL); + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); + + /* Set algorithm parameters */ + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + if (retval != ERROR_OK) { + (void)npcx_quit(bank); + return retval; + } + + /* Issue flash helper algorithm parameters for chip erase */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_EXECUTE); + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + + /* If no error, wait for chip erase finish */ + if (retval == ERROR_OK) + retval = npcx_wait_algo_done(bank, npcx_bank->params_addr); + + /* Regardless of errors, try to close down algo */ + (void)npcx_quit(bank); + + return retval; +} + +static int npcx_erase(struct flash_bank *bank, unsigned int first, + unsigned int last) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + struct npcx_flash_params algo_params; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if ((first == 0) && (last == (bank->num_sectors - 1))) { + /* Request chip erase */ + return npcx_chip_erase(bank); + } + + uint32_t address = first * npcx_bank->sector_length; + uint32_t length = (last - first + 1) * npcx_bank->sector_length; + + /* Make sure we've probed the flash to get the device and size */ + int retval = npcx_auto_probe(bank); + if (retval != ERROR_OK) + return retval; + + retval = npcx_init(bank); + if (retval != ERROR_OK) + return retval; + + /* Set up algorithm parameters for erase command */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address); + target_buffer_set_u32(target, (uint8_t *)&algo_params.len, length); + target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_SECTORS); + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); + + /* Set algorithm parameters */ + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + if (retval != ERROR_OK) { + (void)npcx_quit(bank); + return retval; + } + + /* Issue flash helper algorithm parameters for erase */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_EXECUTE); + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + + /* If no error, wait for erase to finish */ + if (retval == ERROR_OK) + retval = npcx_wait_algo_done(bank, npcx_bank->params_addr); + + /* Regardless of errors, try to close down algo */ + (void)npcx_quit(bank); + + return retval; +} + +static int npcx_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + struct npcx_flash_params algo_params; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Make sure we've probed the flash to get the device and size */ + int retval = npcx_auto_probe(bank); + if (retval != ERROR_OK) + return retval; + + retval = npcx_init(bank); + if (retval != ERROR_OK) + return retval; + + /* Initialize algorithm parameters to default values */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_PROGRAM); + + uint32_t address = offset; + + while (count > 0) { + uint32_t size = (count > NPCX_FLASH_LOADER_BUFFER_SIZE) ? + NPCX_FLASH_LOADER_BUFFER_SIZE : count; + + /* Put the data into buffer */ + retval = target_write_buffer(target, npcx_bank->buffer_addr, + size, buffer); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to write data to target memory"); + break; + } + + /* Update algo parameters for flash write */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address); + target_buffer_set_u32(target, (uint8_t *)&algo_params.len, size); + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT); + + /* Set algorithm parameters */ + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + if (retval != ERROR_OK) + break; + + /* Issue flash helper algorithm parameters for flash write */ + target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_EXECUTE); + retval = target_write_buffer(target, npcx_bank->params_addr, + sizeof(algo_params), (uint8_t *)&algo_params); + if (retval != ERROR_OK) + break; + + /* Wait for flash write finish */ + retval = npcx_wait_algo_done(bank, npcx_bank->params_addr); + if (retval != ERROR_OK) + break; + + count -= size; + buffer += size; + address += size; + } + + /* Regardless of errors, try to close down algo */ + (void)npcx_quit(bank); + + return retval; +} + +static int npcx_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + struct npcx_flash_bank *npcx_bank = bank->driver_priv; + + command_print_sameline(cmd, "%s flash: %s\n", + npcx_bank->family_name, + flash_info[npcx_bank->flash].name); + + return ERROR_OK; +} + +const struct flash_driver npcx_flash = { + .name = "npcx", + .flash_bank_command = npcx_flash_bank_command, + .erase = npcx_erase, + .write = npcx_write, + .read = default_flash_read, + .probe = npcx_probe, + .auto_probe = npcx_auto_probe, + .erase_check = default_flash_blank_check, + .info = npcx_info, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/tcl/board/npcx_evb.cfg b/tcl/board/npcx_evb.cfg new file mode 100644 index 000000000..4f28bc964 --- /dev/null +++ b/tcl/board/npcx_evb.cfg @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Nuvoton NPCX Evaluation Board + +source [find interface/jlink.cfg] +transport select swd + +source [find target/npcx.cfg] diff --git a/tcl/target/npcx.cfg b/tcl/target/npcx.cfg new file mode 100644 index 000000000..1a21e1f7f --- /dev/null +++ b/tcl/target/npcx.cfg @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for Nuvoton NPCX Cortex-M4 Series + +# Adapt based on what transport is active. +source [find target/swj-dp.tcl] + +# Set Chipname +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME NPCX_M4 +} + +# SWD DAP ID of Nuvoton NPCX Cortex-M4. +if { [info exists CPUDAPID ] } { + set _CPUDAPID $CPUDAPID +} else { + set _CPUDAPID 0x4BA00477 +} + +# Work-area is a space in RAM used for flash programming +# By default use 32kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x8000 +} + +# Debug Adapter Target Settings +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUDAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x200c0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# Initial JTAG/SWD speed +# For safety purposes, set for the lowest cpu clock configuration +# 4MHz / 6 = 666KHz, so use 600KHz for it +adapter speed 600 + +# For safety purposes, set for the lowest cpu clock configuration +$_TARGETNAME configure -event reset-start {adapter speed 600} + +# use sysresetreq to perform a system reset +cortex_m reset_config sysresetreq + +# flash configuration +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME From 4b1492bb8e7d15927d3f27aac5432a7b19cef28d Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sat, 6 Mar 2021 22:46:35 +0100 Subject: [PATCH 04/56] flash/stm32l4x: switch to to c loader instead of assembly loader switching to C loader instead of the assembly version will enhance readability will reduce the maintenance effort. besides the switch to C loader, we added a new parameters to the loader like flash_word_size and flash_sr_bsy_mask in order to support properly STM32U5x and STM32G0Bx/G0Cx in dual-bank mode. Change-Id: I24cafc2ba637a065593a0506eae787b21080a0ba Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6109 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- contrib/loaders/flash/stm32/Makefile | 9 +- contrib/loaders/flash/stm32/stm32l4x.S | 105 ------------- contrib/loaders/flash/stm32/stm32l4x.c | 189 +++++++++++++++++++++++ contrib/loaders/flash/stm32/stm32l4x.inc | 15 +- src/flash/nor/stm32l4x.c | 72 ++++----- src/flash/nor/stm32l4x.h | 18 +++ 6 files changed, 259 insertions(+), 149 deletions(-) delete mode 100644 contrib/loaders/flash/stm32/stm32l4x.S create mode 100644 contrib/loaders/flash/stm32/stm32l4x.c diff --git a/contrib/loaders/flash/stm32/Makefile b/contrib/loaders/flash/stm32/Makefile index b58b41284..cee282aa3 100644 --- a/contrib/loaders/flash/stm32/Makefile +++ b/contrib/loaders/flash/stm32/Makefile @@ -6,14 +6,19 @@ CC=$(CROSS_COMPILE)gcc OBJCOPY=$(CROSS_COMPILE)objcopy OBJDUMP=$(CROSS_COMPILE)objdump -CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL + +AFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL +CFLAGS = -c -mthumb -nostdlib -nostartfiles -Os -g -fPIC all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32lx.inc .PHONY: clean %.elf: %.S - $(CC) $(CFLAGS) $< -o $@ + $(CC) $(AFLAGS) $< -o $@ + +stm32l4x.elf: stm32l4x.c + $(CC) $(CFLAGS) -mcpu=cortex-m0plus -fstack-usage -Wa,-adhln=$(<:.c=.lst) $< -o $@ %.lst: %.elf $(OBJDUMP) -S $< > $@ diff --git a/contrib/loaders/flash/stm32/stm32l4x.S b/contrib/loaders/flash/stm32/stm32l4x.S deleted file mode 100644 index 9923ce772..000000000 --- a/contrib/loaders/flash/stm32/stm32l4x.S +++ /dev/null @@ -1,105 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010 by Spencer Oliver * - * spen@spen-soft.co.uk * - * * - * Copyright (C) 2011 Ƙyvind Harboe * - * oyvind.harboe@zylin.com * - * * - * Copyright (C) 2015 Uwe Bonnes * - * bon@elektron.ikp.physik.tu-darmstadt.de * - * * - * Copyright (C) 2018 Andreas Bolsch * - * andreas.bolsch@mni.thm.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * - ***************************************************************************/ - - .text - .syntax unified - .cpu cortex-m0 - .thumb - -/* - * Params : - * r0 = workarea start, status (out) - * r1 = workarea end + 1 - * r2 = target address - * r3 = count (64bit words) - * r4 = flash status register - * r5 = flash control register - * - * Clobbered: - * r6/7 - temp (64-bit) - */ - -#include "../../../../src/flash/nor/stm32l4x.h" - - .thumb_func - .global _start - -_start: - mov r8, r3 /* copy dword count */ -wait_fifo: - ldr r6, [r0, #0] /* read wp */ - cmp r6, #0 /* if wp == 0, */ - beq exit /* then abort */ - ldr r3, [r0, #4] /* read rp */ - subs r6, r6, r3 /* number of bytes available for read in r6 */ - bpl fifo_stat /* if not wrapped around, skip */ - adds r6, r6, r1 /* add end of buffer */ - subs r6, r6, r0 /* sub start of buffer */ -fifo_stat: - cmp r6, #8 /* wait until at least one dword available */ - bcc wait_fifo - - movs r6, #FLASH_PG /* flash program enable */ - str r6, [r5] /* write to FLASH_CR, start operation */ - ldmia r3!, {r6, r7} /* read one dword from src, increment ptr */ - stmia r2!, {r6, r7} /* write one dword to dst, increment ptr */ - dsb - ldr r7, =FLASH_BSY /* FLASH_BSY mask */ -busy: - ldr r6, [r4] /* get FLASH_SR register */ - tst r6, r7 /* BSY == 1 => operation in progress */ - bne busy /* if still set, wait more ... */ - movs r7, #FLASH_ERROR /* all error bits */ - tst r6, r7 /* check for any error bit */ - bne error /* fail ... */ - - cmp r3, r1 /* rp at end of buffer? */ - bcc upd_rp /* if no, then skip */ - subs r3, r3, r1 /* sub end of buffer */ - adds r3, r3, r0 /* add start of buffer */ - adds r3, r3, #8 /* skip wp and rp */ -upd_rp: - str r3, [r0, #4] /* store rp */ - mov r7, r8 /* get dword count */ - subs r7, r7, #1 /* decrement dword count */ - mov r8, r7 /* save dword count */ - beq exit /* exit if done */ - b wait_fifo - - .pool - -error: - movs r3, #0 - str r3, [r0, #4] /* set rp = 0 on error */ -exit: - mov r0, r6 /* return status in r0 */ - movs r6, #0 /* flash program disable */ - str r6, [r5] /* write to FLASH_CR */ - movs r6, #FLASH_ERROR /* all error bits */ - str r6, [r4] /* write to FLASH_CR to clear errors */ - bkpt #0x00 diff --git a/contrib/loaders/flash/stm32/stm32l4x.c b/contrib/loaders/flash/stm32/stm32l4x.c new file mode 100644 index 000000000..bcad98843 --- /dev/null +++ b/contrib/loaders/flash/stm32/stm32l4x.c @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** + * Copyright (C) 2021 Tarek BOCHKATI + * tarek.bouchkati@st.com + */ + +#include +#include "../../../../src/flash/nor/stm32l4x.h" + +static inline __attribute__((always_inline)) +void copy_buffer_u32(uint32_t *dst, uint32_t *src, int len) +{ + for (int i = 0; i < len; i++) + dst[i] = src[i]; +} + +/* this function is assumes that fifo_size is multiple of flash_word_size + * this condition is ensured by target_run_flash_async_algorithm + */ + +void write(volatile struct stm32l4_work_area *work_area, + uint8_t *fifo_end, + uint8_t *target_address, + uint32_t count) +{ + volatile uint32_t *flash_sr = (uint32_t *) work_area->params.flash_sr_addr; + volatile uint32_t *flash_cr = (uint32_t *) work_area->params.flash_cr_addr; + + /* optimization to avoid reading from memory each time */ + uint8_t *rp_cache = work_area->fifo.rp; + + /* fifo_start is used to wrap when we reach fifo_end */ + uint8_t *fifo_start = rp_cache; + + /* enable flash programming */ + *flash_cr = FLASH_PG; + + while (count) { + /* optimization to avoid reading from memory each time */ + uint8_t *wp_cache = work_area->fifo.wp; + if (wp_cache == 0) + break; /* aborted by target_run_flash_async_algorithm */ + + int32_t fifo_size = wp_cache - rp_cache; + if (fifo_size < 0) { + /* consider the linear fifo, we will wrap later */ + fifo_size = fifo_end - rp_cache; + } + + /* wait for at least a flash word */ + while (fifo_size >= work_area->params.flash_word_size) { + copy_buffer_u32((uint32_t *)target_address, + (uint32_t *)rp_cache, + work_area->params.flash_word_size / 4); + + /* update target_address and rp_cache */ + target_address += work_area->params.flash_word_size; + rp_cache += work_area->params.flash_word_size; + + /* wait for the busy flag */ + while (*flash_sr & work_area->params.flash_sr_bsy_mask) + ; + + if (*flash_sr & FLASH_ERROR) { + work_area->fifo.rp = 0; /* set rp to zero 0 on error */ + goto write_end; + } + + /* wrap if reach the fifo_end, and update rp in memory */ + if (rp_cache >= fifo_end) + rp_cache = fifo_start; + + /* flush the rp cache value, + * so target_run_flash_async_algorithm can fill the circular fifo */ + work_area->fifo.rp = rp_cache; + + /* update fifo_size and count */ + fifo_size -= work_area->params.flash_word_size; + count--; + } + } + +write_end: + /* disable flash programming */ + *flash_cr = 0; + + /* soft break the loader */ + __asm("bkpt 0"); +} + +/* by enabling this define 'DEBUG': + * the main() function can help help debugging the loader algo + * note: the application should be linked into RAM */ + +/* #define DEBUG */ + +#ifdef DEBUG +/* device selector: STM32L5 | STM32U5 | STM32WB | STM32WL | STM32WL_CPU2 | STM32G0Bx | ... */ +#define STM32U5 + +/* when using a secure device, and want to test the secure programming enable this define */ +/* #define SECURE */ + +#if defined(STM32U5) +# define FLASH_WORD_SIZE 16 +#else +# define FLASH_WORD_SIZE 8 +#endif + +#if defined(STM32WB) || defined(STM32WL) +# define FLASH_BASE 0x58004000 +#else +# define FLASH_BASE 0x40022000 +#endif + +#if defined(STM32G0Bx) +# define FLASH_BSY_MASK (FLASH_BSY | FLASH_BSY2) +#else +# define FLASH_BSY_MASK FLASH_BSY +#endif + +#if defined(STM32L5) || defined(STM32U5) +# ifdef SECURE +# define FLASH_KEYR_OFFSET 0x0c +# define FLASH_SR_OFFSET 0x24 +# define FLASH_CR_OFFSET 0x2c +# else +# define FLASH_KEYR_OFFSET 0x08 +# define FLASH_SR_OFFSET 0x20 +# define FLASH_CR_OFFSET 0x28 +# endif +#elif defined(STM32WL_CPU2) +# define FLASH_KEYR_OFFSET 0x08 +# define FLASH_SR_OFFSET 0x60 +# define FLASH_CR_OFFSET 0x64 +#else +# define FLASH_KEYR_OFFSET 0x08 +# define FLASH_SR_OFFSET 0x10 +# define FLASH_CR_OFFSET 0x14 +#endif + +#define FLASH_KEYR (uint32_t *)((FLASH_BASE) + (FLASH_KEYR_OFFSET)) +#define FLASH_SR (uint32_t *)((FLASH_BASE) + (FLASH_SR_OFFSET)) +#define FLASH_CR (uint32_t *)((FLASH_BASE) + (FLASH_CR_OFFSET)) + +int main() +{ + const uint32_t count = 2; + const uint32_t buf_size = count * FLASH_WORD_SIZE; + const uint32_t work_area_size = sizeof(struct stm32l4_work_area) + buf_size; + + uint8_t work_area_buf[work_area_size]; + struct stm32l4_work_area *workarea = (struct stm32l4_work_area *)work_area_buf; + + /* fill the workarea struct */ + workarea->params.flash_sr_addr = (uint32_t)(FLASH_SR); + workarea->params.flash_cr_addr = (uint32_t)(FLASH_CR); + workarea->params.flash_word_size = FLASH_WORD_SIZE; + workarea->params.flash_sr_bsy_mask = FLASH_BSY_MASK; + /* note: the workarea->stack is not used, in this configuration */ + + /* programming the existing memory raw content in workarea->fifo.buf */ + /* feel free to fill the memory with magical values ... */ + + workarea->fifo.wp = (uint8_t *)(&workarea->fifo.buf + buf_size); + workarea->fifo.rp = (uint8_t *)&workarea->fifo.buf; + + /* unlock the flash */ + *FLASH_KEYR = KEY1; + *FLASH_KEYR = KEY2; + + /* erase sector 0 */ + *FLASH_CR = FLASH_PER | FLASH_STRT; + while (*FLASH_SR & FLASH_BSY) + ; + + /* flash address, should be aligned to FLASH_WORD_SIZE */ + uint8_t *target_address = (uint8_t *) 0x8000000; + + write(workarea, + (uint8_t *)(workarea + work_area_size), + target_address, + count); + + while (1) + ; +} +#endif /* DEBUG */ diff --git a/contrib/loaders/flash/stm32/stm32l4x.inc b/contrib/loaders/flash/stm32/stm32l4x.inc index df5c7edd1..1ab400a0a 100644 --- a/contrib/loaders/flash/stm32/stm32l4x.inc +++ b/contrib/loaders/flash/stm32/stm32l4x.inc @@ -1,7 +1,10 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ -0x98,0x46,0x06,0x68,0x00,0x2e,0x23,0xd0,0x43,0x68,0xf6,0x1a,0x01,0xd5,0x76,0x18, -0x36,0x1a,0x08,0x2e,0xf5,0xd3,0x01,0x26,0x2e,0x60,0xc0,0xcb,0xc0,0xc2,0xbf,0xf3, -0x4f,0x8f,0x09,0x4f,0x26,0x68,0x3e,0x42,0xfc,0xd1,0xfa,0x27,0x3e,0x42,0x0d,0xd1, -0x8b,0x42,0x02,0xd3,0x5b,0x1a,0x1b,0x18,0x08,0x33,0x43,0x60,0x47,0x46,0x01,0x3f, -0xb8,0x46,0x05,0xd0,0xdd,0xe7,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x23,0x43,0x60, -0x30,0x46,0x00,0x26,0x2e,0x60,0xfa,0x26,0x26,0x60,0x00,0xbe, +0xf0,0xb5,0x87,0xb0,0x07,0x68,0x01,0x93,0x43,0x68,0x04,0x91,0x02,0x93,0x83,0x6f, +0x02,0x99,0x03,0x93,0x01,0x23,0x0b,0x60,0x03,0x9b,0x01,0x99,0x00,0x29,0x1f,0xd0, +0x41,0x6f,0x00,0x29,0x1c,0xd0,0xc9,0x1a,0x01,0xd5,0x04,0x99,0xc9,0x1a,0x84,0x68, +0x8c,0x42,0xf2,0xd8,0x85,0x68,0xac,0x08,0x05,0x94,0x00,0x24,0x05,0x9d,0xa5,0x42, +0x14,0xdc,0x84,0x68,0x12,0x19,0x84,0x68,0x1b,0x19,0x3c,0x68,0xc5,0x68,0x2e,0x00, +0x26,0x40,0x25,0x42,0xf9,0xd1,0xfa,0x25,0x3c,0x68,0x2c,0x42,0x0b,0xd0,0x86,0x67, +0x00,0x23,0x02,0x9a,0x13,0x60,0x00,0xbe,0x07,0xb0,0xf0,0xbd,0xa6,0x00,0x9d,0x59, +0x01,0x34,0x95,0x51,0xe2,0xe7,0x04,0x9c,0x9c,0x42,0x00,0xd8,0x03,0x9b,0x83,0x67, +0x84,0x68,0x09,0x1b,0x01,0x9c,0x01,0x3c,0x01,0x94,0xd0,0xe7, diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3c055616f..ef15013ea 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1319,11 +1319,10 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, { struct target *target = bank->target; struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; - uint32_t buffer_size; struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; - struct reg_param reg_params[6]; + struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; @@ -1345,12 +1344,13 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, return retval; } - /* memory buffer, size *must* be multiple of stm32l4_info->data_width - * plus one dword for rp and one for wp */ - /* FIXME, currently only STM32U5 devices do have a different data_width, - * but STM32U5 device flash programming does not go through this function - * so temporarily continue to consider the default data_width = 8 */ - buffer_size = target_get_working_area_avail(target) & ~(2 * sizeof(uint32_t) - 1); + /* data_width should be multiple of double-word */ + assert(stm32l4_info->data_width % 8 == 0); + const size_t extra_size = sizeof(struct stm32l4_work_area); + uint32_t buffer_size = target_get_working_area_avail(target) - extra_size; + /* buffer_size should be multiple of stm32l4_info->data_width */ + buffer_size &= ~(stm32l4_info->data_width - 1); + if (buffer_size < 256) { LOG_WARNING("large enough working area not available, can't do block memory writes"); target_free_working_area(target, write_algorithm); @@ -1360,7 +1360,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, buffer_size = 16384; } - if (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { + if (target_alloc_working_area_try(target, buffer_size + extra_size, &source) != ERROR_OK) { LOG_ERROR("allocating working area failed"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1371,28 +1371,46 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ - init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (double word-64bit) */ - init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* flash status register */ - init_reg_param(®_params[5], "r5", 32, PARAM_OUT); /* flash control register */ + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (of stm32l4_info->data_width) */ + init_reg_param(®_params[4], "sp", 32, PARAM_OUT); /* write algo stack pointer */ buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, count); - buf_set_u32(reg_params[4].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX)); - buf_set_u32(reg_params[5].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX)); + buf_set_u32(reg_params[4].value, 0, 32, source->address + + offsetof(struct stm32l4_work_area, stack) + LDR_STACK_SIZE); + + struct stm32l4_loader_params loader_extra_params; + + target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_sr_addr, + stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX)); + target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_cr_addr, + stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX)); + target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_word_size, + stm32l4_info->data_width); + target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_sr_bsy_mask, + stm32l4_info->sr_bsy_mask); + + retval = target_write_buffer(target, source->address, sizeof(loader_extra_params), + (uint8_t *) &loader_extra_params); + if (retval != ERROR_OK) + return retval; retval = target_run_flash_async_algorithm(target, buffer, count, stm32l4_info->data_width, 0, NULL, ARRAY_SIZE(reg_params), reg_params, - source->address, source->size, + source->address + offsetof(struct stm32l4_work_area, fifo), + source->size - offsetof(struct stm32l4_work_area, fifo), write_algorithm->address, 0, &armv7m_info); if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("error executing stm32l4 flash write algorithm"); - uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & FLASH_ERROR; + uint32_t error; + stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, &error); + error &= FLASH_ERROR; if (error & FLASH_WRPERR) LOG_ERROR("flash memory write protected"); @@ -1413,7 +1431,6 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); - destroy_reg_param(®_params[5]); return retval; } @@ -1538,24 +1555,7 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) goto err_lock; - /** - * FIXME update the flash loader to use a custom FLASH_SR_BSY mask - * Workaround for STM32G0Bx/G0Cx devices in dual bank mode, - * as the flash loader does not use the SR_BSY2 - */ - bool use_flashloader = stm32l4_info->use_flashloader; - if ((stm32l4_info->part_info->id == 0x467) && stm32l4_info->dual_bank_mode) { - LOG_INFO("Couldn't use the flash loader in dual-bank mode"); - use_flashloader = false; - } else if (stm32l4_info->part_info->id == 0x482) { - /** - * FIXME the current flashloader does not support writing in quad-words - * which is required for STM32U5 devices. - */ - use_flashloader = false; - } - - if (use_flashloader) { + if (stm32l4_info->use_flashloader) { /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5, * the debug is possible only in non-secure state. * Thus means the flashloader will run in non-secure mode, @@ -1567,7 +1567,7 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, count / stm32l4_info->data_width); } - if (!use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + if (!stm32l4_info->use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { LOG_INFO("falling back to single memory accesses"); retval = stm32l4_write_block_without_loader(bank, buffer, offset, count / stm32l4_info->data_width); diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 7b9162b08..2d19cffff 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -92,4 +92,22 @@ #define STM32L5_REGS_SEC_OFFSET 0x10000000 +/* 100 bytes as loader stack should be large enough for the loader to operate */ +#define LDR_STACK_SIZE 100 + +struct stm32l4_work_area { + struct stm32l4_loader_params { + uint32_t flash_sr_addr; + uint32_t flash_cr_addr; + uint32_t flash_word_size; + uint32_t flash_sr_bsy_mask; + } params; + uint8_t stack[LDR_STACK_SIZE]; + struct flash_async_algorithm_circbuf { + uint8_t *wp; + uint8_t *rp; + uint8_t *buf; + } fifo; +}; + #endif From af3575b931b2bbd8b82d64f2f4495bae1741a1b1 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Fri, 26 Mar 2021 13:27:52 +0100 Subject: [PATCH 05/56] flash/stm32l4x: add support of STM32G05/G06x this device has single bank flash architecture up to 64KB (page 2KB) reference: RM0444 rev 5 Change-Id: Ia213c01accb950fcbb7519e08057dae11b4443dd Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6128 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index ef15013ea..1ebf833b8 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -279,6 +279,10 @@ static const struct stm32l4_rev stm32_435_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, }; +static const struct stm32l4_rev stm32_456_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32_460_revs[] = { { 0x1000, "A/Z" } /* A and Z, no typo in RM! */, { 0x2000, "B" }, }; @@ -368,6 +372,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = 0x456, + .revs = stm32_456_revs, + .num_revs = ARRAY_SIZE(stm32_456_revs), + .device_str = "STM32G05/G06xx", + .max_flash_size_kb = 64, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = 0x460, .revs = stm32_460_revs, @@ -1809,6 +1825,7 @@ static int stm32l4_probe(struct flash_bank *bank) } break; case 0x435: /* STM32L43/L44xx */ + case 0x456: /* STM32G05/G06xx */ case 0x460: /* STM32G07/G08xx */ case 0x462: /* STM32L45/L46xx */ case 0x464: /* STM32L41/L42xx */ From 4f371e8eed5c4e479d326cf09f7827884c23b947 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Fri, 26 Mar 2021 15:07:41 +0100 Subject: [PATCH 06/56] flash/stm32l4x: add support of STM32WB1x STM32WB1x devices has a single flash bank up to 320 KB (page 2KB) note: STM32WB5x/WB3x are single banks as well but do have 4KB as page size. note: remove the assert that checks if max_mages is power of two, because STM32WB1x flash size is not a power of 2 Change-Id: Ib514cf989ecb819d25d1c4a65d641d0a1a3d9f18 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6129 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 1ebf833b8..9f7d9e5e0 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -64,16 +64,21 @@ * - for STM32L4P5/Q5x * In 1M FLASH devices bit 22 (DBANK) controls Dual Bank mode. * In 512K FLASH devices bit 21 (DB512K) controls Dual Bank mode. - * */ /* STM32WBxxx series for reference. * - * RM0434 (STM32WB55) + * RM0434 (STM32WB55/WB35x) * http://www.st.com/resource/en/reference_manual/dm00318631.pdf * - * RM0471 (STM32WB50) + * RM0471 (STM32WB50/WB30x) * http://www.st.com/resource/en/reference_manual/dm00622834.pdf + * + * RM0473 (STM32WB15x) + * http://www.st.com/resource/en/reference_manual/dm00649196.pdf + * + * RM0478 (STM32WB10x) + * http://www.st.com/resource/en/reference_manual/dm00689203.pdf */ /* STM32WLxxx series for reference. @@ -335,6 +340,10 @@ static const struct stm32l4_rev stm32_482_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, }; +static const struct stm32l4_rev stm32_494_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, +}; + static const struct stm32l4_rev stm32_495_revs[] = { { 0x2001, "2.1" }, }; @@ -540,6 +549,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x0BFA0000, .otp_size = 512, }, + { + .id = 0x494, + .revs = stm32_494_revs, + .num_revs = ARRAY_SIZE(stm32_494_revs), + .device_str = "STM32WB1x", + .max_flash_size_kb = 320, + .flags = F_NONE, + .flash_regs_base = 0x58004000, + .fsize_addr = 0x1FFF75E0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = 0x495, .revs = stm32_495_revs, @@ -1832,6 +1853,7 @@ static int stm32l4_probe(struct flash_bank *bank) case 0x466: /* STM32G03/G04xx */ case 0x468: /* STM32G43/G44xx */ case 0x479: /* STM32G49/G4Axx */ + case 0x494: /* STM32WB1x */ /* single bank flash */ page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; @@ -1960,10 +1982,8 @@ static int stm32l4_probe(struct flash_bank *bank) /* use *max_flash_size* instead of actual size as the trimmed versions * certainly use the same number of bits - * max_flash_size is always power of two, so max_pages too */ uint32_t max_pages = stm32l4_info->part_info->max_flash_size_kb / page_size_kb; - assert(IS_PWR_OF_2(max_pages)); /* in dual bank mode number of pages is doubled, but extra bit is bank selection */ stm32l4_info->wrpxxr_mask = ((max_pages >> (stm32l4_info->dual_bank_mode ? 1 : 0)) - 1); From 48f267d4adea3e582d5287080f947b0e696d4f22 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sat, 14 Aug 2021 14:31:17 +0100 Subject: [PATCH 07/56] flash/stm32l4x: avoid using magic numbers for device ids Change-Id: I54c41f31c16b91904e8cbca823b90caa3807826d Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6437 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 216 +++++++++++++++++++-------------------- src/flash/nor/stm32l4x.h | 26 ++++- 2 files changed, 133 insertions(+), 109 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 9f7d9e5e0..e4d291e6d 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -276,91 +276,91 @@ struct stm32l4_wrp { /* human readable list of families this drivers supports (sorted alphabetically) */ static const char *device_families = "STM32G0/G4/L4/L4+/L5/U5/WB/WL"; -static const struct stm32l4_rev stm32_415_revs[] = { +static const struct stm32l4_rev stm32l47_l48xx_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } }; -static const struct stm32l4_rev stm32_435_revs[] = { +static const struct stm32l4_rev stm32l43_l44xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, }; -static const struct stm32l4_rev stm32_456_revs[] = { +static const struct stm32l4_rev stm32g05_g06xx_revs[] = { { 0x1000, "A" }, }; -static const struct stm32l4_rev stm32_460_revs[] = { +static const struct stm32l4_rev stm32_g07_g08xx_revs[] = { { 0x1000, "A/Z" } /* A and Z, no typo in RM! */, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_461_revs[] = { +static const struct stm32l4_rev stm32l49_l4axx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_462_revs[] = { +static const struct stm32l4_rev stm32l45_l46xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, }; -static const struct stm32l4_rev stm32_464_revs[] = { +static const struct stm32l4_rev stm32l41_L42xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" }, }; -static const struct stm32l4_rev stm32_466_revs[] = { +static const struct stm32l4_rev stm32g03_g04xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_467_revs[] = { +static const struct stm32l4_rev stm32g0b_g0cxx_revs[] = { { 0x1000, "A" }, }; -static const struct stm32l4_rev stm32_468_revs[] = { +static const struct stm32l4_rev stm32g43_g44xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; -static const struct stm32l4_rev stm32_469_revs[] = { +static const struct stm32l4_rev stm32g47_g48xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; -static const struct stm32l4_rev stm32_470_revs[] = { +static const struct stm32l4_rev stm32l4r_l4sxx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" }, }; -static const struct stm32l4_rev stm32_471_revs[] = { +static const struct stm32l4_rev stm32l4p_l4qxx_revs[] = { { 0x1001, "Z" }, }; -static const struct stm32l4_rev stm32_472_revs[] = { +static const struct stm32l4_rev stm32l55_l56xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_479_revs[] = { +static const struct stm32l4_rev stm32g49_g4axx_revs[] = { { 0x1000, "A" }, }; -static const struct stm32l4_rev stm32_482_revs[] = { +static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_494_revs[] = { +static const struct stm32l4_rev stm32wb1xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, }; -static const struct stm32l4_rev stm32_495_revs[] = { +static const struct stm32l4_rev stm32wb5xx_revs[] = { { 0x2001, "2.1" }, }; -static const struct stm32l4_rev stm32_496_revs[] = { +static const struct stm32l4_rev stm32wb3xx_revs[] = { { 0x1000, "A" }, }; -static const struct stm32l4_rev stm32_497_revs[] = { +static const struct stm32l4_rev stm32wle_wl5xx_revs[] = { { 0x1000, "1.0" }, }; static const struct stm32l4_part_info stm32l4_parts[] = { { - .id = 0x415, - .revs = stm32_415_revs, - .num_revs = ARRAY_SIZE(stm32_415_revs), + .id = DEVID_STM32L47_L48XX, + .revs = stm32l47_l48xx_revs, + .num_revs = ARRAY_SIZE(stm32l47_l48xx_revs), .device_str = "STM32L47/L48xx", .max_flash_size_kb = 1024, .flags = F_HAS_DUAL_BANK, @@ -370,9 +370,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x435, - .revs = stm32_435_revs, - .num_revs = ARRAY_SIZE(stm32_435_revs), + .id = DEVID_STM32L43_L44XX, + .revs = stm32l43_l44xx_revs, + .num_revs = ARRAY_SIZE(stm32l43_l44xx_revs), .device_str = "STM32L43/L44xx", .max_flash_size_kb = 256, .flags = F_NONE, @@ -382,9 +382,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x456, - .revs = stm32_456_revs, - .num_revs = ARRAY_SIZE(stm32_456_revs), + .id = DEVID_STM32G05_G06XX, + .revs = stm32g05_g06xx_revs, + .num_revs = ARRAY_SIZE(stm32g05_g06xx_revs), .device_str = "STM32G05/G06xx", .max_flash_size_kb = 64, .flags = F_NONE, @@ -394,9 +394,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x460, - .revs = stm32_460_revs, - .num_revs = ARRAY_SIZE(stm32_460_revs), + .id = DEVID_STM32G07_G08XX, + .revs = stm32_g07_g08xx_revs, + .num_revs = ARRAY_SIZE(stm32_g07_g08xx_revs), .device_str = "STM32G07/G08xx", .max_flash_size_kb = 128, .flags = F_NONE, @@ -406,9 +406,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x461, - .revs = stm32_461_revs, - .num_revs = ARRAY_SIZE(stm32_461_revs), + .id = DEVID_STM32L49_L4AXX, + .revs = stm32l49_l4axx_revs, + .num_revs = ARRAY_SIZE(stm32l49_l4axx_revs), .device_str = "STM32L49/L4Axx", .max_flash_size_kb = 1024, .flags = F_HAS_DUAL_BANK, @@ -418,9 +418,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x462, - .revs = stm32_462_revs, - .num_revs = ARRAY_SIZE(stm32_462_revs), + .id = DEVID_STM32L45_L46XX, + .revs = stm32l45_l46xx_revs, + .num_revs = ARRAY_SIZE(stm32l45_l46xx_revs), .device_str = "STM32L45/L46xx", .max_flash_size_kb = 512, .flags = F_NONE, @@ -430,9 +430,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x464, - .revs = stm32_464_revs, - .num_revs = ARRAY_SIZE(stm32_464_revs), + .id = DEVID_STM32L41_L42XX, + .revs = stm32l41_L42xx_revs, + .num_revs = ARRAY_SIZE(stm32l41_L42xx_revs), .device_str = "STM32L41/L42xx", .max_flash_size_kb = 128, .flags = F_NONE, @@ -442,10 +442,10 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x466, - .revs = stm32_466_revs, - .num_revs = ARRAY_SIZE(stm32_466_revs), - .device_str = "STM32G03/G04xx", + .id = DEVID_STM32G03_G04XX, + .revs = stm32g03_g04xx_revs, + .num_revs = ARRAY_SIZE(stm32g03_g04xx_revs), + .device_str = "STM32G03x/G04xx", .max_flash_size_kb = 64, .flags = F_NONE, .flash_regs_base = 0x40022000, @@ -454,10 +454,10 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x467, - .revs = stm32_467_revs, - .num_revs = ARRAY_SIZE(stm32_467_revs), - .device_str = "STM32G0Bx/G0Cx", + .id = DEVID_STM32G0B_G0CXX, + .revs = stm32g0b_g0cxx_revs, + .num_revs = ARRAY_SIZE(stm32g0b_g0cxx_revs), + .device_str = "STM32G0B/G0Cx", .max_flash_size_kb = 512, .flags = F_HAS_DUAL_BANK, .flash_regs_base = 0x40022000, @@ -466,9 +466,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x468, - .revs = stm32_468_revs, - .num_revs = ARRAY_SIZE(stm32_468_revs), + .id = DEVID_STM32G43_G44XX, + .revs = stm32g43_g44xx_revs, + .num_revs = ARRAY_SIZE(stm32g43_g44xx_revs), .device_str = "STM32G43/G44xx", .max_flash_size_kb = 128, .flags = F_NONE, @@ -478,9 +478,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x469, - .revs = stm32_469_revs, - .num_revs = ARRAY_SIZE(stm32_469_revs), + .id = DEVID_STM32G47_G48XX, + .revs = stm32g47_g48xx_revs, + .num_revs = ARRAY_SIZE(stm32g47_g48xx_revs), .device_str = "STM32G47/G48xx", .max_flash_size_kb = 512, .flags = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX, @@ -490,9 +490,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x470, - .revs = stm32_470_revs, - .num_revs = ARRAY_SIZE(stm32_470_revs), + .id = DEVID_STM32L4R_L4SXX, + .revs = stm32l4r_l4sxx_revs, + .num_revs = ARRAY_SIZE(stm32l4r_l4sxx_revs), .device_str = "STM32L4R/L4Sxx", .max_flash_size_kb = 2048, .flags = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX, @@ -502,10 +502,10 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x471, - .revs = stm32_471_revs, - .num_revs = ARRAY_SIZE(stm32_471_revs), - .device_str = "STM32L4P5/L4Q5x", + .id = DEVID_STM32L4P_L4QXX, + .revs = stm32l4p_l4qxx_revs, + .num_revs = ARRAY_SIZE(stm32l4p_l4qxx_revs), + .device_str = "STM32L4P/L4Qxx", .max_flash_size_kb = 1024, .flags = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX, .flash_regs_base = 0x40022000, @@ -514,9 +514,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x472, - .revs = stm32_472_revs, - .num_revs = ARRAY_SIZE(stm32_472_revs), + .id = DEVID_STM32L55_L56XX, + .revs = stm32l55_l56xx_revs, + .num_revs = ARRAY_SIZE(stm32l55_l56xx_revs), .device_str = "STM32L55/L56xx", .max_flash_size_kb = 512, .flags = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX | F_HAS_TZ | F_HAS_L5_FLASH_REGS, @@ -526,9 +526,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 512, }, { - .id = 0x479, - .revs = stm32_479_revs, - .num_revs = ARRAY_SIZE(stm32_479_revs), + .id = DEVID_STM32G49_G4AXX, + .revs = stm32g49_g4axx_revs, + .num_revs = ARRAY_SIZE(stm32g49_g4axx_revs), .device_str = "STM32G49/G4Axx", .max_flash_size_kb = 512, .flags = F_NONE, @@ -538,9 +538,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x482, - .revs = stm32_482_revs, - .num_revs = ARRAY_SIZE(stm32_482_revs), + .id = DEVID_STM32U57_U58XX, + .revs = stm32u57_u58xx_revs, + .num_revs = ARRAY_SIZE(stm32u57_u58xx_revs), .device_str = "STM32U57/U58xx", .max_flash_size_kb = 2048, .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, @@ -550,9 +550,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 512, }, { - .id = 0x494, - .revs = stm32_494_revs, - .num_revs = ARRAY_SIZE(stm32_494_revs), + .id = DEVID_STM32WB1XX, + .revs = stm32wb1xx_revs, + .num_revs = ARRAY_SIZE(stm32wb1xx_revs), .device_str = "STM32WB1x", .max_flash_size_kb = 320, .flags = F_NONE, @@ -562,9 +562,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x495, - .revs = stm32_495_revs, - .num_revs = ARRAY_SIZE(stm32_495_revs), + .id = DEVID_STM32WB5XX, + .revs = stm32wb5xx_revs, + .num_revs = ARRAY_SIZE(stm32wb5xx_revs), .device_str = "STM32WB5x", .max_flash_size_kb = 1024, .flags = F_NONE, @@ -574,9 +574,9 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x496, - .revs = stm32_496_revs, - .num_revs = ARRAY_SIZE(stm32_496_revs), + .id = DEVID_STM32WB3XX, + .revs = stm32wb3xx_revs, + .num_revs = ARRAY_SIZE(stm32wb3xx_revs), .device_str = "STM32WB3x", .max_flash_size_kb = 512, .flags = F_NONE, @@ -586,10 +586,10 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { - .id = 0x497, - .revs = stm32_497_revs, - .num_revs = ARRAY_SIZE(stm32_497_revs), - .device_str = "STM32WLEx/WL5x", + .id = DEVID_STM32WLE_WL5XX, + .revs = stm32wle_wl5xx_revs, + .num_revs = ARRAY_SIZE(stm32wle_wl5xx_revs), + .device_str = "STM32WLE/WL5x", .max_flash_size_kb = 256, .flags = F_NONE, .flash_regs_base = 0x58004000, @@ -1658,8 +1658,8 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) */ retval = target_read_u32(bank->target, UID64_IDS, &uid64_ids); if (retval == ERROR_OK && uid64_ids == UID64_IDS_STM32WL) { - /* force the DEV_ID to 0x497 and the REV_ID to unknown */ - *id = 0x00000497; + /* force the DEV_ID to DEVID_STM32WLE_WL5XX and the REV_ID to unknown */ + *id = DEVID_STM32WLE_WL5XX; return ERROR_OK; } } @@ -1825,11 +1825,11 @@ static int stm32l4_probe(struct flash_bank *bank) bool use_dbank_bit = false; switch (device_id) { - case 0x415: /* STM32L47/L48xx */ - case 0x461: /* STM32L49/L4Axx */ + case DEVID_STM32L47_L48XX: + case DEVID_STM32L49_L4AXX: /* if flash size is max (1M) the device is always dual bank - * 0x415: has variants with 512K - * 0x461: has variants with 512 and 256 + * STM32L47/L48xx: has variants with 512K + * STM32L49/L4Axx: has variants with 512 and 256 * for these variants: * if DUAL_BANK = 0 -> single bank * else -> dual bank without gap @@ -1845,21 +1845,21 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case 0x435: /* STM32L43/L44xx */ - case 0x456: /* STM32G05/G06xx */ - case 0x460: /* STM32G07/G08xx */ - case 0x462: /* STM32L45/L46xx */ - case 0x464: /* STM32L41/L42xx */ - case 0x466: /* STM32G03/G04xx */ - case 0x468: /* STM32G43/G44xx */ - case 0x479: /* STM32G49/G4Axx */ - case 0x494: /* STM32WB1x */ + case DEVID_STM32L43_L44XX: + case DEVID_STM32G05_G06XX: + case DEVID_STM32G07_G08XX: + case DEVID_STM32L45_L46XX: + case DEVID_STM32L41_L42XX: + case DEVID_STM32G03_G04XX: + case DEVID_STM32G43_G44XX: + case DEVID_STM32G49_G4AXX: + case DEVID_STM32WB1XX: /* single bank flash */ page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; break; - case 0x467: /* STM32G0B/G0Cxx */ + case DEVID_STM32G0B_G0CXX: /* single/dual bank depending on bit(21) */ page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; @@ -1873,7 +1873,7 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case 0x469: /* STM32G47/G48xx */ + case DEVID_STM32G47_G48XX: /* STM32G47/8 can be single/dual bank: * if DUAL_BANK = 0 -> single bank * else -> dual bank WITH gap @@ -1892,8 +1892,8 @@ static int stm32l4_probe(struct flash_bank *bank) (part_info->max_flash_size_kb - flash_size_kb) / (2 * page_size_kb); } break; - case 0x470: /* STM32L4R/L4Sxx */ - case 0x471: /* STM32L4P5/L4Q5x */ + case DEVID_STM32L4R_L4SXX: + case DEVID_STM32L4P_L4QXX: /* STM32L4R/S can be single/dual bank: * if size = 2M check DBANK bit(22) * if size = 1M check DB1M bit(21) @@ -1913,7 +1913,7 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case 0x472: /* STM32L55/L56xx */ + case DEVID_STM32L55_L56XX: /* STM32L55/L56xx can be single/dual bank: * if size = 512K check DBANK bit(22) * if size = 256K check DB256K bit(21) @@ -1930,7 +1930,7 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case 0x482: /* STM32U57/U58xx */ + case DEVID_STM32U57_U58XX: /* if flash size is max (2M) the device is always dual bank * otherwise check DUALBANK bit(21) */ @@ -1942,14 +1942,14 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case 0x495: /* STM32WB5x */ - case 0x496: /* STM32WB3x */ + case DEVID_STM32WB5XX: + case DEVID_STM32WB3XX: /* single bank flash */ page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; break; - case 0x497: /* STM32WLEx/WL5x */ + case DEVID_STM32WLE_WL5XX: /* single bank flash */ page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 2d19cffff..566cc2226 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -79,7 +79,7 @@ #define FLASH_SECBB_SECURE 0xFFFFFFFF #define FLASH_SECBB_NON_SECURE 0 -/* other registers */ +/* IDCODE register possible addresses */ #define DBGMCU_IDCODE_G0 0x40015800 #define DBGMCU_IDCODE_L4_G4 0xE0042000 #define DBGMCU_IDCODE_L5 0xE0044000 @@ -87,9 +87,33 @@ #define UID64_IDS 0x1FFF7584 #define UID64_IDS_STM32WL 0x0080E115 +/* Supported device IDs */ +#define DEVID_STM32L47_L48XX 0x415 +#define DEVID_STM32L43_L44XX 0x435 +#define DEVID_STM32G05_G06XX 0x456 +#define DEVID_STM32G07_G08XX 0x460 +#define DEVID_STM32L49_L4AXX 0x461 +#define DEVID_STM32L45_L46XX 0x462 +#define DEVID_STM32L41_L42XX 0x464 +#define DEVID_STM32G03_G04XX 0x466 +#define DEVID_STM32G0B_G0CXX 0x467 +#define DEVID_STM32G43_G44XX 0x468 +#define DEVID_STM32G47_G48XX 0x469 +#define DEVID_STM32L4R_L4SXX 0x470 +#define DEVID_STM32L4P_L4QXX 0x471 +#define DEVID_STM32L55_L56XX 0x472 +#define DEVID_STM32G49_G4AXX 0x479 +#define DEVID_STM32U57_U58XX 0x482 +#define DEVID_STM32WB1XX 0x494 +#define DEVID_STM32WB5XX 0x495 +#define DEVID_STM32WB3XX 0x496 +#define DEVID_STM32WLE_WL5XX 0x497 + +/* known Flash base addresses */ #define STM32_FLASH_BANK_BASE 0x08000000 #define STM32_FLASH_S_BANK_BASE 0x0C000000 +/* offset between non-secure and secure flash registers */ #define STM32L5_REGS_SEC_OFFSET 0x10000000 /* 100 bytes as loader stack should be large enough for the loader to operate */ From c7eaaf620488c3268d02313dd5a30101d7aff37b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 30 Aug 2021 01:01:40 +0200 Subject: [PATCH 08/56] openocd: prepare for jimtcl 0.81 'expr' syntax change Jimtcl commit 1843b79a03dd ("expr: TIP 526, only support a single arg") drops the support for multi-argument syntax for the TCL command 'expr'. All the scripts distributed with OpenOCD are already compliant with the new syntax. To avoid breaking user script, introduce a replacement for 'expr' command that handles the old syntax while issuing a deprecated warning. This change should be part of OpenOCD v0.12.0, then reverted. Change-Id: Ib08aa8ebcb634c81a3ce9d24fb4938b0418c947c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6510 Reviewed-by: Oleksij Rempel Reviewed-by: Tarek BOCHKATI Tested-by: jenkins --- src/openocd.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/openocd.c b/src/openocd.c index b4571b464..12bd52c58 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -234,6 +234,65 @@ static int openocd_register_commands(struct command_context *cmd_ctx) return register_commands(cmd_ctx, NULL, openocd_command_handlers); } +/* + * TODO: to be removed after v0.12.0 + * workaround for syntax change of "expr" in jimtcl 0.81 + * replace "expr" with openocd version that prints the deprecated msg + */ +struct jim_scriptobj { + void *token; + Jim_Obj *filename_obj; + int len; + int subst_flags; + int in_use; + int firstline; + int linenr; + int missing; +}; + +static int jim_expr_command(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + if (argc == 2) + return Jim_EvalExpression(interp, argv[1]); + + if (argc > 2) { + Jim_Obj *obj = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(obj); + const char *s = Jim_String(obj); + struct jim_scriptobj *script = Jim_GetIntRepPtr(interp->currentScriptObj); + if (interp->currentScriptObj == interp->emptyObj || + strcmp(interp->currentScriptObj->typePtr->name, "script") || + script->subst_flags || + script->filename_obj == interp->emptyObj) + LOG_WARNING("DEPRECATED! use 'expr { %s }' not 'expr %s'", s, s); + else + LOG_WARNING("DEPRECATED! (%s:%d) use 'expr { %s }' not 'expr %s'", + Jim_String(script->filename_obj), script->linenr, s, s); + int retcode = Jim_EvalExpression(interp, obj); + Jim_DecrRefCount(interp, obj); + return retcode; + } + + Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); + return JIM_ERR; +} + +static const struct command_registration expr_handler[] = { + { + .name = "expr", + .jim_handler = jim_expr_command, + .mode = COMMAND_ANY, + .help = "", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static int workaround_for_jimtcl_expr(struct command_context *cmd_ctx) +{ + return register_commands(cmd_ctx, NULL, expr_handler); +} + struct command_context *global_cmd_ctx; static struct command_context *setup_command_handler(Jim_Interp *interp) @@ -246,6 +305,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) /* register subsystem commands */ typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value); static const command_registrant_t command_registrants[] = { + &workaround_for_jimtcl_expr, &openocd_register_commands, &server_register_commands, &gdb_register_commands, From 01f1f599c5a6b0cbfb0878e5129c7185e17f8216 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 11 Apr 2021 23:54:44 +0200 Subject: [PATCH 09/56] jimtcl: update to master branch 20210715 This version of jimtcl: - fixes memory leak in API Jim_CreateCommand(); - fixes 'make distcheck'; - uses single-argument syntax for 'expr'. With the 'expr' syntax already fixed in all the tcl scripts in OpenOCD, let's use the latest jimtcl to check it and anticipate any further issues. By using this version, the workaround for the memory leak and for distcheck can be reverted. Change-Id: I58e1bdc752a728f1b479de1c55067b698e817ef5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6226 Reviewed-by: Tarek BOCHKATI Reviewed-by: zapb Tested-by: jenkins --- jimtcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jimtcl b/jimtcl index fb923fab4..2d66360c6 160000 --- a/jimtcl +++ b/jimtcl @@ -1 +1 @@ -Subproject commit fb923fab4f0cf276c336d98692d00df6a943791d +Subproject commit 2d66360c61d2a89d4008e8bad12ae3aa5f0331e2 From 3359419e6a121e73361c74fcae08999aa85330da Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 30 Aug 2021 14:20:26 +0200 Subject: [PATCH 10/56] tcl/board/arty_s7: Fix proc and chip name Tested with Digilent Arty S7 board. Change-Id: I064f3b6537ae8d765d7f380ad53b922d584fdbe7 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/6509 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/arty_s7.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcl/board/arty_s7.cfg b/tcl/board/arty_s7.cfg index 5ab408391..a5e26fc94 100644 --- a/tcl/board/arty_s7.cfg +++ b/tcl/board/arty_s7.cfg @@ -23,7 +23,7 @@ adapter speed 25000 # openocd -f board/arty_s7.cfg -c "init;\ # jtagspi_init 0 bscan_spi_xc7s??.bit;\ # jtagspi_program bitstream.bin 0;\ -# xc7s_program xc7s.tap;\ +# xc7_program xc7.tap;\ # shutdown" # # jtagspi flash proxies can be found at: From 3ae2583b48861c7cc8674b66984189e6f58dc666 Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Sun, 29 Aug 2021 18:27:52 +0900 Subject: [PATCH 11/56] target: cortex_m: Fix a typo VECTRESET According to ARM Cortex M3 technical reference manual, it's "VECTRESET" instead of "VECRESET". Change-Id: Iff5534beac2b313cee6da3252d76d4d44a61eeed Signed-off-by: Yasushi SHOJI Reviewed-on: https://review.openocd.org/c/openocd/+/6508 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index f3c8527cf..08f2eb911 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1243,7 +1243,7 @@ static int cortex_m_assert_reset(struct target *target) retval = ERROR_OK; } else { /* Use a standard Cortex-M3 software reset mechanism. - * We default to using VECRESET as it is supported on all current cores + * We default to using VECTRESET as it is supported on all current cores * (except Cortex-M0, M0+ and M1 which support SYSRESETREQ only!) * This has the disadvantage of not resetting the peripherals, so a * reset-init event handler is needed to perform any peripheral resets. From be22b93a445b26213860617bdb9c3c2c35806bef Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 1 Mar 2020 23:00:15 +0100 Subject: [PATCH 12/56] tcl/board: add st_nucleo_g0.cfg to cover known STM32G0 NUCLEO boards known boards are NUCLEO-G031K8, NUCLEO-G070RB, NUCLEO-G071RB note: this work safely with STM32G0316-DISCO, STM32G071B-DISCO and STM32G081B-EVAL Change-Id: I483b6f44409228cd8c2c97b3c560927d1645c517 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/5483 Reviewed-by: Andreas Bolsch Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/st_nucleo_g0.cfg | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tcl/board/st_nucleo_g0.cfg diff --git a/tcl/board/st_nucleo_g0.cfg b/tcl/board/st_nucleo_g0.cfg new file mode 100644 index 000000000..f8e67a043 --- /dev/null +++ b/tcl/board/st_nucleo_g0.cfg @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is for all ST NUCLEO with any STM32G0. Known boards at the moment: +# NUCLEO-G031K8 +# https://www.st.com/en/evaluation-tools/nucleo-g031k8.html +# NUCLEO-G070RB +# https://www.st.com/en/evaluation-tools/nucleo-g070rb.html +# NUCLEO-G071RB +# https://www.st.com/en/evaluation-tools/nucleo-g071rb.html +# NUCLEO-G0B1RE +# https://www.st.com/en/evaluation-tools/nucleo-g0b1re.html + +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32g0x.cfg] + +reset_config srst_only From 57c61cee4b538b449421bc6ff8ebca5be70e60b1 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 1 Mar 2020 23:11:10 +0100 Subject: [PATCH 13/56] tcl/board: add st_nucleo_g4.cfg to cover known STM32G4 NUCLEO boards known boards are NUCLEO-G431KB, NUCLEO-G431RB and NUCLEO-G474RE note: this work safely with B-G431B-ESC1, B-G474E-DPOW1, STM32G474E-EVAL and STM32G484E-EVAL Change-Id: I132a97e1816620b182983edc8a4b272b52b9241d Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/5484 Reviewed-by: Andreas Bolsch Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/st_nucleo_g4.cfg | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tcl/board/st_nucleo_g4.cfg diff --git a/tcl/board/st_nucleo_g4.cfg b/tcl/board/st_nucleo_g4.cfg new file mode 100644 index 000000000..8e583e77d --- /dev/null +++ b/tcl/board/st_nucleo_g4.cfg @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is for all ST NUCLEO with any STM32G4. Known boards at the moment: +# NUCLEO-G431KB +# https://www.st.com/en/evaluation-tools/nucleo-g431kb.html +# NUCLEO-G431RB +# https://www.st.com/en/evaluation-tools/nucleo-g431rb.html +# NUCLEO-G474RE +# https://www.st.com/en/evaluation-tools/nucleo-g474re.html +# NUCLEO-G491RE +# https://www.st.com/en/evaluation-tools/nucleo-g491re.html + +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32g4x.cfg] + +reset_config srst_only From 9f733ba2f274c425178780812d1c44fa44e464e4 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 29 Jul 2021 21:44:55 +0100 Subject: [PATCH 14/56] flash/nor/tcl: fix the flash name returned by 'flash list' command The 'flash list' command returns the driver name as flash name which seems to be incorrect, the proposal is: - to fix this by returning the flash name - and add a new item 'driver' in the returned list example: before the change > flash list {name stm32l4x base 134217728 size 0 bus_width 0 chip_width 0} {name stm32l4x base 201326592 size 0 bus_width 0 chip_width 0} {name stm32l4x base 200933376 size 0 bus_width 0 chip_width 0} after the change > flash list {name stm32l5x.flash_ns driver stm32l4x ...} {name stm32l5x.flash_alias_s driver stm32l4x ...} {name stm32l5x.otp driver stm32l4x ...} Change-Id: I6d307b73c457549981a93c260be344378719af82 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6425 Reviewed-by: zapb Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/tcl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index cbc64dcc4..613012b7b 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1350,6 +1350,8 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv) Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1)); + Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->name, -1)); + Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "driver", -1)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base)); From f24a283ac7765df6f09694a4cee99150cb645ac1 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 10 Aug 2021 15:32:37 +0100 Subject: [PATCH 15/56] flash/nor/tcl: 'flash list' command: add the flash bank target add the target assigned to the flash bank at creation this is useful in daisy chains, to filter out the target banks. Change-Id: Ic39e44914e34bb62991783762e5a65ef8871e82f Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6426 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- src/flash/nor/tcl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 613012b7b..228e76fd0 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1361,6 +1361,8 @@ static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv) Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width)); Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1)); Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width)); + Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "target", -1)); + Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, target_name(p->target), -1)); Jim_ListAppendElement(interp, list, elem); } From cdb6ea4f9ff6f61dc4eeadab4dd3edd5d49ab88e Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 29 Aug 2021 16:33:55 +0100 Subject: [PATCH 16/56] flash/stm32l4x: fix segmentation fault with HLA adapters and STM32WLx devices CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1. Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault. Change-Id: I501f5b69e629aa8d2836b5194063d74d5bfddb12 Signed-off-by: Tarek BOCHKATI Fixes: https://github.com/STMicroelectronics/OpenOCD/issues/6 Reviewed-on: https://review.openocd.org/c/openocd/+/6535 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index e4d291e6d..8734aeb78 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1646,7 +1646,10 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) struct cortex_m_common *cortex_m = target_to_cm(bank->target); - if (cortex_m->core_info->partno == CORTEX_M0P_PARTNO && cortex_m->armv7m.debug_ap->ap_num == 1) { + /* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1. + * Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */ + if (cortex_m->core_info->partno == CORTEX_M0P_PARTNO && + cortex_m->armv7m.debug_ap && cortex_m->armv7m.debug_ap->ap_num == 1) { uint32_t uid64_ids; /* UID64 is contains @@ -1954,7 +1957,10 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if (armv7m->debug_ap->ap_num == 1) + + /* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1. + * Using HLA adapters armv7m->debug_ap is null, and checking ap_num triggers a segfault */ + if (armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) stm32l4_info->flash_regs = stm32wl_cpu2_flash_regs; break; default: From 5070425d6a5457cb83ebf01b59746a66ccbe4e93 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 29 Aug 2021 20:52:50 +0100 Subject: [PATCH 17/56] flash/stm32l4x: introduce is_max_flash_size and use it Change-Id: Idb421b9cf737d222baf4dd890032f69dec7a366e Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6536 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 8734aeb78..56288ee05 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1818,6 +1818,8 @@ static int stm32l4_probe(struct flash_bank *bank) /* did we assign a flash size? */ assert((flash_size_kb != 0xffff) && flash_size_kb); + const bool is_max_flash_size = flash_size_kb == stm32l4_info->part_info->max_flash_size_kb; + stm32l4_info->bank1_sectors = 0; stm32l4_info->hole_sectors = 0; @@ -1825,7 +1827,6 @@ static int stm32l4_probe(struct flash_bank *bank) int page_size_kb = 0; stm32l4_info->dual_bank_mode = false; - bool use_dbank_bit = false; switch (device_id) { case DEVID_STM32L47_L48XX: @@ -1843,7 +1844,7 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages; /* check DUAL_BANK bit[21] if the flash is less than 1M */ - if (flash_size_kb == 1024 || (stm32l4_info->optr & BIT(21))) { + if (is_max_flash_size || (stm32l4_info->optr & BIT(21))) { stm32l4_info->dual_bank_mode = true; stm32l4_info->bank1_sectors = num_pages / 2; } @@ -1907,9 +1908,8 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb; - if ((use_dbank_bit && (stm32l4_info->optr & BIT(22))) || - (!use_dbank_bit && (stm32l4_info->optr & BIT(21)))) { + if ((is_max_flash_size && (stm32l4_info->optr & BIT(22))) || + (!is_max_flash_size && (stm32l4_info->optr & BIT(21)))) { stm32l4_info->dual_bank_mode = true; page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; @@ -1924,9 +1924,8 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb; - if ((use_dbank_bit && (stm32l4_info->optr & BIT(22))) || - (!use_dbank_bit && (stm32l4_info->optr & BIT(21)))) { + if ((is_max_flash_size && (stm32l4_info->optr & BIT(22))) || + (!is_max_flash_size && (stm32l4_info->optr & BIT(21)))) { stm32l4_info->dual_bank_mode = true; page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; @@ -1940,7 +1939,7 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if ((flash_size_kb == part_info->max_flash_size_kb) || (stm32l4_info->optr & BIT(21))) { + if (is_max_flash_size || (stm32l4_info->optr & BIT(21))) { stm32l4_info->dual_bank_mode = true; stm32l4_info->bank1_sectors = num_pages / 2; } From e63297045b252fedb748bb6557823417590cd879 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 29 Aug 2021 21:48:49 +0100 Subject: [PATCH 18/56] flash/stm32l4x: do not use magic number for dual bank option bits Change-Id: I27211e7d44b48f65546e31710ec6ae129acb416f Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6537 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 34 +++++++++++++++++----------------- src/flash/nor/stm32l4x.h | 8 ++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 56288ee05..f76bc45fe 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1843,8 +1843,8 @@ static int stm32l4_probe(struct flash_bank *bank) num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - /* check DUAL_BANK bit[21] if the flash is less than 1M */ - if (is_max_flash_size || (stm32l4_info->optr & BIT(21))) { + /* check DUAL_BANK option bit if the flash is less than 1M */ + if (is_max_flash_size || (stm32l4_info->optr & FLASH_L4_DUAL_BANK)) { stm32l4_info->dual_bank_mode = true; stm32l4_info->bank1_sectors = num_pages / 2; } @@ -1864,14 +1864,14 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages; break; case DEVID_STM32G0B_G0CXX: - /* single/dual bank depending on bit(21) */ + /* single/dual bank depending on DUAL_BANK option bit */ page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; stm32l4_info->cr_bker_mask = FLASH_BKER_G0; /* check DUAL_BANK bit */ - if (stm32l4_info->optr & BIT(21)) { + if (stm32l4_info->optr & FLASH_G0_DUAL_BANK) { stm32l4_info->sr_bsy_mask = FLASH_BSY | FLASH_BSY2; stm32l4_info->dual_bank_mode = true; stm32l4_info->bank1_sectors = num_pages / 2; @@ -1885,7 +1885,7 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if (stm32l4_info->optr & BIT(22)) { + if (stm32l4_info->optr & FLASH_G4_DUAL_BANK) { stm32l4_info->dual_bank_mode = true; page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; @@ -1899,17 +1899,17 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32L4R_L4SXX: case DEVID_STM32L4P_L4QXX: /* STM32L4R/S can be single/dual bank: - * if size = 2M check DBANK bit(22) - * if size = 1M check DB1M bit(21) + * if size = 2M check DBANK bit + * if size = 1M check DB1M bit * STM32L4P/Q can be single/dual bank - * if size = 1M check DBANK bit(22) - * if size = 512K check DB512K bit(21) + * if size = 1M check DBANK bit + * if size = 512K check DB512K bit (same as DB1M bit) */ page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if ((is_max_flash_size && (stm32l4_info->optr & BIT(22))) || - (!is_max_flash_size && (stm32l4_info->optr & BIT(21)))) { + if ((is_max_flash_size && (stm32l4_info->optr & FLASH_L4R_DBANK)) || + (!is_max_flash_size && (stm32l4_info->optr & FLASH_LRR_DB1M))) { stm32l4_info->dual_bank_mode = true; page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; @@ -1918,14 +1918,14 @@ static int stm32l4_probe(struct flash_bank *bank) break; case DEVID_STM32L55_L56XX: /* STM32L55/L56xx can be single/dual bank: - * if size = 512K check DBANK bit(22) - * if size = 256K check DB256K bit(21) + * if size = 512K check DBANK bit + * if size = 256K check DB256K bit */ page_size_kb = 4; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if ((is_max_flash_size && (stm32l4_info->optr & BIT(22))) || - (!is_max_flash_size && (stm32l4_info->optr & BIT(21)))) { + if ((is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DBANK)) || + (!is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DB256))) { stm32l4_info->dual_bank_mode = true; page_size_kb = 2; num_pages = flash_size_kb / page_size_kb; @@ -1934,12 +1934,12 @@ static int stm32l4_probe(struct flash_bank *bank) break; case DEVID_STM32U57_U58XX: /* if flash size is max (2M) the device is always dual bank - * otherwise check DUALBANK bit(21) + * otherwise check DUALBANK */ page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - if (is_max_flash_size || (stm32l4_info->optr & BIT(21))) { + if (is_max_flash_size || (stm32l4_info->optr & FLASH_U5_DUALBANK)) { stm32l4_info->dual_bank_mode = true; stm32l4_info->bank1_sectors = num_pages / 2; } diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 566cc2226..4cc50a040 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -70,6 +70,14 @@ /* FLASH_OPTR register bits */ #define FLASH_RDP_MASK 0xFF +#define FLASH_G0_DUAL_BANK BIT(21) +#define FLASH_G4_DUAL_BANK BIT(22) +#define FLASH_L4_DUAL_BANK BIT(21) +#define FLASH_L4R_DBANK BIT(22) +#define FLASH_LRR_DB1M BIT(21) +#define FLASH_L5_DBANK BIT(22) +#define FLASH_L5_DB256 BIT(21) +#define FLASH_U5_DUALBANK BIT(21) #define FLASH_TZEN BIT(31) /* FLASH secure block based bank 1/2 register offsets */ From f78f9a90a6c4f8abedbac8a4047631cbe3ea0e17 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 1 Sep 2021 14:25:10 -0700 Subject: [PATCH 19/56] In SMP config, replicate watchpoints on each core This works well with gdb on RISC-V, since hardware breakpoints are per-core and gdb thinks that targets are really processes on a machine. Are there targets where this is a bad idea? Should the target definition specify whether this behavior is desired or not? Change-Id: Ia32be2707b04347fd8bf2ca6fbb2b0ceaad3704a Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/6528 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/target/breakpoints.c | 68 ++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 4ba9d6b46..dfec75051 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -95,7 +95,9 @@ fail: return retval; } - LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", + LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT + " of length 0x%8.8x, (BPID: %" PRIu32 ")", + target->coreid, breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -410,8 +412,8 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) return NULL; } -int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, - enum watchpoint_rw rw, uint32_t value, uint32_t mask) +int watchpoint_add_internal(struct target *target, target_addr_t address, + uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; @@ -466,8 +468,9 @@ bye: return retval; } - LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT - " of length 0x%8.8" PRIx32 " (WPID: %d)", + LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT + " of length 0x%8.8" PRIx32 " (WPID: %d)", + target->coreid, watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, (*watchpoint_p)->length, @@ -476,6 +479,30 @@ bye: return ERROR_OK; } +int watchpoint_add(struct target *target, target_addr_t address, + uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) +{ + int retval = ERROR_OK; + if (target->smp) { + struct target_list *head; + struct target *curr; + head = target->head; + + while (head != (struct target_list *)NULL) { + curr = head->target; + retval = watchpoint_add_internal(curr, address, length, rw, value, + mask); + if (retval != ERROR_OK) + return retval; + head = head->next; + } + return retval; + } else { + return watchpoint_add_internal(target, address, length, rw, value, + mask); + } +} + static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) { struct watchpoint *watchpoint = target->watchpoints; @@ -497,7 +524,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint free(watchpoint); } -void watchpoint_remove(struct target *target, target_addr_t address) +int watchpoint_remove_internal(struct target *target, target_addr_t address) { struct watchpoint *watchpoint = target->watchpoints; @@ -507,10 +534,33 @@ void watchpoint_remove(struct target *target, target_addr_t address) watchpoint = watchpoint->next; } - if (watchpoint) + if (watchpoint) { watchpoint_free(target, watchpoint); - else - LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); + return 1; + } else { + if (!target->smp) + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); + return 0; + } +} + +void watchpoint_remove(struct target *target, target_addr_t address) +{ + if (target->smp) { + unsigned int num_watchpoints = 0; + struct target_list *head; + struct target *curr; + head = target->head; + while (head) { + curr = head->target; + num_watchpoints += watchpoint_remove_internal(curr, address); + head = head->next; + } + if (num_watchpoints == 0) + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address); + } else { + watchpoint_remove_internal(target, address); + } } void watchpoint_clear_target(struct target *target) From b61a280860f9ceb9bc38125c48d2f0f4d35f1c11 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 9 Sep 2021 22:14:36 +0100 Subject: [PATCH 20/56] flash/stm32l4x: fix flash programming in 64-bit hosts stm32l4_work_area struct is shared between the loader and stm32l4x flash driver '*wp' and '*rp' pointers' size is 4 bytes each since stm32l4x devices have 32-bit processors. however when used in openocd code, their size depends on the host if the host is 32-bit, then the size is 4 bytes each. if the host is 64-bit, then the size is 8 bytes each. to avoid this size difference, change their types depending on the usage (pointers for the loader, and 32-bit integers in openocd code). Change-Id: I0a3df4bb4bf872b01cdb9357eb28307868d7d469 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6556 Tested-by: jenkins Reviewed-by: Yestin Sun Reviewed-by: Tomas Vanek --- contrib/loaders/flash/stm32/stm32l4x.c | 2 ++ src/flash/nor/stm32l4x.c | 7 +++++-- src/flash/nor/stm32l4x.h | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/contrib/loaders/flash/stm32/stm32l4x.c b/contrib/loaders/flash/stm32/stm32l4x.c index bcad98843..54c88a335 100644 --- a/contrib/loaders/flash/stm32/stm32l4x.c +++ b/contrib/loaders/flash/stm32/stm32l4x.c @@ -5,6 +5,8 @@ * tarek.bouchkati@st.com */ +#define OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X + #include #include "../../../../src/flash/nor/stm32l4x.h" diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index f76bc45fe..0182aae66 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1405,16 +1405,19 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; - init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ + /* contrib/loaders/flash/stm32/stm32l4x.c:write() arguments */ + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* stm32l4_work_area ptr , status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (of stm32l4_info->data_width) */ - init_reg_param(®_params[4], "sp", 32, PARAM_OUT); /* write algo stack pointer */ buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, count); + + /* write algo stack pointer */ + init_reg_param(®_params[4], "sp", 32, PARAM_OUT); buf_set_u32(reg_params[4].value, 0, 32, source->address + offsetof(struct stm32l4_work_area, stack) + LDR_STACK_SIZE); diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 4cc50a040..4458c0875 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -136,9 +136,24 @@ struct stm32l4_work_area { } params; uint8_t stack[LDR_STACK_SIZE]; struct flash_async_algorithm_circbuf { + /* note: stm32l4_work_area struct is shared between the loader + * and stm32l4x flash driver. + * + * '*wp' and '*rp' pointers' size is 4 bytes each since stm32l4x + * devices have 32-bit processors. + * however when used in openocd code, their size depends on the host + * if the host is 32-bit, then the size is 4 bytes each. + * if the host is 64-bit, then the size is 8 bytes each. + * to avoid this size difference, change their types depending on the + * usage (pointers for the loader, and 32-bit integers in openocd code). + */ +#ifdef OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X uint8_t *wp; uint8_t *rp; - uint8_t *buf; +#else + uint32_t wp; + uint32_t rp; +#endif /* OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X */ } fifo; }; From fc74ccda52eced1f7be9fc99f071b0f47a7044ea Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Sun, 29 Aug 2021 22:09:46 +0100 Subject: [PATCH 21/56] tcl/target/stm32(f7/h7)x: do not assume presence of the reset do not force the presence of the reset line, since some custom boards may do not contain the reset line. Change-Id: I031ab34012b34a1b49def9db16461f9de0ae29cc Signed-off-by: Tarek BOCHKATI Reported-by: Fleck Fixes: https://sourceforge.net/p/openocd/tickets/316/ Reviewed-on: https://review.openocd.org/c/openocd/+/6506 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- tcl/board/stm327x6g_eval.cfg | 2 ++ tcl/board/stm32f723e-disco.cfg | 2 ++ tcl/board/stm32f746g-disco.cfg | 2 ++ tcl/board/stm32f769i-disco.cfg | 2 ++ tcl/board/stm32f7discovery.cfg | 2 ++ tcl/board/stm32h735g-disco.cfg | 2 ++ tcl/board/stm32h745i-disco.cfg | 2 ++ tcl/board/stm32h747i-disco.cfg | 2 ++ tcl/board/stm32h750b-disco.cfg | 2 ++ tcl/board/stm32h7b3i-disco.cfg | 2 ++ tcl/target/stm32f7x.cfg | 2 +- tcl/target/stm32h7x.cfg | 2 +- 12 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tcl/board/stm327x6g_eval.cfg b/tcl/board/stm327x6g_eval.cfg index a5e5896b3..3d522f59d 100644 --- a/tcl/board/stm327x6g_eval.cfg +++ b/tcl/board/stm327x6g_eval.cfg @@ -8,3 +8,5 @@ set WORKAREASIZE 0x40000 source [find target/stm32f7x.cfg] + +reset_config srst_only diff --git a/tcl/board/stm32f723e-disco.cfg b/tcl/board/stm32f723e-disco.cfg index 3c04d86f0..b809c5e46 100644 --- a/tcl/board/stm32f723e-disco.cfg +++ b/tcl/board/stm32f723e-disco.cfg @@ -14,6 +14,8 @@ set QUADSPI 1 source [find target/stm32f7x.cfg] +reset_config srst_only + # QUADSPI initialization proc qspi_init { } { global a diff --git a/tcl/board/stm32f746g-disco.cfg b/tcl/board/stm32f746g-disco.cfg index 14e89e162..5d2c1a465 100644 --- a/tcl/board/stm32f746g-disco.cfg +++ b/tcl/board/stm32f746g-disco.cfg @@ -14,6 +14,8 @@ set QUADSPI 1 source [find target/stm32f7x.cfg] +reset_config srst_only + # QUADSPI initialization proc qspi_init { } { global a diff --git a/tcl/board/stm32f769i-disco.cfg b/tcl/board/stm32f769i-disco.cfg index cc4334bf4..75dffd8db 100644 --- a/tcl/board/stm32f769i-disco.cfg +++ b/tcl/board/stm32f769i-disco.cfg @@ -14,6 +14,8 @@ set QUADSPI 1 source [find target/stm32f7x.cfg] +reset_config srst_only + # QUADSPI initialization proc qspi_init { } { global a diff --git a/tcl/board/stm32f7discovery.cfg b/tcl/board/stm32f7discovery.cfg index 7d1bc9665..d6cbff465 100644 --- a/tcl/board/stm32f7discovery.cfg +++ b/tcl/board/stm32f7discovery.cfg @@ -10,3 +10,5 @@ transport select hla_swd set WORKAREASIZE 0x40000 source [find target/stm32f7x.cfg] + +reset_config srst_only diff --git a/tcl/board/stm32h735g-disco.cfg b/tcl/board/stm32h735g-disco.cfg index 405e47024..cb5caa4af 100644 --- a/tcl/board/stm32h735g-disco.cfg +++ b/tcl/board/stm32h735g-disco.cfg @@ -17,6 +17,8 @@ if {![info exists OCTOSPI1]} { source [find target/stm32h7x.cfg] +reset_config srst_only + # OCTOSPI initialization # octo: 8-line mode proc octospi_init { octo } { diff --git a/tcl/board/stm32h745i-disco.cfg b/tcl/board/stm32h745i-disco.cfg index 5adcfea16..5a587ae8c 100644 --- a/tcl/board/stm32h745i-disco.cfg +++ b/tcl/board/stm32h745i-disco.cfg @@ -16,6 +16,8 @@ if {![info exists QUADSPI]} { source [find target/stm32h7x_dual_bank.cfg] +reset_config srst_only + source [find board/stm32h7x_dual_qspi.cfg] $_CHIPNAME.cpu0 configure -event reset-init { diff --git a/tcl/board/stm32h747i-disco.cfg b/tcl/board/stm32h747i-disco.cfg index 22fd74aea..698ef5884 100644 --- a/tcl/board/stm32h747i-disco.cfg +++ b/tcl/board/stm32h747i-disco.cfg @@ -16,6 +16,8 @@ if {![info exists QUADSPI]} { source [find target/stm32h7x_dual_bank.cfg] +reset_config srst_only + # QUADSPI initialization # qpi: 4-line mode proc qspi_init { qpi } { diff --git a/tcl/board/stm32h750b-disco.cfg b/tcl/board/stm32h750b-disco.cfg index e6062035a..609cf3853 100644 --- a/tcl/board/stm32h750b-disco.cfg +++ b/tcl/board/stm32h750b-disco.cfg @@ -16,6 +16,8 @@ if {![info exists QUADSPI]} { source [find target/stm32h7x.cfg] +reset_config srst_only + source [find board/stm32h7x_dual_qspi.cfg] $_CHIPNAME.cpu0 configure -event reset-init { diff --git a/tcl/board/stm32h7b3i-disco.cfg b/tcl/board/stm32h7b3i-disco.cfg index e5512eade..0c4cc23be 100644 --- a/tcl/board/stm32h7b3i-disco.cfg +++ b/tcl/board/stm32h7b3i-disco.cfg @@ -17,6 +17,8 @@ if {![info exists OCTOSPI1]} { source [find target/stm32h7x_dual_bank.cfg] +reset_config srst_only + # OCTOSPI initialization # octo: 8-line mode proc octospi_init { octo } { diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg index 3c7679de2..91ab2891b 100644 --- a/tcl/target/stm32f7x.cfg +++ b/tcl/target/stm32f7x.cfg @@ -82,7 +82,7 @@ if {[using_jtag]} { # # This target is compatible with connect_assert_srst, which may be set in a # board file. -reset_config srst_only srst_nogate +reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to diff --git a/tcl/target/stm32h7x.cfg b/tcl/target/stm32h7x.cfg index 877976c1a..f2a5c42c6 100644 --- a/tcl/target/stm32h7x.cfg +++ b/tcl/target/stm32h7x.cfg @@ -142,7 +142,7 @@ if {[using_jtag]} { # usage does not work with HLA, so is not done by default. That change could be # made in a local configuration file if connect_assert_srst mode is needed for # a specific application and a non-HLA adapter is in use. -reset_config srst_only srst_nogate +reset_config srst_nogate if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to From c865879eb81b6e5fca58bed8b63f6336b98ec425 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 2 Sep 2021 15:56:50 +0100 Subject: [PATCH 22/56] doc: add a note to use 'stm32l4x option_load' after changing option bytes Change-Id: I502be27da892e393731d11e02203c736e77033d0 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6533 Tested-by: jenkins Reviewed-by: Karl Palsson Reviewed-by: Paul Fertser Reviewed-by: Tomas Vanek --- doc/openocd.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 9c94c7168..6a8350a51 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7348,11 +7348,15 @@ Some stm32l4x-specific commands are defined: @deffn {Command} {stm32l4x lock} num Locks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. + +@emph{Note:} To apply the protection change immediately, use @command{stm32l4x option_load}. @end deffn @deffn {Command} {stm32l4x unlock} num Unlocks the entire stm32 device. The @var{num} parameter is a value shown by @command{flash banks}. + +@emph{Note:} To apply the protection change immediately, use @command{stm32l4x option_load}. @end deffn @deffn Command {stm32l4x flashloader} num [@option{enable} | @option{disable}] @@ -7390,6 +7394,8 @@ The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offs is the register offset of the Option byte to write, and @var{reg_mask} is the mask to apply when writing the register (only bits with a '1' will be touched). +@emph{Note:} To apply the option bytes change immediately, use @command{stm32l4x option_load}. + For example to write the WRP1AR option bytes: @example stm32l4x option_write 0 0x28 0x00FF0000 0x00FF00FF From ea562985b5eff536feea022b074122b21c3610ea Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 26 Aug 2021 10:41:35 +0100 Subject: [PATCH 23/56] gerrit url: update the gerrit server address to https://review.openocd.org change the gerrit server address from http://openocd.zylin.com to the new address in order to avoid re-directions. Change-Id: I76e128c277f63783d1a6f63a6a387aa838f51f80 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6481 Tested-by: jenkins Reviewed-by: Antonio Borneo --- HACKING | 18 +++++++++--------- doc/openocd.texi | 2 +- tools/initial.sh | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/HACKING b/HACKING index c1a6b0e8a..cf3f58906 100644 --- a/HACKING +++ b/HACKING @@ -91,7 +91,7 @@ Add yourself to the GPL copyright for non-trivial changes. @section stepbystep Step by step procedure --# Create a Gerrit account at: http://openocd.zylin.com +-# Create a Gerrit account at: https://review.openocd.org - On subsequent sign ins, use the full URL prefaced with 'http://' For example: http://user_identifier.open_id_provider.com -# Add a username to your profile. @@ -121,18 +121,18 @@ Add yourself to the GPL copyright for non-trivial changes. to instruct git locally how to send off the changes. -# Add a new remote to git using Gerrit username: @code -git remote add review ssh://USERNAME@openocd.zylin.com:29418/openocd.git +git remote add review ssh://USERNAME@review.openocd.org:29418/openocd.git git config remote.review.push HEAD:refs/for/master @endcode Or with http only: @code -git remote add review http://USERNAME@openocd.zylin.com/p/openocd.git +git remote add review https://USERNAME@review.openocd.org/p/openocd.git git config remote.review.push HEAD:refs/for/master @endcode - The http password is configured from your gerrit settings - http://openocd.zylin.com/#/settings/http-password. + The http password is configured from your gerrit settings - https://review.openocd.org/#/settings/http-password. \note If you want to simplify http access you can also add your http password to the url as follows: @code -git remote add review http://USERNAME:PASSWORD@openocd.zylin.com/p/openocd.git +git remote add review https://USERNAME:PASSWORD@review.openocd.org/p/openocd.git @endcode \note All contributions should be pushed to @c refs/for/master on the Gerrit server, even if you plan to use several local branches for different @@ -140,11 +140,11 @@ topics. It is possible because @c for/master is not a traditional Git branch. -# You will need to install this hook, we will look into a better solution: @code -scp -p -P 29418 USERNAME@openocd.zylin.com:hooks/commit-msg .git/hooks/ +scp -p -P 29418 USERNAME@review.openocd.org:hooks/commit-msg .git/hooks/ @endcode Or with http only: @code -wget http://openocd.zylin.com/tools/hooks/commit-msg +wget https://review.openocd.org/tools/hooks/commit-msg mv commit-msg .git/hooks chmod +x .git/hooks/commit-msg @endcode @@ -228,10 +228,10 @@ not have to) be disregarded if all conditions listed below are met: - reviewer does not answer e-mails for another month. @section browsing Browsing Patches -All OpenOCD patches can be reviewed here. +All OpenOCD patches can be reviewed here. @section reviewing Reviewing Patches -From the main Review +From the main Review page select the patch you want to review and click on that patch. On the appearing page select the download method (top right). Apply the patch. After building and testing you can leave a note with the "Reply" diff --git a/doc/openocd.texi b/doc/openocd.texi index 6a8350a51..8572ce4a7 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -265,7 +265,7 @@ listed in the Doxyfile configuration at the top of the source tree. All changes in the OpenOCD Git repository go through the web-based Gerrit Code Review System: -@uref{http://openocd.zylin.com/} +@uref{https://review.openocd.org/} After a one-time registration and repository setup, anyone can push commits from their local Git repository directly into Gerrit. diff --git a/tools/initial.sh b/tools/initial.sh index 446b98bda..eafc9c138 100755 --- a/tools/initial.sh +++ b/tools/initial.sh @@ -11,7 +11,7 @@ add_remote() { remote_exist=`grep remote .git/config | grep review | wc -l` if [ "x$remote_exist" = "x0" ] ; then - git remote add review ssh://$USERNAME@openocd.zylin.com:29418/openocd.git + git remote add review ssh://$USERNAME@review.openocd.org:29418/openocd.git git config remote.review.push HEAD:refs/for/master else echo "Remote review exists" @@ -25,7 +25,7 @@ update_commit_msg() mv commit-msg $save_file printf "%-30s" "Updating commit-msg" status="OK" - wget -o log http://openocd.zylin.com/tools/hooks/commit-msg || status="FAIL" + wget -o log https://review.openocd.org/tools/hooks/commit-msg || status="FAIL" echo $status if [ $status = "FAIL" ] ; then mv $save_file commit-msg From 79800db98a985bcd601e8a892aed76d96548a51b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 Sep 2021 23:01:09 +0200 Subject: [PATCH 24/56] openocd: remove last NULL comparisons The NULL pointers preceded by cast where not detected by the scripting tools looking for NULL pointer comparison. Remove them and, while there, further simplify the code and apply the other coding style rules. Change-Id: Ia7406122e07ef56ef311579ab0ee7ddb22c8e4b5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6539 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI --- src/jtag/drivers/jlink.c | 2 +- src/rtos/linux.c | 13 ++++++------- src/rtos/rtos.c | 4 ++-- src/server/gdb_server.c | 8 +++++--- src/target/armv7a.c | 2 +- src/target/armv7a_cache.c | 2 +- src/target/armv7a_cache_l2x.c | 2 +- src/target/armv8_cache.c | 2 +- src/target/breakpoints.c | 12 ++++++------ src/target/cortex_a.c | 6 +++--- src/target/mips_m4k.c | 6 +++--- src/target/smp.c | 2 +- src/target/target.c | 4 ++-- 13 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 63bcda1f4..319ca380a 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -573,7 +573,7 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) return ERROR_JTAG_INIT_FAILED; } - use_usb_location = (jtag_usb_get_location() != NULL); + use_usb_location = !!jtag_usb_get_location(); if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { LOG_ERROR("Multiple devices found, specify the desired device"); diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 11a55c434..84b4c6524 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -195,13 +195,12 @@ static int linux_os_thread_reg_list(struct rtos *rtos, found = 0; do { if (head->target->coreid == next->core_id) { - target = head->target; found = 1; - } else - head = head->next; - - } while ((head != (struct target_list *)NULL) && (found == 0)); + break; + } + head = head->next; + } while (head); if (found == 0) { LOG_ERROR @@ -414,7 +413,7 @@ static int get_current(struct target *target, int create) ctt = ctt->next; } - while (head != (struct target_list *)NULL) { + while (head) { struct reg **reg_list; int reg_list_size; int retval; @@ -1397,7 +1396,7 @@ static int linux_os_smp_init(struct target *target) struct current_thread *ct; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { if (head->target->rtos != rtos) { struct linux_os *smp_os_linux = (struct linux_os *)head->target->rtos->rtos_specific_params; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 0e747e3e4..eaad5e50c 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -234,7 +234,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s uint64_t addr = 0; size_t reply_len; char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */ - struct symbol_table_elem *next_sym = NULL; + struct symbol_table_elem *next_sym; struct target *target = get_target_from_connection(connection); struct rtos *os = target->rtos; @@ -272,7 +272,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s next_sym = next_symbol(os, cur_sym, addr); /* Should never happen unless the debugger misbehaves */ - if (next_sym == NULL) { + if (!next_sym) { LOG_WARNING("RTOS: Debugger sent us qSymbol with '%s' that we did not ask for", cur_sym); goto done; } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 015baa1d8..a16b4ccbe 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3006,8 +3006,10 @@ static bool gdb_handle_vrun_packet(struct connection *connection, const char *pa free(next_hex_encoded_field(&parse, ';')); char *cmdline = next_hex_encoded_field(&parse, ';'); - char *arg; - while (cmdline && (arg = next_hex_encoded_field(&parse, ';')) != NULL) { + while (cmdline) { + char *arg = next_hex_encoded_field(&parse, ';'); + if (!arg) + break; char *new_cmdline = alloc_printf("%s %s", cmdline, arg); free(cmdline); free(arg); @@ -3549,7 +3551,7 @@ static int gdb_target_start(struct target *target, const char *port) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if (curr != target) curr->gdb_service = gdb_service; diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 6de79c389..2259fa560 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -207,7 +207,7 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; /* initialize all target in this cluster (smp target) * l2 cache must be configured after smp declaration */ - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index fa6df2a27..4078fdde2 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -140,7 +140,7 @@ int armv7a_cache_auto_flush_all_data(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if (curr->state == TARGET_HALTED) retval = armv7a_l1_d_cache_clean_inval_all(curr); diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c index 8ecdb008d..6b42fae53 100644 --- a/src/target/armv7a_cache_l2x.c +++ b/src/target/armv7a_cache_l2x.c @@ -210,7 +210,7 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t /* initialize all targets in this cluster (smp target) * l2 cache must be configured after smp declaration */ - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index b668b8422..f05ac07cd 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -252,7 +252,7 @@ static int armv8_flush_all_data(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if (curr->state == TARGET_HALTED) { LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index dfec75051..dd901ef25 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -224,7 +224,7 @@ int breakpoint_add(struct target *target, if (type == BKPT_SOFT) return breakpoint_add_internal(head->target, address, length, type); - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; retval = breakpoint_add_internal(curr, address, length, type); if (retval != ERROR_OK) @@ -247,7 +247,7 @@ int context_breakpoint_add(struct target *target, struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; retval = context_breakpoint_add_internal(curr, asid, length, type); if (retval != ERROR_OK) @@ -271,7 +271,7 @@ int hybrid_breakpoint_add(struct target *target, struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type); if (retval != ERROR_OK) @@ -347,7 +347,7 @@ void breakpoint_remove(struct target *target, target_addr_t address) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; num_breakpoints += breakpoint_remove_internal(curr, address); head = head->next; @@ -365,7 +365,7 @@ void breakpoint_remove_all(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; breakpoint_remove_all_internal(curr); head = head->next; @@ -389,7 +389,7 @@ void breakpoint_clear_target(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; breakpoint_clear_target_internal(curr); head = head->next; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index b1f22067f..241f2e684 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -641,7 +641,7 @@ static struct target *get_cortex_a(struct target *target, int32_t coreid) struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; @@ -657,7 +657,7 @@ static int cortex_a_halt_smp(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED) && target_was_examined(curr)) @@ -953,7 +953,7 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) struct target *curr; target_addr_t address; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index cd0689351..ca4416981 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -131,7 +131,7 @@ static struct target *get_mips_m4k(struct target *target, int32_t coreid) struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; @@ -146,7 +146,7 @@ static int mips_m4k_halt_smp(struct target *target) struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { int ret = ERROR_OK; curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED)) @@ -417,7 +417,7 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { int ret = ERROR_OK; curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { diff --git a/src/target/smp.c b/src/target/smp.c index 94c4da5a8..518f6e458 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -137,7 +137,7 @@ COMMAND_HANDLER(handle_smp_gdb_command) int retval = ERROR_OK; struct target_list *head; head = target->head; - if (head != (struct target_list *)NULL) { + if (head) { if (CMD_ARGC == 1) { int coreid = 0; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); diff --git a/src/target/target.c b/src/target/target.c index 7bace83f9..49f205a97 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5999,7 +5999,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) new = malloc(sizeof(struct target_list)); new->target = target; new->next = (struct target_list *)NULL; - if (head == (struct target_list *)NULL) { + if (!head) { head = new; curr = head; } else { @@ -6011,7 +6011,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* now parse the list of cpu and put the target in smp mode*/ curr = head; - while (curr != (struct target_list *)NULL) { + while (curr) { target = curr->target; target->smp = 1; target->head = head; From 73c64167997f9f4312767896581a57acc5b8a98f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 Sep 2021 23:22:27 +0200 Subject: [PATCH 25/56] target: do not cast NULL in assignment NULL is defined as 'void *'. There is no need to cast NULL while assigning it to a pointer. Change-Id: Ibaf18e5d47329707ec9c1c184cd4bba2e8e702ff Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6540 Reviewed-by: Tomas Vanek Reviewed-by: Tarek BOCHKATI Tested-by: jenkins --- src/target/target.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 49f205a97..6571e9c6f 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5978,10 +5978,10 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int i; const char *targetname; int retval, len; - struct target *target = (struct target *) NULL; + struct target *target = NULL; struct target_list *head, *curr, *new; - curr = (struct target_list *) NULL; - head = (struct target_list *) NULL; + curr = NULL; + head = NULL; retval = 0; LOG_DEBUG("%d", argc); @@ -5998,7 +5998,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (target) { new = malloc(sizeof(struct target_list)); new->target = target; - new->next = (struct target_list *)NULL; + new->next = NULL; if (!head) { head = new; curr = head; From 00b16b294faad9102db8a56df537be443f74d18f Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Wed, 8 Sep 2021 23:14:34 +0100 Subject: [PATCH 26/56] hla: Increase HLA_MAX_USB_IDS We are already at the limit for the number of VID/PID pairs declared in stlink.cfg and stlink-dap.cfg. Increase the maximum number of pairs from 8 to 16 to make room for a few more devices. Signed-off-by: Andreas Sandberg Change-Id: Ifad8e7ef67b930edbb5421730f00eb3390812f06 Reviewed-on: https://review.openocd.org/c/openocd/+/6554 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Antonio Borneo --- src/jtag/hla/hla_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index a1c95cde1..c882acf48 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -29,7 +29,7 @@ enum e_hl_transports; /** */ extern const char *hl_transports[]; -#define HLA_MAX_USB_IDS 8 +#define HLA_MAX_USB_IDS 16 struct hl_interface_param_s { /** */ From 564e7576ab13fc0aec06581630eff398c8cf87bd Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Wed, 8 Sep 2021 23:09:51 +0100 Subject: [PATCH 27/56] stlink: Add PID for V3 device without MSD Add the 0x3754 PID used by some STLINK-V3 devices when MSD has been disabled. This PID has been observed on a Nucleo-G431RB board. Signed-off-by: Andreas Sandberg Change-Id: Idb85874fa5a9dff5940bae7e95426a956693b976 Reviewed-on: https://review.openocd.org/c/openocd/+/6555 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Antonio Borneo --- contrib/60-openocd.rules | 1 + src/jtag/drivers/stlink_usb.c | 2 ++ tcl/interface/stlink-dap.cfg | 2 +- tcl/interface/stlink.cfg | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index a6ff995e1..94573a83a 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -93,6 +93,7 @@ ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374d", MODE="660", GROUP="plugdev", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374e", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3753", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", MODE="660", GROUP="plugdev", TAG+="uaccess" # Cypress SuperSpeed Explorer Kit ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0007", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2bbd03b6a..e8e2472ee 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -90,6 +90,7 @@ #define STLINK_V3E_PID (0x374E) #define STLINK_V3S_PID (0x374F) #define STLINK_V3_2VCP_PID (0x3753) +#define STLINK_V3E_NO_MSD_PID (0x3754) /* * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and @@ -3130,6 +3131,7 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param) case STLINK_V3E_PID: case STLINK_V3S_PID: case STLINK_V3_2VCP_PID: + case STLINK_V3E_NO_MSD_PID: h->version.stlink = 3; h->tx_ep = STLINK_V2_1_TX_EP; h->trace_ep = STLINK_V2_1_TRACE_EP; diff --git a/tcl/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg index ac4de18f9..d912a5560 100644 --- a/tcl/interface/stlink-dap.cfg +++ b/tcl/interface/stlink-dap.cfg @@ -9,7 +9,7 @@ # adapter driver st-link -st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 +st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 # transport select dapdirect_jtag # transport select dapdirect_swd diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index 54cd63eb6..cb8e00494 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -6,7 +6,7 @@ adapter driver hla hla_layout stlink hla_device_desc "ST-LINK" -hla_vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 +hla_vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 # Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 # devices seem to have serial numbers with unreadable characters. ST-LINK/V2 From 1efd12a6de0787097d08807809643905b7d03d68 Mon Sep 17 00:00:00 2001 From: Florian Zaruba Date: Tue, 7 Sep 2021 18:22:13 +0200 Subject: [PATCH 28/56] jep106.inc: Update to revision JEP106BC Signed-off-by: Florian Zaruba Change-Id: I566eb331b2884de3df5ad3f02c2ec7961539257b Reviewed-on: https://review.openocd.org/c/openocd/+/6551 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/jep106.inc | 214 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 206 insertions(+), 8 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 76e6137be..41afdb845 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -27,7 +27,7 @@ [0][0x15 - 1] = "NXP (Philips)", [0][0x16 - 1] = "Synertek", [0][0x17 - 1] = "Texas Instruments", -[0][0x18 - 1] = "Toshiba", +[0][0x18 - 1] = "Kioxia Corporation", [0][0x19 - 1] = "Xicor", [0][0x1a - 1] = "Zilog", [0][0x1b - 1] = "Eurotechnique", @@ -44,7 +44,7 @@ [0][0x26 - 1] = "Visic", [0][0x27 - 1] = "Intl. CMOS Technology", [0][0x28 - 1] = "SSSI", -[0][0x29 - 1] = "MicrochipTechnology", +[0][0x29 - 1] = "Microchip Technology", [0][0x2a - 1] = "Ricoh Ltd", [0][0x2b - 1] = "VLSI", [0][0x2c - 1] = "Micron Technology", @@ -85,7 +85,7 @@ [0][0x4f - 1] = "I3 Design System", [0][0x50 - 1] = "Klic", [0][0x51 - 1] = "Crosspoint Solutions", -[0][0x52 - 1] = "Alliance Semiconductor", +[0][0x52 - 1] = "Alliance Memory Inc", [0][0x53 - 1] = "Tandem", [0][0x54 - 1] = "Hewlett-Packard", [0][0x55 - 1] = "Integrated Silicon Solutions", @@ -1017,7 +1017,7 @@ [8][0x03 - 1] = "Fairchild", [8][0x04 - 1] = "Mercury Systems", [8][0x05 - 1] = "Sonics Inc", -[8][0x06 - 1] = "ICC Intelligent Platforms GmbH", +[8][0x06 - 1] = "Emerson Automation Solutions", [8][0x07 - 1] = "Shenzhen Jinge Information Co Ltd", [8][0x08 - 1] = "SCWW", [8][0x09 - 1] = "Silicon Motion Inc", @@ -1048,7 +1048,7 @@ [8][0x22 - 1] = "TSP Global Co Ltd", [8][0x23 - 1] = "HighX", [8][0x24 - 1] = "Shenzhen Elicks Technology", -[8][0x25 - 1] = "ISSI/Chingis", +[8][0x25 - 1] = "XinKai/Silicon Kaiser", [8][0x26 - 1] = "Google Inc", [8][0x27 - 1] = "Dasima International Development", [8][0x28 - 1] = "Leahkinn Technology Limited", @@ -1280,7 +1280,7 @@ [10][0x0e - 1] = "AITC Memory", [10][0x0f - 1] = "UNIC Memory Technology Co Ltd", [10][0x10 - 1] = "Shenzhen Huafeng Science Technology", -[10][0x11 - 1] = "ChangXin Memory Technologies Inc", +[10][0x11 - 1] = "CXMT", [10][0x12 - 1] = "Guangzhou Xinyi Heng Computer Trading Firm", [10][0x13 - 1] = "SambaNova Systems", [10][0x14 - 1] = "V-GEN", @@ -1334,11 +1334,11 @@ [10][0x44 - 1] = "UPMEM", [10][0x45 - 1] = "Chun Well Technology Holding Limited", [10][0x46 - 1] = "Astera Labs Inc", -[10][0x47 - 1] = "VMEMORY Co Ltd", +[10][0x47 - 1] = "Winconway", [10][0x48 - 1] = "Advantech Co Ltd", [10][0x49 - 1] = "Chengdu Fengcai Electronic Technology", [10][0x4a - 1] = "The Boeing Company", -[10][0x4b - 1] = "ThinCI Inc", +[10][0x4b - 1] = "Blaize Inc", [10][0x4c - 1] = "Ramonster Technology Co Ltd", [10][0x4d - 1] = "Wuhan Naonongmai Technology Co Ltd", [10][0x4e - 1] = "Shenzhen Hui ShingTong Technology", @@ -1413,4 +1413,202 @@ [11][0x15 - 1] = "Jazer", [11][0x16 - 1] = "Xiamen Semiconductor Investment Group", [11][0x17 - 1] = "Guangzhou Longdao Network Tech Co", +[11][0x18 - 1] = "Shenzhen Futian SEC Electronic Market", +[11][0x19 - 1] = "Allegro Microsystems LLC", +[11][0x1a - 1] = "Hunan RunCore Innovation Technology", +[11][0x1b - 1] = "C-Corsa Technology", +[11][0x1c - 1] = "Zhuhai Chuangfeixin Technology Co Ltd", +[11][0x1d - 1] = "Beijing InnoMem Technologies Co Ltd", +[11][0x1e - 1] = "YooTin", +[11][0x1f - 1] = "Shenzhen Pengxiong Technology Co Ltd", +[11][0x20 - 1] = "Dongguan Yingbang Commercial Trading Co", +[11][0x21 - 1] = "Shenzhen Ronisys Electronics Co Ltd", +[11][0x22 - 1] = "Hongkong Xinlan Guangke Co Ltd", +[11][0x23 - 1] = "Apex Microelectronics Co Ltd", +[11][0x24 - 1] = "Beijing Hongda Jinming Technology Co Ltd", +[11][0x25 - 1] = "Ling Rui Technology (Shenzhen) Co Ltd", +[11][0x26 - 1] = "Hongkong Hyunion Electronics Co Ltd", +[11][0x27 - 1] = "Starsystems Inc", +[11][0x28 - 1] = "Shenzhen Yingjiaxun Industrial Co Ltd", +[11][0x29 - 1] = "Dongguan Crown Code Electronic Commerce", +[11][0x2a - 1] = "Monolithic Power Systems Inc", +[11][0x2b - 1] = "WuHan SenNaiBo E-Commerce Co Ltd", +[11][0x2c - 1] = "Hangzhou Hikstorage Technology Co", +[11][0x2d - 1] = "Shenzhen Goodix Technology Co Ltd", +[11][0x2e - 1] = "Aigo Electronic Technology Co Ltd", +[11][0x2f - 1] = "Hefei Konsemi Storage Technology Co Ltd", +[11][0x30 - 1] = "Cactus Technologies Limited", +[11][0x31 - 1] = "DSIN", +[11][0x32 - 1] = "Blu Wireless Technology", +[11][0x33 - 1] = "Nanjing UCUN Technology Inc", +[11][0x34 - 1] = "Acacia Communications", +[11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd", +[11][0x36 - 1] = "Zyzyx", +[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd", +[11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd", +[11][0x39 - 1] = "Syzexion", +[11][0x3a - 1] = "Kembona", +[11][0x3b - 1] = "Qingdao Thunderobot Technology Co Ltd", +[11][0x3c - 1] = "Morse Micro", +[11][0x3d - 1] = "Shenzhen Envida Technology Co Ltd", +[11][0x3e - 1] = "UDStore Solution Limited", +[11][0x3f - 1] = "Shunlie", +[11][0x40 - 1] = "Shenzhen Xin Hong Rui Tech Ltd", +[11][0x41 - 1] = "Shenzhen Yze Technology Co Ltd", +[11][0x42 - 1] = "Shenzhen Huang Pu He Xin Technology", +[11][0x43 - 1] = "Xiamen Pengpai Microelectronics Co Ltd", +[11][0x44 - 1] = "JISHUN", +[11][0x45 - 1] = "Shenzhen WODPOSIT Technology Co", +[11][0x46 - 1] = "Unistar", +[11][0x47 - 1] = "UNICORE Electronic (Suzhou) Co Ltd", +[11][0x48 - 1] = "Axonne Inc", +[11][0x49 - 1] = "Shenzhen SOVERECA Technology Co", +[11][0x4a - 1] = "Dire Wolf", +[11][0x4b - 1] = "Whampoa Core Technology Co Ltd", +[11][0x4c - 1] = "CSI Halbleiter GmbH", +[11][0x4d - 1] = "ONE Semiconductor", +[11][0x4e - 1] = "SimpleMachines Inc", +[11][0x4f - 1] = "Shenzhen Chengyi Qingdian Electronic", +[11][0x50 - 1] = "Shenzhen Xinlianxin Network Technology", +[11][0x51 - 1] = "Vayyar Imaging Ltd", +[11][0x52 - 1] = "Paisen Network Technology Co Ltd", +[11][0x53 - 1] = "Shenzhen Fengwensi Technology Co Ltd", +[11][0x54 - 1] = "Caplink Technology Limited", +[11][0x55 - 1] = "JJT Solution Co Ltd", +[11][0x56 - 1] = "HOSIN Global Electronics Co Ltd", +[11][0x57 - 1] = "Shenzhen KingDisk Century Technology", +[11][0x58 - 1] = "SOYO", +[11][0x59 - 1] = "DIT Technology Co Ltd", +[11][0x5a - 1] = "iFound", +[11][0x5b - 1] = "Aril Computer Company", +[11][0x5c - 1] = "ASUS", +[11][0x5d - 1] = "Shenzhen Ruiyingtong Technology Co", +[11][0x5e - 1] = "HANA Micron", +[11][0x5f - 1] = "RANSOR", +[11][0x60 - 1] = "Axiado Corporation", +[11][0x61 - 1] = "Tesla Corporation", +[11][0x62 - 1] = "Pingtouge (Shanghai) Semiconductor Co", +[11][0x63 - 1] = "S3Plus Technologies SA", +[11][0x64 - 1] = "Integrated Silicon Solution Israel Ltd", +[11][0x65 - 1] = "GreenWaves Technologies", +[11][0x66 - 1] = "NUVIA Inc", +[11][0x67 - 1] = "Guangzhou Shuvrwine Technology Co", +[11][0x68 - 1] = "Shenzhen Hangshun Chip Technology", +[11][0x69 - 1] = "Chengboliwei Electronic Business", +[11][0x6a - 1] = "Kowin Memory Technology Co Ltd", +[11][0x6b - 1] = "Euronet Technology Inc", +[11][0x6c - 1] = "SCY", +[11][0x6d - 1] = "Shenzhen Xinhongyusheng Electrical", +[11][0x6e - 1] = "PICOCOM", +[11][0x6f - 1] = "Shenzhen Toooogo Memory Technology", +[11][0x70 - 1] = "VLSI Solution", +[11][0x71 - 1] = "Costar Electronics Inc", +[11][0x72 - 1] = "Shenzhen Huatop Technology Co Ltd", +[11][0x73 - 1] = "Inspur Electronic Information Industry", +[11][0x74 - 1] = "Shenzhen Boyuan Computer Technology", +[11][0x75 - 1] = "Beijing Welldisk Electronics Co Ltd", +[11][0x76 - 1] = "Suzhou EP Semicon Co Ltd", +[11][0x77 - 1] = "Zhejiang Dahua Memory Technology", +[11][0x78 - 1] = "Virtu Financial", +[11][0x79 - 1] = "Datotek International Co Ltd", +[11][0x7a - 1] = "Telecom and Microelectronics Industries", +[11][0x7b - 1] = "Echow Technology Ltd", +[11][0x7c - 1] = "APEX-INFO", +[11][0x7d - 1] = "Yingpark", +[11][0x7e - 1] = "Shenzhen Bigway Tech Co Ltd", +[12][0x01 - 1] = "Beijing Haawking Technology Co Ltd", +[12][0x02 - 1] = "Open HW Group", +[12][0x03 - 1] = "JHICC", +[12][0x04 - 1] = "ncoder AG", +[12][0x05 - 1] = "ThinkTech Information Technology Co", +[12][0x06 - 1] = "Shenzhen Chixingzhe Technology Co Ltd", +[12][0x07 - 1] = "Biao Ram Technology Co Ltd", +[12][0x08 - 1] = "Shenzhen Kaizhuoyue Electronics Co Ltd", +[12][0x09 - 1] = "Shenzhen YC Storage Technology Co Ltd", +[12][0x0a - 1] = "Shenzhen Chixingzhe Technology Co", +[12][0x0b - 1] = "Wink Semiconductor (Shenzhen) Co Ltd", +[12][0x0c - 1] = "AISTOR", +[12][0x0d - 1] = "Palma Ceia SemiDesign", +[12][0x0e - 1] = "EM Microelectronic-Marin SA", +[12][0x0f - 1] = "Shenzhen Monarch Memory Technology", +[12][0x10 - 1] = "Reliance Memory Inc", +[12][0x11 - 1] = "Jesis", +[12][0x12 - 1] = "Espressif Systems (Shanghai) Co Ltd", +[12][0x13 - 1] = "Shenzhen Sati Smart Technology Co Ltd", +[12][0x14 - 1] = "NeuMem Co Ltd", +[12][0x15 - 1] = "Lifelong", +[12][0x16 - 1] = "Beijing Oitech Technology Co Ltd", +[12][0x17 - 1] = "Groupe LDLC", +[12][0x18 - 1] = "Semidynamics Technology Services SLU", +[12][0x19 - 1] = "swordbill", +[12][0x1a - 1] = "YIREN", +[12][0x1b - 1] = "Shenzhen Yinxiang Technology Co Ltd", +[12][0x1c - 1] = "PoweV Electronic Technology Co Ltd", +[12][0x1d - 1] = "LEORICE", +[12][0x1e - 1] = "Waymo LLC", +[12][0x1f - 1] = "Ventana Micro Systems", +[12][0x20 - 1] = "Hefei Guangxin Microelectronics Co Ltd", +[12][0x21 - 1] = "Shenzhen Sooner Industrial Co Ltd", +[12][0x22 - 1] = "Horizon Robotics", +[12][0x23 - 1] = "Tangem AG", +[12][0x24 - 1] = "FuturePath Technology (Shenzhen) Co", +[12][0x25 - 1] = "RC Module", +[12][0x26 - 1] = "Team Research Inc", +[12][0x27 - 1] = "ICMAX Technologies Co Limited", +[12][0x28 - 1] = "Lynxi Technologies Ltd Co", +[12][0x29 - 1] = "Guangzhou Taisupanke Computer Equipment", +[12][0x2a - 1] = "Ceremorphic Inc", +[12][0x2b - 1] = "Biwin Storage Technology Co Ltd", +[12][0x2c - 1] = "Beijing ESWIN Computing Technology", +[12][0x2d - 1] = "WeForce Co Ltd", +[12][0x2e - 1] = "Shenzhen Fanxiang Information Technology", +[12][0x2f - 1] = "Unisoc", +[12][0x30 - 1] = "YingChu", +[12][0x31 - 1] = "GUANCUN", +[12][0x32 - 1] = "IPASON", +[12][0x33 - 1] = "Ayar Labs", +[12][0x34 - 1] = "Amazon", +[12][0x35 - 1] = "Shenzhen Xinxinshun Technology Co", +[12][0x36 - 1] = "Galois Inc", +[12][0x37 - 1] = "Ubilite Inc", +[12][0x38 - 1] = "Shenzhen Quanzing Technology Co Ltd", +[12][0x39 - 1] = "Group RZX Technology LTDA", +[12][0x3a - 1] = "Yottac Technology (XI'AN) Cooperation", +[12][0x3b - 1] = "Shenzhen RuiRen Technology Co Ltd", +[12][0x3c - 1] = "Group Star Technology Co Ltd", +[12][0x3d - 1] = "RWA (Hong Kong) Ltd", +[12][0x3e - 1] = "Genesys Logic Inc", +[12][0x3f - 1] = "T3 Robotics Inc.", +[12][0x40 - 1] = "Biostar Microtech International Corp", +[12][0x41 - 1] = "Shenzhen SXmicro Technology Co Ltd", +[12][0x42 - 1] = "Shanghai Yili Computer Technology Co", +[12][0x43 - 1] = "Zhixin Semicoducotor Co Ltd", +[12][0x44 - 1] = "uFound", +[12][0x45 - 1] = "Aigo Data Security Technology Co. Ltd", +[12][0x46 - 1] = ".GXore Technologies", +[12][0x47 - 1] = "Shenzhen Pradeon Intelligent Technology", +[12][0x48 - 1] = "Power LSI", +[12][0x49 - 1] = "PRIME", +[12][0x4a - 1] = "Shenzhen Juyang Innovative Technology", +[12][0x4b - 1] = "CERVO", +[12][0x4c - 1] = "SiEngine Technology Co., Ltd.", +[12][0x4d - 1] = "Beijing Unigroup Tsingteng MicroSystem", +[12][0x4e - 1] = "Brainsao GmbH", +[12][0x4f - 1] = "Credo Technology Group Ltd", +[12][0x50 - 1] = "Shanghai Biren Technology Co Ltd", +[12][0x51 - 1] = "Nucleu Semiconductor", +[12][0x52 - 1] = "Shenzhen Guangshuo Electronics Co Ltd", +[12][0x53 - 1] = "ZhongsihangTechnology Co Ltd", +[12][0x54 - 1] = "Suzhou Mainshine Electronic Co Ltd.", +[12][0x55 - 1] = "Guangzhou Riss Electronic Technology", +[12][0x56 - 1] = "Shenzhen Cloud Security Storage Co", +[12][0x57 - 1] = "ROG", +[12][0x58 - 1] = "Perceive", +[12][0x59 - 1] = "e-peas", +[12][0x5a - 1] = "Fraunhofer IPMS", +[12][0x5b - 1] = "Shenzhen Daxinlang Electronic Tech Co", +[12][0x5c - 1] = "Abacus Peripherals Private Limited", +[12][0x5d - 1] = "OLOy Technology", +[12][0x5e - 1] = "Wuhan P&S Semiconductor Co Ltd", +[12][0x5f - 1] = "Sitrus Technology", /* EOF */ From 050fcb176071cadc7142c4d9acd3f5a9e67d3ac6 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Wed, 11 Aug 2021 01:14:21 +0100 Subject: [PATCH 29/56] helper/command: fix echo return values the echo command is managed through command handler and not jim_handler to be consistent rename the handler from jim_echo to handle_echo and update the return values Fixes: 4747af362de0 (JIM: document "echo" command) Change-Id: I5ae87ea802d8430b573fb83daa6b35490b5d5775 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6549 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/command.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index e5529d97f..7c29f73e6 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -718,16 +718,18 @@ static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } -COMMAND_HANDLER(jim_echo) +COMMAND_HANDLER(handle_echo) { if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) { LOG_USER_N("%s", CMD_ARGV[1]); - return JIM_OK; + return ERROR_OK; } + if (CMD_ARGC != 1) - return JIM_ERR; + return ERROR_FAIL; + LOG_USER("%s", CMD_ARGV[0]); - return JIM_OK; + return ERROR_OK; } /* Capture progress output and return as tcl return value. If the @@ -1219,7 +1221,7 @@ static const struct command_registration command_builtin_handlers[] = { }, { .name = "echo", - .handler = jim_echo, + .handler = handle_echo, .mode = COMMAND_ANY, .help = "Logs a message at \"user\" priority. " "Option \"-n\" suppresses trailing newline", From a1903f2867037ada39ab814658e1034eb96d1827 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 2 Sep 2021 12:03:59 +0100 Subject: [PATCH 30/56] flash/stm32l4x: fix dual bank support for STM32L552xC devices For STM32L552xC devices with 256K flash: dual bank mode is activated if DB256 is set page size is 2KB if DBANK is set For parts with 512K (aka STM32L5x2xE): DBANK controls both of dual/single bank mode and page size as well. Change-Id: I8be668d5552fefe81acffaf2e3e35ef5e938162e Signed-off-by: Tarek BOCHKATI Reported-by: Patrik Bachan Fixes: https://sourceforge.net/p/openocd/tickets/317/ Reviewed-on: https://review.openocd.org/c/openocd/+/6538 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/flash/nor/stm32l4x.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 0182aae66..8c292e76d 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1923,15 +1923,17 @@ static int stm32l4_probe(struct flash_bank *bank) /* STM32L55/L56xx can be single/dual bank: * if size = 512K check DBANK bit * if size = 256K check DB256K bit + * + * default page size is 4kb, if DBANK = 1, the page size is 2kb. */ - page_size_kb = 4; + + page_size_kb = (stm32l4_info->optr & FLASH_L5_DBANK) ? 2 : 4; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; + if ((is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DBANK)) || (!is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DB256))) { stm32l4_info->dual_bank_mode = true; - page_size_kb = 2; - num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages / 2; } break; From a0bd3c9924870c3b8f428648410181040dabc33c Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 15 Sep 2021 10:34:21 +0100 Subject: [PATCH 31/56] Partially Revert "flash/stm32l4x: introduce flash programming without loader" This partially reverts commit 1247eee4e6e5. There is no reasonable use cases where work-area should be enabled and working, and it can't be used for the flash loader. Instead of introducing driver specific property, users can disable flash load by disabling work-area, for example by setting it to 0. But still we keep the function stm32l4_write_block_without_loader to be used when workarea is not available (no sufficient size or zero) Change-Id: Ibb046c74df354c6067bac978e8ef7efb47d9fd2b Signed-off-by: Oleksij Rempel Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6569 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 7 ------ src/flash/nor/stm32l4x.c | 54 ++++++++++------------------------------ 2 files changed, 13 insertions(+), 48 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 8572ce4a7..138922d08 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7359,13 +7359,6 @@ The @var{num} parameter is a value shown by @command{flash banks}. @emph{Note:} To apply the protection change immediately, use @command{stm32l4x option_load}. @end deffn -@deffn Command {stm32l4x flashloader} num [@option{enable} | @option{disable}] -Enables or disables the flashloader usage (enabled by default), -when disabled it will fall back to direct memory access to program the Flash or OTP memories. -if neither @option{enabled} nor @option{disable} are specified, the command will display -the current configuration. -@end deffn - @deffn {Command} {stm32l4x mass_erase} num Mass erases the entire stm32l4x device. The @var{num} parameter is a value shown by @command{flash banks}. diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 8c292e76d..3ef8bf894 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -252,7 +252,6 @@ struct stm32l4_flash_bank { uint32_t flash_regs_base; const uint32_t *flash_regs; bool otp_enabled; - bool use_flashloader; enum stm32l4_rdp rdp; bool tzen; uint32_t optr; @@ -619,7 +618,6 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command) stm32l4_info->probed = false; stm32l4_info->otp_enabled = false; stm32l4_info->user_bank_size = bank->size; - stm32l4_info->use_flashloader = true; return ERROR_OK; } @@ -1595,20 +1593,21 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) goto err_lock; - if (stm32l4_info->use_flashloader) { - /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5, - * the debug is possible only in non-secure state. - * Thus means the flashloader will run in non-secure mode, - * and the workarea need to be in non-secure RAM */ - if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0_5)) - LOG_INFO("RDP level is 0.5, the work-area should reside in non-secure RAM"); - retval = stm32l4_write_block(bank, buffer, offset, - count / stm32l4_info->data_width); - } + /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5, + * the debug is possible only in non-secure state. + * Thus means the flashloader will run in non-secure mode, + * and the workarea need to be in non-secure RAM */ + if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0_5)) + LOG_WARNING("RDP = 0x55, the work-area should be in non-secure RAM (check SAU partitioning)"); - if (!stm32l4_info->use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { - LOG_INFO("falling back to single memory accesses"); + /* first try to write using the loader, for better performance */ + retval = stm32l4_write_block(bank, buffer, offset, + count / stm32l4_info->data_width); + + /* if resources are not available write without a loader */ + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + LOG_WARNING("falling back to programming without a flash loader (slower)"); retval = stm32l4_write_block_without_loader(bank, buffer, offset, count / stm32l4_info->data_width); } @@ -2266,26 +2265,6 @@ COMMAND_HANDLER(stm32l4_handle_trustzone_command) return stm32l4_perform_obl_launch(bank); } -COMMAND_HANDLER(stm32l4_handle_flashloader_command) -{ - if (CMD_ARGC < 1 || CMD_ARGC > 2) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct flash_bank *bank; - int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); - if (retval != ERROR_OK) - return retval; - - struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; - - if (CMD_ARGC == 2) - COMMAND_PARSE_ENABLE(CMD_ARGV[1], stm32l4_info->use_flashloader); - - command_print(CMD, "FlashLoader usage is %s", stm32l4_info->use_flashloader ? "enabled" : "disabled"); - - return ERROR_OK; -} - COMMAND_HANDLER(stm32l4_handle_option_load_command) { if (CMD_ARGC != 1) @@ -2491,13 +2470,6 @@ static const struct command_registration stm32l4_exec_command_handlers[] = { .usage = "bank_id", .help = "Unlock entire protected flash device.", }, - { - .name = "flashloader", - .handler = stm32l4_handle_flashloader_command, - .mode = COMMAND_EXEC, - .usage = " [enable|disable]", - .help = "Configure the flashloader usage", - }, { .name = "mass_erase", .handler = stm32l4_handle_mass_erase_command, From c4e6034e26b40cc440356eb35b3372b220806e5e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Aug 2021 19:08:23 +0200 Subject: [PATCH 32/56] armv7m.h: relax dependency from 'arm_adi_v5.h' The include file 'armv7m.h' includes 'arm_adi_v5.h' only to get the definition of 'struct adiv5_ap', but doesn't need the struct content. Reducing the cross dependencies speeds-up the compile time during code development by avoiding re-compiling file. Relax the dependency by locally declaring 'struct adiv5_ap' in 'armv7m.h' and remove the include of 'arm_adi_v5.h'. Fix the other files that have now lost the includes file that 'arm_adi_v5.h' depends from. Change-Id: Ic0d40b17db6045fa43f348bda83eaf211a6b347d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6468 Tested-by: jenkins Reviewed-by: Daniel Goehring Reviewed-by: Tarek BOCHKATI --- src/flash/nor/at91sam4l.c | 1 + src/flash/nor/at91samd.c | 1 + src/flash/nor/atsame5.c | 1 + src/flash/nor/bluenrg-x.c | 1 + src/flash/nor/cc3220sf.c | 1 + src/flash/nor/kinetis.c | 1 + src/flash/nor/kinetis_ke.c | 1 + src/flash/nor/max32xxx.c | 1 + src/flash/nor/nrf5.c | 1 + src/flash/nor/psoc6.c | 1 + src/flash/nor/sim3x.c | 1 + src/flash/nor/stellaris.c | 1 + src/flash/nor/stm32l4x.c | 1 + src/flash/nor/stmqspi.c | 1 + src/jtag/drivers/stlink_usb.c | 1 + src/target/armv7m.c | 2 ++ src/target/armv7m.h | 3 ++- src/target/cortex_m.c | 1 + src/target/hla_target.c | 1 + 19 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index f8c6f6490..77dc07f7c 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -22,6 +22,7 @@ #include "imp.h" +#include #include /* At this time, the SAM4L Flash is available in these capacities: diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index d4ac4c998..5cefd1766 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -23,6 +23,7 @@ #include "imp.h" #include "helper/binarybuffer.h" +#include #include #define SAMD_NUM_PROT_BLOCKS 16 diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index 203c470ca..9ab0e8113 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -28,6 +28,7 @@ #include "helper/binarybuffer.h" #include +#include #include /* A note to prefixing. diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index a686e83d3..60eccefaf 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include #include "helper/types.h" #include #include diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c index b29653841..723e605c7 100644 --- a/src/flash/nor/cc3220sf.c +++ b/src/flash/nor/cc3220sf.c @@ -21,6 +21,7 @@ #include "imp.h" #include "cc3220sf.h" +#include #include #include #include diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 3aa4c6bb5..edb4eb58f 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 513b072dd..dc3b37ecb 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -41,6 +41,7 @@ #include "imp.h" #include #include +#include #include #include diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index d11af9094..e7a690d3a 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -21,6 +21,7 @@ #endif #include "imp.h" +#include #include #include diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 8870164d2..c96415547 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -23,6 +23,7 @@ #endif #include "imp.h" +#include #include #include #include diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index b8b520237..a929d3304 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -24,6 +24,7 @@ #include #include "imp.h" +#include #include "target/target.h" #include "target/cortex_m.h" #include "target/breakpoints.h" diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 20b5e3972..2938ed1ab 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -27,6 +27,7 @@ #include #include #include +#include #include /* SI32_DEVICEID0 */ diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index d2638c152..6135c9574 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -30,6 +30,7 @@ #include "jtag/interface.h" #include "imp.h" #include +#include #include #define DID0_VER(did0) ((did0 >> 28)&0x07) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3ef8bf894..a363cd42d 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "bits.h" #include "stm32l4x.h" diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index 0abd8449b..8278601db 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -40,6 +40,7 @@ #endif #include "imp.h" +#include #include #include #include diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index e8e2472ee..4bd07b49f 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 68da020a1..ffc8ca875 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -44,6 +44,8 @@ #include "algorithm.h" #include "register.h" #include "semihosting_common.h" +#include +#include #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ diff --git a/src/target/armv7m.h b/src/target/armv7m.h index f3eb90f24..2816a9145 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -25,10 +25,11 @@ #ifndef OPENOCD_TARGET_ARMV7M_H #define OPENOCD_TARGET_ARMV7M_H -#include "arm_adi_v5.h" #include "arm.h" #include "armv7m_trace.h" +struct adiv5_ap; + extern const int armv7m_psp_reg_map[]; extern const int armv7m_msp_reg_map[]; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 08f2eb911..5deb9bf4a 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -34,6 +34,7 @@ #include "cortex_m.h" #include "target_request.h" #include "target_type.h" +#include "arm_adi_v5.h" #include "arm_disassembler.h" #include "register.h" #include "arm_opcodes.h" diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 91861054f..c67c9cc89 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -37,6 +37,7 @@ #include "target_type.h" #include "armv7m.h" #include "cortex_m.h" +#include "arm_adi_v5.h" #include "arm_semihosting.h" #include "target_request.h" #include From 06d2e430db6933b01b15246e9a4b9392afd8ddbc Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Aug 2021 16:46:30 +0200 Subject: [PATCH 33/56] arm_coresight: add include file and use it Several magic numbers related to ARM CoreSight specification IHI0029E are spread around OpenOCD code. Define through macros the ARM CoreSight magic numbers and collect them in a single include file. Use the new macros wherever possible. Change-Id: I9b0c1c651ce4ffbaf08d31791ef16e95983ee4cb Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6446 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Daniel Goehring --- src/target/Makefile.am | 1 + src/target/aarch64.c | 5 +- src/target/arm_adi_v5.c | 86 +++++++++++++++------------------ src/target/arm_coresight.h | 99 ++++++++++++++++++++++++++++++++++++++ src/target/cortex_a.c | 5 +- 5 files changed, 145 insertions(+), 51 deletions(-) create mode 100644 src/target/arm_coresight.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 34a78517a..49e882fe6 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -165,6 +165,7 @@ ARC_SRC = \ %C%_libtarget_la_SOURCES += \ %D%/algorithm.h \ %D%/arm.h \ + %D%/arm_coresight.h \ %D%/arm_dpm.h \ %D%/arm_jtag.h \ %D%/arm_adi_v5.h \ diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 70e727cf9..fc6bd6b30 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -29,6 +29,7 @@ #include "target_type.h" #include "armv8_opcodes.h" #include "armv8_cache.h" +#include "arm_coresight.h" #include "arm_semihosting.h" #include "jtag/interface.h" #include "smp.h" @@ -2578,8 +2579,8 @@ static int aarch64_examine_first(struct target *target) retval = dap_get_debugbase(armv8->debug_ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; - /* Lookup 0x15 -- Processor DAP */ - retval = dap_lookup_cs_component(armv8->debug_ap, dbgbase, 0x15, + /* Lookup Processor DAP */ + retval = dap_lookup_cs_component(armv8->debug_ap, dbgbase, ARM_CS_C9_DEVTYPE_CORE_DEBUG, &armv8->debug_base, &coreidx); if (retval != ERROR_OK) return retval; diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index c29554239..3ac89719b 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -75,8 +75,10 @@ #include "jtag/interface.h" #include "arm.h" #include "arm_adi_v5.h" +#include "arm_coresight.h" #include "jtag/swd.h" #include "transport/transport.h" +#include #include #include #include @@ -891,11 +893,6 @@ static const char *class_description[16] = { [0xF] = "CoreLink, PrimeCell or System component", }; -static bool is_dap_cid_ok(uint32_t cid) -{ - return (cid & 0xffff0fff) == 0xb105000d; -} - /* * This function checks the ID for each access port to find the requested Access Port type */ @@ -1006,17 +1003,18 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, if (retval != ERROR_OK) return retval; - component_base = dbgbase + (target_addr_t)(romentry & 0xFFFFF000); + component_base = dbgbase + (target_addr_t)(romentry & ARM_CS_ROMENTRY_OFFSET_MASK); - if (romentry & 0x1) { + if (romentry & ARM_CS_ROMENTRY_PRESENT) { uint32_t c_cid1; - retval = mem_ap_read_atomic_u32(ap, component_base | 0xff4, &c_cid1); + retval = mem_ap_read_atomic_u32(ap, component_base + ARM_CS_CIDR1, &c_cid1); if (retval != ERROR_OK) { LOG_ERROR("Can't read component with base address " TARGET_ADDR_FMT ", the corresponding core might be turned off", component_base); return retval; } - if (((c_cid1 >> 4) & 0x0f) == 1) { + unsigned int class = (c_cid1 & ARM_CS_CIDR1_CLASS_MASK) >> ARM_CS_CIDR1_CLASS_SHIFT; + if (class == ARM_CS_CLASS_0X1_ROM_TABLE) { retval = dap_lookup_cs_component(ap, component_base, type, addr, idx); if (retval == ERROR_OK) @@ -1025,10 +1023,10 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return retval; } - retval = mem_ap_read_atomic_u32(ap, component_base | 0xfcc, &devtype); + retval = mem_ap_read_atomic_u32(ap, component_base + ARM_CS_C9_DEVTYPE, &devtype); if (retval != ERROR_OK) return retval; - if ((devtype & 0xff) == type) { + if ((devtype & ARM_CS_C9_DEVTYPE_MASK) == type) { if (!*idx) { *addr = component_base; break; @@ -1047,7 +1045,7 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, uint32_t *cid, uint64_t *pid) { - assert((component_base & 0xFFF) == 0); + assert(IS_ALIGNED(component_base, ARM_CS_ALIGN)); assert(ap && cid && pid); uint32_t cid0, cid1, cid2, cid3; @@ -1055,31 +1053,31 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u int retval; /* IDs are in last 4K section */ - retval = mem_ap_read_u32(ap, component_base + 0xFE0, &pid0); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR0, &pid0); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFE4, &pid1); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR1, &pid1); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFE8, &pid2); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR2, &pid2); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFEC, &pid3); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR3, &pid3); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFD0, &pid4); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR4, &pid4); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFF0, &cid0); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR0, &cid0); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFF4, &cid1); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR1, &cid1); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFF8, &cid2); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR2, &cid2); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(ap, component_base + 0xFFC, &cid3); + retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR3, &cid3); if (retval != ERROR_OK) return retval; @@ -1100,14 +1098,6 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u return ERROR_OK; } -/* The designer identity code is encoded as: - * bits 11:8 : JEP106 Bank (number of continuation codes), only valid when bit 7 is 1. - * bit 7 : Set when bits 6:0 represent a JEP106 ID and cleared when bits 6:0 represent - * a legacy ASCII Identity Code. - * bits 6:0 : JEP106 Identity Code (without parity) or legacy ASCII code according to bit 7. - * JEP106 is a standard available from jedec.org - */ - /* Part number interpretations are from Cortex * core specs, the CoreSight components TRM * (ARM DDI 0314H), CoreSight System Design @@ -1262,23 +1252,23 @@ static int dap_rom_display(struct command_invocation *cmd, return ERROR_OK; /* Don't abort recursion */ } - if (!is_dap_cid_ok(cid)) { + if (!is_valid_arm_cs_cidr(cid)) { command_print(cmd, "\t\tInvalid CID 0x%08" PRIx32, cid); return ERROR_OK; /* Don't abort recursion */ } /* component may take multiple 4K pages */ - uint32_t size = (pid >> 36) & 0xf; + uint32_t size = ARM_CS_PIDR_SIZE(pid); if (size > 0) command_print(cmd, "\t\tStart address " TARGET_ADDR_FMT, base_addr - 0x1000 * size); command_print(cmd, "\t\tPeripheral ID 0x%010" PRIx64, pid); - uint8_t class = (cid >> 12) & 0xf; - uint16_t part_num = pid & 0xfff; - uint16_t designer_id = ((pid >> 32) & 0xf) << 7 | ((pid >> 12) & 0x7f); + uint8_t class = (cid & ARM_CS_CIDR_CLASS_MASK) >> ARM_CS_CIDR_CLASS_SHIFT; + uint16_t part_num = ARM_CS_PIDR_PART(pid); + uint16_t designer_id = ARM_CS_PIDR_DESIGNER(pid); - if (pid & 0x00080000) { + if (pid & ARM_CS_PIDR_JEDEC) { /* JEP106 code */ command_print(cmd, "\t\tDesigner is 0x%03" PRIx16 ", %s", designer_id, jep106_manufacturer(designer_id)); @@ -1310,13 +1300,13 @@ static int dap_rom_display(struct command_invocation *cmd, command_print(cmd, "\t\tPart is 0x%" PRIx16", %s %s", part_num, type, full); command_print(cmd, "\t\tComponent class is 0x%" PRIx8 ", %s", class, class_description[class]); - if (class == 1) { /* ROM Table */ + if (class == ARM_CS_CLASS_0X1_ROM_TABLE) { uint32_t memtype; - retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &memtype); + retval = mem_ap_read_atomic_u32(ap, base_addr + ARM_CS_C1_MEMTYPE, &memtype); if (retval != ERROR_OK) return retval; - if (memtype & 0x01) + if (memtype & ARM_CS_C1_MEMTYPE_SYSMEM_MASK) command_print(cmd, "\t\tMEMTYPE system memory present on bus"); else command_print(cmd, "\t\tMEMTYPE system memory not present: dedicated debug bus"); @@ -1329,9 +1319,10 @@ static int dap_rom_display(struct command_invocation *cmd, return retval; command_print(cmd, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", tabs, entry_offset, romentry); - if (romentry & 0x01) { + if (romentry & ARM_CS_ROMENTRY_PRESENT) { /* Recurse. "romentry" is signed */ - retval = dap_rom_display(cmd, ap, base_addr + (int32_t)(romentry & 0xFFFFF000), depth + 1); + retval = dap_rom_display(cmd, ap, base_addr + (int32_t)(romentry & ARM_CS_ROMENTRY_OFFSET_MASK), + depth + 1); if (retval != ERROR_OK) return retval; } else if (romentry != 0) { @@ -1341,15 +1332,16 @@ static int dap_rom_display(struct command_invocation *cmd, break; } } - } else if (class == 9) { /* CoreSight component */ + } else if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) { const char *major = "Reserved", *subtype = "Reserved"; uint32_t devtype; - retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &devtype); + retval = mem_ap_read_atomic_u32(ap, base_addr + ARM_CS_C9_DEVTYPE, &devtype); if (retval != ERROR_OK) return retval; - unsigned minor = (devtype >> 4) & 0x0f; - switch (devtype & 0x0f) { + unsigned int minor = (devtype & ARM_CS_C9_DEVTYPE_SUB_MASK) >> ARM_CS_C9_DEVTYPE_SUB_SHIFT; + unsigned int devtype_major = (devtype & ARM_CS_C9_DEVTYPE_MAJOR_MASK) >> ARM_CS_C9_DEVTYPE_MAJOR_SHIFT; + switch (devtype_major) { case 0: major = "Miscellaneous"; switch (minor) { @@ -1482,10 +1474,10 @@ static int dap_rom_display(struct command_invocation *cmd, } break; } - command_print(cmd, "\t\tType is 0x%02" PRIx8 ", %s, %s", - (uint8_t)(devtype & 0xff), + command_print(cmd, "\t\tType is 0x%02x, %s, %s", + devtype & ARM_CS_C9_DEVTYPE_MASK, major, subtype); - /* REVISIT also show 0xfc8 DevId */ + /* REVISIT also show ARM_CS_C9_DEVID */ } return ERROR_OK; diff --git a/src/target/arm_coresight.h b/src/target/arm_coresight.h new file mode 100644 index 000000000..42e6c5eb6 --- /dev/null +++ b/src/target/arm_coresight.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * General info from: + * ARM CoreSight Architecture Specification v3.0 IHI0029E + */ + +#ifndef OPENOCD_TARGET_ARM_CORESIGHT_H +#define OPENOCD_TARGET_ARM_CORESIGHT_H + +#include +#include + +#include + +#define ARM_CS_ALIGN (0x1000) + +/* mandatory registers */ +#define ARM_CS_PIDR0 (0xFE0) +#define ARM_CS_PIDR1 (0xFE4) +#define ARM_CS_PIDR2 (0xFE8) +#define ARM_CS_PIDR3 (0xFEC) +#define ARM_CS_PIDR4 (0xFD0) +#define ARM_CS_PIDR5 (0xFD4) +#define ARM_CS_PIDR6 (0xFD8) +#define ARM_CS_PIDR7 (0xFDC) + +/* + * When PIDR bit JEDEC is zero, only the lowers 7 bits of DESIGNER are valid + * and represent a legacy ASCII Identity Code. + */ +#define ARM_CS_PIDR_PART(pidr) ((pidr) & 0x0FFF) +#define ARM_CS_PIDR_DESIGNER(pidr) \ +({ \ + typeof(pidr) _x = (pidr); \ + ((_x >> 25) & 0x780) | ((_x >> 12) & 0x7F); \ +}) +#define ARM_CS_PIDR_JEDEC BIT(19) +#define ARM_CS_PIDR_SIZE(pidr) (((pidr) >> 36) & 0x000F) + +#define ARM_CS_CIDR0 (0xFF0) +#define ARM_CS_CIDR1 (0xFF4) +#define ARM_CS_CIDR2 (0xFF8) +#define ARM_CS_CIDR3 (0xFFC) + +#define ARM_CS_CIDR_CLASS_MASK (0x0000F000) +#define ARM_CS_CIDR_CLASS_SHIFT (12) +#define ARM_CS_CLASS_0X1_ROM_TABLE (0x1) +#define ARM_CS_CLASS_0X9_CS_COMPONENT (0x9) + +#define ARM_CS_CIDR1_CLASS_MASK (0x000000F0) +#define ARM_CS_CIDR1_CLASS_SHIFT (4) + +static inline bool is_valid_arm_cs_cidr(uint32_t cidr) +{ + return (cidr & ~ARM_CS_CIDR_CLASS_MASK) == 0xB105000D; +} + +/* Class 0x9 only registers */ +#define ARM_CS_C9_DEVARCH (0xFBC) + +#define ARM_CS_C9_DEVARCH_ARCHID_MASK (0x0000FFFF) +#define ARM_CS_C9_DEVARCH_ARCHID_SHIFT (0) +#define ARM_CS_C9_DEVARCH_REVISION_MASK (0x000F0000) +#define ARM_CS_C9_DEVARCH_REVISION_SHIFT (16) +#define ARM_CS_C9_DEVARCH_PRESENT BIT(20) +#define ARM_CS_C9_DEVARCH_ARCHITECT_MASK (0xFFE00000) +#define ARM_CS_C9_DEVARCH_ARCHITECT_SHIFT (21) + +#define ARM_CS_C9_DEVID (0xFC8) + +#define ARM_CS_C9_DEVID_FORMAT_MASK (0x0000000F) +#define ARM_CS_C9_DEVID_FORMAT_32BIT (0) +#define ARM_CS_C9_DEVID_FORMAT_64BIT (1) +#define ARM_CS_C9_DEVID_SYSMEM_MASK BIT(4) +#define ARM_CS_C9_DEVID_PRR_MASK BIT(5) +#define ARM_CS_C9_DEVID_CP_MASK BIT(5) + +#define ARM_CS_C9_DEVTYPE (0xFCC) + +#define ARM_CS_C9_DEVTYPE_MAJOR_MASK (0x0000000F) +#define ARM_CS_C9_DEVTYPE_MAJOR_SHIFT (0) +#define ARM_CS_C9_DEVTYPE_SUB_MASK (0x000000F0) +#define ARM_CS_C9_DEVTYPE_SUB_SHIFT (4) + +#define ARM_CS_C9_DEVTYPE_MASK (0x000000FF) +#define ARM_CS_C9_DEVTYPE_CORE_DEBUG (0x00000015) + +/* Class 0x1 only registers */ +#define ARM_CS_C1_MEMTYPE ARM_CS_C9_DEVTYPE + +#define ARM_CS_C1_MEMTYPE_SYSMEM_MASK BIT(0) + +/* The coding of ROM entry present differs between Class 0x9 and Class 0x1, + * but we can simplify the whole management */ +#define ARM_CS_ROMENTRY_PRESENT BIT(0) +#define ARM_CS_ROMENTRY_OFFSET_MASK (0xFFFFF000U) + +#endif /* OPENOCD_TARGET_ARM_CORESIGHT_H */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 241f2e684..bf65544f5 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -56,6 +56,7 @@ #include "armv7a_mmu.h" #include "target_request.h" #include "target_type.h" +#include "arm_coresight.h" #include "arm_opcodes.h" #include "arm_semihosting.h" #include "jtag/interface.h" @@ -2921,8 +2922,8 @@ static int cortex_a_examine_first(struct target *target) retval = dap_get_debugbase(armv7a->debug_ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; - /* Lookup 0x15 -- Processor DAP */ - retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15, + /* Lookup Processor DAP */ + retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, ARM_CS_C9_DEVTYPE_CORE_DEBUG, &armv7a->debug_base, &coreidx); if (retval != ERROR_OK) { LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.", From ddbc13a6f22751aa40c8e6bd120e88dcb28257b0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 10 Aug 2021 18:09:28 +0200 Subject: [PATCH 34/56] arm_adi_v5: simplify handling of AP type The complete AP type should include 'class' and 'manufacturer'. Cleanup the definition of AP type from AP_REG_IDR register. Include the check of 'class', together with manufacturer and type. Add the new MEM-AP from ARM IHI0074C. Change-Id: Ic8db7c040108ba237b54f73b1abe24b8b853699b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6447 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Daniel Goehring --- src/target/arm_adi_v5.c | 81 ++++++++++++++++------------------------- src/target/arm_adi_v5.h | 52 ++++++++++++++++---------- 2 files changed, 64 insertions(+), 69 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 3ac89719b..469cb10ca 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -893,6 +893,30 @@ static const char *class_description[16] = { [0xF] = "CoreLink, PrimeCell or System component", }; +static const struct { + enum ap_type type; + const char *description; +} ap_types[] = { + { AP_TYPE_JTAG_AP, "JTAG-AP" }, + { AP_TYPE_COM_AP, "COM-AP" }, + { AP_TYPE_AHB3_AP, "MEM-AP AHB3" }, + { AP_TYPE_APB_AP, "MEM-AP APB2 or APB3" }, + { AP_TYPE_AXI_AP, "MEM-AP AXI3 or AXI4" }, + { AP_TYPE_AHB5_AP, "MEM-AP AHB5" }, + { AP_TYPE_APB4_AP, "MEM-AP APB4" }, + { AP_TYPE_AXI5_AP, "MEM-AP AXI5" }, + { AP_TYPE_AHB5H_AP, "MEM-AP AHB5 with enhanced HPROT" }, +}; + +static const char *ap_type_to_description(enum ap_type type) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(ap_types); i++) + if (type == ap_types[i].type) + return ap_types[i].description; + + return "Unknown"; +} + /* * This function checks the ID for each access port to find the requested Access Port type */ @@ -912,29 +936,12 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a retval = dap_run(dap); - /* IDR bits: - * 31-28 : Revision - * 27-24 : JEDEC bank (0x4 for ARM) - * 23-17 : JEDEC code (0x3B for ARM) - * 16-13 : Class (0b1000=Mem-AP) - * 12-8 : Reserved - * 7-4 : AP Variant (non-zero for JTAG-AP) - * 3-0 : AP Type (0=JTAG-AP 1=AHB-AP 2=APB-AP 4=AXI-AP) - */ - /* Reading register for a non-existent AP should not cause an error, * but just to be sure, try to continue searching if an error does happen. */ - if ((retval == ERROR_OK) && /* Register read success */ - ((id_val & IDR_JEP106) == IDR_JEP106_ARM) && /* Jedec codes match */ - ((id_val & IDR_TYPE) == type_to_find)) { /* type matches*/ - + if (retval == ERROR_OK && (id_val & AP_TYPE_MASK) == type_to_find) { LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")", - (type_to_find == AP_TYPE_AHB3_AP) ? "AHB3-AP" : - (type_to_find == AP_TYPE_AHB5_AP) ? "AHB5-AP" : - (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" : - (type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" : - (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown", + ap_type_to_description(type_to_find), ap_num, id_val); *ap_out = &dap->ap[ap_num]; @@ -942,12 +949,7 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a } } - LOG_DEBUG("No %s found", - (type_to_find == AP_TYPE_AHB3_AP) ? "AHB3-AP" : - (type_to_find == AP_TYPE_AHB5_AP) ? "AHB5-AP" : - (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" : - (type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" : - (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown"); + LOG_DEBUG("No %s found", ap_type_to_description(type_to_find)); return ERROR_FAIL; } @@ -1113,8 +1115,6 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u #define ANY_ID 0x1000 -#define ARM_ID 0x23B - static const struct { uint16_t designer_id; uint16_t part_num; @@ -1490,7 +1490,6 @@ int dap_info_command(struct command_invocation *cmd, uint32_t apid; target_addr_t dbgbase; target_addr_t dbgaddr; - uint8_t mem_ap; /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ retval = dap_get_debugbase(ap, &dbgbase, &apid); @@ -1503,32 +1502,14 @@ int dap_info_command(struct command_invocation *cmd, return ERROR_FAIL; } - switch (apid & (IDR_JEP106 | IDR_TYPE)) { - case IDR_JEP106_ARM | AP_TYPE_JTAG_AP: - command_print(cmd, "\tType is JTAG-AP"); - break; - case IDR_JEP106_ARM | AP_TYPE_AHB3_AP: - command_print(cmd, "\tType is MEM-AP AHB3"); - break; - case IDR_JEP106_ARM | AP_TYPE_AHB5_AP: - command_print(cmd, "\tType is MEM-AP AHB5"); - break; - case IDR_JEP106_ARM | AP_TYPE_APB_AP: - command_print(cmd, "\tType is MEM-AP APB"); - break; - case IDR_JEP106_ARM | AP_TYPE_AXI_AP: - command_print(cmd, "\tType is MEM-AP AXI"); - break; - default: - command_print(cmd, "\tUnknown AP type"); - break; - } + command_print(cmd, "\tType is %s", ap_type_to_description(apid & AP_TYPE_MASK)); /* NOTE: a MEM-AP may have a single CoreSight component that's * not a ROM table ... or have no such components at all. */ - mem_ap = (apid & IDR_CLASS) == AP_CLASS_MEM_AP; - if (mem_ap) { + const unsigned int class = (apid & AP_REG_IDR_CLASS_MASK) >> AP_REG_IDR_CLASS_SHIFT; + + if (class == AP_REG_IDR_CLASS_MEM_AP) { if (is_64bit_ap(ap)) dbgaddr = 0xFFFFFFFFFFFFFFFFull; else diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 73ceea03f..0e1b95f50 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -33,6 +33,9 @@ #include "arm_jtag.h" #include "helper/bits.h" +/* JEP106 ID for ARM */ +#define ARM_ID 0x23B + /* three-bit ACK values for SWD access (sent LSB first) */ #define SWD_ACK_OK 0x1 #define SWD_ACK_WAIT 0x2 @@ -157,13 +160,28 @@ #define MEM_AP_REG_CFG_INVALID 0xFFFFFFF8 /* Fields of the MEM-AP's IDR register */ -#define IDR_REV (0xFUL << 28) -#define IDR_JEP106 (0x7FFUL << 17) -#define IDR_CLASS (0xFUL << 13) -#define IDR_VARIANT (0xFUL << 4) -#define IDR_TYPE (0xFUL << 0) +#define AP_REG_IDR_REVISION_MASK (0xF0000000) +#define AP_REG_IDR_REVISION_SHIFT (28) +#define AP_REG_IDR_DESIGNER_MASK (0x0FFE0000) +#define AP_REG_IDR_DESIGNER_SHIFT (17) +#define AP_REG_IDR_CLASS_MASK (0x0001E000) +#define AP_REG_IDR_CLASS_SHIFT (13) +#define AP_REG_IDR_VARIANT_MASK (0x000000F0) +#define AP_REG_IDR_VARIANT_SHIFT (4) +#define AP_REG_IDR_TYPE_MASK (0x0000000F) +#define AP_REG_IDR_TYPE_SHIFT (0) -#define IDR_JEP106_ARM 0x04760000 +#define AP_REG_IDR_CLASS_NONE (0x0) +#define AP_REG_IDR_CLASS_COM (0x1) +#define AP_REG_IDR_CLASS_MEM_AP (0x8) + +#define AP_REG_IDR_VALUE(d, c, t) (\ + (((d) << AP_REG_IDR_DESIGNER_SHIFT) & AP_REG_IDR_DESIGNER_MASK) | \ + (((c) << AP_REG_IDR_CLASS_SHIFT) & AP_REG_IDR_CLASS_MASK) | \ + (((t) << AP_REG_IDR_TYPE_SHIFT) & AP_REG_IDR_TYPE_MASK) \ +) + +#define AP_TYPE_MASK (AP_REG_IDR_DESIGNER_MASK | AP_REG_IDR_CLASS_MASK | AP_REG_IDR_TYPE_MASK) /* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */ enum swd_special_seq { @@ -349,23 +367,19 @@ struct dap_ops { void (*quit)(struct adiv5_dap *dap); }; -/* - * Access Port classes - */ -enum ap_class { - AP_CLASS_NONE = 0x00000, /* No class defined */ - AP_CLASS_MEM_AP = 0x10000, /* MEM-AP */ -}; - /* * Access Port types */ enum ap_type { - AP_TYPE_JTAG_AP = 0x0, /* JTAG-AP - JTAG master for controlling other JTAG devices */ - AP_TYPE_AHB3_AP = 0x1, /* AHB3 Memory-AP */ - AP_TYPE_APB_AP = 0x2, /* APB Memory-AP */ - AP_TYPE_AXI_AP = 0x4, /* AXI Memory-AP */ - AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */ + AP_TYPE_JTAG_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_NONE, 0), /* JTAG-AP */ + AP_TYPE_COM_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_COM, 0), /* COM-AP */ + AP_TYPE_AHB3_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 1), /* AHB3 Memory-AP */ + AP_TYPE_APB_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 2), /* APB2 or APB3 Memory-AP */ + AP_TYPE_AXI_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 4), /* AXI3 or AXI4 Memory-AP */ + AP_TYPE_AHB5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 5), /* AHB5 Memory-AP */ + AP_TYPE_APB4_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 6), /* APB4 Memory-AP */ + AP_TYPE_AXI5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 7), /* AXI5 Memory-AP */ + AP_TYPE_AHB5H_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 8), /* AHB5 with enhanced HPROT Memory-AP */ }; /* Check the ap->cfg_reg Long Address field (bit 1) From cf6909a57c4d5fe859476df8a60ab2d2ba4a96b0 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Tue, 10 Aug 2021 16:26:42 +0200 Subject: [PATCH 35/56] arm_adi_v5: move in a separate function devtype decode/display For readability, move in a separate function the decoding and the display of devtype register. The function will be reused with ADIv6. Split from change https://review.openocd.org/6077/ Change-Id: I7a26a2c9759d5db5f9acfae5c169b90b3deb2f18 Signed-off-by: Kevin Burke Signed-off-by: Daniel Goehring Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6448 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 289 +++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 140 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 469cb10ca..f9f4254e8 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1227,6 +1227,150 @@ static const struct { { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ }; +static int dap_devtype_display(struct command_invocation *cmd, uint32_t devtype) +{ + const char *major = "Reserved", *subtype = "Reserved"; + const unsigned int minor = (devtype & ARM_CS_C9_DEVTYPE_SUB_MASK) >> ARM_CS_C9_DEVTYPE_SUB_SHIFT; + const unsigned int devtype_major = (devtype & ARM_CS_C9_DEVTYPE_MAJOR_MASK) >> ARM_CS_C9_DEVTYPE_MAJOR_SHIFT; + switch (devtype_major) { + case 0: + major = "Miscellaneous"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 4: + subtype = "Validation component"; + break; + } + break; + case 1: + major = "Trace Sink"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Port"; + break; + case 2: + subtype = "Buffer"; + break; + case 3: + subtype = "Router"; + break; + } + break; + case 2: + major = "Trace Link"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Funnel, router"; + break; + case 2: + subtype = "Filter"; + break; + case 3: + subtype = "FIFO, buffer"; + break; + } + break; + case 3: + major = "Trace Source"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 6: + subtype = "Software"; + break; + } + break; + case 4: + major = "Debug Control"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Trigger Matrix"; + break; + case 2: + subtype = "Debug Auth"; + break; + case 3: + subtype = "Power Requestor"; + break; + } + break; + case 5: + major = "Debug Logic"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 5: + subtype = "Memory"; + break; + } + break; + case 6: + major = "Performance Monitor"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 5: + subtype = "Memory"; + break; + } + break; + } + command_print(cmd, "\t\tType is 0x%02x, %s, %s", + devtype & ARM_CS_C9_DEVTYPE_MASK, + major, subtype); + return ERROR_OK; +} + static int dap_rom_display(struct command_invocation *cmd, struct adiv5_ap *ap, target_addr_t dbgbase, int depth) { @@ -1333,150 +1477,15 @@ static int dap_rom_display(struct command_invocation *cmd, } } } else if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) { - const char *major = "Reserved", *subtype = "Reserved"; - uint32_t devtype; retval = mem_ap_read_atomic_u32(ap, base_addr + ARM_CS_C9_DEVTYPE, &devtype); if (retval != ERROR_OK) return retval; - unsigned int minor = (devtype & ARM_CS_C9_DEVTYPE_SUB_MASK) >> ARM_CS_C9_DEVTYPE_SUB_SHIFT; - unsigned int devtype_major = (devtype & ARM_CS_C9_DEVTYPE_MAJOR_MASK) >> ARM_CS_C9_DEVTYPE_MAJOR_SHIFT; - switch (devtype_major) { - case 0: - major = "Miscellaneous"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 4: - subtype = "Validation component"; - break; - } - break; - case 1: - major = "Trace Sink"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Port"; - break; - case 2: - subtype = "Buffer"; - break; - case 3: - subtype = "Router"; - break; - } - break; - case 2: - major = "Trace Link"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Funnel, router"; - break; - case 2: - subtype = "Filter"; - break; - case 3: - subtype = "FIFO, buffer"; - break; - } - break; - case 3: - major = "Trace Source"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 6: - subtype = "Software"; - break; - } - break; - case 4: - major = "Debug Control"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Trigger Matrix"; - break; - case 2: - subtype = "Debug Auth"; - break; - case 3: - subtype = "Power Requestor"; - break; - } - break; - case 5: - major = "Debug Logic"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 5: - subtype = "Memory"; - break; - } - break; - case 6: - major = "Performance Monitor"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 5: - subtype = "Memory"; - break; - } - break; - } - command_print(cmd, "\t\tType is 0x%02x, %s, %s", - devtype & ARM_CS_C9_DEVTYPE_MASK, - major, subtype); + + retval = dap_devtype_display(cmd, devtype); + if (retval != ERROR_OK) + return retval; + /* REVISIT also show ARM_CS_C9_DEVID */ } From 02b5fa51039a61ab3bebec7fea578ef58e36673f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 17 Aug 2021 01:05:39 +0200 Subject: [PATCH 36/56] arm_adi_v5: add helper to search for part number Improve code readability and prepare to re-use the helper. Change-Id: Iee5e01047c82be3dd86707f5c283f0b20cc4070d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6449 Tested-by: jenkins Reviewed-by: Daniel Goehring Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 53 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f9f4254e8..0d458e2b5 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1115,12 +1115,12 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u #define ANY_ID 0x1000 -static const struct { +static const struct dap_part_nums { uint16_t designer_id; uint16_t part_num; const char *type; const char *full; -} dap_partnums[] = { +} dap_part_nums[] = { { ARM_ID, 0x000, "Cortex-M3 SCS", "(System Control Space)", }, { ARM_ID, 0x001, "Cortex-M3 ITM", "(Instrumentation Trace Module)", }, { ARM_ID, 0x002, "Cortex-M3 DWT", "(Data Watchpoint and Trace)", }, @@ -1227,6 +1227,22 @@ static const struct { { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ }; +static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num) +{ + static const struct dap_part_nums unknown = { + .type = "Unrecognized", + .full = "", + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(dap_part_nums); i++) { + if (dap_part_nums[i].designer_id != designer_id && dap_part_nums[i].designer_id != ANY_ID) + continue; + if (dap_part_nums[i].part_num == part_num) + return &dap_part_nums[i]; + } + return &unknown; +} + static int dap_devtype_display(struct command_invocation *cmd, uint32_t devtype) { const char *major = "Reserved", *subtype = "Reserved"; @@ -1408,41 +1424,24 @@ static int dap_rom_display(struct command_invocation *cmd, command_print(cmd, "\t\tPeripheral ID 0x%010" PRIx64, pid); - uint8_t class = (cid & ARM_CS_CIDR_CLASS_MASK) >> ARM_CS_CIDR_CLASS_SHIFT; - uint16_t part_num = ARM_CS_PIDR_PART(pid); - uint16_t designer_id = ARM_CS_PIDR_DESIGNER(pid); + const unsigned int class = (cid & ARM_CS_CIDR_CLASS_MASK) >> ARM_CS_CIDR_CLASS_SHIFT; + const unsigned int part_num = ARM_CS_PIDR_PART(pid); + unsigned int designer_id = ARM_CS_PIDR_DESIGNER(pid); if (pid & ARM_CS_PIDR_JEDEC) { /* JEP106 code */ - command_print(cmd, "\t\tDesigner is 0x%03" PRIx16 ", %s", + command_print(cmd, "\t\tDesigner is 0x%03x, %s", designer_id, jep106_manufacturer(designer_id)); } else { /* Legacy ASCII ID, clear invalid bits */ designer_id &= 0x7f; - command_print(cmd, "\t\tDesigner ASCII code 0x%02" PRIx16 ", %s", + command_print(cmd, "\t\tDesigner ASCII code 0x%02x, %s", designer_id, designer_id == 0x41 ? "ARM" : ""); } - /* default values to be overwritten upon finding a match */ - const char *type = "Unrecognized"; - const char *full = ""; - - /* search dap_partnums[] array for a match */ - for (unsigned entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) { - - if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID)) - continue; - - if (dap_partnums[entry].part_num != part_num) - continue; - - type = dap_partnums[entry].type; - full = dap_partnums[entry].full; - break; - } - - command_print(cmd, "\t\tPart is 0x%" PRIx16", %s %s", part_num, type, full); - command_print(cmd, "\t\tComponent class is 0x%" PRIx8 ", %s", class, class_description[class]); + const struct dap_part_nums *partnum = pidr_to_part_num(designer_id, part_num); + command_print(cmd, "\t\tPart is 0x%03x, %s %s", part_num, partnum->type, partnum->full); + command_print(cmd, "\t\tComponent class is 0x%x, %s", class, class_description[class]); if (class == ARM_CS_CLASS_0X1_ROM_TABLE) { uint32_t memtype; From c55fbe190ba68b5fcc7b839c647f579479437293 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 17 Aug 2021 00:13:05 +0200 Subject: [PATCH 37/56] arm_adi_v5: add arm SoC-600 part numbers Extract new part numbers from ARM CoreSight System-on-Chip SoC-600 Technical Reference Manual Revision r4p1 and add them to the array dap_partnums. Change-Id: I88d8aa3c084f6e832b75032e75bfb6d377a08360 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6450 Tested-by: jenkins Reviewed-by: Daniel Goehring Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0d458e2b5..66d084952 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1131,6 +1131,7 @@ static const struct dap_part_nums { { ARM_ID, 0x00c, "Cortex-M4 SCS", "(System Control Space)", }, { ARM_ID, 0x00d, "CoreSight ETM11", "(Embedded Trace)", }, { ARM_ID, 0x00e, "Cortex-M7 FPB", "(Flash Patch and Breakpoint)", }, + { ARM_ID, 0x193, "SoC-600 TSGEN", "(Timestamp Generator)", }, { ARM_ID, 0x470, "Cortex-M1 ROM", "(ROM Table)", }, { ARM_ID, 0x471, "Cortex-M0 ROM", "(ROM Table)", }, { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", }, @@ -1192,6 +1193,19 @@ static const struct dap_part_nums { { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d8, "Cortex-A72 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9da, "Cortex-A35 PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, + { ARM_ID, 0x9e2, "SoC-600 APB-AP", "(APB4 Memory Access Port)", }, + { ARM_ID, 0x9e3, "SoC-600 AHB-AP", "(AHB5 Memory Access Port)", }, + { ARM_ID, 0x9e4, "SoC-600 AXI-AP", "(AXI Memory Access Port)", }, + { ARM_ID, 0x9e5, "SoC-600 APv1 Adapter", "(Access Port v1 Adapter)", }, + { ARM_ID, 0x9e6, "SoC-600 JTAG-AP", "(JTAG Access Port)", }, + { ARM_ID, 0x9e7, "SoC-600 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x9e8, "SoC-600 TMC ETR/ETS", "(Embedded Trace Router/Streamer)", }, + { ARM_ID, 0x9e9, "SoC-600 TMC ETB", "(Embedded Trace Buffer)", }, + { ARM_ID, 0x9ea, "SoC-600 TMC ETF", "(Embedded Trace FIFO)", }, + { ARM_ID, 0x9eb, "SoC-600 ATB Funnel", "(Trace Funnel)", }, + { ARM_ID, 0x9ec, "SoC-600 ATB Replicator", "(Trace Replicator)", }, + { ARM_ID, 0x9ed, "SoC-600 CTI", "(Cross Trigger)", }, + { ARM_ID, 0x9ee, "SoC-600 CATU", "(Address Translation Unit)", }, { ARM_ID, 0xc05, "Cortex-A5 Debug", "(Debug Unit)", }, { ARM_ID, 0xc07, "Cortex-A7 Debug", "(Debug Unit)", }, { ARM_ID, 0xc08, "Cortex-A8 Debug", "(Debug Unit)", }, From 8f73bd3d48f2629df3b4a3732abf9659c41a046b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 19 Aug 2021 18:22:28 +0200 Subject: [PATCH 38/56] arm_adi_v5: add arm Cortex-R52 part numbers Extract new part numbers from Arm Cortex-R52 Processor Technical Reference Manual Revision r1p3 and add them to the array dap_partnums. Change-Id: I8020f36de587951af60422ef33d7e438dc7d9d53 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6451 Tested-by: jenkins Reviewed-by: Daniel Goehring Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 66d084952..159c613a0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1135,6 +1135,8 @@ static const struct dap_part_nums { { ARM_ID, 0x470, "Cortex-M1 ROM", "(ROM Table)", }, { ARM_ID, 0x471, "Cortex-M0 ROM", "(ROM Table)", }, { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", }, + { ARM_ID, 0x492, "Cortex-R52 GICD", "(Distributor)", }, + { ARM_ID, 0x493, "Cortex-R52 GICR", "(Redistributor)", }, { ARM_ID, 0x4a1, "Cortex-A53 ROM", "(v8 Memory Map ROM Table)", }, { ARM_ID, 0x4a2, "Cortex-A57 ROM", "(ROM Table)", }, { ARM_ID, 0x4a3, "Cortex-A53 ROM", "(v7 Memory Map ROM Table)", }, @@ -1143,6 +1145,7 @@ static const struct dap_part_nums { { ARM_ID, 0x4aa, "Cortex-A35 ROM", "(v8 Memory Map ROM Table)", }, { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", }, { ARM_ID, 0x4b5, "Cortex-R5 ROM", "(ROM Table)", }, + { ARM_ID, 0x4b8, "Cortex-R52 ROM", "(ROM Table)", }, { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", }, { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", }, { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", }, @@ -1188,6 +1191,7 @@ static const struct dap_part_nums { { ARM_ID, 0x9a9, "Cortex-M7 TPIU", "(Trace Port Interface Unit)", }, { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9b6, "Cortex-R52 PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, @@ -1220,6 +1224,7 @@ static const struct dap_part_nums { { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, { 0x017, 0x9af, "MSP432 ROM", "(ROM Table)" }, { 0x01f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, { 0x041, 0x1db, "XMC4500 ROM", "(ROM Table)" }, From a931c99f5bef63129f7f6a634d2e03d8420a68ad Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Thu, 19 Aug 2021 17:44:38 +0200 Subject: [PATCH 39/56] arm_adi_v5: add arm Neoverse N1 part numbers Split from change https://review.openocd.org/6077/ Change-Id: I5e3d3736beb741de3940ea6e23b0ccbf47e8dec7 Signed-off-by: Kevin Burke Signed-off-by: Daniel Goehring Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6452 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 159c613a0..4fa9bb7f6 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1224,6 +1224,7 @@ static const struct dap_part_nums { { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", }, { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, { 0x017, 0x9af, "MSP432 ROM", "(ROM Table)" }, { 0x01f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, From 122f36ed7b6bb0ddbf72cd6cf4c1058afc32a837 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 19 Aug 2021 18:02:14 +0200 Subject: [PATCH 40/56] arm_adi_v5: add arm Neoverse N2 part numbers Change-Id: Ib7a8c9d460f12762f6d106e9331e84b6d2dec213 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6453 Tested-by: jenkins Reviewed-by: Daniel Goehring Reviewed-by: Tarek BOCHKATI --- src/target/arm_adi_v5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 4fa9bb7f6..f813d8552 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1226,6 +1226,7 @@ static const struct dap_part_nums { { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", }, { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd49, "Neoverse N2", "(Debug Unit)", }, { 0x017, 0x9af, "MSP432 ROM", "(ROM Table)" }, { 0x01f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, { 0x041, 0x1db, "XMC4500 ROM", "(ROM Table)" }, From 2a43137619e384bee38ea58d817a0d15876d2473 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 21 Aug 2021 00:35:32 +0200 Subject: [PATCH 41/56] arm_adi_v5: drop ANY_ID from table dap_part_nums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial version of the table dap_part_nums contains only the part number of the device and not the manufacturer ID. This causes collisions between devices with same part number but from different manufacturer. The table has been extended to include the manufacturer JEDEC code in commit 2f131d3c3004 ("ARM ADIv5: CoreSight ROM decode part number and designer id"). For two old/legacy table's entries reported without manufacturer code it was defined a special ANY_ID manufacturer, meaning skip the check for manufacturer! The two legacy entries report the comment "from OMAP3 memmap", and thanks to the associated string has been possible through Google to identify a Master Report [1] about using OpenOCD with the OMAP3 in a BeagleBoard. The ROM table is printed with OpenOCD command "dap info 1" at page 8 and reports the Peripheral ID required to extract the manufacturer ID that, out of any surprise, belong to Texas Instruments. Set the two missing manufacturer ID to Texas Instruments JEDEC code. Remove the now redundant definition and use of ANY_ID. While revisiting this old code, remove also the useless comment "0x113: what?". It was introduced in commit ddade10d4a93 ("ARM ADIv5: "dap info" gets more readable") and from the same dump in [1] it's clearly another element in OMAP3. It is listed as entry 0x8 in the ROM table and there is no further info available. OpenOCD will anyway list it as: Designer is 0x017, Texas Instruments Part is 0x113, Unrecognized Another link https://elinux.org/BeagleBoardOpenOCD reports the text "Part number 0x113: This is ????", which sounds familiar! No public document from Texas Instruments reports what is this device at address 0x54012000. [1] Warren Clay Grant - University of Texas at Austin "Implementation of an Open Source JTAG Debugging Development Chain for the BeagleBoard ARMĀ® Cortex A-8" - May 2012 Link: https://repositories.lib.utexas.edu/bitstream/handle/2152/ETD-UT-2012-05-5478/GRANT-MASTERS-REPORT.pdf Change-Id: I7e007addbb5c6e90303e4e8c110c7d27810fbe9c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6454 Tested-by: jenkins Reviewed-by: Daniel Goehring --- src/target/arm_adi_v5.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f813d8552..8d6d6618b 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1107,14 +1107,6 @@ static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, u * from chip observation (e.g. TI SDTI). */ -/* The legacy code only used the part number field to identify CoreSight peripherals. - * This meant that the same part number from two different manufacturers looked the same. - * It is desirable for all future additions to identify with both part number and JEP106. - * "ANY_ID" is a wildcard (any JEP106) only to preserve legacy behavior for legacy entries. - */ - -#define ANY_ID 0x1000 - static const struct dap_part_nums { uint16_t designer_id; uint16_t part_num; @@ -1227,6 +1219,8 @@ static const struct dap_part_nums { { ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", }, { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, { ARM_ID, 0xd49, "Neoverse N2", "(Debug Unit)", }, + { 0x017, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ + { 0x017, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ { 0x017, 0x9af, "MSP432 ROM", "(ROM Table)" }, { 0x01f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, { 0x041, 0x1db, "XMC4500 ROM", "(ROM Table)" }, @@ -1243,9 +1237,6 @@ static const struct dap_part_nums { { 0x1eb, 0x211, "Tegra 210 ROM", "(ROM Table)", }, { 0x1eb, 0x302, "Denver Debug", "(Debug Unit)", }, { 0x1eb, 0x402, "Denver PMU", "(Performance Monitor Unit)", }, - /* legacy comment: 0x113: what? */ - { ANY_ID, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ - { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ }; static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num) @@ -1255,12 +1246,10 @@ static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, un .full = "", }; - for (unsigned int i = 0; i < ARRAY_SIZE(dap_part_nums); i++) { - if (dap_part_nums[i].designer_id != designer_id && dap_part_nums[i].designer_id != ANY_ID) - continue; - if (dap_part_nums[i].part_num == part_num) + for (unsigned int i = 0; i < ARRAY_SIZE(dap_part_nums); i++) + if (dap_part_nums[i].designer_id == designer_id && dap_part_nums[i].part_num == part_num) return &dap_part_nums[i]; - } + return &unknown; } From 7b504370f732a00d803163cab2b1750bde1927cf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 17 Sep 2021 18:47:20 +0200 Subject: [PATCH 42/56] arm_tpiu_swo: fix support for deprecated 'tpiu' command before 'init' Commit dc7b32ea4a00 ("armv7m_trace: get rid of the old tpiu code") is not handling correctly the old 'tpiu' command if it is run during the config phase (before command 'init'). Move the call to the old event handler 'trace-config' in function jim_arm_tpiu_swo_enable(), so it is correctly executed after 'init'. Add the call to the old event handler 'trace-config' also during jim_arm_tpiu_swo_disable(), to match the old behaviour. Add more information while alerting that the event 'trace-config' is deprecated. Change-Id: If831d9159b4634c74e19c04099d041a6e2be3f2a Signed-off-by: Antonio Borneo Fixes: dc7b32ea4a00 ("armv7m_trace: get rid of the old tpiu code") Reviewed-on: https://review.openocd.org/c/openocd/+/6561 Tested-by: jenkins Reviewed-by: Karl Palsson --- src/target/arm_tpiu_swo.c | 12 +++++++++++- src/target/target.c | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 746ab393e..8b1d012ed 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -764,6 +764,10 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE); + /* START_DEPRECATED_TPIU */ + target_handle_event(target, TARGET_EVENT_TRACE_CONFIG); + /* END_DEPRECATED_TPIU */ + obj->enabled = true; return JIM_OK; @@ -817,6 +821,13 @@ static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const } arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_DISABLE); + + /* START_DEPRECATED_TPIU */ + struct command_context *cmd_ctx = current_command_context(interp); + struct target *target = get_current_target(cmd_ctx); + target_handle_event(target, TARGET_EVENT_TRACE_CONFIG); + /* END_DEPRECATED_TPIU */ + return JIM_OK; } @@ -1112,7 +1123,6 @@ COMMAND_HANDLER(handle_tpiu_deprecated_config_command) if (retval != ERROR_OK) return retval; - target_handle_event(target, TARGET_EVENT_TRACE_CONFIG); return ERROR_OK; } diff --git a/src/target/target.c b/src/target/target.c index 6571e9c6f..6d3bf7787 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4983,7 +4983,7 @@ no_params: if (goi->isconfigure) { /* START_DEPRECATED_TPIU */ if (n->value == TARGET_EVENT_TRACE_CONFIG) - LOG_INFO("DEPRECATED target event %s", n->name); + LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); /* END_DEPRECATED_TPIU */ bool replace = true; From e48093b395808692145bf320e6d206561670107c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 17 Sep 2021 18:37:41 +0200 Subject: [PATCH 43/56] openocd: prevent jimtcl error message while testing commands The jimtcl API Jim_GetCommand() sets an error message when the command is not found and flag JIM_ERRMSG is set. OpenOCD is checking if the command has already been registered, thus 'command not found' is the desired case. Pass flag JIM_NONE to prevent jimtcl from setting the error message. Change-Id: I3329c2f8722eda0cc9a5f9cbd888a37915b46107 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6562 Tested-by: jenkins --- src/target/arm_cti.c | 2 +- src/target/arm_dap.c | 2 +- src/target/arm_tpiu_swo.c | 2 +- src/target/target.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 7d005e2b1..c776e9c2a 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -465,7 +465,7 @@ static int cti_create(struct jim_getopt_info *goi) /* COMMAND */ jim_getopt_obj(goi, &new_cmd); /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); + cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); if (cmd) { cp = Jim_GetString(new_cmd, NULL); Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp); diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 2f21aa170..94edfc09d 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -230,7 +230,7 @@ static int dap_create(struct jim_getopt_info *goi) /* COMMAND */ jim_getopt_obj(goi, &new_cmd); /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); + cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); if (cmd) { cp = Jim_GetString(new_cmd, NULL); Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp); diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 8b1d012ed..f2b514826 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -880,7 +880,7 @@ static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *o assert(cmd_ctx); /* does this command exist? */ - cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_ERRMSG); + cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE); if (cmd) { Jim_SetResultFormatted(interp, "Command: %s Exists", obj->name); return JIM_ERR; diff --git a/src/target/target.c b/src/target/target.c index 6d3bf7787..fa0c2b256 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5715,7 +5715,7 @@ static int target_create(struct jim_getopt_info *goi) /* COMMAND */ jim_getopt_obj(goi, &new_cmd); /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); + cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); if (cmd) { cp = Jim_GetString(new_cmd, NULL); Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); From 5765a0ce14485aadc6b74c6e2b4f15b73df14603 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 2 Sep 2021 11:11:30 -0700 Subject: [PATCH 44/56] Speed up remote bitbang. 1. Use TCP_NODELAY, which makes things twice as fast. 2. Get rid of a bunch of unnecessary socket block/non-block calls, which improves speed another 10% or so. Change-Id: I415db5746d55374a14564b1973b81e3517f5cb67 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/6534 Tested-by: jenkins Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/jtag/drivers/remote_bitbang.c | 154 +++++++++++++++++------------- 1 file changed, 87 insertions(+), 67 deletions(-) diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index ce1a06544..6ab7cc9c5 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -23,6 +23,7 @@ #ifndef _WIN32 #include #include +#include #endif #include "helper/system.h" #include "helper/replacements.h" @@ -40,35 +41,87 @@ static uint8_t remote_bitbang_send_buf[512]; static unsigned int remote_bitbang_send_buf_used; /* Circular buffer. When start == end, the buffer is empty. */ -static char remote_bitbang_recv_buf[64]; +static char remote_bitbang_recv_buf[256]; static unsigned int remote_bitbang_recv_buf_start; static unsigned int remote_bitbang_recv_buf_end; -static bool remote_bitbang_buf_full(void) +static bool remote_bitbang_recv_buf_full(void) { return remote_bitbang_recv_buf_end == ((remote_bitbang_recv_buf_start + sizeof(remote_bitbang_recv_buf) - 1) % sizeof(remote_bitbang_recv_buf)); } -/* Read any incoming data, placing it into the buffer. */ -static int remote_bitbang_fill_buf(void) +static bool remote_bitbang_recv_buf_empty(void) { - socket_nonblock(remote_bitbang_fd); - while (!remote_bitbang_buf_full()) { - unsigned int contiguous_available_space; - if (remote_bitbang_recv_buf_end >= remote_bitbang_recv_buf_start) { - contiguous_available_space = sizeof(remote_bitbang_recv_buf) - - remote_bitbang_recv_buf_end; - if (remote_bitbang_recv_buf_start == 0) - contiguous_available_space -= 1; - } else { - contiguous_available_space = remote_bitbang_recv_buf_start - - remote_bitbang_recv_buf_end - 1; + return remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end; +} + +static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void) +{ + if (remote_bitbang_recv_buf_end >= remote_bitbang_recv_buf_start) { + unsigned int space = sizeof(remote_bitbang_recv_buf) - + remote_bitbang_recv_buf_end; + if (remote_bitbang_recv_buf_start == 0) + space -= 1; + return space; + } else { + return remote_bitbang_recv_buf_start - + remote_bitbang_recv_buf_end - 1; + } +} + +static int remote_bitbang_flush(void) +{ + if (remote_bitbang_send_buf_used <= 0) + return ERROR_OK; + + unsigned int offset = 0; + while (offset < remote_bitbang_send_buf_used) { + ssize_t written = write_socket(remote_bitbang_fd, remote_bitbang_send_buf + offset, + remote_bitbang_send_buf_used - offset); + if (written < 0) { + log_socket_error("remote_bitbang_putc"); + remote_bitbang_send_buf_used = 0; + return ERROR_FAIL; } + offset += written; + } + remote_bitbang_send_buf_used = 0; + return ERROR_OK; +} + +enum block_bool { + NO_BLOCK, + BLOCK +}; + +/* Read any incoming data, placing it into the buffer. */ +static int remote_bitbang_fill_buf(enum block_bool block) +{ + if (remote_bitbang_recv_buf_empty()) { + /* If the buffer is empty, reset it to 0 so we get more + * contiguous space. */ + remote_bitbang_recv_buf_start = 0; + remote_bitbang_recv_buf_end = 0; + } + + if (block == BLOCK) { + if (remote_bitbang_flush() != ERROR_OK) + return ERROR_FAIL; + socket_block(remote_bitbang_fd); + } + + bool first = true; + while (!remote_bitbang_recv_buf_full()) { + unsigned int contiguous_available_space = + remote_bitbang_recv_buf_contiguous_available_space(); ssize_t count = read_socket(remote_bitbang_fd, remote_bitbang_recv_buf + remote_bitbang_recv_buf_end, contiguous_available_space); + if (first && block == BLOCK) + socket_nonblock(remote_bitbang_fd); + first = false; if (count > 0) { remote_bitbang_recv_buf_end += count; if (remote_bitbang_recv_buf_end == sizeof(remote_bitbang_recv_buf)) @@ -92,26 +145,6 @@ static int remote_bitbang_fill_buf(void) return ERROR_OK; } -static int remote_bitbang_flush(void) -{ - if (remote_bitbang_send_buf_used <= 0) - return ERROR_OK; - - unsigned int offset = 0; - while (offset < remote_bitbang_send_buf_used) { - ssize_t written = write_socket(remote_bitbang_fd, remote_bitbang_send_buf + offset, - remote_bitbang_send_buf_used - offset); - if (written < 0) { - log_socket_error("remote_bitbang_putc"); - remote_bitbang_send_buf_used = 0; - return ERROR_FAIL; - } - offset += written; - } - remote_bitbang_send_buf_used = 0; - return ERROR_OK; -} - typedef enum { NO_FLUSH, FLUSH_SEND_BUF @@ -157,47 +190,25 @@ static bb_value_t char_to_int(int c) } } -/* Get the next read response. */ -static bb_value_t remote_bitbang_rread(void) -{ - if (remote_bitbang_flush() != ERROR_OK) - return ERROR_FAIL; - - /* Enable blocking access. */ - socket_block(remote_bitbang_fd); - char c; - ssize_t count = read_socket(remote_bitbang_fd, &c, 1); - if (count == 1) { - return char_to_int(c); - } else { - remote_bitbang_quit(); - LOG_ERROR("read_socket: count=%d", (int) count); - log_socket_error("read_socket"); - return BB_ERROR; - } -} - static int remote_bitbang_sample(void) { - if (remote_bitbang_fill_buf() != ERROR_OK) + if (remote_bitbang_fill_buf(NO_BLOCK) != ERROR_OK) return ERROR_FAIL; - assert(!remote_bitbang_buf_full()); + assert(!remote_bitbang_recv_buf_full()); return remote_bitbang_queue('R', NO_FLUSH); } static bb_value_t remote_bitbang_read_sample(void) { - if (remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end) { - if (remote_bitbang_fill_buf() != ERROR_OK) - return ERROR_FAIL; + if (remote_bitbang_recv_buf_empty()) { + if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK) + return BB_ERROR; } - if (remote_bitbang_recv_buf_start != remote_bitbang_recv_buf_end) { - int c = remote_bitbang_recv_buf[remote_bitbang_recv_buf_start]; - remote_bitbang_recv_buf_start = - (remote_bitbang_recv_buf_start + 1) % sizeof(remote_bitbang_recv_buf); - return char_to_int(c); - } - return remote_bitbang_rread(); + assert(!remote_bitbang_recv_buf_empty()); + int c = remote_bitbang_recv_buf[remote_bitbang_recv_buf_start]; + remote_bitbang_recv_buf_start = + (remote_bitbang_recv_buf_start + 1) % sizeof(remote_bitbang_recv_buf); + return char_to_int(c); } static int remote_bitbang_write(int tck, int tms, int tdi) @@ -261,6 +272,13 @@ static int remote_bitbang_init_tcp(void) close(fd); } + /* We work hard to collapse the writes into the minimum number, so when + * we write something we want to get it to the other end of the + * connection as fast as possible. */ + int one = 1; + /* On Windows optval has to be a const char *. */ + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)); + freeaddrinfo(result); /* No longer needed */ if (!rp) { /* No address succeeded */ @@ -314,6 +332,8 @@ static int remote_bitbang_init(void) if (remote_bitbang_fd < 0) return remote_bitbang_fd; + socket_nonblock(remote_bitbang_fd); + LOG_INFO("remote_bitbang driver initialized"); return ERROR_OK; } From 2f424b7eb776b3d32f2b58a3ffd91ff1d5657404 Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Thu, 16 Sep 2021 10:00:25 -0700 Subject: [PATCH 45/56] driver/linuxgpiod: add support for opendrain srst Some MCUs (e.g. the STM32F3) directly expose the internal reset line to an external pin. When this signal is driven by a push/pull line, it can actually be inhibited by the external driver. This results in a setup where the MCU cannot reset itself, for example, by a watchdog timeout or a sysreset request. To fix this condition, support for open drain output on the SRST line is required. Note that because `reset_config srst_open_drain` is the default, all users of this adapter will switch over to an open drain output unless explicitly configured otherwise. Signed-off-by: Alex Crawford Change-Id: I89b39b03aa03f826ed3c45793412780448940bcc Reviewed-on: https://review.openocd.org/c/openocd/+/6559 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/linuxgpiod.c | 43 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 42c8a3140..dd50b4406 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -278,7 +278,7 @@ static int linuxgpiod_quit(void) return ERROR_OK; } -static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset) +static struct gpiod_line *helper_get_line(const char *label, unsigned int offset, int val, int dir, int flags) { struct gpiod_line *line; int retval; @@ -289,33 +289,34 @@ static struct gpiod_line *helper_get_input_line(const char *label, unsigned int return NULL; } - retval = gpiod_line_request_input(line, "OpenOCD"); + struct gpiod_line_request_config config = { + .consumer = "OpenOCD", + .request_type = dir, + .flags = flags, + }; + + retval = gpiod_line_request(line, &config, val); if (retval < 0) { - LOG_ERROR("Error request_input line %s", label); + LOG_ERROR("Error requesting gpio line %s", label); return NULL; } return line; } +static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset) +{ + return helper_get_line(label, offset, 0, GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0); +} + static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val) { - struct gpiod_line *line; - int retval; + return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0); +} - line = gpiod_chip_get_line(gpiod_chip, offset); - if (!line) { - LOG_ERROR("Error get line %s", label); - return NULL; - } - - retval = gpiod_line_request_output(line, "OpenOCD", val); - if (retval < 0) { - LOG_ERROR("Error request_output line %s", label); - return NULL; - } - - return line; +static struct gpiod_line *helper_get_open_drain_output_line(const char *label, unsigned int offset, int val) +{ + return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN); } static int linuxgpiod_init(void) @@ -381,7 +382,11 @@ static int linuxgpiod_init(void) } if (is_gpio_valid(srst_gpio)) { - gpiod_srst = helper_get_output_line("srst", srst_gpio, 1); + if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL) + gpiod_srst = helper_get_output_line("srst", srst_gpio, 1); + else + gpiod_srst = helper_get_open_drain_output_line("srst", srst_gpio, 1); + if (!gpiod_srst) goto out_error; } From c3993d3188da5976a64f47d4cbf4d7e5b63f0c8d Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 14 Sep 2021 21:26:47 +0100 Subject: [PATCH 46/56] tcl/stm32wlx.cfg: comply with new jimtcl expr syntax Change-Id: I2e9fd528817b14396c7643801aeea5c8dde668e0 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6557 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/stm32wlx.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcl/target/stm32wlx.cfg b/tcl/target/stm32wlx.cfg index edb3fb32b..fafe9bcba 100644 --- a/tcl/target/stm32wlx.cfg +++ b/tcl/target/stm32wlx.cfg @@ -151,7 +151,7 @@ proc stm32wlx_get_chipname {} { if {$sep == -1} { return $t } - return [string range $t 0 [expr $sep - 1]] + return [string range $t 0 [expr {$sep - 1}]] } # like mrw, but with target selection From ba1061fe1daf0071499e40da860350979105b69e Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Wed, 8 Sep 2021 12:49:50 +0100 Subject: [PATCH 47/56] target/cortex_m: enhance multi-core examine logs Giving the example of STM32WL55x the examine log is the following: Info : stm32wlx.cpu0: hardware has 6 breakpoints, 4 watchpoints Info : stm32wlx.cpu1: hardware has 4 breakpoints, 2 watchpoints After this change the examine log becomes: Info : stm32wlx.cpu0: Cortex-M4 r0p1 processor detected Info : stm32wlx.cpu0: target has 6 breakpoints, 4 watchpoints Info : stm32wlx.cpu1: Cortex-M0+ r0p1 processor detected Info : stm32wlx.cpu1: target has 4 breakpoints, 2 watchpoints Change-Id: I1873a75eb76f0819342c441129427b38e984f0df Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6553 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 5deb9bf4a..3412c5677 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2082,8 +2082,12 @@ int cortex_m_examine(struct target *target) armv7m->arm.arch = cortex_m->core_info->arch; - LOG_DEBUG("%s r%" PRId8 "p%" PRId8 " processor detected", - cortex_m->core_info->name, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf)); + LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected", + target_name(target), + cortex_m->core_info->name, + (uint8_t)((cpuid >> 20) & 0xf), + (uint8_t)((cpuid >> 0) & 0xf)); + cortex_m->maskints_erratum = false; if (core_partno == CORTEX_M7_PARTNO) { uint8_t rev, patch; @@ -2192,7 +2196,7 @@ int cortex_m_examine(struct target *target) cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ - LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", + LOG_INFO("%s: target has %d breakpoints, %d watchpoints", target_name(target), cortex_m->fp_num_code, cortex_m->dwt_num_comp); From 98d9f1168cbdc59e4c2c0b1f01b225a4df9ad98a Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 7 Sep 2021 14:25:32 +0100 Subject: [PATCH 48/56] target: reset target examined flag if target::examine() fails For example: before this change in cortex_m_examine, if we fail reading CPUID we return a failure code but target was set to examined which is not consistent. Change-Id: I9f0ebe8f811849e54d1b350b0db506cb3fdd58f4 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6548 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index fa0c2b256..35e9b5332 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -717,6 +717,15 @@ static int no_mmu(struct target *target, int *enabled) return ERROR_OK; } +/** + * Reset the @c examined flag for the given target. + * Pure paranoia -- targets are zeroed on allocation. + */ +static inline void target_reset_examined(struct target *target) +{ + target->examined = false; +} + static int default_examine(struct target *target) { target_set_examined(target); @@ -737,10 +746,12 @@ int target_examine_one(struct target *target) int retval = target->type->examine(target); if (retval != ERROR_OK) { + target_reset_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_FAIL); return retval; } + target_set_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); return ERROR_OK; @@ -1522,15 +1533,6 @@ static int target_profiling(struct target *target, uint32_t *samples, num_samples, seconds); } -/** - * Reset the @c examined flag for the given target. - * Pure paranoia -- targets are zeroed on allocation. - */ -static void target_reset_examined(struct target *target) -{ - target->examined = false; -} - static int handle_target(void *priv); static int target_init_one(struct command_context *cmd_ctx, @@ -3055,7 +3057,7 @@ static int handle_target(void *priv) /* Target examination could have failed due to unstable connection, * but we set the examined flag anyway to repoll it later */ if (retval != ERROR_OK) { - target->examined = true; + target_set_examined(target); LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", target->backoff.times * polling_interval); return retval; @@ -5308,8 +5310,13 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv } int e = target->type->examine(target); - if (e != ERROR_OK) + if (e != ERROR_OK) { + target_reset_examined(target); return JIM_ERR; + } + + target_set_examined(target); + return JIM_OK; } From 745b40d99a1f76a362ebfac92a85f775abde6c18 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 19 Sep 2021 21:52:44 +0200 Subject: [PATCH 49/56] udev: add ASIX Presto programmer The driver is in OpenOCD since 2007, but the USB VID/PID have never been listed in udev rules. Change-Id: I77df469929dd7f6b6483678c0e76f22c30a7614c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6563 Tested-by: jenkins --- contrib/60-openocd.rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index 94573a83a..4ecb485b1 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -68,6 +68,9 @@ ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="660", GROUP="plugdev", # Amontec JTAGkey and JTAGkey-tiny ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev", TAG+="uaccess" +# ASIX Presto programmer +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="f1a0", MODE="660", GROUP="plugdev", TAG+="uaccess" + # Nuvoton NuLink ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511b", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511c", MODE="660", GROUP="plugdev", TAG+="uaccess" From b5a24386e49ca643ab750543e3818172d37fbc54 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 17 Mar 2021 00:02:16 +0100 Subject: [PATCH 50/56] stlink-dap: add 'cmd' to send arbitrary commands Either for testing new commands and to retrieve information that don't fit in any specific place of OpenOCD, for example monitoring the target's VDD power supply from a TCL script. Change-Id: Id43ced92c799b115bb1da1c236090b0752329051 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6564 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI --- doc/openocd.texi | 20 ++++++++++++++++ src/jtag/drivers/stlink_usb.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 138922d08..7bf0fe98b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3131,6 +3131,26 @@ Specifies the serial number of the adapter. @deffn {Config Command} {st-link vid_pid} [vid pid]+ Pairs of vendor IDs and product IDs of the device. @end deffn + +@deffn {Command} {st-link cmd} rx_n (tx_byte)+ +Sends an arbitrary command composed by the sequence of bytes @var{tx_byte} +and receives @var{rx_n} bytes. + +For example, the command to read the target's supply voltage is one byte 0xf7 followed +by 15 bytes zero. It returns 8 bytes, where the first 4 bytes represent the ADC sampling +of the reference voltage 1.2V and the last 4 bytes represent the ADC sampling of half +the target's supply voltage. +@example +> st-link cmd 8 0xf7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0xf1 0x05 0x00 0x00 0x0b 0x08 0x00 0x00 +@end example +The result can be converted to Volts (ignoring the most significant bytes, always zero) +@example +> set a [st-link cmd 8 0xf7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] +> echo [expr 2*1.2*([lindex $a 4]+256*[lindex $a 5])/([lindex $a 0]+256*[lindex $a 1])] +3.24891518738 +@end example +@end deffn @end deffn @deffn {Interface Driver} {opendous} diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 4bd07b49f..a52370863 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -4222,6 +4222,43 @@ COMMAND_HANDLER(stlink_dap_backend_command) return ERROR_OK; } +#define BYTES_PER_LINE 16 +COMMAND_HANDLER(stlink_dap_cmd_command) +{ + unsigned int rx_n, tx_n; + struct stlink_usb_handle_s *h = stlink_dap_handle; + + if (CMD_ARGC < 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], rx_n); + tx_n = CMD_ARGC - 1; + if (tx_n > STLINK_SG_SIZE || rx_n > STLINK_DATA_SIZE) { + LOG_ERROR("max %x byte sent and %d received", STLINK_SG_SIZE, STLINK_DATA_SIZE); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + stlink_usb_init_buffer(h, h->rx_ep, rx_n); + + for (unsigned int i = 0; i < tx_n; i++) { + uint8_t byte; + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[i + 1], byte); + h->cmdbuf[h->cmdidx++] = byte; + } + + int retval = stlink_usb_xfer_noerrcheck(h, h->databuf, rx_n); + if (retval != ERROR_OK) { + LOG_ERROR("Error %d", retval); + return retval; + } + + for (unsigned int i = 0; i < rx_n; i++) + command_print_sameline(CMD, "0x%02x%c", h->databuf[i], + ((i == (rx_n - 1)) || ((i % BYTES_PER_LINE) == (BYTES_PER_LINE - 1))) ? '\n' : ' '); + + return ERROR_OK; +} + /** */ static const struct command_registration stlink_dap_subcommand_handlers[] = { { @@ -4245,6 +4282,13 @@ static const struct command_registration stlink_dap_subcommand_handlers[] = { .help = "select which ST-Link backend to use", .usage = "usb | tcp [port]", }, + { + .name = "cmd", + .handler = stlink_dap_cmd_command, + .mode = COMMAND_EXEC, + .help = "send arbitrary command", + .usage = "rx_n (tx_byte)+", + }, COMMAND_REGISTRATION_DONE }; From e4872054108a3a18dc651b45dea679696e14ee7f Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 21 Sep 2021 11:43:21 -0700 Subject: [PATCH 51/56] uint64_t->target_addr_t for stack pointers. This might be incomplete. It's just a quick attempt to reduce some of the difference between riscv-openocd and mainline. Other stack pointers can be updated as I come across them. Change-Id: Id3311b8a1bb0667f309a26d36b67093bfeb8380a Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/6586 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/rtos.c | 2 +- src/rtos/rtos.h | 4 ++-- src/rtos/rtos_riot_stackings.c | 4 ++-- src/rtos/rtos_standard_stackings.c | 34 +++++++++++++++--------------- src/rtos/rtos_standard_stackings.h | 8 +++---- src/rtos/zephyr.c | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index eaad5e50c..f401c3d30 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -616,7 +616,7 @@ int rtos_generic_stack_read(struct target *target, LOG_OUTPUT("\r\n"); #endif - int64_t new_stack_ptr; + target_addr_t new_stack_ptr; if (stacking->calculate_process_stack) { new_stack_ptr = stacking->calculate_process_stack(target, stack_data, stacking, stack_ptr); diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 81751fe0a..dc7a64f43 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -108,10 +108,10 @@ struct rtos_register_stacking { * just use stacking->stack_registers_size * stack_growth_direction * to calculate adjustment. */ - int64_t (*calculate_process_stack)(struct target *target, + target_addr_t (*calculate_process_stack)(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr); + target_addr_t stack_ptr); const struct stack_register_offset *register_offsets; }; diff --git a/src/rtos/rtos_riot_stackings.c b/src/rtos/rtos_riot_stackings.c index 98e02edfc..abf08c8ff 100644 --- a/src/rtos/rtos_riot_stackings.c +++ b/src/rtos/rtos_riot_stackings.c @@ -27,9 +27,9 @@ /* This works for the M0 and M34 stackings as xPSR is in a fixed * location */ -static int64_t rtos_riot_cortex_m_stack_align(struct target *target, +static target_addr_t rtos_riot_cortex_m_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr) + target_addr_t stack_ptr) { const int XPSR_OFFSET = 0x40; return rtos_cortex_m_stack_align(target, stack_data, stacking, diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 90c642a00..c3eef5c06 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -152,29 +152,29 @@ static const struct stack_register_offset rtos_standard_nds32_n1068_stack_offset { 35, 0x10, 32 }, /* IFC_LP */ }; -static int64_t rtos_generic_stack_align(struct target *target, +static target_addr_t rtos_generic_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr, int align) + target_addr_t stack_ptr, int align) { - int64_t new_stack_ptr; - int64_t aligned_stack_ptr; + target_addr_t new_stack_ptr; + target_addr_t aligned_stack_ptr; new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; - aligned_stack_ptr = new_stack_ptr & ~((int64_t)align - 1); + aligned_stack_ptr = new_stack_ptr & ~((target_addr_t)align - 1); if (aligned_stack_ptr != new_stack_ptr && stacking->stack_growth_direction == -1) { /* If we have a downward growing stack, the simple alignment code * above results in a wrong result (since it rounds down to nearest * alignment). We want to round up so add an extra align. */ - aligned_stack_ptr += (int64_t)align; + aligned_stack_ptr += (target_addr_t)align; } return aligned_stack_ptr; } -int64_t rtos_generic_stack_align8(struct target *target, +target_addr_t rtos_generic_stack_align8(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr) + target_addr_t stack_ptr) { return rtos_generic_stack_align(target, stack_data, stacking, stack_ptr, 8); @@ -199,13 +199,13 @@ int64_t rtos_generic_stack_align8(struct target *target, * This is just a helper function for use in the calculate_process_stack * function for a given architecture/rtos. */ -int64_t rtos_cortex_m_stack_align(struct target *target, +target_addr_t rtos_cortex_m_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr, size_t xpsr_offset) + target_addr_t stack_ptr, size_t xpsr_offset) { const uint32_t ALIGN_NEEDED = (1 << 9); uint32_t xpsr; - int64_t new_stack_ptr; + target_addr_t new_stack_ptr; new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; @@ -220,27 +220,27 @@ int64_t rtos_cortex_m_stack_align(struct target *target, return new_stack_ptr; } -static int64_t rtos_standard_cortex_m3_stack_align(struct target *target, +static target_addr_t rtos_standard_cortex_m3_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr) + target_addr_t stack_ptr) { const int XPSR_OFFSET = 0x3c; return rtos_cortex_m_stack_align(target, stack_data, stacking, stack_ptr, XPSR_OFFSET); } -static int64_t rtos_standard_cortex_m4f_stack_align(struct target *target, +static target_addr_t rtos_standard_cortex_m4f_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr) + target_addr_t stack_ptr) { const int XPSR_OFFSET = 0x40; return rtos_cortex_m_stack_align(target, stack_data, stacking, stack_ptr, XPSR_OFFSET); } -static int64_t rtos_standard_cortex_m4f_fpu_stack_align(struct target *target, +static target_addr_t rtos_standard_cortex_m4f_fpu_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr) + target_addr_t stack_ptr) { const int XPSR_OFFSET = 0x80; return rtos_cortex_m_stack_align(target, stack_data, stacking, diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h index ad319d2a0..d18f1797c 100644 --- a/src/rtos/rtos_standard_stackings.h +++ b/src/rtos/rtos_standard_stackings.h @@ -30,11 +30,11 @@ extern const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking; extern const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking; extern const struct rtos_register_stacking rtos_standard_cortex_r4_stacking; extern const struct rtos_register_stacking rtos_standard_nds32_n1068_stacking; -int64_t rtos_generic_stack_align8(struct target *target, +target_addr_t rtos_generic_stack_align8(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr); -int64_t rtos_cortex_m_stack_align(struct target *target, + target_addr_t stack_ptr); +target_addr_t rtos_cortex_m_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, - int64_t stack_ptr, size_t xpsr_offset); + target_addr_t stack_ptr, size_t xpsr_offset); #endif /* OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H */ diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c index a59673557..630511636 100644 --- a/src/rtos/zephyr.c +++ b/src/rtos/zephyr.c @@ -189,9 +189,9 @@ enum zephyr_symbol_values { ZEPHYR_VAL_COUNT }; -static int64_t zephyr_cortex_m_stack_align(struct target *target, +static target_addr_t zephyr_cortex_m_stack_align(struct target *target, const uint8_t *stack_data, - const struct rtos_register_stacking *stacking, int64_t stack_ptr) + const struct rtos_register_stacking *stacking, target_addr_t stack_ptr) { return rtos_cortex_m_stack_align(target, stack_data, stacking, stack_ptr, ARM_XPSR_OFFSET); From 05752557dd0dcab76250ab12377d59435b74204d Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Sun, 29 Aug 2021 18:18:01 +0900 Subject: [PATCH 52/56] helper: Remove src/helper from include dirs The header files under src/helper/ can currently be included with either #include or #include This is because we specify both "src/" and "src/helper/" directories as include directories. Some files name under "src/helper/", such as types.h, log.h, and util.h are too generic and could be ambiguous depending on the search path. This commit remove "src/helper/" from our include dir and make C files include explicitly. Change-Id: I38fc9b96ba01a513d4a72757d40007e21b502f25 Signed-off-by: Yasushi SHOJI Reviewed-on: https://review.openocd.org/c/openocd/+/6507 Tested-by: jenkins Reviewed-by: Antonio Borneo --- Makefile.am | 1 - src/flash/nor/psoc6.c | 4 ++-- src/flash/nor/stm32l4x.c | 2 +- src/helper/command.h | 2 +- src/helper/jim-nvp.c | 2 +- src/jtag/drivers/libusb_helper.c | 2 +- src/rtos/rtos.h | 2 +- src/server/server.c | 2 +- src/target/armv7m_trace.h | 2 +- src/target/mips64_pracc.c | 2 +- src/target/riscv/riscv-011.c | 2 +- src/target/riscv/riscv-013.c | 2 +- src/target/riscv/riscv.c | 8 ++++---- src/target/riscv/riscv_semihosting.c | 2 +- src/target/target_type.h | 2 +- 15 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3858093b6..7e5e22973 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,7 +36,6 @@ AM_CFLAGS = $(GCC_WARNINGS) AM_CPPFLAGS = $(HOST_CPPFLAGS)\ -I$(top_srcdir)/src \ -I$(top_builddir)/src \ - -I$(top_srcdir)/src/helper \ -DPKGDATADIR=\"$(pkgdatadir)\" \ -DBINDIR=\"$(bindir)\" diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index a929d3304..8a4121950 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -24,12 +24,12 @@ #include #include "imp.h" -#include +#include "helper/time_support.h" +#include "target/arm_adi_v5.h" #include "target/target.h" #include "target/cortex_m.h" #include "target/breakpoints.h" #include "target/target_type.h" -#include "time_support.h" #include "target/algorithm.h" /************************************************************************************************** diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index a363cd42d..e5100a015 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -26,10 +26,10 @@ #include "imp.h" #include #include +#include #include #include #include -#include "bits.h" #include "stm32l4x.h" /* STM32L4xxx series for reference. diff --git a/src/helper/command.h b/src/helper/command.h index f38701983..fb9e50c85 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -24,8 +24,8 @@ #include #include -#include +#include #include #include diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index e21bc680d..738ed7943 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -41,8 +41,8 @@ * official policies, either expressed or implied, of the Jim Tcl Project. */ +#include "jim-nvp.h" #include -#include int jim_get_nvp(Jim_Interp *interp, Jim_Obj *objptr, const struct jim_nvp *nvp_table, const struct jim_nvp **result) diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index f285bdcac..3308d8742 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -20,9 +20,9 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include #include #include "libusb_helper.h" -#include "log.h" /* * comment from libusb: diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index dc7a64f43..8309de402 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -21,7 +21,7 @@ #include "server/server.h" #include "target/target.h" -#include +#include typedef int64_t threadid_t; typedef int64_t symbol_address_t; diff --git a/src/server/server.c b/src/server/server.c index 64acd3689..3f579bfc6 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -27,13 +27,13 @@ #endif #include "server.h" +#include #include #include #include #include "openocd.h" #include "tcl_server.h" #include "telnet_server.h" -#include "time_support.h" #include diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h index eaee6a48f..7e4977aba 100644 --- a/src/target/armv7m_trace.h +++ b/src/target/armv7m_trace.h @@ -18,8 +18,8 @@ #ifndef OPENOCD_TARGET_ARMV7M_TRACE_H #define OPENOCD_TARGET_ARMV7M_TRACE_H +#include #include -#include /** * @file diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index b2af39ced..9583ad767 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -20,7 +20,7 @@ #include "mips64.h" #include "mips64_pracc.h" -#include "time_support.h" +#include #define STACK_DEPTH 32 diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 7a5e990ca..86a95f635 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -16,7 +16,7 @@ #include "target/target.h" #include "target/algorithm.h" #include "target/target_type.h" -#include "log.h" +#include #include "jtag/jtag.h" #include "target/register.h" #include "target/breakpoints.h" diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 24fb79ccf..fdebdd413 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -16,7 +16,7 @@ #include "target/target.h" #include "target/algorithm.h" #include "target/target_type.h" -#include "log.h" +#include #include "jtag/jtag.h" #include "target/register.h" #include "target/breakpoints.h" diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 8f1f398b3..07fb95550 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -8,14 +8,14 @@ #include "config.h" #endif +#include +#include #include "target/target.h" #include "target/algorithm.h" #include "target/target_type.h" -#include "log.h" #include "jtag/jtag.h" #include "target/register.h" #include "target/breakpoints.h" -#include "helper/time_support.h" #include "riscv.h" #include "gdb_regs.h" #include "rtos/rtos.h" @@ -1870,10 +1870,10 @@ static int riscv_checksum_memory(struct target *target, LOG_DEBUG("address=0x%" TARGET_PRIxADDR "; count=0x%" PRIx32, address, count); static const uint8_t riscv32_crc_code[] = { -#include "../../contrib/loaders/checksum/riscv32_crc.inc" +#include "contrib/loaders/checksum/riscv32_crc.inc" }; static const uint8_t riscv64_crc_code[] = { -#include "../../contrib/loaders/checksum/riscv64_crc.inc" +#include "contrib/loaders/checksum/riscv64_crc.inc" }; static const uint8_t *crc_code; diff --git a/src/target/riscv/riscv_semihosting.c b/src/target/riscv/riscv_semihosting.c index 90b8ddb4f..0072b9afe 100644 --- a/src/target/riscv/riscv_semihosting.c +++ b/src/target/riscv/riscv_semihosting.c @@ -41,7 +41,7 @@ #include "config.h" #endif -#include "log.h" +#include #include "target/target.h" #include "target/semihosting_common.h" diff --git a/src/target/target_type.h b/src/target/target_type.h index cf30cf8cc..d6b6086b3 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -25,7 +25,7 @@ #ifndef OPENOCD_TARGET_TARGET_TYPE_H #define OPENOCD_TARGET_TARGET_TYPE_H -#include +#include struct target; From 9188115296917ce74ad5b0f83451414735225ce5 Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Sun, 5 Sep 2021 21:59:57 +0900 Subject: [PATCH 53/56] gitignore: Add GNU Global tag files This commit adds GNU Global[1] tag files to .gitignore. [1]: https://www.gnu.org/software/global/ Change-Id: Ia09fb359cfdfeadd9538cf6352d353e6475e85c7 Signed-off-by: Yasushi SHOJI Reviewed-on: https://review.openocd.org/c/openocd/+/6541 Tested-by: jenkins Reviewed-by: Antonio Borneo --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index e25d1ba96..955ca3c2e 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,8 @@ TAGS # ctags tag files tags + +# GNU Global tag files +GPATH +GRTAGS +GTAGS From 6112814f45efb8ea9debff163eeba1c57720bda5 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 5 Oct 2021 17:47:17 -0700 Subject: [PATCH 54/56] Fix build. Change-Id: I12f90bed9a1fe470ef3d49f9219227ee0de928b6 --- src/target/riscv/riscv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 3a80c78eb..a37949ce5 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -10,7 +10,7 @@ struct riscv_program; #include "gdb_regs.h" #include "jtag/jtag.h" #include "target/register.h" -#include "command.h" +#include /* The register cache is statically allocated. */ #define RISCV_MAX_HARTS 1024 From c67a887a00789ae7cdb46027b198576672cbf408 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 6 Oct 2021 13:26:48 -0700 Subject: [PATCH 55/56] Attempt to fix tracking of examined status. Fails dual-hart RV64 FreeRTOS test. Change-Id: If0d6000b0daf116c0efa6072fb545bca9bf54ffe --- src/target/riscv/riscv-013.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index f739fc753..ec9cef736 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1615,11 +1615,7 @@ static int examine(struct target *target) LOG_ERROR("Debugger is not authenticated to target Debug Module. " "(dmstatus=0x%x). Use `riscv authdata_read` and " "`riscv authdata_write` commands to authenticate.", dmstatus); - /* If we return ERROR_FAIL here, then in a multicore setup the next - * core won't be examined, which means we won't set up the - * authentication commands for them, which means the config script - * needs to be a lot more complex. */ - return ERROR_OK; + return ERROR_FAIL; } if (dmi_read(target, &info->sbcs, DM_SBCS) != ERROR_OK) @@ -1748,8 +1744,6 @@ static int examine(struct target *target) if (!halted) riscv013_step_or_resume_current_hart(target, false, false); - target_set_examined(target); - if (target->smp) { bool haltgroup_supported; if (set_haltgroup(target, &haltgroup_supported) != ERROR_OK) @@ -1810,7 +1804,7 @@ static int riscv013_authdata_write(struct target *target, uint32_t value, unsign return ERROR_FAIL; target_list_t *entry; list_for_each_entry(entry, &dm->target_list, list) { - if (examine(entry->target) != ERROR_OK) + if (target_examine_one(entry->target) != ERROR_OK) result = ERROR_FAIL; } return result; From 52b2a4a74455337387357bda341b5cb56310e793 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 6 Oct 2021 13:45:14 -0700 Subject: [PATCH 56/56] Fix incorrectly resolved conflict. Change-Id: I8dde5f2fc1dbc7b4de6091a934cbe160baadb504 Signed-off-by: Tim Newsome --- src/rtos/rtos_standard_stackings.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index d2bf5a3c1..465dd6711 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -321,11 +321,13 @@ static target_addr_t rtos_generic_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, target_addr_t stack_ptr, int align) { - target_addr_t new_stack_ptr; - target_addr_t aligned_stack_ptr; - new_stack_ptr = stack_ptr - stacking->stack_growth_direction * - stacking->stack_registers_size; - aligned_stack_ptr = new_stack_ptr & ~((target_addr_t)align - 1); + target_addr_t new_stack_ptr = stack_ptr; + if (stacking->stack_growth_direction > 0) + new_stack_ptr -= stacking->stack_registers_size; + else + new_stack_ptr += stacking->stack_registers_size; + target_addr_t aligned_stack_ptr = new_stack_ptr & ~((int64_t)align - 1); + if (aligned_stack_ptr != new_stack_ptr && stacking->stack_growth_direction == -1) { /* If we have a downward growing stack, the simple alignment code