diff options
author | Tim Newsome <tim@sifive.com> | 2021-10-05 17:46:02 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2021-10-05 17:46:02 -0700 |
commit | 1775341ef81417f3fe18e8df9628ce6a96f81a38 (patch) | |
tree | 34367880702efd084471f3045bd4d3854d5543c7 | |
parent | 5215fc52abc3d204b66a05939c5257495b940cb6 (diff) | |
parent | 9188115296917ce74ad5b0f83451414735225ce5 (diff) | |
download | riscv-openocd-1775341ef81417f3fe18e8df9628ce6a96f81a38.zip riscv-openocd-1775341ef81417f3fe18e8df9628ce6a96f81a38.tar.gz riscv-openocd-1775341ef81417f3fe18e8df9628ce6a96f81a38.tar.bz2 |
Merge branch 'master' into from_upstream
Conflicts:
src/jtag/drivers/remote_bitbang.c
src/rtos/rtos_standard_stackings.c
src/rtos/rtos_standard_stackings.h
src/target/breakpoints.c
src/target/riscv/riscv.c
src/target/target.c
Change-Id: Ia6fcba3d43be8ea31728f3bcc2be6cb7e3ccc5c5
102 files changed, 3027 insertions, 907 deletions
@@ -95,3 +95,8 @@ TAGS # ctags tag files tags + +# GNU Global tag files +GPATH +GRTAGS +GTAGS @@ -117,7 +117,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. @@ -147,18 +147,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 @@ -166,11 +166,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 @@ -254,10 +254,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 <a href="http://openocd.zylin.com/">here</a>. +All OpenOCD patches can be reviewed <a href="https://review.openocd.org/">here</a>. @section reviewing Reviewing Patches -From the main <a href="http://openocd.zylin.com/#/q/status:open,n,z">Review +From the main <a href="https://review.openocd.org/#/q/status:open,n,z">Review page</a> 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/Makefile.am b/Makefile.am index 5c625de..d2d1993 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,7 +37,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)\"\ -DFD_SETSIZE=128 diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index a6ff995..4ecb485 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" @@ -93,6 +96,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/contrib/loaders/flash/npcx/Makefile b/contrib/loaders/flash/npcx/Makefile new file mode 100644 index 0000000..293bd02 --- /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 0000000..4312fdb --- /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 0000000..d60624a --- /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 <mlchao@nuvoton.com> + * Wealian Liao <WHLIAO@nuvoton.com> + */ + +#include <stdint.h> +#include <string.h> +#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 0000000..cc4f1ad --- /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 <mlchao@nuvoton.com> + * Wealian Liao <WHLIAO@nuvoton.com> + */ + +#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 0000000..0d78252 --- /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 0000000..9ec1c5e --- /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 <mlchao@nuvoton.com> + * Wealian Liao <WHLIAO@nuvoton.com> + */ + +#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/contrib/loaders/flash/stm32/Makefile b/contrib/loaders/flash/stm32/Makefile index b58b412..cee282a 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 9923ce7..0000000 --- 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 0000000..54c88a3 --- /dev/null +++ b/contrib/loaders/flash/stm32/stm32l4x.c @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** + * Copyright (C) 2021 Tarek BOCHKATI + * tarek.bouchkati@st.com + */ + +#define OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X + +#include <stdint.h> +#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 df5c7ed..1ab400a 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/doc/openocd.texi b/doc/openocd.texi index bcfc53f..de07c7f 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. @@ -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} @@ -6777,6 +6797,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. @@ -7337,18 +7368,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}. -@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. +@emph{Note:} To apply the protection change immediately, use @command{stm32l4x option_load}. @end deffn @deffn {Command} {stm32l4x mass_erase} num @@ -7379,6 +7407,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 diff --git a/jimtcl b/jimtcl -Subproject fb923fab4f0cf276c336d98692d00df6a943791 +Subproject 2d66360c61d2a89d4008e8bad12ae3aa5f0331e diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 661cee9..a091744 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/at91sam4l.c b/src/flash/nor/at91sam4l.c index f8c6f64..77dc07f 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -22,6 +22,7 @@ #include "imp.h" +#include <jtag/jtag.h> #include <target/cortex_m.h> /* 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 d4ac4c9..5cefd17 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 <jtag/jtag.h> #include <target/cortex_m.h> #define SAMD_NUM_PROT_BLOCKS 16 diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index 203c470..9ab0e81 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -28,6 +28,7 @@ #include "helper/binarybuffer.h" #include <helper/time_support.h> +#include <jtag/jtag.h> #include <target/cortex_m.h> /* A note to prefixing. diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index a686e83..60eccef 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include <helper/binarybuffer.h> #include "helper/types.h" #include <target/algorithm.h> #include <target/armv7m.h> diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c index b296538..723e605 100644 --- a/src/flash/nor/cc3220sf.c +++ b/src/flash/nor/cc3220sf.c @@ -21,6 +21,7 @@ #include "imp.h" #include "cc3220sf.h" +#include <helper/binarybuffer.h> #include <helper/time_support.h> #include <target/algorithm.h> #include <target/armv7m.h> diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 77403cd..dc966ed 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -57,6 +57,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; @@ -131,6 +132,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/kinetis.c b/src/flash/nor/kinetis.c index 3aa4c6b..edb4eb5 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -38,6 +38,7 @@ #include <helper/time_support.h> #include <target/target_type.h> #include <target/algorithm.h> +#include <target/arm_adi_v5.h> #include <target/armv7m.h> #include <target/cortex_m.h> diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 513b072..dc3b37e 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -41,6 +41,7 @@ #include "imp.h" #include <helper/binarybuffer.h> #include <target/algorithm.h> +#include <target/arm_adi_v5.h> #include <target/armv7m.h> #include <target/cortex_m.h> diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index d11af90..e7a690d 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -21,6 +21,7 @@ #endif #include "imp.h" +#include <helper/binarybuffer.h> #include <target/algorithm.h> #include <target/armv7m.h> diff --git a/src/flash/nor/npcx.c b/src/flash/nor/npcx.c new file mode 100644 index 0000000..af623e5 --- /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 <mlchao@nuvoton.com> + * Wealian Liao <WHLIAO@nuvoton.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include <helper/binarybuffer.h> +#include <helper/time_support.h> +#include <target/armv7m.h> +#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/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 8870164..c964155 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -23,6 +23,7 @@ #endif #include "imp.h" +#include <helper/binarybuffer.h> #include <target/algorithm.h> #include <target/armv7m.h> #include <helper/types.h> diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index b8b5202..8a41219 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -24,11 +24,12 @@ #include <time.h> #include "imp.h" +#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/sim3x.c b/src/flash/nor/sim3x.c index 20b5e39..2938ed1 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -27,6 +27,7 @@ #include <helper/binarybuffer.h> #include <helper/time_support.h> #include <target/algorithm.h> +#include <target/arm_adi_v5.h> #include <target/cortex_m.h> /* SI32_DEVICEID0 */ diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index d2638c1..6135c95 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 <target/algorithm.h> +#include <target/arm_adi_v5.h> #include <target/armv7m.h> #define DID0_VER(did0) ((did0 >> 28)&0x07) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3c05561..e5100a0 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -26,9 +26,10 @@ #include "imp.h" #include <helper/align.h> #include <helper/binarybuffer.h> +#include <helper/bits.h> #include <target/algorithm.h> +#include <target/arm_adi_v5.h> #include <target/cortex_m.h> -#include "bits.h" #include "stm32l4x.h" /* STM32L4xxx series for reference. @@ -64,16 +65,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. @@ -247,7 +253,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; @@ -271,83 +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_460_revs[] = { +static const struct stm32l4_rev stm32g05_g06xx_revs[] = { + { 0x1000, "A" }, +}; + +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_495_revs[] = { +static const struct stm32l4_rev stm32wb1xx_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, +}; + +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, @@ -357,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, @@ -369,9 +382,21 @@ 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_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, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75E0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, + { + .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, @@ -381,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, @@ -393,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, @@ -405,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, @@ -417,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, @@ -429,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, @@ -441,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, @@ -453,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, @@ -465,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, @@ -477,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, @@ -489,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, @@ -501,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, @@ -513,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, @@ -525,9 +550,21 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 512, }, { - .id = 0x495, - .revs = stm32_495_revs, - .num_revs = ARRAY_SIZE(stm32_495_revs), + .id = DEVID_STM32WB1XX, + .revs = stm32wb1xx_revs, + .num_revs = ARRAY_SIZE(stm32wb1xx_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 = DEVID_STM32WB5XX, + .revs = stm32wb5xx_revs, + .num_revs = ARRAY_SIZE(stm32wb5xx_revs), .device_str = "STM32WB5x", .max_flash_size_kb = 1024, .flags = F_NONE, @@ -537,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, @@ -549,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, @@ -582,7 +619,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; } @@ -1319,11 +1355,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 +1380,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 +1396,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; } @@ -1368,31 +1404,52 @@ 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 (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) */ 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)); + + /* 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); + + 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 +1470,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,37 +1594,21 @@ 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) { - /* 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"); + /* 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)"); - retval = stm32l4_write_block(bank, buffer, offset, - count / stm32l4_info->data_width); - } + /* first try to write using the loader, for better performance */ + retval = stm32l4_write_block(bank, buffer, offset, + count / stm32l4_info->data_width); - if (!use_flashloader || retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { - LOG_INFO("falling back to single memory accesses"); + /* 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); } @@ -1609,7 +1649,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 @@ -1621,8 +1664,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; } } @@ -1778,6 +1821,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; @@ -1785,14 +1830,13 @@ 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 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 @@ -1802,39 +1846,41 @@ 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 (flash_size_kb == 1024 || (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; } break; - case 0x435: /* STM32L43/L44xx */ - 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 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 */ - /* single/dual bank depending on bit(21) */ + case DEVID_STM32G0B_G0CXX: + /* 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; } 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 @@ -1842,7 +1888,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; @@ -1853,69 +1899,72 @@ 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) + * 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; - 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 & 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; 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) + * 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; - 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 & 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; - 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) + * otherwise check DUALBANK */ 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 & FLASH_U5_DUALBANK)) { stm32l4_info->dual_bank_mode = true; 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; 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: @@ -1943,10 +1992,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); @@ -2219,26 +2266,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) @@ -2445,13 +2472,6 @@ static const struct command_registration stm32l4_exec_command_handlers[] = { .help = "Unlock entire protected flash device.", }, { - .name = "flashloader", - .handler = stm32l4_handle_flashloader_command, - .mode = COMMAND_EXEC, - .usage = "<bank_id> [enable|disable]", - .help = "Configure the flashloader usage", - }, - { .name = "mass_erase", .handler = stm32l4_handle_mass_erase_command, .mode = COMMAND_EXEC, diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 7b9162b..4458c08 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 */ @@ -79,7 +87,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 +95,66 @@ #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 */ +#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 { + /* 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; +#else + uint32_t wp; + uint32_t rp; +#endif /* OPENOCD_CONTRIB_LOADERS_FLASH_STM32_STM32L4X */ + } fifo; +}; + #endif diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index 0abd844..8278601 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -40,6 +40,7 @@ #endif #include "imp.h" +#include <helper/binarybuffer.h> #include <helper/bits.h> #include <helper/time_support.h> #include <target/algorithm.h> diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 857da9e..fceb1e3 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1351,6 +1351,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)); @@ -1360,6 +1362,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); } diff --git a/src/helper/command.c b/src/helper/command.c index e5529d9..7c29f73 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", diff --git a/src/helper/command.h b/src/helper/command.h index f387019..fb9e50c 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -24,8 +24,8 @@ #include <stdint.h> #include <stdbool.h> -#include <jim-nvp.h> +#include <helper/jim-nvp.h> #include <helper/list.h> #include <helper/types.h> diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index df93a5c..ccf65f7 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", @@ -1016,7 +1016,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", @@ -1047,7 +1047,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", @@ -1279,7 +1279,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", @@ -1333,11 +1333,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", @@ -1412,4 +1412,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 */ diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index e21bc68..738ed79 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 <string.h> -#include <jim-nvp.h> 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/jlink.c b/src/jtag/drivers/jlink.c index 63bcda1..319ca38 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/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index f285bdc..3308d87 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 <helper/log.h> #include <jtag/drivers/jtag_usb_common.h> #include "libusb_helper.h" -#include "log.h" /* * comment from libusb: diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 42c8a31..dd50b44 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_output_line(const char *label, unsigned int offset, int val) +static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset) { - struct gpiod_line *line; - int retval; - - line = gpiod_chip_get_line(gpiod_chip, offset); - if (!line) { - LOG_ERROR("Error get line %s", label); - return NULL; - } + return helper_get_line(label, offset, 0, GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0); +} - retval = gpiod_line_request_output(line, "OpenOCD", val); - if (retval < 0) { - LOG_ERROR("Error request_output line %s", label); - return NULL; - } +static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val) +{ + return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0); +} - 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; } diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 0b5b8fc..6ab7cc9 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -91,13 +91,13 @@ static int remote_bitbang_flush(void) return ERROR_OK; } -typedef enum { +enum block_bool { NO_BLOCK, BLOCK -} block_bool_t; +}; /* Read any incoming data, placing it into the buffer. */ -static int remote_bitbang_fill_buf(block_bool_t block) +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 @@ -277,7 +277,7 @@ static int remote_bitbang_init_tcp(void) * 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)); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)); freeaddrinfo(result); /* No longer needed */ diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2bbd03b..a523708 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -41,6 +41,7 @@ #include <jtag/hla/hla_transport.h> #include <jtag/hla/hla_interface.h> #include <jtag/swim.h> +#include <target/arm_adi_v5.h> #include <target/target.h> #include <transport/transport.h> @@ -90,6 +91,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 +3132,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; @@ -4219,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[] = { { @@ -4242,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 }; diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index a1c95cd..c882acf 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 { /** */ diff --git a/src/openocd.c b/src/openocd.c index b4571b4..12bd52c 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, diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 11a55c4..84b4c65 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 e0b285b..fafbda2 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -242,7 +242,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; @@ -280,7 +280,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/rtos/rtos.h b/src/rtos/rtos.h index 641bdf2..2e41c14 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -21,7 +21,7 @@ #include "server/server.h" #include "target/target.h" -#include <jim-nvp.h> +#include <helper/jim-nvp.h> typedef int64_t threadid_t; typedef int64_t symbol_address_t; diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 589811b..d2bf5a3 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -321,19 +321,18 @@ 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 = 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); + 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); 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; } @@ -365,13 +364,13 @@ target_addr_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; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 0dbbc49..b38f79e 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3093,8 +3093,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); @@ -3641,7 +3643,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/server/server.c b/src/server/server.c index 64acd36..3f579bf 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -27,13 +27,13 @@ #endif #include "server.h" +#include <helper/time_support.h> #include <target/target.h> #include <target/target_request.h> #include <target/openrisc/jsp_server.h> #include "openocd.h" #include "tcl_server.h" #include "telnet_server.h" -#include "time_support.h" #include <signal.h> diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 36b017c..2ebcff1 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; @@ -435,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--; } @@ -474,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"); @@ -502,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 (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! */ + 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; + } } } @@ -591,7 +769,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 +807,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 +831,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 +869,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 +892,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; diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 34a7851..49e882f 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 70e727c..fc6bd6b 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 c295542..8d6d661 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 <helper/align.h> #include <helper/jep106.h> #include <helper/time_support.h> #include <helper/list.h> @@ -891,9 +893,28 @@ static const char *class_description[16] = { [0xF] = "CoreLink, PrimeCell or System component", }; -static bool is_dap_cid_ok(uint32_t cid) +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) { - return (cid & 0xffff0fff) == 0xb105000d; + for (unsigned int i = 0; i < ARRAY_SIZE(ap_types); i++) + if (type == ap_types[i].type) + return ap_types[i].description; + + return "Unknown"; } /* @@ -915,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]; @@ -945,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; } @@ -1006,17 +1005,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 +1025,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 +1047,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 +1055,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 +1100,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 @@ -1115,22 +1107,12 @@ 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 - -#define ARM_ID 0x23B - -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)", }, @@ -1141,9 +1123,12 @@ static const struct { { 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)", }, + { 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)", }, @@ -1152,6 +1137,7 @@ static const struct { { 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)", }, @@ -1197,11 +1183,25 @@ static const struct { { 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)", }, { 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)", }, @@ -1216,6 +1216,11 @@ static const struct { { 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)", }, + { 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)" }, @@ -1232,11 +1237,166 @@ static const struct { { 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) +{ + 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].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"; + 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) { @@ -1262,61 +1422,44 @@ 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); + 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 & 0x00080000) { + 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" : "<unknown>"); } - /* 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; - } + 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]); - 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 +1472,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,151 +1485,17 @@ static int dap_rom_display(struct command_invocation *cmd, break; } } - } else if (class == 9) { /* CoreSight component */ - const char *major = "Reserved", *subtype = "Reserved"; - + } else if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) { 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) { - 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%02" PRIx8 ", %s, %s", - (uint8_t)(devtype & 0xff), - major, subtype); - /* REVISIT also show 0xfc8 DevId */ + + retval = dap_devtype_display(cmd, devtype); + if (retval != ERROR_OK) + return retval; + + /* REVISIT also show ARM_CS_C9_DEVID */ } return ERROR_OK; @@ -1498,7 +1508,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); @@ -1511,32 +1520,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 73ceea0..0e1b95f 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 IDR_JEP106_ARM 0x04760000 +#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 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 { @@ -350,22 +368,18 @@ struct dap_ops { }; /* - * 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) diff --git a/src/target/arm_coresight.h b/src/target/arm_coresight.h new file mode 100644 index 0000000..42e6c5e --- /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 <stdbool.h> +#include <stdint.h> + +#include <src/helper/bits.h> + +#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/arm_cti.c b/src/target/arm_cti.c index 7d005e2..c776e9c 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 2f21aa1..94edfc0 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 746ab39..f2b5148 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; } @@ -869,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; @@ -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/armv7a.c b/src/target/armv7a.c index 6de79c3..2259fa5 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 fa6df2a..4078fdd 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 8ecdb00..6b42fae 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/armv7m.c b/src/target/armv7m.c index 68da020..ffc8ca8 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 <helper/log.h> +#include <helper/binarybuffer.h> #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ diff --git a/src/target/armv7m.h b/src/target/armv7m.h index f3eb90f..2816a91 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/armv7m_trace.h b/src/target/armv7m_trace.h index eaee6a4..7e4977a 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 <helper/command.h> #include <target/target.h> -#include <command.h> /** * @file diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index b668b84..f05ac07 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 c7719ab..dd901ef 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; @@ -468,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, @@ -496,9 +497,10 @@ int watchpoint_add(struct target *target, target_addr_t address, head = head->next; } return retval; - } else + } else { return watchpoint_add_internal(target, address, length, rw, value, mask); + } } static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove) @@ -544,20 +546,21 @@ int watchpoint_remove_internal(struct target *target, target_addr_t address) void watchpoint_remove(struct target *target, target_addr_t address) { - int found = 0; if (target->smp) { + unsigned int num_watchpoints = 0; struct target_list *head; struct target *curr; head = target->head; - while (head != (struct target_list *)NULL) { + while (head) { curr = head->target; - found += watchpoint_remove_internal(curr, address); + num_watchpoints += watchpoint_remove_internal(curr, address); head = head->next; } - if (found == 0) - LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); - } else + 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) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index b1f2206..bf65544 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" @@ -641,7 +642,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 +658,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 +954,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)) { @@ -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.", diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index f3c8527..3412c56 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" @@ -1243,7 +1244,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. @@ -2081,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; @@ -2191,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); diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 9186105..c67c9cc 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 <rtt/rtt.h> diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index b2af39c..9583ad7 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 <helper/time_support.h> #define STACK_DEPTH 32 diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index cd06893..ca44169 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/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 8fa86cc..bc0b0fc 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 <helper/log.h> #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 eb380cb..f739fc7 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 <helper/log.h> #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 d71a9c6..3d0144d 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -8,10 +8,11 @@ #include "config.h" #endif +#include <helper/log.h> +#include <helper/time_support.h> #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" @@ -1989,10 +1990,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 11f4a7e..b347212 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 <helper/log.h> #include "target/target.h" #include "target/semihosting_common.h" diff --git a/src/target/smp.c b/src/target/smp.c index 94c4da5..518f6e4 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 8194b3b..457dc86 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; @@ -4986,7 +4988,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; @@ -5311,8 +5313,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; } @@ -5718,7 +5725,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); @@ -5982,10 +5989,10 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) const char *targetname; int retval, len; static int smp_group = 1; - 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); @@ -6002,8 +6009,8 @@ 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; - if (head == (struct target_list *)NULL) { + new->next = NULL; + if (!head) { head = new; curr = head; } else { @@ -6015,7 +6022,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 = smp_group; target->head = head; diff --git a/src/target/target_type.h b/src/target/target_type.h index cf30cf8..d6b6086 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 <jim-nvp.h> +#include <helper/jim-nvp.h> struct target; diff --git a/tcl/board/arty_s7.cfg b/tcl/board/arty_s7.cfg index 5ab4083..a5e26fc 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: diff --git a/tcl/board/npcx_evb.cfg b/tcl/board/npcx_evb.cfg new file mode 100644 index 0000000..4f28bc9 --- /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/board/st_nucleo_g0.cfg b/tcl/board/st_nucleo_g0.cfg new file mode 100644 index 0000000..f8e67a0 --- /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 diff --git a/tcl/board/st_nucleo_g4.cfg b/tcl/board/st_nucleo_g4.cfg new file mode 100644 index 0000000..8e583e7 --- /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 diff --git a/tcl/board/stm327x6g_eval.cfg b/tcl/board/stm327x6g_eval.cfg index a5e5896..3d522f5 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 3c04d86..b809c5e 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 14e89e1..5d2c1a4 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 cc4334b..75dffd8 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 7d1bc96..d6cbff4 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 405e470..cb5caa4 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 5adcfea..5a587ae 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 22fd74a..698ef58 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 e606203..609cf38 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 e5512ea..0c4cc23 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/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg index ac4de18..d912a55 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 54cd63e..cb8e004 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 diff --git a/tcl/target/npcx.cfg b/tcl/target/npcx.cfg new file mode 100644 index 0000000..1a21e1f --- /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 diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg index 3c7679d..91ab289 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 877976c..f2a5c42 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 diff --git a/tcl/target/stm32wlx.cfg b/tcl/target/stm32wlx.cfg index edb3fb3..fafe9bc 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 diff --git a/tools/initial.sh b/tools/initial.sh index 446b98b..eafc9c1 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 |