commit
950e5d414f
|
@ -95,3 +95,8 @@ TAGS
|
|||
|
||||
# ctags tag files
|
||||
tags
|
||||
|
||||
# GNU Global tag files
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
|
|
18
HACKING
18
HACKING
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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,
|
|
@ -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");
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
}
|
|
@ -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 */
|
|
@ -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 $< > $@
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
2
jimtcl
2
jimtcl
|
@ -1 +1 @@
|
|||
Subproject commit fb923fab4f0cf276c336d98692d00df6a943791d
|
||||
Subproject commit 2d66360c61d2a89d4008e8bad12ae3aa5f0331e2
|
|
@ -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 \
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <helper/binarybuffer.h>
|
||||
#include "helper/types.h"
|
||||
#include <target/algorithm.h>
|
||||
#include <target/armv7m.h>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#endif
|
||||
|
||||
#include "imp.h"
|
||||
#include <helper/binarybuffer.h>
|
||||
#include <target/algorithm.h>
|
||||
#include <target/armv7m.h>
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include "imp.h"
|
||||
#include <helper/binarybuffer.h>
|
||||
#include <target/algorithm.h>
|
||||
#include <target/armv7m.h>
|
||||
#include <helper/types.h>
|
||||
|
|
|
@ -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"
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
LOG_WARNING("RDP = 0x55, the work-area should be in non-secure RAM (check SAU partitioning)");
|
||||
|
||||
/* 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)
|
||||
|
@ -2444,13 +2471,6 @@ static const struct command_registration stm32l4_exec_command_handlers[] = {
|
|||
.usage = "bank_id",
|
||||
.help = "Unlock entire protected flash device.",
|
||||
},
|
||||
{
|
||||
.name = "flashloader",
|
||||
.handler = stm32l4_handle_flashloader_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank_id> [enable|disable]",
|
||||
.help = "Configure the flashloader usage",
|
||||
},
|
||||
{
|
||||
.name = "mass_erase",
|
||||
.handler = stm32l4_handle_mass_erase_command,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -278,7 +278,7 @@ static int linuxgpiod_quit(void)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset)
|
||||
static struct gpiod_line *helper_get_line(const char *label, unsigned int offset, int val, int dir, int flags)
|
||||
{
|
||||
struct gpiod_line *line;
|
||||
int retval;
|
||||
|
@ -289,33 +289,34 @@ static struct gpiod_line *helper_get_input_line(const char *label, unsigned int
|
|||
return NULL;
|
||||
}
|
||||
|
||||
retval = gpiod_line_request_input(line, "OpenOCD");
|
||||
struct gpiod_line_request_config config = {
|
||||
.consumer = "OpenOCD",
|
||||
.request_type = dir,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
retval = gpiod_line_request(line, &config, val);
|
||||
if (retval < 0) {
|
||||
LOG_ERROR("Error request_input line %s", label);
|
||||
LOG_ERROR("Error requesting gpio line %s", label);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset)
|
||||
{
|
||||
return helper_get_line(label, offset, 0, GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0);
|
||||
}
|
||||
|
||||
static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val)
|
||||
{
|
||||
struct gpiod_line *line;
|
||||
int retval;
|
||||
|
||||
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, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0);
|
||||
}
|
||||
|
||||
retval = gpiod_line_request_output(line, "OpenOCD", val);
|
||||
if (retval < 0) {
|
||||
LOG_ERROR("Error request_output line %s", label);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return line;
|
||||
static struct gpiod_line *helper_get_open_drain_output_line(const char *label, unsigned int offset, int val)
|
||||
{
|
||||
return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN);
|
||||
}
|
||||
|
||||
static int linuxgpiod_init(void)
|
||||
|
@ -381,7 +382,11 @@ static int linuxgpiod_init(void)
|
|||
}
|
||||
|
||||
if (is_gpio_valid(srst_gpio)) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
/** */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
break;
|
||||
}
|
||||
head = head->next;
|
||||
|
||||
} while ((head != (struct target_list *)NULL) && (found == 0));
|
||||
} 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -327,13 +327,14 @@ static target_addr_t rtos_generic_stack_align(struct target *target,
|
|||
else
|
||||
new_stack_ptr += stacking->stack_registers_size;
|
||||
target_addr_t aligned_stack_ptr = new_stack_ptr & ~((int64_t)align - 1);
|
||||
|
||||
if (aligned_stack_ptr != new_stack_ptr &&
|
||||
stacking->stack_growth_direction == -1) {
|
||||
/* If we have a downward growing stack, the simple alignment code
|
||||
* 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 +366,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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,6 +678,7 @@ static void telnet_auto_complete(struct connection *connection)
|
|||
|
||||
/* validate the command */
|
||||
bool ignore_cmd = false;
|
||||
if (!is_variable_auto_completion) {
|
||||
Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE);
|
||||
|
||||
if (!jim_cmd) {
|
||||
|
@ -518,6 +695,7 @@ static void telnet_auto_complete(struct connection *connection)
|
|||
ignore_cmd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save the command in the prediction list */
|
||||
if (!ignore_cmd) {
|
||||
|
@ -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);
|
||||
|
||||
retval = telnet_exec_line(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;
|
||||
|
||||
} 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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,124 +1237,28 @@ 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 int dap_rom_display(struct command_invocation *cmd,
|
||||
struct adiv5_ap *ap, target_addr_t dbgbase, int depth)
|
||||
static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num)
|
||||
{
|
||||
int retval;
|
||||
uint64_t pid;
|
||||
uint32_t cid;
|
||||
char tabs[16] = "";
|
||||
static const struct dap_part_nums unknown = {
|
||||
.type = "Unrecognized",
|
||||
.full = "",
|
||||
};
|
||||
|
||||
if (depth > 16) {
|
||||
command_print(cmd, "\tTables too deep");
|
||||
return ERROR_FAIL;
|
||||
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;
|
||||
}
|
||||
|
||||
if (depth)
|
||||
snprintf(tabs, sizeof(tabs), "[L%02d] ", depth);
|
||||
|
||||
target_addr_t base_addr = dbgbase & 0xFFFFFFFFFFFFF000ull;
|
||||
command_print(cmd, "\t\tComponent base address " TARGET_ADDR_FMT, base_addr);
|
||||
|
||||
retval = dap_read_part_id(ap, base_addr, &cid, &pid);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(cmd, "\t\tCan't read component, the corresponding core might be turned off");
|
||||
return ERROR_OK; /* Don't abort recursion */
|
||||
}
|
||||
|
||||
if (!is_dap_cid_ok(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;
|
||||
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);
|
||||
|
||||
if (pid & 0x00080000) {
|
||||
/* JEP106 code */
|
||||
command_print(cmd, "\t\tDesigner is 0x%03" PRIx16 ", %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",
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
uint32_t memtype;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &memtype);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (memtype & 0x01)
|
||||
command_print(cmd, "\t\tMEMTYPE system memory present on bus");
|
||||
else
|
||||
command_print(cmd, "\t\tMEMTYPE system memory not present: dedicated debug bus");
|
||||
|
||||
/* Read ROM table entries from base address until we get 0x00000000 or reach the reserved area */
|
||||
for (uint16_t entry_offset = 0; entry_offset < 0xF00; entry_offset += 4) {
|
||||
uint32_t romentry;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr | entry_offset, &romentry);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
command_print(cmd, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "",
|
||||
tabs, entry_offset, romentry);
|
||||
if (romentry & 0x01) {
|
||||
/* Recurse. "romentry" is signed */
|
||||
retval = dap_rom_display(cmd, ap, base_addr + (int32_t)(romentry & 0xFFFFF000), depth + 1);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
} else if (romentry != 0) {
|
||||
command_print(cmd, "\t\tComponent not present");
|
||||
} else {
|
||||
command_print(cmd, "\t%s\tEnd of ROM table", tabs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (class == 9) { /* CoreSight component */
|
||||
static int dap_devtype_display(struct command_invocation *cmd, uint32_t devtype)
|
||||
{
|
||||
const char *major = "Reserved", *subtype = "Reserved";
|
||||
|
||||
uint32_t devtype;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &devtype);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
unsigned minor = (devtype >> 4) & 0x0f;
|
||||
switch (devtype & 0x0f) {
|
||||
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) {
|
||||
|
@ -1482,10 +1391,111 @@ static int dap_rom_display(struct command_invocation *cmd,
|
|||
}
|
||||
break;
|
||||
}
|
||||
command_print(cmd, "\t\tType is 0x%02" PRIx8 ", %s, %s",
|
||||
(uint8_t)(devtype & 0xff),
|
||||
command_print(cmd, "\t\tType is 0x%02x, %s, %s",
|
||||
devtype & ARM_CS_C9_DEVTYPE_MASK,
|
||||
major, subtype);
|
||||
/* REVISIT also show 0xfc8 DevId */
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int dap_rom_display(struct command_invocation *cmd,
|
||||
struct adiv5_ap *ap, target_addr_t dbgbase, int depth)
|
||||
{
|
||||
int retval;
|
||||
uint64_t pid;
|
||||
uint32_t cid;
|
||||
char tabs[16] = "";
|
||||
|
||||
if (depth > 16) {
|
||||
command_print(cmd, "\tTables too deep");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (depth)
|
||||
snprintf(tabs, sizeof(tabs), "[L%02d] ", depth);
|
||||
|
||||
target_addr_t base_addr = dbgbase & 0xFFFFFFFFFFFFF000ull;
|
||||
command_print(cmd, "\t\tComponent base address " TARGET_ADDR_FMT, base_addr);
|
||||
|
||||
retval = dap_read_part_id(ap, base_addr, &cid, &pid);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(cmd, "\t\tCan't read component, the corresponding core might be turned off");
|
||||
return ERROR_OK; /* Don't abort recursion */
|
||||
}
|
||||
|
||||
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 = 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);
|
||||
|
||||
const unsigned int class = (cid & ARM_CS_CIDR_CLASS_MASK) >> ARM_CS_CIDR_CLASS_SHIFT;
|
||||
const unsigned int part_num = ARM_CS_PIDR_PART(pid);
|
||||
unsigned int designer_id = ARM_CS_PIDR_DESIGNER(pid);
|
||||
|
||||
if (pid & ARM_CS_PIDR_JEDEC) {
|
||||
/* JEP106 code */
|
||||
command_print(cmd, "\t\tDesigner is 0x%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%02x, %s",
|
||||
designer_id, designer_id == 0x41 ? "ARM" : "<unknown>");
|
||||
}
|
||||
|
||||
const struct dap_part_nums *partnum = pidr_to_part_num(designer_id, part_num);
|
||||
command_print(cmd, "\t\tPart is 0x%03x, %s %s", part_num, partnum->type, partnum->full);
|
||||
command_print(cmd, "\t\tComponent class is 0x%x, %s", class, class_description[class]);
|
||||
|
||||
if (class == ARM_CS_CLASS_0X1_ROM_TABLE) {
|
||||
uint32_t memtype;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr + ARM_CS_C1_MEMTYPE, &memtype);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
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");
|
||||
|
||||
/* Read ROM table entries from base address until we get 0x00000000 or reach the reserved area */
|
||||
for (uint16_t entry_offset = 0; entry_offset < 0xF00; entry_offset += 4) {
|
||||
uint32_t romentry;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr | entry_offset, &romentry);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
command_print(cmd, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "",
|
||||
tabs, entry_offset, romentry);
|
||||
if (romentry & ARM_CS_ROMENTRY_PRESENT) {
|
||||
/* Recurse. "romentry" is signed */
|
||||
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) {
|
||||
command_print(cmd, "\t\tComponent not present");
|
||||
} else {
|
||||
command_print(cmd, "\t%s\tEnd of ROM table", tabs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) {
|
||||
uint32_t devtype;
|
||||
retval = mem_ap_read_atomic_u32(ap, base_addr + ARM_CS_C9_DEVTYPE, &devtype);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
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
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#include "arm_jtag.h"
|
||||
#include "helper/bits.h"
|
||||
|
||||
/* JEP106 ID for ARM */
|
||||
#define ARM_ID 0x23B
|
||||
|
||||
/* three-bit ACK values for SWD access (sent LSB first) */
|
||||
#define SWD_ACK_OK 0x1
|
||||
#define SWD_ACK_WAIT 0x2
|
||||
|
@ -157,13 +160,28 @@
|
|||
#define MEM_AP_REG_CFG_INVALID 0xFFFFFFF8
|
||||
|
||||
/* Fields of the MEM-AP's IDR register */
|
||||
#define IDR_REV (0xFUL << 28)
|
||||
#define IDR_JEP106 (0x7FFUL << 17)
|
||||
#define IDR_CLASS (0xFUL << 13)
|
||||
#define IDR_VARIANT (0xFUL << 4)
|
||||
#define IDR_TYPE (0xFUL << 0)
|
||||
#define AP_REG_IDR_REVISION_MASK (0xF0000000)
|
||||
#define AP_REG_IDR_REVISION_SHIFT (28)
|
||||
#define AP_REG_IDR_DESIGNER_MASK (0x0FFE0000)
|
||||
#define AP_REG_IDR_DESIGNER_SHIFT (17)
|
||||
#define AP_REG_IDR_CLASS_MASK (0x0001E000)
|
||||
#define AP_REG_IDR_CLASS_SHIFT (13)
|
||||
#define AP_REG_IDR_VARIANT_MASK (0x000000F0)
|
||||
#define AP_REG_IDR_VARIANT_SHIFT (4)
|
||||
#define AP_REG_IDR_TYPE_MASK (0x0000000F)
|
||||
#define AP_REG_IDR_TYPE_SHIFT (0)
|
||||
|
||||
#define IDR_JEP106_ARM 0x04760000
|
||||
#define AP_REG_IDR_CLASS_NONE (0x0)
|
||||
#define AP_REG_IDR_CLASS_COM (0x1)
|
||||
#define AP_REG_IDR_CLASS_MEM_AP (0x8)
|
||||
|
||||
#define AP_REG_IDR_VALUE(d, c, t) (\
|
||||
(((d) << AP_REG_IDR_DESIGNER_SHIFT) & AP_REG_IDR_DESIGNER_MASK) | \
|
||||
(((c) << AP_REG_IDR_CLASS_SHIFT) & AP_REG_IDR_CLASS_MASK) | \
|
||||
(((t) << AP_REG_IDR_TYPE_SHIFT) & AP_REG_IDR_TYPE_MASK) \
|
||||
)
|
||||
|
||||
#define AP_TYPE_MASK (AP_REG_IDR_DESIGNER_MASK | AP_REG_IDR_CLASS_MASK | AP_REG_IDR_TYPE_MASK)
|
||||
|
||||
/* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */
|
||||
enum swd_special_seq {
|
||||
|
@ -349,23 +367,19 @@ struct dap_ops {
|
|||
void (*quit)(struct adiv5_dap *dap);
|
||||
};
|
||||
|
||||
/*
|
||||
* Access Port classes
|
||||
*/
|
||||
enum ap_class {
|
||||
AP_CLASS_NONE = 0x00000, /* No class defined */
|
||||
AP_CLASS_MEM_AP = 0x10000, /* MEM-AP */
|
||||
};
|
||||
|
||||
/*
|
||||
* Access Port types
|
||||
*/
|
||||
enum ap_type {
|
||||
AP_TYPE_JTAG_AP = 0x0, /* JTAG-AP - JTAG master for controlling other JTAG devices */
|
||||
AP_TYPE_AHB3_AP = 0x1, /* AHB3 Memory-AP */
|
||||
AP_TYPE_APB_AP = 0x2, /* APB Memory-AP */
|
||||
AP_TYPE_AXI_AP = 0x4, /* AXI Memory-AP */
|
||||
AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */
|
||||
AP_TYPE_JTAG_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_NONE, 0), /* JTAG-AP */
|
||||
AP_TYPE_COM_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_COM, 0), /* COM-AP */
|
||||
AP_TYPE_AHB3_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 1), /* AHB3 Memory-AP */
|
||||
AP_TYPE_APB_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 2), /* APB2 or APB3 Memory-AP */
|
||||
AP_TYPE_AXI_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 4), /* AXI3 or AXI4 Memory-AP */
|
||||
AP_TYPE_AHB5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 5), /* AHB5 Memory-AP */
|
||||
AP_TYPE_APB4_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 6), /* APB4 Memory-AP */
|
||||
AP_TYPE_AXI5_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 7), /* AXI5 Memory-AP */
|
||||
AP_TYPE_AHB5H_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 8), /* AHB5 with enhanced HPROT Memory-AP */
|
||||
};
|
||||
|
||||
/* Check the ap->cfg_reg Long Address field (bit 1)
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
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,10 +497,11 @@ 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,21 +546,22 @@ 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)
|
||||
{
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "mips64.h"
|
||||
#include "mips64_pracc.h"
|
||||
|
||||
#include "time_support.h"
|
||||
#include <helper/time_support.h>
|
||||
|
||||
#define STACK_DEPTH 32
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
@ -1615,11 +1615,7 @@ static int examine(struct target *target)
|
|||
LOG_ERROR("Debugger is not authenticated to target Debug Module. "
|
||||
"(dmstatus=0x%x). Use `riscv authdata_read` and "
|
||||
"`riscv authdata_write` commands to authenticate.", dmstatus);
|
||||
/* If we return ERROR_FAIL here, then in a multicore setup the next
|
||||
* core won't be examined, which means we won't set up the
|
||||
* authentication commands for them, which means the config script
|
||||
* needs to be a lot more complex. */
|
||||
return ERROR_OK;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (dmi_read(target, &info->sbcs, DM_SBCS) != ERROR_OK)
|
||||
|
@ -1748,8 +1744,6 @@ static int examine(struct target *target)
|
|||
if (!halted)
|
||||
riscv013_step_or_resume_current_hart(target, false, false);
|
||||
|
||||
target_set_examined(target);
|
||||
|
||||
if (target->smp) {
|
||||
bool haltgroup_supported;
|
||||
if (set_haltgroup(target, &haltgroup_supported) != ERROR_OK)
|
||||
|
@ -1810,7 +1804,7 @@ static int riscv013_authdata_write(struct target *target, uint32_t value, unsign
|
|||
return ERROR_FAIL;
|
||||
target_list_t *entry;
|
||||
list_for_each_entry(entry, &dm->target_list, list) {
|
||||
if (examine(entry->target) != ERROR_OK)
|
||||
if (target_examine_one(entry->target) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,7 @@ struct riscv_program;
|
|||
#include "gdb_regs.h"
|
||||
#include "jtag/jtag.h"
|
||||
#include "target/register.h"
|
||||
#include "command.h"
|
||||
#include <helper/command.h>
|
||||
|
||||
/* The register cache is statically allocated. */
|
||||
#define RISCV_MAX_HARTS 1024
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include <helper/log.h>
|
||||
|
||||
#include "target/target.h"
|
||||
#include "target/semihosting_common.h"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -8,3 +8,5 @@
|
|||
set WORKAREASIZE 0x40000
|
||||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
|
|
@ -14,6 +14,8 @@ set QUADSPI 1
|
|||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
||||
# QUADSPI initialization
|
||||
proc qspi_init { } {
|
||||
global a
|
||||
|
|
|
@ -14,6 +14,8 @@ set QUADSPI 1
|
|||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
||||
# QUADSPI initialization
|
||||
proc qspi_init { } {
|
||||
global a
|
||||
|
|
|
@ -14,6 +14,8 @@ set QUADSPI 1
|
|||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
||||
# QUADSPI initialization
|
||||
proc qspi_init { } {
|
||||
global a
|
||||
|
|
|
@ -10,3 +10,5 @@ transport select hla_swd
|
|||
set WORKAREASIZE 0x40000
|
||||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
|
|
@ -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 } {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 } {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 } {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue