Merge remote-tracking branch 'origin/riscv' into HEAD

compliance_dev
Megan Wachs 2018-02-06 10:26:22 -08:00
commit 5cf705d360
131 changed files with 8126 additions and 3226 deletions

View File

@ -4,11 +4,16 @@ dist: trusty
matrix:
include:
- os: linux
env: BUILD=x86_64-linux-gnu
env:
- BUILD=x86_64-linux-gnu
- EXECUTABLE=openocd
compiler: gcc
- os: linux
env: BUILD=i686-linux-gnu CFLAGS=-m32
env:
- BUILD=i686-linux-gnu
- CFLAGS=-m32
- EXECUTABLE=openocd
addons:
apt:
packages:
@ -16,17 +21,33 @@ matrix:
compiler: gcc
- os: linux
env: BUILD=x86_64-linux-gnu
env:
- BUILD=x86_64-linux-gnu
- EXECUTABLE=openocd
compiler: clang
- os: linux
env: BUILD=i686-linux-gnu CFLAGS=-m32
env:
- BUILD=i686-linux-gnu
- CFLAGS=-m32
- EXECUTABLE=openocd
compiler: clang
addons:
apt:
packages:
- gcc-multilib
- os: linux
env:
- BUILD=i686-w64-mingw
- CONFIGURE_ARGS="--build=i686-unknown-linux-gnu --host=i686-w64-mingw32"
- EXECUTABLE=openocd.exe
compiler: i686-w64-mingw32-gcc
addons:
apt:
packages:
- binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686
script:
- ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi && make
- file src/openocd
- ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi $CONFIGURE_ARGS && make
- file src/$EXECUTABLE

View File

@ -571,7 +571,7 @@ AS_IF([test "x$build_buspirate" = "xyes"], [
AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
AS_IF([test -f "$srcdir/jimtcl/configure.ac"], [
AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim --with-ext="eventloop array clock regexp stdlib tclcompat" --without-ext="default"])
AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim])
], [
AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.])
])
@ -628,7 +628,7 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [
PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no])
])
PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.1],
PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
[use_libjaylink=yes], [use_libjaylink=no])
m4_define([PROCESS_ADAPTERS], [
@ -655,7 +655,7 @@ PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1])
PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi])
PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x])
PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi])
PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_libusb1" = "xyes" -a "x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libusb-1.x or libjaylink-0.1])
PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.1])
AS_IF([test "x$build_openjtag" = "xyes"], [
AS_IF([test "x$use_libusb1" != "xyes" -a "x$use_libusb0" != "xyes"], [

View File

@ -1,6 +1,6 @@
.PHONY: arm clean-arm
all: arm
all: arm stm8
common_dirs = \
checksum \
@ -32,3 +32,6 @@ clean: clean-arm
for d in $(common_dirs); do \
$(MAKE) -C $$d clean; \
done
stm8:
$(MAKE) -C erase_check stm8

View File

@ -6,6 +6,12 @@ ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy
ARM_AFLAGS = -EL
STM8_CROSS_COMPILE ?= stm8-
STM8_AS ?= $(STM8_CROSS_COMPILE)as
STM8_OBJCOPY ?= $(STM8_CROSS_COMPILE)objcopy
STM8_AFLAGS =
arm: armv4_5_erase_check.inc armv7m_erase_check.inc armv7m_0_erase_check.inc
armv4_5_%.elf: armv4_5_%.s
@ -26,5 +32,16 @@ armv7m_%.bin: armv7m_%.elf
armv7m_%.inc: armv7m_%.bin
$(BIN2C) < $< > $@
stm8: stm8_erase_check.inc
stm8_%.elf: stm8_%.s
$(STM8_AS) $(STM8_AFLAGS) $< -o $@
stm8_%.bin: stm8_%.elf
$(STM8_OBJCOPY) -Obinary $< $@
stm8_%.inc: stm8_%.bin
$(BIN2C) < $< > $@
clean:
-rm -f *.elf *.bin *.inc

View File

@ -0,0 +1,5 @@
/* Autogenerated with ../../../src/helper/bin2char.sh */
0x00,0x80,0x00,0x00,0x80,0x00,0x96,0xcf,0x00,0x22,0x1e,0x01,0x16,0x04,0xa6,0xff,
0x90,0x5d,0x26,0x04,0x0d,0x03,0x27,0x17,0x90,0x5d,0x26,0x02,0x0a,0x03,0x90,0x5a,
0x92,0xbc,0x00,0x00,0xa1,0xff,0x26,0x07,0x5c,0x26,0xe5,0x0c,0x00,0x20,0xe1,0x1f,
0x01,0x17,0x04,0x8b,

View File

@ -0,0 +1,69 @@
/*
Copyright (C) 2017 Ake Rehnman
ake.rehnman(at)gmail.com
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 3 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, see <http://www.gnu.org/licenses/>.
*/
;;
;; erase check memory code
;;
.org 0x0
;; start address
start_addr: .byte 0x00
.word 0x8000
;; byte count
byte_cnt: .byte 0x00
.word 0x8000
;
; SP must point to start_addr on entry
; first relocate start_addr to the location
; we are running at
start:
ldw X,SP
ldw .cont+2,X
ldw X,(start_addr+1,SP) ;start addr
ldw Y,(byte_cnt+1,SP) ;count
ld A,#0xff
;
; if count == 0 return
.L1:
tnzw Y
jrne .decrcnt ;continue if low word != 0
tnz (byte_cnt,SP) ;high byte
jreq .exit ;goto exit
;
; decrement count (byte_cnt)
.decrcnt:
tnzw Y ;low word count
jrne .decr1
dec (byte_cnt,SP) ;high byte
.decr1:
decw Y; decr low word
;
; first check if [start_addr] is 0xff
.cont:
ldf A, [start_addr.e]
cp A,#0xff
jrne .exit ;exit if not 0xff
;
; increment start_addr (addr)
incw X
jrne .L1
inc (start_addr,SP) ;increment high byte
jra .L1
;
.exit:
ldw (start_addr+1,SP),X ;start addr
ldw (byte_cnt+1,SP),Y ;count
break

View File

@ -44,11 +44,7 @@
#define EFM32_MSC_ADDRB_OFFSET 0x010
#define EFM32_MSC_WDATA_OFFSET 0x018
#define EFM32_MSC_STATUS_OFFSET 0x01c
#define EFM32_MSC_LOCK_OFFSET 0x03c
/* unlock MSC */
ldr r6, =#0x1b71
str r6, [r0, #EFM32_MSC_LOCK_OFFSET]
/* set WREN to 1 */
movs r6, #1
str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET]

View File

@ -0,0 +1,121 @@
/***************************************************************************
* Copyright (C) 2017 by STMicroelectronics *
* *
* 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-m7
.thumb
.thumb_func
/*
* To assemble:
* arm-none-eabi-gcc -c stm32h7x.S
*
* To disassemble:
* arm-none-eabi-objdump -d stm32h7x.o
*
* To generate binary file:
* arm-none-eabi-objcopy -O binary stm32h7x.o stm32h7_flash_write_code.bin
*
* To generate include file:
* xxd -i stm32h7_flash_write_code.bin
*/
/*
* Code limitations:
* The workarea must have size multiple of 4 bytes, since R/W
* operations are all at 32 bits.
* The workarea must be big enough to contain 32 bytes of data,
* thus the minimum size is (rp, wp, data) = 4 + 4 + 32 = 40 bytes.
* To benefit from concurrent host write-to-buffer and target
* write-to-flash, the workarea must be way bigger than the minimum.
*/
/*
* Params :
* r0 = workarea start, status (out)
* r1 = workarea end
* r2 = target address
* r3 = count (256 bit words)
* r4 = flash reg base
*
* Clobbered:
* r5 - rp
* r6 - wp, status, tmp
* r7 - loop index, tmp
*/
#define STM32_FLASH_CR_OFFSET 0x0C /* offset of CR register in FLASH struct */
#define STM32_FLASH_SR_OFFSET 0x10 /* offset of SR register in FLASH struct */
#define STM32_CR_PROG 0x00000032 /* PSIZE64 | PG */
#define STM32_SR_BUSY_MASK 0x00000001 /* BSY */
#define STM32_SR_ERROR_MASK 0x03ee0000 /* DBECCERR | SNECCERR | RDSERR | RDPERR | OPERR
| INCERR | STRBERR | PGSERR | WRPERR */
code:
ldr r5, [r0, #4] /* read rp */
wait_fifo:
ldr r6, [r0, #0] /* read wp */
cbz r6, exit /* abort if wp == 0, status = 0 */
subs r6, r6, r5 /* number of bytes available for read in r6 */
ittt mi /* if wrapped around */
addmi r6, r1 /* add size of buffer */
submi r6, r0
submi r6, #8
cmp r6, #32 /* wait until 32 bytes are available */
bcc wait_fifo
mov r6, #STM32_CR_PROG
str r6, [r4, #STM32_FLASH_CR_OFFSET]
mov r7, #8 /* program by 8 words = 32 bytes */
write_flash:
ldr r6, [r5], #0x04 /* read one word from src, increment ptr */
str r6, [r2], #0x04 /* write one word to dst, increment ptr */
dsb
cmp r5, r1 /* if rp >= end of buffer ... */
it cs
addcs r5, r0, #8 /* ... then wrap at buffer start */
subs r7, r7, #1 /* decrement loop index */
bne write_flash /* loop if not done */
busy:
ldr r6, [r4, #STM32_FLASH_SR_OFFSET]
tst r6, #STM32_SR_BUSY_MASK
bne busy /* operation in progress, wait ... */
ldr r7, stm32_sr_error_mask
tst r6, r7
bne error /* fail... */
str r5, [r0, #4] /* store rp */
subs r3, r3, #1 /* decrement count */
bne wait_fifo /* loop if not done */
b exit
error:
movs r7, #0
str r7, [r0, #4] /* set rp = 0 on error */
exit:
mov r0, r6 /* return status in r0 */
bkpt #0x00
stm32_sr_error_mask:
.word STM32_SR_ERROR_MASK

View File

@ -2948,8 +2948,8 @@ Specifies the serial number of the adapter.
Specifies the adapter layout to use.
@end deffn
@deffn {Config Command} {hla_vid_pid} vid pid
The vendor ID and product ID of the device.
@deffn {Config Command} {hla_vid_pid} [vid pid]+
Pairs of vendor IDs and product IDs of the device.
@end deffn
@deffn {Command} {hla_command} command
@ -4503,12 +4503,6 @@ and (if the target is using it) after SRST has been
released on the scan chain.
@item @b{reset-end}
@* Issued as the final step in @command{reset} processing.
@ignore
@item @b{reset-halt-post}
@* Currently not used
@item @b{reset-halt-pre}
@* Currently not used
@end ignore
@item @b{reset-init}
@* Used by @b{reset init} command for board-specific initialization.
This event fires after @emph{reset-deassert-post}.
@ -4525,12 +4519,6 @@ before @command{reset_init} is called.
This is the most robust place to use @command{jtag_rclk}
or @command{adapter_khz} to switch to a low JTAG clock rate,
when reset disables PLLs needed to use a fast clock.
@ignore
@item @b{reset-wait-pos}
@* Currently not used
@item @b{reset-wait-pre}
@* Currently not used
@end ignore
@item @b{resume-start}
@* Before any target is resumed
@item @b{resume-end}
@ -5767,17 +5755,19 @@ Show information about flash driver.
@end deffn
@deffn {Flash Driver} nrf51
@deffn {Flash Driver} nrf5
All members of the nRF51 microcontroller families from Nordic Semiconductor
include internal flash and use ARM Cortex-M0 core.
Also, the nRF52832 microcontroller from Nordic Semiconductor, which include
internal flash and use an ARM Cortex-M4F core.
@example
flash bank $_FLASHNAME nrf51 0 0x00000000 0 0 $_TARGETNAME
flash bank $_FLASHNAME nrf5 0 0x00000000 0 0 $_TARGETNAME
@end example
Some nrf51-specific commands are defined:
Some nrf5-specific commands are defined:
@deffn Command {nrf51 mass_erase}
@deffn Command {nrf5 mass_erase}
Erases the contents of the code memory and user information
configuration registers as well. It must be noted that this command
works only for chips that do not have factory pre-programmed region 0
@ -5886,9 +5876,6 @@ All members of the Stellaris LM3Sxxx, LM4x and Tiva C microcontroller
families from Texas Instruments include internal flash. The driver
automatically recognizes a number of these chips using the chip
identification register, and autoconfigures itself.
@footnote{Currently there is a @command{stellaris mass_erase} command.
That seems pointless since the same effect can be had using the
standard @command{flash erase_address} command.}
@example
flash bank $_FLASHNAME stellaris 0 0 0 0 $_TARGETNAME
@ -5934,11 +5921,7 @@ as per the following example.
flash bank $_FLASHNAME stm32f1x 0x08080000 0 0 0 $_TARGETNAME
@end example
Some stm32f1x-specific commands
@footnote{Currently there is a @command{stm32f1x mass_erase} command.
That seems pointless since the same effect can be had using the
standard @command{flash erase_address} command.}
are defined:
Some stm32f1x-specific commands are defined:
@deffn Command {stm32f1x lock} num
Locks the entire stm32 device.
@ -5950,6 +5933,11 @@ Unlocks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32f1x mass_erase} num
Mass erases the entire stm32f1x device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32f1x options_read} num
Read and display the stm32 option bytes written by
the @command{stm32f1x options_write} command.
@ -5968,6 +5956,10 @@ include internal flash and use ARM Cortex-M3/M4/M7 cores.
The driver automatically recognizes a number of these chips using
the chip identification register, and autoconfigures itself.
@example
flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME
@end example
Note that some devices have been found that have a flash size register that contains
an invalid value, to workaround this issue you can override the probed value used by
the flash driver.
@ -5988,6 +5980,11 @@ Unlocks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32f2x mass_erase} num
Mass erases the entire stm32f2x device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32f2x options_read} num
Reads and displays user options and (where implemented) boot_addr0, boot_addr1, optcr2.
The @var{num} parameter is a value shown by @command{flash banks}.
@ -6007,12 +6004,52 @@ The @var{num} parameter is a value shown by @command{flash banks}, @var{optcr2}
@end deffn
@end deffn
@deffn {Flash Driver} stm32h7x
All members of the STM32H7 microcontroller families from ST Microelectronics
include internal flash and use ARM Cortex-M7 core.
The driver automatically recognizes a number of these chips using
the chip identification register, and autoconfigures itself.
@example
flash bank $_FLASHNAME stm32h7x 0 0 0 0 $_TARGETNAME
@end example
Note that some devices have been found that have a flash size register that contains
an invalid value, to workaround this issue you can override the probed value used by
the flash driver.
@example
flash bank $_FLASHNAME stm32h7x 0 0x20000 0 0 $_TARGETNAME
@end example
Some stm32h7x-specific commands are defined:
@deffn Command {stm32h7x lock} num
Locks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32h7x unlock} num
Unlocks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32h7x mass_erase} num
Mass erases the entire stm32h7x device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@end deffn
@deffn {Flash Driver} stm32lx
All members of the STM32L microcontroller families from ST Microelectronics
include internal flash and use ARM Cortex-M3 and Cortex-M0+ cores.
The driver automatically recognizes a number of these chips using
the chip identification register, and autoconfigures itself.
@example
flash bank $_FLASHNAME stm32lx 0 0 0 0 $_TARGETNAME
@end example
Note that some devices have been found that have a flash size register that contains
an invalid value, to workaround this issue you can override the probed value used by
the flash driver. If you use 0 as the bank base address, it tells the
@ -6025,6 +6062,16 @@ flash bank $_FLASHNAME stm32lx 0x08000000 0x20000 0 0 $_TARGETNAME
Some stm32lx-specific commands are defined:
@deffn Command {stm32lx lock} num
Locks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32lx unlock} num
Unlocks the entire stm32 device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@deffn Command {stm32lx mass_erase} num
Mass erases the entire stm32lx device (all flash banks and EEPROM
data). This is the only way to unlock a protected flash (unless RDP
@ -6033,6 +6080,42 @@ The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@end deffn
@deffn {Flash Driver} stm32l4x
All members of the STM32L4 microcontroller families from ST Microelectronics
include internal flash and use ARM Cortex-M4 cores.
The driver automatically recognizes a number of these chips using
the chip identification register, and autoconfigures itself.
@example
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
@end example
Note that some devices have been found that have a flash size register that contains
an invalid value, to workaround this issue you can override the probed value used by
the flash driver.
@example
flash bank $_FLASHNAME stm32l4x 0x08000000 0x40000 0 0 $_TARGETNAME
@end example
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}.
@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 mass_erase} num
Mass erases the entire stm32l4x device.
The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn
@end deffn
@deffn {Flash Driver} str7x
All members of the STR7 microcontroller family from ST Microelectronics
include internal flash and use ARM7TDMI cores.
@ -7602,6 +7685,20 @@ requests by using a special SVC instruction that is trapped at the
Supervisor Call vector by OpenOCD.
@end deffn
@deffn Command {arm semihosting_cmdline} [@option{enable}|@option{disable}]
@cindex ARM semihosting
Set the command line to be passed to the debuggee.
@example
arm semihosting_cmdline argv0 argv1 argv2 ...
@end example
This option lets one set the command line arguments to be passed to
the program. The first argument (argv0) is the program name in a
standard C environment (argv[0]). Depending on the program (not much
programs look at argv[0]), argv0 is ignored and can be any string.
@end deffn
@deffn Command {arm semihosting_fileio} [@option{enable}|@option{disable}]
@cindex ARM semihosting
Display status of semihosting fileio, after optionally changing that

View File

@ -259,11 +259,11 @@ static int mg_dsk_wait(mg_io_type_wait wait_local, uint32_t time_var)
case mg_io_wait_rdy:
if (status & mg_io_rbit_status_ready)
return ERROR_OK;
/* fallthrough */
case mg_io_wait_drq:
if (status & mg_io_rbit_status_data_req)
return ERROR_OK;
/* fallthrough */
default:
break;
}

View File

@ -281,6 +281,7 @@ static int imx31_command(struct nand_device *nand, uint8_t command)
* offset == one half of page size
*/
in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
break;
default:
in_sram_address = MX3_NF_MAIN_BUFFER0;
}

View File

@ -37,7 +37,7 @@ NOR_DRIVERS = \
%D%/mrvlqspi.c \
%D%/niietcm4.c \
%D%/non_cfi.c \
%D%/nrf51.c \
%D%/nrf5.c \
%D%/numicro.c \
%D%/ocl.c \
%D%/pic32mx.c \
@ -50,6 +50,7 @@ NOR_DRIVERS = \
%D%/stm32f2x.c \
%D%/stm32lx.c \
%D%/stm32l4x.c \
%D%/stm32h7x.c \
%D%/str7x.c \
%D%/str9x.c \
%D%/str9xpec.c \

View File

@ -49,6 +49,7 @@ extern struct flash_driver lpcspifi_flash;
extern struct flash_driver mdr_flash;
extern struct flash_driver mrvlqspi_flash;
extern struct flash_driver niietcm4_flash;
extern struct flash_driver nrf5_flash;
extern struct flash_driver nrf51_flash;
extern struct flash_driver numicro_flash;
extern struct flash_driver ocl_flash;
@ -60,6 +61,7 @@ extern struct flash_driver stm32f1x_flash;
extern struct flash_driver stm32f2x_flash;
extern struct flash_driver stm32lx_flash;
extern struct flash_driver stm32l4x_flash;
extern struct flash_driver stm32h7x_flash;
extern struct flash_driver stmsmi_flash;
extern struct flash_driver str7x_flash;
extern struct flash_driver str9x_flash;
@ -103,6 +105,7 @@ static struct flash_driver *flash_drivers[] = {
&mdr_flash,
&mrvlqspi_flash,
&niietcm4_flash,
&nrf5_flash,
&nrf51_flash,
&numicro_flash,
&ocl_flash,
@ -114,6 +117,7 @@ static struct flash_driver *flash_drivers[] = {
&stm32f2x_flash,
&stm32lx_flash,
&stm32l4x_flash,
&stm32h7x_flash,
&stmsmi_flash,
&str7x_flash,
&str9x_flash,

View File

@ -49,6 +49,8 @@
#define EZR_FAMILY_ID_WONDER_GECKO 120
#define EZR_FAMILY_ID_LEOPARD_GECKO 121
#define EZR_FAMILY_ID_HAPPY_GECKO 122
#define EFR_FAMILY_ID_MIGHTY_GECKO 16
#define EFR_FAMILY_ID_BLUE_GECKO 20
#define EFM32_FLASH_ERASE_TMO 100
#define EFM32_FLASH_WDATAREADY_TMO 100
@ -72,27 +74,31 @@
#define EFM32_MSC_DI_PROD_REV (EFM32_MSC_DEV_INFO+0x1ff)
#define EFM32_MSC_REGBASE 0x400c0000
#define EFM32_MSC_WRITECTRL (EFM32_MSC_REGBASE+0x008)
#define EFR32_MSC_REGBASE 0x400e0000
#define EFM32_MSC_REG_WRITECTRL 0x008
#define EFM32_MSC_WRITECTRL_WREN_MASK 0x1
#define EFM32_MSC_WRITECMD (EFM32_MSC_REGBASE+0x00c)
#define EFM32_MSC_REG_WRITECMD 0x00c
#define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x1
#define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x2
#define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x8
#define EFM32_MSC_ADDRB (EFM32_MSC_REGBASE+0x010)
#define EFM32_MSC_WDATA (EFM32_MSC_REGBASE+0x018)
#define EFM32_MSC_STATUS (EFM32_MSC_REGBASE+0x01c)
#define EFM32_MSC_REG_ADDRB 0x010
#define EFM32_MSC_REG_WDATA 0x018
#define EFM32_MSC_REG_STATUS 0x01c
#define EFM32_MSC_STATUS_BUSY_MASK 0x1
#define EFM32_MSC_STATUS_LOCKED_MASK 0x2
#define EFM32_MSC_STATUS_INVADDR_MASK 0x4
#define EFM32_MSC_STATUS_WDATAREADY_MASK 0x8
#define EFM32_MSC_STATUS_WORDTIMEOUT_MASK 0x10
#define EFM32_MSC_STATUS_ERASEABORTED_MASK 0x20
#define EFM32_MSC_LOCK (EFM32_MSC_REGBASE+0x03c)
#define EFM32_MSC_REG_LOCK 0x03c
#define EFR32_MSC_REG_LOCK 0x040
#define EFM32_MSC_LOCK_LOCKKEY 0x1b71
struct efm32x_flash_bank {
int probed;
uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
uint32_t reg_base;
uint32_t reg_lock;
};
struct efm32_info {
@ -132,11 +138,30 @@ static int efm32x_get_prod_rev(struct flash_bank *bank, uint8_t *prev)
return target_read_u8(bank->target, EFM32_MSC_DI_PROD_REV, prev);
}
static int efm32x_read_reg_u32(struct flash_bank *bank, target_addr_t offset,
uint32_t *value)
{
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
uint32_t base = efm32x_info->reg_base;
return target_read_u32(bank->target, base + offset, value);
}
static int efm32x_write_reg_u32(struct flash_bank *bank, target_addr_t offset,
uint32_t value)
{
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
uint32_t base = efm32x_info->reg_base;
return target_write_u32(bank->target, base + offset, value);
}
static int efm32x_read_info(struct flash_bank *bank,
struct efm32_info *efm32_info)
{
int ret;
uint32_t cpuid = 0;
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
memset(efm32_info, 0, sizeof(struct efm32_info));
@ -175,6 +200,15 @@ static int efm32x_read_info(struct flash_bank *bank,
if (ERROR_OK != ret)
return ret;
if (EFR_FAMILY_ID_BLUE_GECKO == efm32_info->part_family ||
EFR_FAMILY_ID_MIGHTY_GECKO == efm32_info->part_family) {
efm32x_info->reg_base = EFR32_MSC_REGBASE;
efm32x_info->reg_lock = EFR32_MSC_REG_LOCK;
} else {
efm32x_info->reg_base = EFM32_MSC_REGBASE;
efm32x_info->reg_lock = EFM32_MSC_REG_LOCK;
}
if (EFM_FAMILY_ID_GECKO == efm32_info->part_family ||
EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family)
efm32_info->page_size = 512;
@ -208,7 +242,9 @@ static int efm32x_read_info(struct flash_bank *bank,
}
} else if (EFM_FAMILY_ID_WONDER_GECKO == efm32_info->part_family ||
EZR_FAMILY_ID_WONDER_GECKO == efm32_info->part_family ||
EZR_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
EZR_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family ||
EFR_FAMILY_ID_BLUE_GECKO == efm32_info->part_family ||
EFR_FAMILY_ID_MIGHTY_GECKO == efm32_info->part_family) {
uint8_t pg_size = 0;
ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
&pg_size);
@ -241,6 +277,10 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
case EZR_FAMILY_ID_HAPPY_GECKO:
printed = snprintf(buf, buf_size, "EZR32 ");
break;
case EFR_FAMILY_ID_MIGHTY_GECKO:
case EFR_FAMILY_ID_BLUE_GECKO:
printed = snprintf(buf, buf_size, "EFR32 ");
break;
default:
printed = snprintf(buf, buf_size, "EFM32 ");
}
@ -276,6 +316,12 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
case EZR_FAMILY_ID_HAPPY_GECKO:
printed = snprintf(buf, buf_size, "Happy Gecko");
break;
case EFR_FAMILY_ID_BLUE_GECKO:
printed = snprintf(buf, buf_size, "Blue Gecko");
break;
case EFR_FAMILY_ID_MIGHTY_GECKO:
printed = snprintf(buf, buf_size, "Mighty Gecko");
break;
}
buf += printed;
@ -319,7 +365,7 @@ static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
int ret = 0;
uint32_t reg_val = 0;
ret = target_read_u32(bank->target, reg, &reg_val);
ret = efm32x_read_reg_u32(bank, reg, &reg_val);
if (ERROR_OK != ret)
return ret;
@ -328,18 +374,19 @@ static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
else
reg_val &= ~bitmask;
return target_write_u32(bank->target, reg, reg_val);
return efm32x_write_reg_u32(bank, reg, reg_val);
}
static int efm32x_set_wren(struct flash_bank *bank, int write_enable)
{
return efm32x_set_reg_bits(bank, EFM32_MSC_WRITECTRL,
return efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECTRL,
EFM32_MSC_WRITECTRL_WREN_MASK, write_enable);
}
static int efm32x_msc_lock(struct flash_bank *bank, int lock)
{
return target_write_u32(bank->target, EFM32_MSC_LOCK,
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
return efm32x_write_reg_u32(bank, efm32x_info->reg_lock,
(lock ? 0 : EFM32_MSC_LOCK_LOCKKEY));
}
@ -350,7 +397,7 @@ static int efm32x_wait_status(struct flash_bank *bank, int timeout,
uint32_t status = 0;
while (1) {
ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
if (ERROR_OK != ret)
break;
@ -389,16 +436,16 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr);
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
if (ERROR_OK != ret)
return ret;
ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
if (ERROR_OK != ret)
return ret;
ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
if (ERROR_OK != ret)
return ret;
@ -412,7 +459,7 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
return ERROR_FAIL;
}
ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
EFM32_MSC_WRITECMD_ERASEPAGE_MASK, 1);
if (ERROR_OK != ret)
return ret;
@ -589,6 +636,7 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
uint32_t address = bank->base + offset;
struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
int ret = ERROR_OK;
/* see contrib/loaders/flash/efm32.S for src */
@ -598,10 +646,7 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
/* #define EFM32_MSC_ADDRB_OFFSET 0x010 */
/* #define EFM32_MSC_WDATA_OFFSET 0x018 */
/* #define EFM32_MSC_STATUS_OFFSET 0x01c */
/* #define EFM32_MSC_LOCK_OFFSET 0x03c */
0x15, 0x4e, /* ldr r6, =#0x1b71 */
0xc6, 0x63, /* str r6, [r0, #EFM32_MSC_LOCK_OFFSET] */
0x01, 0x26, /* movs r6, #1 */
0x86, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET] */
@ -660,11 +705,9 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
/* exit: */
0x30, 0x46, /* mov r0, r6 */
0x00, 0xbe, /* bkpt #0 */
/* LOCKKEY */
0x71, 0x1b, 0x00, 0x00
};
/* flash write code */
if (target_alloc_working_area(target, sizeof(efm32x_flash_write_code),
&write_algorithm) != ERROR_OK) {
@ -697,7 +740,7 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
buf_set_u32(reg_params[0].value, 0, 32, EFM32_MSC_REGBASE);
buf_set_u32(reg_params[0].value, 0, 32, efm32x_info->reg_base);
buf_set_u32(reg_params[1].value, 0, 32, count);
buf_set_u32(reg_params[2].value, 0, 32, source->address);
buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
@ -762,16 +805,16 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
/* if not called, GDB errors will be reported during large writes */
keep_alive();
ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr);
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
if (ERROR_OK != ret)
return ret;
ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
if (ERROR_OK != ret)
return ret;
ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
if (ERROR_OK != ret)
return ret;
@ -792,13 +835,13 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
return ret;
}
ret = target_write_u32(bank->target, EFM32_MSC_WDATA, val);
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_WDATA, val);
if (ERROR_OK != ret) {
LOG_ERROR("WDATA write failed");
return ret;
}
ret = target_write_u32(bank->target, EFM32_MSC_WRITECMD,
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_WRITECMD,
EFM32_MSC_WRITECMD_WRITEONCE_MASK);
if (ERROR_OK != ret) {
LOG_ERROR("WRITECMD write failed");

View File

@ -1,7 +1,7 @@
/***************************************************************************
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
* Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
* *
* *
* 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 *
@ -18,7 +18,7 @@
/* The Freedom E SPI controller is a SPI bus controller
* specifically designed for SPI Flash Memories on Freedom E platforms.
*
*
* Two working modes are available:
* - SW mode: the SPI is controlled by SW. Any custom commands can be sent
* on the bus. Writes are only possible in this mode.
@ -127,7 +127,7 @@
int __a; \
uint32_t __v; \
\
__a = target_read_u32(target, ctrl_base + (a), &__v); \
__a = target_read_u32(target, ctrl_base + (a), &__v); \
if (__a != ERROR_OK) { \
LOG_ERROR("FESPI_READ_REG error"); \
return __a; \
@ -139,7 +139,7 @@
{ \
int __r; \
\
__r = target_write_u32(target, ctrl_base + (a), (v)); \
__r = target_write_u32(target, ctrl_base + (a), (v)); \
if (__r != ERROR_OK) { \
LOG_ERROR("FESPI_WRITE_REG error"); \
return __r; \
@ -163,7 +163,7 @@ struct fespi_target {
uint32_t ctrl_base;
};
//TODO !!! What is the right naming convention here?
/* TODO !!! What is the right naming convention here? */
static const struct fespi_target target_devices[] = {
/* name, tap_idcode, ctrl_base */
{ "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 },
@ -189,16 +189,17 @@ FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
fespi_info->probed = 0;
fespi_info->ctrl_base = 0;
if (CMD_ARGC >= 7) {
int temp;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp);
fespi_info->ctrl_base = (uint32_t) temp;
LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base);
int temp;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp);
fespi_info->ctrl_base = (uint32_t) temp;
LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base);
}
return ERROR_OK;
}
static int fespi_set_dir (struct flash_bank * bank, bool dir) {
static int fespi_set_dir(struct flash_bank *bank, bool dir)
{
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base;
@ -211,7 +212,8 @@ static int fespi_set_dir (struct flash_bank * bank, bool dir) {
}
static int fespi_txwm_wait(struct flash_bank *bank) {
static int fespi_txwm_wait(struct flash_bank *bank)
{
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base;
@ -219,9 +221,8 @@ static int fespi_txwm_wait(struct flash_bank *bank) {
int64_t start = timeval_ms();
while (1) {
if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM) {
if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM)
break;
}
int64_t now = timeval_ms();
if (now - start > 1000) {
LOG_ERROR("ip.txwm didn't get set.");
@ -233,7 +234,8 @@ static int fespi_txwm_wait(struct flash_bank *bank) {
}
static int fespi_tx(struct flash_bank *bank, uint8_t in){
static int fespi_tx(struct flash_bank *bank, uint8_t in)
{
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base;
@ -241,9 +243,8 @@ static int fespi_tx(struct flash_bank *bank, uint8_t in){
int64_t start = timeval_ms();
while (1) {
if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0) {
if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0)
break;
}
int64_t now = timeval_ms();
if (now - start > 1000) {
LOG_ERROR("txfifo stayed negative.");
@ -276,14 +277,14 @@ static int fespi_rx(struct flash_bank *bank, uint8_t *out)
}
}
if (out) {
if (out)
*out = value & 0xff;
}
return ERROR_OK;
}
//TODO!!! Why don't we need to call this after writing?
static int fespi_wip (struct flash_bank * bank, int timeout)
/* TODO!!! Why don't we need to call this after writing? */
static int fespi_wip(struct flash_bank *bank, int timeout)
{
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
@ -326,26 +327,34 @@ static int fespi_erase_sector(struct flash_bank *bank, int sector)
int retval;
retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
retval = fespi_tx(bank, fespi_info->dev->erase_cmd);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
sector = bank->sectors[sector].offset;
retval = fespi_tx(bank, sector >> 16);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
retval = fespi_tx(bank, sector >> 8);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
retval = fespi_tx(bank, sector);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK) {return retval;}
if (retval != ERROR_OK)
return retval;
FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
if (retval != ERROR_OK){return retval;}
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
@ -384,9 +393,9 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));
retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK){
LOG_ERROR("WM Didn't go high before attempting.");
return retval;
if (retval != ERROR_OK) {
LOG_ERROR("WM Didn't go high before attempting.");
return retval;
}
/* Disable Hardware accesses*/
@ -394,7 +403,7 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
/* poll WIP */
retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
if (retval != ERROR_OK)
if (retval != ERROR_OK)
return retval;
for (sector = first; sector <= last; sector++) {
@ -427,7 +436,7 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
uint32_t ctrl_base = fespi_info->ctrl_base;
uint32_t ii;
//TODO!!! assert that len < page size
/* TODO!!! assert that len < page size */
fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
fespi_txwm_wait(bank);
@ -440,9 +449,8 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
fespi_tx(bank, offset >> 8);
fespi_tx(bank, offset);
for (ii = 0; ii < len; ii++) {
for (ii = 0; ii < len; ii++)
fespi_tx(bank, buffer[ii]);
}
fespi_txwm_wait(bank);
@ -457,8 +465,9 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
* Here's the source for the algorithm.
* You can turn it into the array below using:
sed -n '/ALGO_START$/,/ALGO_END/ p' fespi.c | \
riscv32-unknown-elf-gcc -x assembler-with-cpp - -nostdlib -nostartfiles -o tmp.o && \
riscv32-unknown-elf-objcopy -O binary tmp.o algorithm.bin && \
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -x \
assembler-with-cpp - -nostdlib -nostartfiles -o tmp.o && \
riscv64-unknown-elf-objcopy -O binary tmp.o algorithm.bin && \
xxd -i algorithm.bin
// ALGO_START
@ -487,67 +496,67 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
.global _start
_start:
command_table:
j main // 0
ebreak // 4
j tx // 8
j txwm_wait // 12
j write_reg // 16
j main // 0
ebreak // 4
j tx // 8
j txwm_wait // 12
j write_reg // 16
j wip_wait // 20
j set_dir // 24
j set_dir // 24
// Execute the program.
main:
lbu t0, 0(a1)
addi a1, a1, 1
la t1, command_table
add t0, t0, t1
jr t0
lbu t0, 0(a1)
addi a1, a1, 1
la t1, command_table
add t0, t0, t1
jr t0
// Read 1 byte the contains the number of bytes to transmit. Then read those
// bytes from the program and transmit them one by one.
tx:
lbu t1, 0(a1) // read number of bytes to transmit
addi a1, a1, 1
lbu t1, 0(a1) // read number of bytes to transmit
addi a1, a1, 1
1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
bltz t0, 1b
lbu t0, 0(a1) // Load byte to write
sw t0, FESPI_REG_TXFIFO(a0)
addi a1, a1, 1
addi t1, t1, -1
bgtz t1, 1b
j main
bltz t0, 1b
lbu t0, 0(a1) // Load byte to write
sw t0, FESPI_REG_TXFIFO(a0)
addi a1, a1, 1
addi t1, t1, -1
bgtz t1, 1b
j main
// Wait until TXWM is set.
txwm_wait:
1: lw t0, FESPI_REG_IP(a0)
andi t0, t0, FESPI_IP_TXWM
beqz t0, 1b
j main
andi t0, t0, FESPI_IP_TXWM
beqz t0, 1b
j main
// Read 1 byte that contains the offset of the register to write, and 1 byte
// that contains the data to write.
write_reg:
lbu t0, 0(a1) // read register to write
add t0, t0, a0
lbu t1, 1(a1) // read value to write
addi a1, a1, 2
sw t1, 0(t0)
j main
lbu t0, 0(a1) // read register to write
add t0, t0, a0
lbu t1, 1(a1) // read value to write
addi a1, a1, 2
sw t1, 0(t0)
j main
wip_wait:
li a2, SPIFLASH_READ_STATUS
jal txrx_byte
jal txrx_byte
// discard first result
1: li a2, 0
jal txrx_byte
jal txrx_byte
andi t0, a2, SPIFLASH_BSY_BIT
bnez t0, 1b
j main
txrx_byte: // transmit the byte in a2, receive a bit into a2
lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
bltz t0, txrx_byte
sw a2, FESPI_REG_TXFIFO(a0)
bltz t0, txrx_byte
sw a2, FESPI_REG_TXFIFO(a0)
1: lw a2, FESPI_REG_RXFIFO(a0)
bltz a2, 1b
ret
@ -556,8 +565,8 @@ set_dir:
lw t0, FESPI_REG_FMT(a0)
li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
and t0, t0, t1
lbu t1, 0(a1) // read value to OR in
addi a1, a1, 1
lbu t1, 0(a1) // read value to OR in
addi a1, a1, 1
or t0, t0, t1
sw t0, FESPI_REG_FMT(a0)
j main
@ -565,24 +574,24 @@ set_dir:
// ALGO_END
*/
static const uint8_t algorithm_bin[] = {
0x6f, 0x00, 0xc0, 0x01, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0xc0, 0x02,
0x6f, 0x00, 0x00, 0x05, 0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x07,
0x6f, 0x00, 0x00, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x17, 0x03, 0x00, 0x00, 0x13, 0x03, 0xc3, 0xfd, 0xb3, 0x82, 0x62, 0x00,
0x67, 0x80, 0x02, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 0x02, 0xfe,
0x6f, 0xf0, 0x1f, 0xf8, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe,
0x23, 0x24, 0xc5, 0x04, 0x03, 0x26, 0xc5, 0x04, 0xe3, 0x4e, 0x06, 0xfe,
0x67, 0x80, 0x00, 0x00, 0x83, 0x22, 0x05, 0x04, 0x13, 0x03, 0x70, 0xff,
0xb3, 0xf2, 0x62, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0xb3, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
0x6f, 0x00, 0xc0, 0x01, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0xc0, 0x02,
0x6f, 0x00, 0x00, 0x05, 0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x07,
0x6f, 0x00, 0x00, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x17, 0x03, 0x00, 0x00, 0x13, 0x03, 0xc3, 0xfd, 0xb3, 0x82, 0x62, 0x00,
0x67, 0x80, 0x02, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 0x02, 0xfe,
0x6f, 0xf0, 0x1f, 0xf8, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe,
0x23, 0x24, 0xc5, 0x04, 0x03, 0x26, 0xc5, 0x04, 0xe3, 0x4e, 0x06, 0xfe,
0x67, 0x80, 0x00, 0x00, 0x83, 0x22, 0x05, 0x04, 0x13, 0x03, 0x70, 0xff,
0xb3, 0xf2, 0x62, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0xb3, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
};
#define STEP_EXIT 4
#define STEP_TX 8
@ -598,7 +607,7 @@ struct algorithm_steps {
uint8_t **steps;
};
struct algorithm_steps *as_new(unsigned size)
static struct algorithm_steps *as_new(unsigned size)
{
struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps));
as->size = size;
@ -606,7 +615,7 @@ struct algorithm_steps *as_new(unsigned size)
return as;
}
struct algorithm_steps *as_delete(struct algorithm_steps *as)
static struct algorithm_steps *as_delete(struct algorithm_steps *as)
{
for (unsigned step = 0; step < as->used; step++) {
free(as->steps[step]);
@ -616,7 +625,7 @@ struct algorithm_steps *as_delete(struct algorithm_steps *as)
return NULL;
}
int as_empty(struct algorithm_steps *as)
static int as_empty(struct algorithm_steps *as)
{
for (unsigned s = 0; s < as->used; s++) {
if (as->steps[s][0] != STEP_NOP)
@ -625,8 +634,8 @@ int as_empty(struct algorithm_steps *as)
return 1;
}
// Return size of compiled program.
unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
/* Return size of compiled program. */
static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
unsigned target_size)
{
unsigned offset = 0;
@ -684,16 +693,15 @@ unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
LOG_DEBUG("%d-byte program:", offset);
for (unsigned i = 0; i < offset;) {
char buf[80];
for (unsigned x = 0; i < offset && x < 16; x++, i++) {
for (unsigned x = 0; i < offset && x < 16; x++, i++)
sprintf(buf + x*3, "%02x ", target[i]);
}
LOG_DEBUG("%s", buf);
}
return offset;
}
void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
static void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
{
LOG_DEBUG("count=%d", count);
while (count > 0) {
@ -709,14 +717,14 @@ void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
}
}
void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
static void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
{
uint8_t data[1];
data[0] = byte;
as_add_tx(as, 1, data);
}
void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
static void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
{
assert(as->used < as->size);
as->steps[as->used] = malloc(3);
@ -726,7 +734,7 @@ void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
as->used++;
}
void as_add_txwm_wait(struct algorithm_steps *as)
static void as_add_txwm_wait(struct algorithm_steps *as)
{
assert(as->used < as->size);
as->steps[as->used] = malloc(1);
@ -734,7 +742,7 @@ void as_add_txwm_wait(struct algorithm_steps *as)
as->used++;
}
void as_add_wip_wait(struct algorithm_steps *as)
static void as_add_wip_wait(struct algorithm_steps *as)
{
assert(as->used < as->size);
as->steps[as->used] = malloc(1);
@ -742,7 +750,7 @@ void as_add_wip_wait(struct algorithm_steps *as)
as->used++;
}
void as_add_set_dir(struct algorithm_steps *as, bool dir)
static void as_add_set_dir(struct algorithm_steps *as, bool dir)
{
assert(as->used < as->size);
as->steps[as->used] = malloc(2);
@ -771,7 +779,7 @@ static int steps_add_buffer_write(struct algorithm_steps *as,
as_add_txwm_wait(as);
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
// fespi_wip()
/* fespi_wip() */
as_add_set_dir(as, FESPI_DIR_RX);
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
as_add_wip_wait(as);
@ -788,19 +796,20 @@ static int steps_execute(struct algorithm_steps *as,
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base;
uint8_t *data_buf = malloc(data_wa->size);
int xlen = riscv_xlen(target);
struct reg_param reg_params[2];
init_reg_param(&reg_params[0], "x10", xlen, PARAM_OUT);
init_reg_param(&reg_params[1], "x11", xlen, PARAM_OUT);
init_reg_param(&reg_params[0], "a0", xlen, PARAM_OUT);
init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
buf_set_u64(reg_params[0].value, 0, xlen, ctrl_base);
buf_set_u64(reg_params[1].value, 0, xlen, data_wa->address);
while (!as_empty(as)) {
keep_alive();
uint8_t *data_buf = malloc(data_wa->size);
unsigned bytes = as_compile(as, data_buf, data_wa->size);
int retval = target_write_buffer(target, data_wa->address, bytes,
data_buf);
free(data_buf);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to write data to 0x%" TARGET_PRIxADDR ": %d",
data_wa->address, retval);
@ -908,11 +917,10 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
cur_count = 4 - (offset & 3);
if (cur_count > count)
cur_count = count;
if (algorithm_wa) {
if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, cur_count);
} else {
else
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
}
if (retval != ERROR_OK)
goto err;
offset += cur_count;
@ -929,11 +937,10 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
else
cur_count = count & ~3;
if (algorithm_wa) {
if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, cur_count);
} else {
else
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
}
if (retval != ERROR_OK)
goto err;
@ -945,18 +952,16 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
/* buffer tail */
if (count > 0) {
if (algorithm_wa) {
if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, count);
} else {
else
retval = slow_fespi_write_buffer(bank, buffer, offset, count);
}
if (retval != ERROR_OK)
goto err;
}
if (algorithm_wa) {
if (algorithm_wa)
retval = steps_execute(as, bank, algorithm_wa, data_wa);
}
err:
if (algorithm_wa) {
@ -964,6 +969,8 @@ err:
target_free_working_area(target, algorithm_wa);
}
as_delete(as);
/* Switch to HW mode before return to prompt */
FESPI_ENABLE_HW_MODE();
return retval;
@ -1041,27 +1048,27 @@ static int fespi_probe(struct flash_bank *bank)
fespi_info->probed = 0;
if (fespi_info->ctrl_base == 0) {
for (target_device = target_devices ; target_device->name ; ++target_device)
if (target_device->tap_idcode == target->tap->idcode)
break;
for (target_device = target_devices ; target_device->name ; ++target_device)
if (target_device->tap_idcode == target->tap->idcode)
break;
if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
target->tap->idcode);
return ERROR_FAIL;
}
if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
target->tap->idcode);
return ERROR_FAIL;
}
fespi_info->ctrl_base = target_device->ctrl_base;
fespi_info->ctrl_base = target_device->ctrl_base;
LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32,
target_device->name, bank->base);
LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32,
target_device->name, bank->base);
} else {
LOG_DEBUG("Assuming FESPI as specified at address 0x%x with ctrl at 0x%x",
fespi_info->ctrl_base,
bank->base);
}
ctrl_base = fespi_info->ctrl_base;
ctrl_base = fespi_info->ctrl_base;
/* read and decode flash ID; returns in SW mode */
FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));

View File

@ -1959,7 +1959,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
unsigned cpu_mhz = 120;
unsigned idx;
bool use_nvm_marking = false;
char flash_marking[8], nvm_marking[2];
char flash_marking[11], nvm_marking[2];
char name[40];
k_chip->probed = false;
@ -2126,6 +2126,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX1: /* errata 7534 - should be K63 */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX2: /* errata 7534 - should be K64 */
subfamid += 2; /* errata 7534 fix */
/* fallthrough */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX3:
/* K63FN1M0 */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX4:

File diff suppressed because it is too large Load Diff

View File

@ -31,53 +31,56 @@
* from device datasheets and Linux SPI flash drivers. */
const struct flash_device flash_devices[] = {
/* name, erase_cmd, chip_erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
FLASH_ID("st m25p10", 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
FLASH_ID("st m25p20", 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25p40", 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m25p80", 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
FLASH_ID("st m25p16", 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
FLASH_ID("st m25p32", 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
FLASH_ID("st m25p64", 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
FLASH_ID("st m25p128", 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
FLASH_ID("st m45pe10", 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m45pe20", 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m45pe40", 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m45pe80", 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl116k", 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl132k", 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
FLASH_ID("mac 25l1005", 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25lp128", 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q64cv", 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
FLASH_ID("win w25q128fv", 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
FLASH_ID("gd gd25q20", 0x20, 0xc7, 0x00c84012, 0x100, 0x1000, 0x80000),
FLASH_ID("gd gd25q16c", 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
FLASH_ID("gd gd25q32c", 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
FLASH_ID("gd gd25q128c", 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
FLASH_ID(NULL, 0, 0, 0, 0, 0, 0)
FLASH_ID("st m25p05", 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
FLASH_ID("st m25p10", 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
FLASH_ID("st m25p20", 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25p40", 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m25p80", 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
FLASH_ID("st m25p16", 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
FLASH_ID("st m25p32", 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
FLASH_ID("st m25p64", 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
FLASH_ID("st m25p128", 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
FLASH_ID("st m45pe10", 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m45pe20", 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m45pe40", 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m45pe80", 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl116k", 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl132k", 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
FLASH_ID("mac 25l1005", 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
FLASH_ID("micron n25q256 3v", 0xd8, 0xc7, 0x0019ba20, 0x100, 0x10000, 0x2000000),
FLASH_ID("micron n25q256 1.8v", 0xd8, 0xc7, 0x0019bb20, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25lp128", 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25wp256d", 0xd8, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q64cv", 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
FLASH_ID("win w25q128fv", 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
FLASH_ID("gd gd25q20", 0x20, 0xc7, 0x00c84012, 0x100, 0x1000, 0x80000),
FLASH_ID("gd gd25q16c", 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
FLASH_ID("gd gd25q32c", 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
FLASH_ID("gd gd25q128c", 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
FLASH_ID(NULL, 0, 0, 0, 0, 0, 0)
};

View File

@ -143,9 +143,8 @@
#define FLASH_PSIZE_16 (1 << 8)
#define FLASH_PSIZE_32 (2 << 8)
#define FLASH_PSIZE_64 (3 << 8)
/* The sector number encoding is not straight binary for dual bank flash.
* Warning: evaluates the argument multiple times */
#define FLASH_SNB(a) ((((a) >= 12) ? 0x10 | ((a) - 12) : (a)) << 3)
/* The sector number encoding is not straight binary for dual bank flash. */
#define FLASH_SNB(a) ((a) << 3)
#define FLASH_LOCK (1 << 31)
/* FLASH_SR register bits */
@ -489,6 +488,7 @@ static int stm32x_protect_check(struct flash_bank *bank)
static int stm32x_erase(struct flash_bank *bank, int first, int last)
{
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
struct target *target = bank->target;
int i;
@ -516,8 +516,14 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
*/
for (i = first; i <= last; i++) {
int snb;
if (stm32x_info->has_large_mem && i >= 12)
snb = (i - 12) | 0x10;
else
snb = i;
retval = target_write_u32(target,
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(snb) | FLASH_STRT);
if (retval != ERROR_OK)
return retval;
@ -1047,7 +1053,8 @@ static int stm32x_probe(struct flash_bank *bank)
if (device_id == 0x451) {
for (i = 0; i < num_prot_blocks; i++) {
bank->prot_blocks[i].offset = bank->sectors[i << 1].offset;
bank->prot_blocks[i].size = bank->sectors[i << 1].size << 1;
bank->prot_blocks[i].size = bank->sectors[i << 1].size
+ bank->sectors[(i << 1) + 1].size;
}
}
} else {

1183
src/flash/nor/stm32h7x.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -726,16 +726,13 @@ reset_pg_and_lock:
static int stm32lx_read_id_code(struct target *target, uint32_t *id)
{
/* read stm32 device id register */
int retval = target_read_u32(target, DBGMCU_IDCODE, id);
if (retval != ERROR_OK)
return retval;
/* STM32L0 parts will have 0 there, try reading the L0's location for
* DBG_IDCODE in case this is an L0 part. */
if (*id == 0)
struct armv7m_common *armv7m = target_to_armv7m(target);
int retval;
if (armv7m->arm.is_armv6m == true)
retval = target_read_u32(target, DBGMCU_IDCODE_L0, id);
else
/* read stm32 device id register */
retval = target_read_u32(target, DBGMCU_IDCODE, id);
return retval;
}

View File

@ -931,13 +931,13 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
/* If OTP Write protection is enabled (User 2), list each
* sector that has it enabled */
char otp_str[8];
char otp_str[14];
if (otp_enabled) {
strcat(prot_str, "\nOTP Protection is enabled for sectors:\n");
for (int i = 0; i < bank->num_sectors; i++) {
if (fb->write_prot_otp[i]) {
snprintf(otp_str, sizeof(otp_str), "- %d\n", i);
strncat(prot_str, otp_str, ARRAY_SIZE(otp_str));
strncat(prot_str, otp_str, sizeof(prot_str) - strlen(prot_str) - 1);
}
}
}

View File

@ -1456,8 +1456,8 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
return ERROR_COMMAND_SYNTAX_ERROR;
}
/* fall through */
}
/* fallthrough */
case 0:
LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
break;

View File

@ -37,6 +37,9 @@
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#if IS_WIN32 && !IS_CYGWIN
#include <windows.h>
#endif
static int help_flag, version_flag;

View File

@ -199,6 +199,17 @@ static inline int close_socket(int sock)
#endif
}
static inline void socket_block(int fd)
{
#ifdef _WIN32
unsigned long nonblock = 0;
ioctlsocket(fd, FIONBIO, &nonblock);
#else
int oldopts = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, oldopts & ~O_NONBLOCK);
#endif
}
static inline void socket_nonblock(int fd)
{
#ifdef _WIN32

View File

@ -838,108 +838,57 @@ int default_interface_jtag_execute_queue(void)
int result = jtag->execute_queue();
#if 0
// TODO: I like these better than some of the other JTAG debug statements,
// but having both is silly.
struct jtag_command *cmd = jtag_command_queue;
while (debug_level >= LOG_LVL_DEBUG && cmd) {
switch (cmd->type) {
case JTAG_SCAN:
#if 0
LOG_DEBUG("JTAG %s SCAN to %s",
DEBUG_JTAG_IO("JTAG %s SCAN to %s",
cmd->cmd.scan->ir_scan ? "IR" : "DR",
tap_state_name(cmd->cmd.scan->end_state));
for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
struct scan_field *field = cmd->cmd.scan->fields + i;
if (field->out_value) {
char *str = buf_to_str(field->out_value, field->num_bits, 16);
LOG_DEBUG(" %db out: %s", field->num_bits, str);
DEBUG_JTAG_IO(" %db out: %s", field->num_bits, str);
free(str);
}
if (field->in_value) {
char *str = buf_to_str(field->in_value, field->num_bits, 16);
LOG_DEBUG(" %db in: %s", field->num_bits, str);
DEBUG_JTAG_IO(" %db in: %s", field->num_bits, str);
free(str);
}
if (field->check_value) {
char *str = buf_to_str(field->check_value, field->num_bits, 16);
LOG_DEBUG(" %db check: %s", field->num_bits, str);
free(str);
}
if (field->check_mask) {
char *str = buf_to_str(field->check_mask, field->num_bits, 16);
LOG_DEBUG(" %db mask: %s", field->num_bits, str);
free(str);
}
}
#endif
{
uint8_t *buf = NULL;
int scan_bits = jtag_build_buffer(cmd->cmd.scan, &buf);
char *str_out = buf_to_str(buf, scan_bits, 16);
free(buf);
LOG_DEBUG("vvv jtag_scan(%d, %d, %d'h%s, %d); // %s",
cmd->cmd.scan->ir_scan,
scan_bits,
scan_bits, str_out,
cmd->cmd.scan->end_state, tap_state_name(cmd->cmd.scan->end_state));
free(str_out);
struct scan_field *last_field = cmd->cmd.scan->fields + cmd->cmd.scan->num_fields - 1;
if (last_field->in_value) {
char *str_in = buf_to_str(last_field->in_value, last_field->num_bits, 16);
LOG_DEBUG("vvv jtag_check_tdo(%d, %d'h%s);",
last_field->num_bits,
last_field->num_bits, str_in);
free(str_in);
}
}
break;
case JTAG_TLR_RESET:
#if 0
LOG_DEBUG("JTAG TLR RESET to %s",
tap_state_name(cmd->cmd.statemove->end_state));
#endif
LOG_DEBUG("vvv jtag_tlr_reset(%d); // %s",
cmd->cmd.statemove->end_state,
DEBUG_JTAG_IO("JTAG TLR RESET to %s",
tap_state_name(cmd->cmd.statemove->end_state));
break;
case JTAG_RUNTEST:
#if 0
LOG_DEBUG("JTAG RUNTEST %d cycles to %s",
DEBUG_JTAG_IO("JTAG RUNTEST %d cycles to %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
#endif
LOG_DEBUG("vvv jtag_runtest(%d, %d); // %s",
cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state,
tap_state_name(cmd->cmd.runtest->end_state));
break;
case JTAG_RESET:
{
#if 0
const char *reset_str[3] = {
"leave", "deassert", "assert"
};
LOG_DEBUG("JTAG RESET %s TRST, %s SRST",
DEBUG_JTAG_IO("JTAG RESET %s TRST, %s SRST",
reset_str[cmd->cmd.reset->trst + 1],
reset_str[cmd->cmd.reset->srst + 1]);
#endif
LOG_DEBUG("vvv jtag_reset(%d, %d);",
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
}
break;
case JTAG_PATHMOVE:
LOG_DEBUG("JTAG PATHMOVE (TODO)");
DEBUG_JTAG_IO("JTAG PATHMOVE (TODO)");
break;
case JTAG_SLEEP:
LOG_DEBUG("JTAG SLEEP (TODO)");
DEBUG_JTAG_IO("JTAG SLEEP (TODO)");
break;
case JTAG_STABLECLOCKS:
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
DEBUG_JTAG_IO("JTAG STABLECLOCKS (TODO)");
break;
case JTAG_TMS:
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
DEBUG_JTAG_IO("JTAG STABLECLOCKS (TODO)");
break;
default:
LOG_ERROR("Unknown JTAG command: %d", cmd->type);
@ -947,7 +896,6 @@ int default_interface_jtag_execute_queue(void)
}
cmd = cmd->next;
}
#endif
return result;
}

View File

@ -958,11 +958,14 @@ static int cmsis_dap_init(void)
retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0);
if (retval != ERROR_OK)
return ERROR_FAIL;
/* Data Phase (bit 2) must be set to 1 if sticky overrun
* detection is enabled */
retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */
if (retval != ERROR_OK)
return ERROR_FAIL;
if (swd_mode) {
/* Data Phase (bit 2) must be set to 1 if sticky overrun
* detection is enabled */
retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */
if (retval != ERROR_OK)
return ERROR_FAIL;
}
retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */
if (retval != ERROR_OK)

View File

@ -855,6 +855,7 @@ COMMAND_HANDLER(ftdi_handle_set_signal_command)
ftdi_set_signal(sig, *CMD_ARGV[1]);
break;
}
/* fallthrough */
default:
LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV[1]);
return ERROR_COMMAND_SYNTAX_ERROR;
@ -1217,14 +1218,17 @@ static int ftdi_swd_switch_seq(enum swd_special_seq seq)
switch (seq) {
case LINE_RESET:
LOG_DEBUG("SWD line reset");
ftdi_swd_swdio_en(true);
mpsse_clock_data_out(mpsse_ctx, swd_seq_line_reset, 0, swd_seq_line_reset_len, SWD_MODE);
break;
case JTAG_TO_SWD:
LOG_DEBUG("JTAG-to-SWD");
ftdi_swd_swdio_en(true);
mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len, SWD_MODE);
break;
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
ftdi_swd_swdio_en(true);
mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len, SWD_MODE);
break;
default:

View File

@ -322,7 +322,7 @@ static int jlink_speed(int speed)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_speeds() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_JTAG_DEVICE_ERROR;
}
@ -349,7 +349,7 @@ static int jlink_speed(int speed)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_set_speed() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_JTAG_DEVICE_ERROR;
}
@ -378,7 +378,7 @@ static bool read_device_config(struct device_config *cfg)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_read_raw_config() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return false;
}
@ -409,7 +409,7 @@ static int select_interface(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_available_interfaces() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_JTAG_INIT_FAILED;
}
@ -422,7 +422,7 @@ static int select_interface(void)
if (ret < 0) {
LOG_ERROR("jaylink_select_interface() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_JTAG_INIT_FAILED;
}
@ -442,8 +442,7 @@ static int jlink_register(void)
ret = jaylink_register(devh, &conn, connlist, &count);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_register() failed: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("jaylink_register() failed: %s.", jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -482,7 +481,7 @@ static bool adjust_swd_buffer_size(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_free_memory() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return false;
}
@ -523,6 +522,9 @@ static int jaylink_log_handler(const struct jaylink_context *ctx,
case JAYLINK_LOG_LEVEL_DEBUG:
tmp = LOG_LVL_DEBUG;
break;
case JAYLINK_LOG_LEVEL_DEBUG_IO:
tmp = LOG_LVL_DEBUG_IO;
break;
default:
tmp = LOG_LVL_WARNING;
}
@ -544,15 +546,21 @@ static int jlink_init(void)
struct jaylink_hardware_status hwstatus;
enum jaylink_usb_address address;
size_t length;
size_t num_devices;
uint32_t host_interfaces;
LOG_DEBUG("Using libjaylink %s (compiled with %s).",
jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING);
if (!jaylink_library_has_cap(JAYLINK_CAP_HIF_USB) && use_usb_address) {
LOG_ERROR("J-Link driver does not support USB devices.");
return ERROR_JTAG_INIT_FAILED;
}
ret = jaylink_init(&jayctx);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_init() failed: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("jaylink_init() failed: %s.", jaylink_strerror(ret));
return ERROR_JTAG_INIT_FAILED;
}
@ -560,34 +568,42 @@ static int jlink_init(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_log_set_callback() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
ret = jaylink_discovery_scan(jayctx, 0);
host_interfaces = JAYLINK_HIF_USB;
if (use_serial_number)
host_interfaces |= JAYLINK_HIF_TCP;
ret = jaylink_discovery_scan(jayctx, host_interfaces);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_discovery_scan() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
ret = jaylink_get_devices(jayctx, &devs, NULL);
ret = jaylink_get_devices(jayctx, &devs, &num_devices);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_devices() failed: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror(ret));
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
if (!use_serial_number && !use_usb_address && num_devices > 1) {
LOG_ERROR("Multiple devices found, specify the desired device.");
jaylink_free_devices(devs, true);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
found_device = false;
if (!use_serial_number && !use_usb_address)
LOG_INFO("No device selected, using first device.");
for (i = 0; devs[i]; i++) {
if (use_serial_number) {
ret = jaylink_device_get_serial_number(devs[i], &tmp);
@ -596,7 +612,7 @@ static int jlink_init(void)
continue;
} else if (ret != JAYLINK_OK) {
LOG_WARNING("jaylink_device_get_serial_number() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
continue;
}
@ -607,9 +623,11 @@ static int jlink_init(void)
if (use_usb_address) {
ret = jaylink_device_get_usb_address(devs[i], &address);
if (ret != JAYLINK_OK) {
if (ret == JAYLINK_ERR_NOT_SUPPORTED) {
continue;
} else if (ret != JAYLINK_OK) {
LOG_WARNING("jaylink_device_get_usb_address() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
continue;
}
@ -624,7 +642,7 @@ static int jlink_init(void)
break;
}
LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
LOG_ERROR("Failed to open device: %s.", jaylink_strerror(ret));
}
jaylink_free_devices(devs, true);
@ -644,7 +662,7 @@ static int jlink_init(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_firmware_version() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_close(devh);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@ -659,7 +677,7 @@ static int jlink_init(void)
ret = jaylink_get_caps(devh, caps);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror_name(ret));
LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror(ret));
jaylink_close(devh);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@ -670,7 +688,7 @@ static int jlink_init(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_extended_caps() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_close(devh);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@ -684,7 +702,7 @@ static int jlink_init(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("Failed to retrieve hardware version: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_close(devh);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@ -725,7 +743,7 @@ static int jlink_init(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_hardware_status() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
jaylink_close(devh);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@ -786,8 +804,7 @@ static int jlink_quit(void)
ret = jaylink_swo_stop(devh);
if (ret != JAYLINK_OK)
LOG_ERROR("jaylink_swo_stop() failed: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror(ret));
}
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) {
@ -795,7 +812,7 @@ static int jlink_quit(void)
if (ret != JAYLINK_OK)
LOG_ERROR("jaylink_unregister() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
}
jaylink_close(devh);
@ -944,7 +961,7 @@ COMMAND_HANDLER(jlink_serial_command)
return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -963,7 +980,7 @@ COMMAND_HANDLER(jlink_handle_hwstatus_command)
if (ret != JAYLINK_OK) {
command_print(CMD_CTX, "jaylink_get_hardware_status() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -995,7 +1012,7 @@ COMMAND_HANDLER(jlink_handle_free_memory_command)
if (ret != JAYLINK_OK) {
command_print(CMD_CTX, "jaylink_get_free_memory() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1077,7 +1094,7 @@ COMMAND_HANDLER(jlink_handle_target_power_command)
if (ret != JAYLINK_OK) {
command_print(CMD_CTX, "jaylink_set_target_power() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1183,7 +1200,7 @@ static int poll_trace(uint8_t *buf, size_t *size)
ret = jaylink_swo_read(devh, buf, &length);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_swo_read() failed: %s.", jaylink_strerror_name(ret));
LOG_ERROR("jaylink_swo_read() failed: %s.", jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1204,7 +1221,7 @@ static uint32_t calculate_trace_buffer_size(void)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_free_memory() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1268,7 +1285,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
ret = jaylink_swo_stop(devh);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror_name(ret));
LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1294,7 +1311,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_swo_get_speeds() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1310,8 +1327,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
buffer_size);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_start_swo() failed: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("jaylink_start_swo() failed: %s.", jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1570,7 +1586,7 @@ COMMAND_HANDLER(jlink_handle_config_write_command)
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_write_raw_config() failed: %s.",
jaylink_strerror_name(ret));
jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1655,8 +1671,7 @@ COMMAND_HANDLER(jlink_handle_emucom_write_command)
LOG_ERROR("Channel not supported by the device.");
return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
LOG_ERROR("Failed to write to channel: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("Failed to write to channel: %s.", jaylink_strerror(ret));
return ERROR_FAIL;
}
@ -1704,8 +1719,7 @@ COMMAND_HANDLER(jlink_handle_emucom_read_command)
free(buf);
return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
LOG_ERROR("Failed to read from channel: %s.",
jaylink_strerror_name(ret));
LOG_ERROR("Failed to read from channel: %s.", jaylink_strerror(ret));
free(buf);
return ERROR_FAIL;
}
@ -1972,7 +1986,7 @@ static int jlink_flush(void)
tap_length, jtag_command_version);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror_name(ret));
LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror(ret));
jlink_tap_init();
return ERROR_JTAG_QUEUE_FAILED;
}
@ -2078,7 +2092,7 @@ static int jlink_swd_run_queue(void)
ret = jaylink_swd_io(devh, tms_buffer, tdi_buffer, tdo_buffer, tap_length);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_swd_io() failed: %s.", jaylink_strerror_name(ret));
LOG_ERROR("jaylink_swd_io() failed: %s.", jaylink_strerror(ret));
goto skip;
}

View File

@ -657,6 +657,7 @@ static int kitprog_swd_switch_seq(enum swd_special_seq seq)
LOG_DEBUG("JTAG to SWD not supported");
/* Fall through to fix target reset issue */
}
/* fallthrough */
case LINE_RESET:
LOG_DEBUG("SWD line reset");
if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)

View File

@ -59,7 +59,7 @@ static int remote_bitbang_buf_full(void)
/* Read any incoming data, placing it into the buffer. */
static void remote_bitbang_fill_buf(void)
{
fcntl(remote_bitbang_fd, F_SETFL, O_NONBLOCK);
socket_nonblock(remote_bitbang_fd);
while (!remote_bitbang_buf_full()) {
unsigned contiguous_available_space;
if (remote_bitbang_end >= remote_bitbang_start) {
@ -76,10 +76,8 @@ static void remote_bitbang_fill_buf(void)
contiguous_available_space);
if (count > 0) {
remote_bitbang_end += count;
// TODO: check for overflow.
if (remote_bitbang_end == sizeof(remote_bitbang_buf)) {
if (remote_bitbang_end == sizeof(remote_bitbang_buf))
remote_bitbang_end = 0;
}
} else if (count == 0) {
return;
} else if (count < 0) {
@ -148,7 +146,7 @@ static int remote_bitbang_rread(void)
}
/* Enable blocking access. */
fcntl(remote_bitbang_fd, F_SETFL, 0);
socket_block(remote_bitbang_fd);
char c;
ssize_t count = read(remote_bitbang_fd, &c, 1);
if (count == 1) {
@ -171,7 +169,7 @@ static int remote_bitbang_read_sample(void)
{
if (remote_bitbang_start != remote_bitbang_end) {
int c = remote_bitbang_buf[remote_bitbang_start];
remote_bitbang_start =
remote_bitbang_start =
(remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
return char_to_int(c);
}

View File

@ -1650,13 +1650,11 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
h->transport = param->transport;
const uint16_t vids[] = { param->vid, 0 };
const uint16_t pids[] = { param->pid, 0 };
const char *serial = param->serial;
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
param->transport, param->vid, param->pid,
param->serial ? param->serial : "");
for (unsigned i = 0; param->vid[i]; i++) {
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
param->transport, param->vid[i], param->pid[i],
param->serial ? param->serial : "");
}
/*
On certain host USB configurations(e.g. MacBook Air)
@ -1668,7 +1666,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
in order to become operational.
*/
do {
if (jtag_libusb_open(vids, pids, serial, &h->fd) != ERROR_OK) {
if (jtag_libusb_open(param->vid, param->pid, param->serial, &h->fd) != ERROR_OK) {
LOG_ERROR("open failed");
goto error_open;
}
@ -1683,8 +1681,14 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
/* RX EP is common for all versions */
h->rx_ep = STLINK_RX_EP;
uint16_t pid;
if (jtag_libusb_get_pid(jtag_libusb_get_device(h->fd), &pid) != ERROR_OK) {
LOG_DEBUG("libusb_get_pid failed");
goto error_open;
}
/* wrap version for first read */
switch (param->pid) {
switch (pid) {
case STLINK_V1_PID:
h->version.stlink = 1;
h->tx_ep = STLINK_TX_EP;
@ -1736,12 +1740,6 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
}
} while (1);
/* compare usb vid/pid */
if ((param->vid != h->vid) || (param->pid != h->pid))
LOG_INFO("vid/pid are not identical: 0x%04X/0x%04X 0x%04X/0x%04X",
param->vid, param->pid,
h->vid, h->pid);
/* check if mode is supported */
err = ERROR_OK;

View File

@ -688,14 +688,18 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
}
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
param->vid, param->pid);
param->vid[0], param->pid[0]);
/* TODO: convert libusb_ calls to jtag_libusb_ */
if (param->vid[1])
LOG_WARNING("Bad configuration: 'hla_vid_pid' command does not accept more than one VID PID pair on ti-icdi!");
if (libusb_init(&h->usb_ctx) != 0) {
LOG_ERROR("libusb init failed");
goto error_open;
}
h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid, param->pid);
h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid[0], param->pid[0]);
if (!h->usb_dev) {
LOG_ERROR("open failed");
goto error_open;

View File

@ -35,7 +35,7 @@
#include <target/target.h>
static struct hl_interface_s hl_if = { {0, 0, 0, 0, 0, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
static struct hl_interface_s hl_if = { {0, 0, { 0 }, { 0 }, 0, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
int hl_interface_open(enum hl_transports tr)
{
@ -264,15 +264,27 @@ COMMAND_HANDLER(hl_interface_handle_layout_command)
COMMAND_HANDLER(hl_interface_handle_vid_pid_command)
{
LOG_DEBUG("hl_interface_handle_vid_pid_command");
if (CMD_ARGC != 2) {
LOG_WARNING("ignoring extra IDs in hl_vid_pid (maximum is 1 pair)");
if (CMD_ARGC > HLA_MAX_USB_IDS * 2) {
LOG_WARNING("ignoring extra IDs in hla_vid_pid "
"(maximum is %d pairs)", HLA_MAX_USB_IDS);
CMD_ARGC = HLA_MAX_USB_IDS * 2;
}
if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
LOG_WARNING("incomplete hla_vid_pid configuration directive");
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], hl_if.param.vid);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], hl_if.param.pid);
unsigned i;
for (i = 0; i < CMD_ARGC; i += 2) {
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], hl_if.param.vid[i / 2]);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], hl_if.param.pid[i / 2]);
}
/*
* Explicitly terminate, in case there are multiple instances of
* hla_vid_pid.
*/
hl_if.param.vid[i / 2] = hl_if.param.pid[i / 2] = 0;
return ERROR_OK;
}

View File

@ -29,15 +29,17 @@ enum e_hl_transports;
/** */
extern const char *hl_transports[];
#define HLA_MAX_USB_IDS 8
struct hl_interface_param_s {
/** */
const char *device_desc;
/** */
const char *serial;
/** */
uint16_t vid;
/** */
uint16_t pid;
/** List of recognised VIDs */
uint16_t vid[HLA_MAX_USB_IDS + 1];
/** List of recognised PIDs */
uint16_t pid[HLA_MAX_USB_IDS + 1];
/** */
unsigned api;
/** */

View File

@ -103,7 +103,7 @@ static struct ChibiOS_params ChibiOS_params_list[] = {
};
#define CHIBIOS_NUM_PARAMS ((int)(sizeof(ChibiOS_params_list)/sizeof(struct ChibiOS_params)))
static int ChibiOS_detect_rtos(struct target *target);
static bool ChibiOS_detect_rtos(struct target *target);
static int ChibiOS_create(struct target *target);
static int ChibiOS_update_threads(struct rtos *rtos);
static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
@ -510,7 +510,7 @@ static int ChibiOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
return 0;
}
static int ChibiOS_detect_rtos(struct target *target)
static bool ChibiOS_detect_rtos(struct target *target)
{
if ((target->rtos->symbols != NULL) &&
((target->rtos->symbols[ChibiOS_VAL_rlist].address != 0) ||
@ -519,14 +519,14 @@ static int ChibiOS_detect_rtos(struct target *target)
if (target->rtos->symbols[ChibiOS_VAL_ch_debug].address == 0) {
LOG_INFO("It looks like the target may be running ChibiOS "
"without ch_debug.");
return 0;
return false;
}
/* looks like ChibiOS with memory map enabled.*/
return 1;
return true;
}
return 0;
return false;
}
static int ChibiOS_create(struct target *target)

View File

@ -99,7 +99,7 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = {
#define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
static int FreeRTOS_detect_rtos(struct target *target);
static bool FreeRTOS_detect_rtos(struct target *target);
static int FreeRTOS_create(struct target *target);
static int FreeRTOS_update_threads(struct rtos *rtos);
static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
@ -528,14 +528,14 @@ static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_i
#endif
static int FreeRTOS_detect_rtos(struct target *target)
static bool FreeRTOS_detect_rtos(struct target *target)
{
if ((target->rtos->symbols != NULL) &&
(target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
/* looks like FreeRTOS */
return 1;
return true;
}
return 0;
return false;
}
static int FreeRTOS_create(struct target *target)

View File

@ -35,7 +35,7 @@ static const struct rtos_register_stacking *get_stacking_info_arm926ejs(const st
static int is_thread_id_valid(const struct rtos *rtos, int64_t thread_id);
static int is_thread_id_valid_arm926ejs(const struct rtos *rtos, int64_t thread_id);
static int ThreadX_detect_rtos(struct target *target);
static bool ThreadX_detect_rtos(struct target *target);
static int ThreadX_create(struct target *target);
static int ThreadX_update_threads(struct rtos *rtos);
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
@ -492,14 +492,14 @@ static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
return 0;
}
static int ThreadX_detect_rtos(struct target *target)
static bool ThreadX_detect_rtos(struct target *target)
{
if ((target->rtos->symbols != NULL) &&
(target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) {
/* looks like ThreadX */
return 1;
return true;
}
return 0;
return false;
}
#if 0

View File

@ -27,7 +27,7 @@
#include "helper/types.h"
#include "rtos_ecos_stackings.h"
static int eCos_detect_rtos(struct target *target);
static bool eCos_detect_rtos(struct target *target);
static int eCos_create(struct target *target);
static int eCos_update_threads(struct rtos *rtos);
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
@ -363,14 +363,14 @@ static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
return 0;
}
static int eCos_detect_rtos(struct target *target)
static bool eCos_detect_rtos(struct target *target)
{
if ((target->rtos->symbols != NULL) &&
(target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
/* looks like eCos */
return 1;
return true;
}
return 0;
return false;
}
static int eCos_create(struct target *target)

View File

@ -31,7 +31,7 @@
#define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
static int embKernel_detect_rtos(struct target *target);
static bool embKernel_detect_rtos(struct target *target);
static int embKernel_create(struct target *target);
static int embKernel_update_threads(struct rtos *rtos);
static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
@ -107,13 +107,13 @@ static const struct embKernel_params embKernel_params_list[] = {
}
};
static int embKernel_detect_rtos(struct target *target)
static bool embKernel_detect_rtos(struct target *target)
{
if (target->rtos->symbols != NULL) {
if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0)
return 1;
return true;
}
return 0;
return false;
}
static int embKernel_create(struct target *target)

View File

@ -309,10 +309,10 @@ static int linux_os_thread_reg_list(struct rtos *rtos,
return ERROR_OK;
}
static int linux_os_detect(struct target *target)
static bool linux_os_detect(struct target *target)
{
LOG_INFO("should no be called");
return 0;
return false;
}
static int linux_os_smp_init(struct target *target);

View File

@ -244,9 +244,9 @@ static int mqx_is_scheduler_running(
}
/*
* API function, return 1 if MQX is present
* API function, return true if MQX is present
*/
static int mqx_detect_rtos(
static bool mqx_detect_rtos(
struct target *target
)
{
@ -254,9 +254,9 @@ static int mqx_detect_rtos(
(target->rtos->symbols != NULL) &&
(target->rtos->symbols[mqx_VAL_mqx_kernel_data].address != 0)
) {
return 1;
return true;
}
return 0;
return false;
}
/*

View File

@ -10,7 +10,7 @@
static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size);
static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size);
static int riscv_detect_rtos(struct target *target)
static bool riscv_detect_rtos(struct target *target)
{
LOG_ERROR("riscv_detect_rtos() unimplemented");
return -1;
@ -79,7 +79,7 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
if (strncmp(packet, "qfThreadInfo", 12) == 0) {
riscv_update_threads(target->rtos);
r->qs_thread_info_offset = 1;
char m[16];
snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid);
gdb_put_packet(connection, m, strlen(m));
@ -264,7 +264,7 @@ static int riscv_gdb_v_packet(struct connection *connection, const char *packet,
static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
{
LOG_DEBUG("Updating RISC-V regiser list for hart %d", (int)(thread_id - 1));
LOG_DEBUG("Updating RISC-V register list for hart %d", (int)(thread_id - 1));
#if 0
LOG_ERROR(" Not actually updating");
@ -279,18 +279,25 @@ static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char
ssize_t hex_reg_list_length = n_regs * reg_chars + 2;
*hex_reg_list = malloc(hex_reg_list_length);
*hex_reg_list[0] = '\0';
char *p = hex_reg_list[0];
for (size_t i = 0; i < n_regs; ++i) {
assert(p - hex_reg_list[0] > 3);
if (riscv_has_register(rtos->target, thread_id, i)) {
uint64_t reg_value = riscv_get_register_on_hart(rtos->target, thread_id - 1, i);
uint64_t reg_value;
int result = riscv_get_register_on_hart(rtos->target, &reg_value,
thread_id - 1, i);
if (result != ERROR_OK)
return JIM_ERR;
for (size_t byte = 0; byte < xlen / 8; ++byte) {
uint8_t reg_byte = reg_value >> (byte * 8);
char hex[3] = {'x', 'x', 'x'};
snprintf(hex, 3, "%02x", reg_byte);
strncat(*hex_reg_list, hex, hex_reg_list_length);
p += snprintf(p, 3, "%02x", reg_byte);
}
} else {
for (size_t byte = 0; byte < xlen / 8; ++byte)
strncat(*hex_reg_list, "xx", hex_reg_list_length);
for (size_t byte = 0; byte < xlen / 8; ++byte) {
strcpy(p, "xx");
p += 2;
}
}
}
LOG_DEBUG("%s", *hex_reg_list);
@ -305,8 +312,7 @@ static int riscv_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
return JIM_OK;
}
const struct rtos_type riscv_rtos =
{
const struct rtos_type riscv_rtos = {
.name = "riscv",
.detect_rtos = riscv_detect_rtos,
.create = riscv_create_rtos,

View File

@ -60,7 +60,7 @@ struct rtos {
struct rtos_type {
const char *name;
int (*detect_rtos)(struct target *target);
bool (*detect_rtos)(struct target *target);
int (*create)(struct target *target);
int (*smp_init)(struct target *target);
int (*update_threads)(struct rtos *rtos);

View File

@ -241,7 +241,7 @@ static int uCOS_III_update_thread_offsets(struct rtos *rtos)
return ERROR_OK;
}
static int uCOS_III_detect_rtos(struct target *target)
static bool uCOS_III_detect_rtos(struct target *target)
{
return target->rtos->symbols != NULL &&
target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0;

View File

@ -71,8 +71,8 @@ struct gdb_connection {
int ctrl_c;
enum target_state frontend_state;
struct image *vflash_image;
int closed;
int busy;
bool closed;
bool busy;
int noack_mode;
/* set flag to true if you want the next stepi to return immediately.
* allowing GDB to pick up a fresh set of register values from the target
@ -215,7 +215,7 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char)
if (gdb_con->buf_cnt > 0)
break;
if (gdb_con->buf_cnt == 0) {
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
@ -227,10 +227,10 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char)
usleep(1000);
break;
case WSAECONNABORTED:
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
case WSAECONNRESET:
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
default:
LOG_ERROR("read: %d", errno);
@ -242,14 +242,14 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char)
usleep(1000);
break;
case ECONNABORTED:
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
case ECONNRESET:
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
default:
LOG_ERROR("read: %s", strerror(errno));
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
#endif
@ -341,7 +341,7 @@ static int gdb_write(struct connection *connection, void *data, int len)
if (connection_write(connection, data, len) == len)
return ERROR_OK;
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
@ -448,7 +448,7 @@ static int gdb_put_packet_inner(struct connection *connection,
return ERROR_OK;
} else {
LOG_ERROR("unknown character(1) 0x%2.2x in reply, dropping connection", reply);
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
} else if (reply == '$') {
@ -458,7 +458,7 @@ static int gdb_put_packet_inner(struct connection *connection,
} else {
LOG_ERROR("unknown character(2) 0x%2.2x in reply, dropping connection",
reply);
gdb_con->closed = 1;
gdb_con->closed = true;
return ERROR_SERVER_REMOTE_CLOSED;
}
}
@ -471,9 +471,9 @@ static int gdb_put_packet_inner(struct connection *connection,
int gdb_put_packet(struct connection *connection, char *buffer, int len)
{
struct gdb_connection *gdb_con = connection->priv;
gdb_con->busy = 1;
gdb_con->busy = true;
int retval = gdb_put_packet_inner(connection, buffer, len);
gdb_con->busy = 0;
gdb_con->busy = false;
/* we sent some data, reset timer for keep alive messages */
kept_alive();
@ -679,9 +679,9 @@ static int gdb_get_packet_inner(struct connection *connection,
static int gdb_get_packet(struct connection *connection, char *buffer, int *len)
{
struct gdb_connection *gdb_con = connection->priv;
gdb_con->busy = 1;
gdb_con->busy = true;
int retval = gdb_get_packet_inner(connection, buffer, len);
gdb_con->busy = 0;
gdb_con->busy = false;
return retval;
}
@ -917,10 +917,11 @@ static int gdb_target_callback_event_handler(struct target *target,
static int gdb_new_connection(struct connection *connection)
{
struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection));
struct gdb_service *gdb_service = connection->service->priv;
struct target *target;
int retval;
int initial_ack;
target = get_target_from_connection(connection);
connection->priv = gdb_connection;
/* initialize gdb connection information */
@ -929,8 +930,8 @@ static int gdb_new_connection(struct connection *connection)
gdb_connection->ctrl_c = 0;
gdb_connection->frontend_state = TARGET_HALTED;
gdb_connection->vflash_image = NULL;
gdb_connection->closed = 0;
gdb_connection->busy = 0;
gdb_connection->closed = false;
gdb_connection->busy = false;
gdb_connection->noack_mode = 0;
gdb_connection->sync = false;
gdb_connection->mem_write_error = false;
@ -949,12 +950,12 @@ static int gdb_new_connection(struct connection *connection)
* GDB session could leave dangling breakpoints if e.g. communication
* timed out.
*/
breakpoint_clear_target(gdb_service->target);
watchpoint_clear_target(gdb_service->target);
breakpoint_clear_target(target);
watchpoint_clear_target(target);
/* clean previous rtos session if supported*/
if ((gdb_service->target->rtos) && (gdb_service->target->rtos->type->clean))
gdb_service->target->rtos->type->clean(gdb_service->target);
if ((target->rtos) && (target->rtos->type->clean))
target->rtos->type->clean(target);
/* remove the initial ACK from the incoming buffer */
retval = gdb_get_char(connection, &initial_ack);
@ -966,7 +967,7 @@ static int gdb_new_connection(struct connection *connection)
*/
if (initial_ack != '+')
gdb_putback_char(connection, initial_ack);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH);
target_call_event_callbacks(target, TARGET_EVENT_GDB_ATTACH);
if (gdb_use_memory_map) {
/* Connect must fail if the memory map can't be set up correctly.
@ -978,7 +979,7 @@ static int gdb_new_connection(struct connection *connection)
for (i = 0; i < flash_get_bank_count(); i++) {
struct flash_bank *p;
p = get_flash_bank_by_num_noprobe(i);
if (p->target != gdb_service->target)
if (p->target != target)
continue;
retval = get_flash_bank_by_num(i, &p);
if (retval != ERROR_OK) {
@ -992,8 +993,8 @@ static int gdb_new_connection(struct connection *connection)
gdb_actual_connections++;
LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s",
gdb_actual_connections,
target_name(gdb_service->target),
target_state_name(gdb_service->target));
target_name(target),
target_state_name(target));
/* DANGER! If we fail subsequently, we must remove this handler,
* otherwise we occasionally see crashes as the timer can invoke the
@ -1007,9 +1008,11 @@ static int gdb_new_connection(struct connection *connection)
static int gdb_connection_closed(struct connection *connection)
{
struct gdb_service *gdb_service = connection->service->priv;
struct target *target;
struct gdb_connection *gdb_connection = connection->priv;
target = get_target_from_connection(connection);
/* we're done forwarding messages. Tear down callback before
* cleaning up connection.
*/
@ -1017,8 +1020,8 @@ static int gdb_connection_closed(struct connection *connection)
gdb_actual_connections--;
LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
target_name(gdb_service->target),
target_state_name(gdb_service->target),
target_name(target),
target_state_name(target),
gdb_actual_connections);
/* see if an image built with vFlash commands is left */
@ -1029,7 +1032,7 @@ static int gdb_connection_closed(struct connection *connection)
}
/* if this connection registered a debug-message receiver delete it */
delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);
delete_debug_msg_receiver(connection->cmd_ctx, target);
if (connection->priv) {
free(connection->priv);
@ -1039,9 +1042,9 @@ static int gdb_connection_closed(struct connection *connection)
target_unregister_event_callback(gdb_target_callback_event_handler, connection);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_END);
target_call_event_callbacks(target, TARGET_EVENT_GDB_END);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
target_call_event_callbacks(target, TARGET_EVENT_GDB_DETACH);
return ERROR_OK;
}
@ -1283,10 +1286,10 @@ static int gdb_get_register_packet(struct connection *connection,
}
if (!reg_list[reg_num]->valid) {
retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
free (reg_list);
free(reg_list);
return gdb_error(connection, retval);
}
}
@ -1344,7 +1347,7 @@ static int gdb_set_register_packet(struct connection *connection,
gdb_target_to_reg(target, separator + 1, chars, bin_buf);
retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf);
if (retval != ERROR_OK){
if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name);
free(bin_buf);
free(reg_list);
@ -2441,7 +2444,7 @@ static int gdb_query_packet(struct connection *connection,
/* skip command character */
packet += 5;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete read memory packet received, dropping connection");
@ -2583,7 +2586,6 @@ static int gdb_v_packet(struct connection *connection,
char const *packet, int packet_size)
{
struct gdb_connection *gdb_connection = connection->priv;
struct gdb_service *gdb_service = connection->service->priv;
int result;
struct target *target = get_target_from_connection(connection);
@ -2629,18 +2631,18 @@ static int gdb_v_packet(struct connection *connection,
flash_set_dirty();
/* perform any target specific operations before the erase */
target_call_event_callbacks(gdb_service->target,
target_call_event_callbacks(target,
TARGET_EVENT_GDB_FLASH_ERASE_START);
/* vFlashErase:addr,length messages require region start and
* end to be "block" aligned ... if padding is ever needed,
* GDB will have become dangerously confused.
*/
result = flash_erase_address_range(gdb_service->target,
false, addr, length);
result = flash_erase_address_range(target, false, addr,
length);
/* perform any target specific operations after the erase */
target_call_event_callbacks(gdb_service->target,
target_call_event_callbacks(target,
TARGET_EVENT_GDB_FLASH_ERASE_END);
/* perform erase */
@ -2695,10 +2697,12 @@ static int gdb_v_packet(struct connection *connection,
/* process the flashing buffer. No need to erase as GDB
* always issues a vFlashErase first. */
target_call_event_callbacks(gdb_service->target,
target_call_event_callbacks(target,
TARGET_EVENT_GDB_FLASH_WRITE_START);
result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_END);
result = flash_write(target, gdb_connection->vflash_image,
&written, 0);
target_call_event_callbacks(target,
TARGET_EVENT_GDB_FLASH_WRITE_END);
if (result != ERROR_OK) {
if (result == ERROR_FLASH_DST_OUT_OF_BANK)
gdb_put_packet(connection, "E.memtype", 9);
@ -2722,9 +2726,8 @@ static int gdb_v_packet(struct connection *connection,
static int gdb_detach(struct connection *connection)
{
struct gdb_service *gdb_service = connection->service->priv;
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
target_call_event_callbacks(get_target_from_connection(connection),
TARGET_EVENT_GDB_DETACH);
return gdb_put_packet(connection, "OK", 2);
}
@ -2803,14 +2806,15 @@ static int gdb_input_inner(struct connection *connection)
/* Do not allocate this on the stack */
static char gdb_packet_buffer[GDB_BUFFER_SIZE];
struct gdb_service *gdb_service = connection->service->priv;
struct target *target = gdb_service->target;
struct target *target;
char const *packet = gdb_packet_buffer;
int packet_size;
int retval;
struct gdb_connection *gdb_con = connection->priv;
static int extended_protocol;
target = get_target_from_connection(connection);
/* drain input buffer. If one of the packets fail, then an error
* packet is replied, if applicable.
*
@ -2980,8 +2984,8 @@ static int gdb_input_inner(struct connection *connection)
break;
case 'R':
/* handle extended restart packet */
breakpoint_clear_target(gdb_service->target);
watchpoint_clear_target(gdb_service->target);
breakpoint_clear_target(target);
watchpoint_clear_target(target);
command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %s",
target_name(target));
/* set connection as attached after reset */

View File

@ -222,7 +222,6 @@ static int telnet_new_connection(struct connection *connection)
telnet_connection->closed = 0;
telnet_connection->line_size = 0;
telnet_connection->line_cursor = 0;
telnet_connection->option_size = 0;
telnet_connection->prompt = strdup("> ");
telnet_connection->state = TELNET_STATE_DATA;

View File

@ -27,11 +27,10 @@
#include <server/server.h>
#define TELNET_BUFFER_SIZE (1024)
#define TELNET_BUFFER_SIZE (10*1024)
#define TELNET_OPTION_MAX_SIZE (128)
#define TELNET_LINE_HISTORY_SIZE (128)
#define TELNET_LINE_MAX_SIZE (256)
#define TELNET_LINE_MAX_SIZE (10*256)
enum telnet_states {
TELNET_STATE_DATA,
@ -51,8 +50,6 @@ struct telnet_connection {
char line[TELNET_LINE_MAX_SIZE];
int line_size;
int line_cursor;
char option[TELNET_OPTION_MAX_SIZE];
int option_size;
char last_escape;
char *history[TELNET_LINE_HISTORY_SIZE];
int next_history;

View File

@ -661,11 +661,13 @@ static int svf_read_command_from_file(FILE *fd)
if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
return ERROR_FAIL;
i = -1;
/* fallthrough */
case '\r':
slash = 0;
/* Don't save '\r' and '\n' if no data is parsed */
if (!cmd_pos)
break;
/* fallthrough */
default:
/* The parsing code currently expects a space
* before parentheses -- "TDI (123)". Also a

View File

@ -19,6 +19,7 @@ noinst_LTLIBRARIES += %D%/libtarget.la
$(AVR32_SRC) \
$(MIPS32_SRC) \
$(NDS32_SRC) \
$(STM8_SRC) \
$(INTEL_IA32_SRC) \
$(RISCV_SRC) \
%D%/avrt.c \
@ -125,6 +126,9 @@ NDS32_SRC = \
%D%/nds32_v3m.c \
%D%/nds32_aice.c
STM8_SRC = \
%D%/stm8.c
INTEL_IA32_SRC = \
%D%/quark_x10xx.c \
%D%/quark_d20xx.c \
@ -213,6 +217,7 @@ RISCV_SRC = \
%D%/nds32_v3.h \
%D%/nds32_v3m.h \
%D%/nds32_aice.h \
%D%/stm8.h \
%D%/lakemont.h \
%D%/x86_32_common.h \
%D%/arm_cti.h

View File

@ -427,7 +427,10 @@ static int swd_init(struct command_context *ctx)
/* First connect after init is not reconnecting. */
dap->do_reconnect = false;
return swd_connect(dap);
int retval = swd_connect(dap);
if (retval != ERROR_OK)
LOG_ERROR("SWD connect failed");
return retval;
}
static struct transport swd_transport = {

View File

@ -157,6 +157,9 @@ struct arm {
int (*setup_semihosting)(struct target *target, int enable);
/** Semihosting command line. */
char *semihosting_cmdline;
/** Backpointer to the target. */
struct target *target;

View File

@ -346,8 +346,10 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
case 4:
outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
/* fallthrough */
case 2:
outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
/* fallthrough */
case 1:
outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
}
@ -509,8 +511,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
case 4:
*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
/* fallthrough */
case 2:
*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
/* fallthrough */
case 1:
*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
}
@ -519,8 +523,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
case 4:
*buffer++ = *read_ptr >> 8 * (address++ & 3);
*buffer++ = *read_ptr >> 8 * (address++ & 3);
/* fallthrough */
case 2:
*buffer++ = *read_ptr >> 8 * (address++ & 3);
/* fallthrough */
case 1:
*buffer++ = *read_ptr >> 8 * (address++ & 3);
}
@ -1053,7 +1059,7 @@ static int dap_rom_display(struct command_context *cmd_ctx,
int retval;
uint64_t pid;
uint32_t cid;
char tabs[7] = "";
char tabs[16] = "";
if (depth > 16) {
command_print(cmd_ctx, "\tTables too deep");

View File

@ -3299,6 +3299,7 @@ static int t2ev_data_immed(uint32_t opcode, uint32_t address,
case 0x10:
case 0x12:
is_signed = true;
/* fallthrough */
case 0x18:
case 0x1a:
/* signed/unsigned saturated add */

View File

@ -465,7 +465,7 @@ static int do_semihosting(struct target *target)
else {
uint32_t a = target_buffer_get_u32(target, params+0);
uint32_t l = target_buffer_get_u32(target, params+4);
char *arg = "foobar";
char *arg = arm->semihosting_cmdline != NULL ? arm->semihosting_cmdline : "";
uint32_t s = strlen(arg) + 1;
if (l < s)
arm->semihosting_result = -1;

View File

@ -1091,6 +1091,42 @@ COMMAND_HANDLER(handle_arm_semihosting_fileio_command)
return ERROR_OK;
}
COMMAND_HANDLER(handle_arm_semihosting_cmdline)
{
struct target *target = get_current_target(CMD_CTX);
unsigned int i;
if (target == NULL) {
LOG_ERROR("No target selected");
return ERROR_FAIL;
}
struct arm *arm = target_to_arm(target);
if (!is_arm(arm)) {
command_print(CMD_CTX, "current target isn't an ARM");
return ERROR_FAIL;
}
if (!arm->setup_semihosting) {
command_print(CMD_CTX, "semihosting not supported for current target");
return ERROR_FAIL;
}
free(arm->semihosting_cmdline);
arm->semihosting_cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
for (i = 1; i < CMD_ARGC; i++) {
char *cmdline = alloc_printf("%s %s", arm->semihosting_cmdline, CMD_ARGV[i]);
if (cmdline == NULL)
break;
free(arm->semihosting_cmdline);
arm->semihosting_cmdline = cmdline;
}
return ERROR_OK;
}
static const struct command_registration arm_exec_command_handlers[] = {
{
.name = "reg",
@ -1133,6 +1169,13 @@ static const struct command_registration arm_exec_command_handlers[] = {
.usage = "['enable'|'disable']",
.help = "activate support for semihosting operations",
},
{
"semihosting_cmdline",
.handler = handle_arm_semihosting_cmdline,
.mode = COMMAND_EXEC,
.usage = "arguments",
.help = "command line arguments to be passed to program",
},
{
"semihosting_fileio",
.handler = handle_arm_semihosting_fileio_command,

View File

@ -355,7 +355,7 @@ int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
break;
case 7:
LOG_INFO("inner: Write-Back, no Write-Allocate");
break;
default:
LOG_INFO("inner: %" PRIx32 " ???", INNER);
}

View File

@ -174,7 +174,7 @@ target_to_armv7m(struct target *target)
return container_of(target->arch_info, struct armv7m_common, arm);
}
static inline bool is_armv7m(struct armv7m_common *armv7m)
static inline bool is_armv7m(const struct armv7m_common *armv7m)
{
return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
}

View File

@ -168,12 +168,8 @@ static int cortex_m_single_step_core(struct target *target)
{
struct cortex_m_common *cortex_m = target_to_cm(target);
struct armv7m_common *armv7m = &cortex_m->armv7m;
uint32_t dhcsr_save;
int retval;
/* backup dhcsr reg */
dhcsr_save = cortex_m->dcb_dhcsr;
/* Mask interrupts before clearing halt, if done already. This avoids
* Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
* HALT can put the core into an unknown state.
@ -191,7 +187,6 @@ static int cortex_m_single_step_core(struct target *target)
LOG_DEBUG(" ");
/* restore dhcsr reg */
cortex_m->dcb_dhcsr = dhcsr_save;
cortex_m_clear_halt(target);
return ERROR_OK;
@ -242,7 +237,7 @@ static int cortex_m_endreset_event(struct target *target)
if (retval != ERROR_OK)
return retval;
if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS);
if (retval != ERROR_OK)
return retval;
}
@ -1005,12 +1000,12 @@ static int cortex_m_assert_reset(struct target *target)
/* Store important errors instead of failing and proceed to reset assert */
if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN))
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS);
/* If the processor is sleeping in a WFI or WFE instruction, the
* C_HALT bit must be asserted to regain control */
if (retval == ERROR_OK && (cortex_m->dcb_dhcsr & S_SLEEP))
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
retval = cortex_m_write_debug_halt_mask(target, C_HALT, 0);
mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
/* Ignore less important errors */
@ -1018,8 +1013,7 @@ static int cortex_m_assert_reset(struct target *target)
if (!target->reset_halt) {
/* Set/Clear C_MASKINTS in a separate operation */
if (cortex_m->dcb_dhcsr & C_MASKINTS)
mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
DBGKEY | C_DEBUGEN | C_HALT);
cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
/* clear any debug flags before resuming */
cortex_m_clear_halt(target);

View File

@ -816,7 +816,7 @@ static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *ar
uint32_t *data = malloc(count * sizeof(uint32_t));
int result;
result = target_read_buffer(target, address, count * 4, (uint8_t *)data);
char data_str[11];
char data_str[12];
jim_wide i;
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));

View File

@ -88,7 +88,6 @@ static int jsp_new_connection(struct connection *connection)
telnet_connection->closed = 0;
telnet_connection->line_size = 0;
telnet_connection->line_cursor = 0;
telnet_connection->option_size = 0;
telnet_connection->state = TELNET_STATE_DATA;
/* negotiate telnet options */

View File

@ -114,9 +114,9 @@ struct reg_data_type {
};
struct reg {
/** Canonical name of the register. */
/* Canonical name of the register. */
const char *name;
/** Number that gdb uses to access this register. */
/* Number that gdb uses to access this register. */
uint32_t number;
/* TODO. This should probably be const. */
struct reg_feature *feature;

View File

@ -17,7 +17,7 @@ static uint32_t load(const struct target *target, unsigned int rd,
return ld(rd, base, offset);
}
assert(0);
return 0; // Silence -Werror=return-type
return 0; /* Silence -Werror=return-type */
}
static uint32_t store(const struct target *target, unsigned int src,
@ -32,7 +32,7 @@ static uint32_t store(const struct target *target, unsigned int src,
return sd(src, base, offset);
}
assert(0);
return 0; // Silence -Werror=return-type
return 0; /* Silence -Werror=return-type */
}
#endif

View File

@ -42,20 +42,19 @@ bool riscv_batch_full(struct riscv_batch *batch)
return batch->used_scans > (batch->allocated_scans - 4);
}
void riscv_batch_run(struct riscv_batch *batch)
int riscv_batch_run(struct riscv_batch *batch)
{
if (batch->used_scans == 0) {
LOG_DEBUG("Ignoring empty batch.");
return;
return ERROR_OK;
}
keep_alive();
keep_alive();
LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans);
riscv_batch_add_nop(batch);
for (size_t i = 0; i < batch->used_scans; ++i) {
dump_field(batch->fields + i);
jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
if (batch->idle_count > 0)
jtag_add_runtest(batch->idle_count, TAP_IDLE);
@ -64,11 +63,13 @@ void riscv_batch_run(struct riscv_batch *batch)
LOG_DEBUG("executing queue");
if (jtag_execute_queue() != ERROR_OK) {
LOG_ERROR("Unable to execute JTAG queue");
abort();
return ERROR_FAIL;
}
for (size_t i = 0; i < batch->used_scans; ++i)
dump_field(batch->fields + i);
return ERROR_OK;
}
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data)
@ -139,8 +140,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
void dump_field(const struct scan_field *field)
{
static const char *op_string[] = {"-", "r", "w", "?"};
static const char *status_string[] = {"+", "?", "F", "b"};
static const char * const op_string[] = {"-", "r", "w", "?"};
static const char * const status_string[] = {"+", "?", "F", "b"};
if (debug_level < LOG_LVL_DEBUG)
return;

View File

@ -48,7 +48,7 @@ void riscv_batch_free(struct riscv_batch *batch);
bool riscv_batch_full(struct riscv_batch *batch);
/* Executes this scan batch. */
void riscv_batch_run(struct riscv_batch *batch);
int riscv_batch_run(struct riscv_batch *batch);
/* Adds a DMI write to this batch. */
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data);

View File

@ -173,12 +173,6 @@
#define CSR_DCSR_EBREAKM_LENGTH 1
#define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET)
/*
* When 1, {\tt ebreak} instructions in Hypervisor Mode enter Debug Mode.
*/
#define CSR_DCSR_EBREAKH_OFFSET 14
#define CSR_DCSR_EBREAKH_LENGTH 1
#define CSR_DCSR_EBREAKH (0x1U << CSR_DCSR_EBREAKH_OFFSET)
/*
* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode.
*/
#define CSR_DCSR_EBREAKS_OFFSET 13
@ -207,9 +201,10 @@
/*
* 0: Increment counters as usual.
*
* 1: Don't increment any counters while in Debug Mode. This includes
* the {\tt cycle} and {\tt instret} CSRs. This is preferred for most
* debugging scenarios.
* 1: Don't increment any counters while in Debug Mode or on {\tt
* ebreak} instructions that cause entry into Debug Mode. These
* counters include the {\tt cycle} and {\tt instret} CSRs. This is
* preferred for most debugging scenarios.
*
* An implementation may choose not to support writing to this bit.
* The debugger must read back the value it writes to check whether
@ -300,7 +295,7 @@
*
* Other values are reserved for future use.
*/
#define CSR_TDATA1_TYPE_OFFSET XLEN-4
#define CSR_TDATA1_TYPE_OFFSET (XLEN-4)
#define CSR_TDATA1_TYPE_LENGTH 4
#define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET)
/*
@ -312,14 +307,14 @@
*
* This bit is only writable from Debug Mode.
*/
#define CSR_TDATA1_HMODE_OFFSET XLEN-5
#define CSR_TDATA1_HMODE_LENGTH 1
#define CSR_TDATA1_HMODE (0x1ULL << CSR_TDATA1_HMODE_OFFSET)
#define CSR_TDATA1_DMODE_OFFSET (XLEN-5)
#define CSR_TDATA1_DMODE_LENGTH 1
#define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
/*
* Trigger-specific data.
*/
#define CSR_TDATA1_DATA_OFFSET 0
#define CSR_TDATA1_DATA_LENGTH XLEN - 5
#define CSR_TDATA1_DATA_LENGTH (XLEN - 5)
#define CSR_TDATA1_DATA (((1L<<XLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET)
#define CSR_TDATA2 0x7a2
#define CSR_TDATA2_DATA_OFFSET 0
@ -330,10 +325,10 @@
#define CSR_TDATA3_DATA_LENGTH XLEN
#define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET)
#define CSR_MCONTROL 0x7a1
#define CSR_MCONTROL_TYPE_OFFSET XLEN-4
#define CSR_MCONTROL_TYPE_OFFSET (XLEN-4)
#define CSR_MCONTROL_TYPE_LENGTH 4
#define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET)
#define CSR_MCONTROL_DMODE_OFFSET XLEN-5
#define CSR_MCONTROL_DMODE_OFFSET (XLEN-5)
#define CSR_MCONTROL_DMODE_LENGTH 1
#define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET)
/*
@ -344,7 +339,7 @@
* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
* size.
*/
#define CSR_MCONTROL_MASKMAX_OFFSET XLEN-11
#define CSR_MCONTROL_MASKMAX_OFFSET (XLEN-11)
#define CSR_MCONTROL_MASKMAX_LENGTH 6
#define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET)
/*
@ -390,7 +385,7 @@
* 0: Raise a breakpoint exception. (Used when software wants to use
* the trigger module without an external debugger attached.)
*
* 1: Enter Debug Mode. (Only supported when \Fhmode is 1.)
* 1: Enter Debug Mode. (Only supported when \Fdmode is 1.)
*
* 2: Start tracing.
*
@ -446,12 +441,6 @@
#define CSR_MCONTROL_M_LENGTH 1
#define CSR_MCONTROL_M (0x1ULL << CSR_MCONTROL_M_OFFSET)
/*
* When set, enable this trigger in H mode.
*/
#define CSR_MCONTROL_H_OFFSET 5
#define CSR_MCONTROL_H_LENGTH 1
#define CSR_MCONTROL_H (0x1ULL << CSR_MCONTROL_H_OFFSET)
/*
* When set, enable this trigger in S mode.
*/
#define CSR_MCONTROL_S_OFFSET 4
@ -483,16 +472,16 @@
#define CSR_MCONTROL_LOAD_LENGTH 1
#define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET)
#define CSR_ICOUNT 0x7a1
#define CSR_ICOUNT_TYPE_OFFSET XLEN-4
#define CSR_ICOUNT_TYPE_OFFSET (XLEN-4)
#define CSR_ICOUNT_TYPE_LENGTH 4
#define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET)
#define CSR_ICOUNT_DMODE_OFFSET XLEN-5
#define CSR_ICOUNT_DMODE_OFFSET (XLEN-5)
#define CSR_ICOUNT_DMODE_LENGTH 1
#define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET)
/*
* When count is decremented to 0, the trigger fires. Instead of
* changing \Fcount from 1 to 0, it is also acceptable for hardware to
* clear \Fm, \Fh, \Fs, and \Fu. This allows \Fcount to be hard-wired
* clear \Fm, \Fs, and \Fu. This allows \Fcount to be hard-wired
* to 1 if this register just exists for single step.
*/
#define CSR_ICOUNT_COUNT_OFFSET 10
@ -506,13 +495,6 @@
#define CSR_ICOUNT_M_LENGTH 1
#define CSR_ICOUNT_M (0x1ULL << CSR_ICOUNT_M_OFFSET)
/*
* When set, every instruction completed or exception taken in in H mode decrements \Fcount
* by 1.
*/
#define CSR_ICOUNT_H_OFFSET 8
#define CSR_ICOUNT_H_LENGTH 1
#define CSR_ICOUNT_H (0x1ULL << CSR_ICOUNT_H_OFFSET)
/*
* When set, every instruction completed or exception taken in S mode decrements \Fcount
* by 1.
*/
@ -532,7 +514,7 @@
* 0: Raise a breakpoint exception. (Used when software wants to use the
* trigger module without an external debugger attached.)
*
* 1: Enter Debug Mode. (Only supported when \Fhmode is 1.)
* 1: Enter Debug Mode. (Only supported when \Fdmode is 1.)
*
* 2: Start tracing.
*
@ -549,13 +531,38 @@
#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
#define DMI_DMSTATUS 0x11
/*
* This field is 1 when all currently selected harts have acknowledged the previous \Fresumereq.
* If 1, then there is an implicit {\tt ebreak} instruction at the
* non-existent word immediately after the Program Buffer. This saves
* the debugger from having to write the {\tt ebreak} itself, and
* allows the Program Buffer to be one word smaller.
*
* This must be 1 when \Fprogbufsize is 1.
*/
#define DMI_DMSTATUS_IMPEBREAK_OFFSET 22
#define DMI_DMSTATUS_IMPEBREAK_LENGTH 1
#define DMI_DMSTATUS_IMPEBREAK (0x1U << DMI_DMSTATUS_IMPEBREAK_OFFSET)
/*
* This field is 1 when all currently selected harts have been reset but the reset has not been acknowledged.
*/
#define DMI_DMSTATUS_ALLHAVERESET_OFFSET 19
#define DMI_DMSTATUS_ALLHAVERESET_LENGTH 1
#define DMI_DMSTATUS_ALLHAVERESET (0x1U << DMI_DMSTATUS_ALLHAVERESET_OFFSET)
/*
* This field is 1 when any currently selected hart has been reset but the reset has not been acknowledged.
*/
#define DMI_DMSTATUS_ANYHAVERESET_OFFSET 18
#define DMI_DMSTATUS_ANYHAVERESET_LENGTH 1
#define DMI_DMSTATUS_ANYHAVERESET (0x1U << DMI_DMSTATUS_ANYHAVERESET_OFFSET)
/*
* This field is 1 when all currently selected harts have acknowledged
* the previous resume request.
*/
#define DMI_DMSTATUS_ALLRESUMEACK_OFFSET 17
#define DMI_DMSTATUS_ALLRESUMEACK_LENGTH 1
#define DMI_DMSTATUS_ALLRESUMEACK (0x1U << DMI_DMSTATUS_ALLRESUMEACK_OFFSET)
/*
* This field is 1 when any currently selected hart has acknowledged the previous \Fresumereq.
* This field is 1 when any currently selected hart has acknowledged
* the previous resume request.
*/
#define DMI_DMSTATUS_ANYRESUMEACK_OFFSET 16
#define DMI_DMSTATUS_ANYRESUMEACK_LENGTH 1
@ -629,6 +636,13 @@
#define DMI_DMSTATUS_AUTHBUSY_OFFSET 6
#define DMI_DMSTATUS_AUTHBUSY_LENGTH 1
#define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET)
/*
* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which
* is not relevant to the Device Tree.
*
* 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the
* Device Tree.
*/
#define DMI_DMSTATUS_DEVTREEVALID_OFFSET 4
#define DMI_DMSTATUS_DEVTREEVALID_LENGTH 1
#define DMI_DMSTATUS_DEVTREEVALID (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET)
@ -649,32 +663,35 @@
#define DMI_DMSTATUS_VERSION (0xfU << DMI_DMSTATUS_VERSION_OFFSET)
#define DMI_DMCONTROL 0x10
/*
* Halt request signal for all currently selected harts. When set to
* 1, each selected hart will halt if it is not currently halted.
* Writes the halt request bit for all currently selected harts.
* When set to 1, each selected hart will halt if it is not currently
* halted.
*
* Writing 1 or 0 has no effect on a hart which is already halted, but
* the bit should be cleared to 0 before the hart is resumed.
* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
* the bit must be cleared to 0 before the hart is resumed.
*
* Writes apply to the new value of \Fhartsel and \Fhasel.
*/
#define DMI_DMCONTROL_HALTREQ_OFFSET 31
#define DMI_DMCONTROL_HALTREQ_LENGTH 1
#define DMI_DMCONTROL_HALTREQ (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET)
#define DMI_DMCONTROL_HALTREQ (0x1ULL << DMI_DMCONTROL_HALTREQ_OFFSET)
/*
* Resume request signal for all currently selected harts. When set to 1,
* each selected hart will resume if it is currently halted.
* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
* Writes the resume request bit for all currently selected harts.
* When set to 1, each selected hart will resume if it is currently
* halted.
*
* The resume request bit is ignored while the halt request bit is
* set.
*
* Writes apply to the new value of \Fhartsel and \Fhasel.
*/
#define DMI_DMCONTROL_RESUMEREQ_OFFSET 30
#define DMI_DMCONTROL_RESUMEREQ_LENGTH 1
#define DMI_DMCONTROL_RESUMEREQ (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET)
#define DMI_DMCONTROL_RESUMEREQ (0x1ULL << DMI_DMCONTROL_RESUMEREQ_OFFSET)
/*
* This optional bit controls reset to all the currently selected harts.
* To perform a reset the debugger writes 1, and then writes 0 to
* deassert the reset signal.
* This optional field writes the reset bit for all the currently
* selected harts. To perform a reset the debugger writes 1, and then
* writes 0 to deassert the reset signal.
*
* If this feature is not implemented, the bit always stays 0, so
* after writing 1 the debugger can read the register back to see if
@ -684,7 +701,16 @@
*/
#define DMI_DMCONTROL_HARTRESET_OFFSET 29
#define DMI_DMCONTROL_HARTRESET_LENGTH 1
#define DMI_DMCONTROL_HARTRESET (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET)
#define DMI_DMCONTROL_HARTRESET (0x1ULL << DMI_DMCONTROL_HARTRESET_OFFSET)
/*
* Writing 1 to this bit clears the {\tt havereset} bits for
* any selected harts.
*
* Writes apply to the new value of \Fhartsel and \Fhasel.
*/
#define DMI_DMCONTROL_ACKHAVERESET_OFFSET 28
#define DMI_DMCONTROL_ACKHAVERESET_LENGTH 1
#define DMI_DMCONTROL_ACKHAVERESET (0x1ULL << DMI_DMCONTROL_ACKHAVERESET_OFFSET)
/*
* Selects the definition of currently selected harts.
*
@ -700,25 +726,26 @@
*/
#define DMI_DMCONTROL_HASEL_OFFSET 26
#define DMI_DMCONTROL_HASEL_LENGTH 1
#define DMI_DMCONTROL_HASEL (0x1U << DMI_DMCONTROL_HASEL_OFFSET)
#define DMI_DMCONTROL_HASEL (0x1ULL << DMI_DMCONTROL_HASEL_OFFSET)
/*
* The DM-specific index of the hart to select. This hart is always part of the
* currently selected harts.
*/
#define DMI_DMCONTROL_HARTSEL_OFFSET 16
#define DMI_DMCONTROL_HARTSEL_LENGTH 10
#define DMI_DMCONTROL_HARTSEL (0x3ffU << DMI_DMCONTROL_HARTSEL_OFFSET)
#define DMI_DMCONTROL_HARTSEL_LENGTH HARTSELLEN
#define DMI_DMCONTROL_HARTSEL (((1L<<HARTSELLEN)-1) << DMI_DMCONTROL_HARTSEL_OFFSET)
/*
* This bit controls the reset signal from the DM to the rest of the
* system. To perform a system reset the debugger writes 1,
* system. The signal should reset every part of the system, including
* every hart, except for the DM and any logic required to access the
* DM.
* To perform a system reset the debugger writes 1,
* and then writes 0
* to deassert the reset. This bit must not reset the Debug Module
* registers. What it does reset is platform-specific (it may
* reset nothing).
* to deassert the reset.
*/
#define DMI_DMCONTROL_NDMRESET_OFFSET 1
#define DMI_DMCONTROL_NDMRESET_LENGTH 1
#define DMI_DMCONTROL_NDMRESET (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET)
#define DMI_DMCONTROL_NDMRESET (0x1ULL << DMI_DMCONTROL_NDMRESET_OFFSET)
/*
* This bit serves as a reset signal for the Debug Module itself.
*
@ -741,7 +768,7 @@
*/
#define DMI_DMCONTROL_DMACTIVE_OFFSET 0
#define DMI_DMCONTROL_DMACTIVE_LENGTH 1
#define DMI_DMCONTROL_DMACTIVE (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET)
#define DMI_DMCONTROL_DMACTIVE (0x1ULL << DMI_DMCONTROL_DMACTIVE_OFFSET)
#define DMI_HARTINFO 0x12
/*
* Number of {\tt dscratch} registers available for the debugger
@ -769,6 +796,9 @@
*
* If \Fdataaccess is 1: Number of 32-bit words in the memory map
* dedicated to shadowing the {\tt data} registers.
*
* Since there are at most 12 {\tt data} registers, the value in this
* register must be 12 or smaller.
*/
#define DMI_HARTINFO_DATASIZE_OFFSET 12
#define DMI_HARTINFO_DATASIZE_LENGTH 4
@ -778,7 +808,7 @@
* shadowing the {\tt data} registers.
*
* If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
* registers are shadowed.
* registers are shadowed, to be used to access relative to \Rzero.
*/
#define DMI_HARTINFO_DATAADDR_OFFSET 0
#define DMI_HARTINFO_DATAADDR_LENGTH 12
@ -891,13 +921,10 @@
#define DMI_ABSTRACTCS 0x16
/*
* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
*
* TODO: Explain what can be done with each size of the buffer, to suggest
* why you would want more or less words.
*/
#define DMI_ABSTRACTCS_PROGSIZE_OFFSET 24
#define DMI_ABSTRACTCS_PROGSIZE_LENGTH 5
#define DMI_ABSTRACTCS_PROGSIZE (0x1fU << DMI_ABSTRACTCS_PROGSIZE_OFFSET)
#define DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET 24
#define DMI_ABSTRACTCS_PROGBUFSIZE_LENGTH 5
#define DMI_ABSTRACTCS_PROGBUFSIZE (0x1fU << DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET)
/*
* 1: An abstract command is currently being executed.
*
@ -938,8 +965,8 @@
* abstract command interface. Valid sizes are 0 - 12.
*/
#define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0
#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 5
#define DMI_ABSTRACTCS_DATACOUNT (0x1fU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 4
#define DMI_ABSTRACTCS_DATACOUNT (0xfU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
#define DMI_COMMAND 0x17
/*
* The type determines the overall functionality of this
@ -957,14 +984,14 @@
#define DMI_COMMAND_CONTROL (0xffffffU << DMI_COMMAND_CONTROL_OFFSET)
#define DMI_ABSTRACTAUTO 0x18
/*
* When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word
* When a bit in this field is 1, read or write accesses to the corresponding {\tt progbuf} word
* cause the command in \Rcommand to be executed again.
*/
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
/*
* When a bit in this field is 1, read or write accesses the corresponding {\tt data} word
* When a bit in this field is 1, read or write accesses to the corresponding {\tt data} word
* cause the command in \Rcommand to be executed again.
*/
#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
@ -991,17 +1018,59 @@
#define DMI_AUTHDATA_DATA_OFFSET 0
#define DMI_AUTHDATA_DATA_LENGTH 32
#define DMI_AUTHDATA_DATA (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET)
#define DMI_SBADDRESS3 0x37
/*
* Accesses bits 127:96 of the physical address in {\tt sbaddress} (if
* the system address bus is that wide).
*/
#define DMI_SBADDRESS3_ADDRESS_OFFSET 0
#define DMI_SBADDRESS3_ADDRESS_LENGTH 32
#define DMI_SBADDRESS3_ADDRESS (0xffffffffU << DMI_SBADDRESS3_ADDRESS_OFFSET)
#define DMI_SBCS 0x38
/*
* When a 1 is written here, triggers a read at the address in {\tt
* sbaddress} using the access size set by \Fsbaccess.
* 0: The System Bus interface conforms to mainline drafts of this
* spec older than 1 January, 2018.
*
* 1: The System Bus interface conforms to this version of the spec.
*
* Other values are reserved for future versions.
*/
#define DMI_SBCS_SBSINGLEREAD_OFFSET 20
#define DMI_SBCS_SBSINGLEREAD_LENGTH 1
#define DMI_SBCS_SBSINGLEREAD (0x1U << DMI_SBCS_SBSINGLEREAD_OFFSET)
#define DMI_SBCS_SBVERSION_OFFSET 29
#define DMI_SBCS_SBVERSION_LENGTH 3
#define DMI_SBCS_SBVERSION (0x7U << DMI_SBCS_SBVERSION_OFFSET)
/*
* Select the access size to use for system bus accesses triggered by
* writes to the {\tt sbaddress} registers or \Rsbdatazero.
* Set when the debugger attempts to read data while a read is in
* progress, or when the debugger initiates a new access while one is
* already in progress (while \Fsbbusy is set). It remains set until
* it's explicitly cleared by the debugger.
*
* While this field is non-zero, no more system bus accesses can be
* initiated by the debug module.
*/
#define DMI_SBCS_SBBUSYERROR_OFFSET 22
#define DMI_SBCS_SBBUSYERROR_LENGTH 1
#define DMI_SBCS_SBBUSYERROR (0x1U << DMI_SBCS_SBBUSYERROR_OFFSET)
/*
* When 1, indicates the system bus master is busy. (Whether the
* system bus itself is busy is related, but not the same thing.) This
* bit goes high immediately when a read or write is requested for any
* reason, and does not go low until the access is fully completed.
*
* To avoid race conditions, debuggers must not try to clear \Fsberror
* until they read \Fsbbusy as 0.
*/
#define DMI_SBCS_SBBUSY_OFFSET 21
#define DMI_SBCS_SBBUSY_LENGTH 1
#define DMI_SBCS_SBBUSY (0x1U << DMI_SBCS_SBBUSY_OFFSET)
/*
* When 1, every write to \Rsbaddresszero automatically triggers a
* system bus read at the new address.
*/
#define DMI_SBCS_SBREADONADDR_OFFSET 20
#define DMI_SBCS_SBREADONADDR_LENGTH 1
#define DMI_SBCS_SBREADONADDR (0x1U << DMI_SBCS_SBREADONADDR_OFFSET)
/*
* Select the access size to use for system bus accesses.
*
* 0: 8-bit
*
@ -1013,28 +1082,26 @@
*
* 4: 128-bit
*
* If an unsupported system bus access size is written here,
* the DM may not perform the access, or may perform the access
* with any access size.
* If \Fsbaccess has an unsupported value when the DM starts a bus
* access, the access is not performed and \Fsberror is set to 3.
*/
#define DMI_SBCS_SBACCESS_OFFSET 17
#define DMI_SBCS_SBACCESS_LENGTH 3
#define DMI_SBCS_SBACCESS (0x7U << DMI_SBCS_SBACCESS_OFFSET)
/*
* When 1, the internal address value (used by the system bus master)
* is incremented by the access size (in bytes) selected in \Fsbaccess
* after every system bus access.
* When 1, {\tt sbaddress} is incremented by the access size (in
* bytes) selected in \Fsbaccess after every system bus access.
*/
#define DMI_SBCS_SBAUTOINCREMENT_OFFSET 16
#define DMI_SBCS_SBAUTOINCREMENT_LENGTH 1
#define DMI_SBCS_SBAUTOINCREMENT (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET)
/*
* When 1, every read from \Rsbdatazero automatically triggers a system
* bus read at the new address.
* When 1, every read from \Rsbdatazero automatically triggers a
* system bus read at the (possibly auto-incremented) address.
*/
#define DMI_SBCS_SBAUTOREAD_OFFSET 15
#define DMI_SBCS_SBAUTOREAD_LENGTH 1
#define DMI_SBCS_SBAUTOREAD (0x1U << DMI_SBCS_SBAUTOREAD_OFFSET)
#define DMI_SBCS_SBREADONDATA_OFFSET 15
#define DMI_SBCS_SBREADONDATA_LENGTH 1
#define DMI_SBCS_SBREADONDATA (0x1U << DMI_SBCS_SBREADONDATA_OFFSET)
/*
* When the debug module's system bus
* master causes a bus error, this field gets set. The bits in this
@ -1049,11 +1116,6 @@
* 2: A bad address was accessed.
*
* 3: There was some other error (eg. alignment).
*
* 4: The system bus master was busy when one of the
* {\tt sbaddress} or {\tt sbdata} registers was written,
* or the {\tt sbdata} register was read when it had
* stale data.
*/
#define DMI_SBCS_SBERROR_OFFSET 12
#define DMI_SBCS_SBERROR_LENGTH 3
@ -1097,54 +1159,54 @@
#define DMI_SBCS_SBACCESS8 (0x1U << DMI_SBCS_SBACCESS8_OFFSET)
#define DMI_SBADDRESS0 0x39
/*
* Accesses bits 31:0 of the internal address.
* Accesses bits 31:0 of the physical address in {\tt sbaddress}.
*/
#define DMI_SBADDRESS0_ADDRESS_OFFSET 0
#define DMI_SBADDRESS0_ADDRESS_LENGTH 32
#define DMI_SBADDRESS0_ADDRESS (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET)
#define DMI_SBADDRESS1 0x3a
/*
* Accesses bits 63:32 of the internal address (if the system address
* bus is that wide).
* Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
* the system address bus is that wide).
*/
#define DMI_SBADDRESS1_ADDRESS_OFFSET 0
#define DMI_SBADDRESS1_ADDRESS_LENGTH 32
#define DMI_SBADDRESS1_ADDRESS (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET)
#define DMI_SBADDRESS2 0x3b
/*
* Accesses bits 95:64 of the internal address (if the system address
* bus is that wide).
* Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
* the system address bus is that wide).
*/
#define DMI_SBADDRESS2_ADDRESS_OFFSET 0
#define DMI_SBADDRESS2_ADDRESS_LENGTH 32
#define DMI_SBADDRESS2_ADDRESS (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET)
#define DMI_SBDATA0 0x3c
/*
* Accesses bits 31:0 of the internal data.
* Accesses bits 31:0 of {\tt sbdata}.
*/
#define DMI_SBDATA0_DATA_OFFSET 0
#define DMI_SBDATA0_DATA_LENGTH 32
#define DMI_SBDATA0_DATA (0xffffffffU << DMI_SBDATA0_DATA_OFFSET)
#define DMI_SBDATA1 0x3d
/*
* Accesses bits 63:32 of the internal data (if the system bus is
* that wide).
* Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
* wide).
*/
#define DMI_SBDATA1_DATA_OFFSET 0
#define DMI_SBDATA1_DATA_LENGTH 32
#define DMI_SBDATA1_DATA (0xffffffffU << DMI_SBDATA1_DATA_OFFSET)
#define DMI_SBDATA2 0x3e
/*
* Accesses bits 95:64 of the internal data (if the system bus is
* that wide).
* Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
* wide).
*/
#define DMI_SBDATA2_DATA_OFFSET 0
#define DMI_SBDATA2_DATA_LENGTH 32
#define DMI_SBDATA2_DATA (0xffffffffU << DMI_SBDATA2_DATA_OFFSET)
#define DMI_SBDATA3 0x3f
/*
* Accesses bits 127:96 of the internal data (if the system bus is
* that wide).
* Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
* wide).
*/
#define DMI_SBDATA3_DATA_OFFSET 0
#define DMI_SBDATA3_DATA_LENGTH 32
@ -1188,6 +1250,9 @@
* 0: Don't do the operation specified by \Fwrite.
*
* 1: Do the operation specified by \Fwrite.
*
* This bit can be used to just execute the Program Buffer without
* having to worry about placing valid values into \Fsize or \Fregno.
*/
#define AC_ACCESS_REGISTER_TRANSFER_OFFSET 17
#define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1
@ -1223,8 +1288,9 @@
/*
* Contains the privilege level the hart was operating in when Debug
* Mode was entered. The encoding is described in Table
* \ref{tab:privlevel}. A user can write this value to change the
* hart's privilege level when exiting Debug Mode.
* \ref{tab:privlevel}, and matches the privilege level encoding from
* the RISC-V Privileged ISA Specification. A user can write this
* value to change the hart's privilege level when exiting Debug Mode.
*/
#define VIRT_PRIV_PRV_OFFSET 0
#define VIRT_PRIV_PRV_LENGTH 2

View File

@ -17,10 +17,14 @@
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
#define MSTATUS_MPRV 0x00020000
#define MSTATUS_PUM 0x00040000
#define MSTATUS_SUM 0x00040000
#define MSTATUS_MXR 0x00080000
#define MSTATUS_VM 0x1F000000
#define MSTATUS_TVM 0x00100000
#define MSTATUS_TW 0x00200000
#define MSTATUS_TSR 0x00400000
#define MSTATUS32_SD 0x80000000
#define MSTATUS_UXL 0x0000000300000000
#define MSTATUS_SXL 0x0000000C00000000
#define MSTATUS64_SD 0x8000000000000000
#define SSTATUS_UIE 0x00000001
@ -30,8 +34,10 @@
#define SSTATUS_SPP 0x00000100
#define SSTATUS_FS 0x00006000
#define SSTATUS_XS 0x00018000
#define SSTATUS_PUM 0x00040000
#define SSTATUS_SUM 0x00040000
#define SSTATUS_MXR 0x00080000
#define SSTATUS32_SD 0x80000000
#define SSTATUS_UXL 0x0000000300000000
#define SSTATUS64_SD 0x8000000000000000
#define DCSR_XDEBUGVER (3U<<30)
@ -107,12 +113,30 @@
#define PRV_H 2
#define PRV_M 3
#define VM_MBARE 0
#define VM_MBB 1
#define VM_MBBID 2
#define VM_SV32 8
#define VM_SV39 9
#define VM_SV48 10
#define SATP32_MODE 0x80000000
#define SATP32_ASID 0x7FC00000
#define SATP32_PPN 0x003FFFFF
#define SATP64_MODE 0xF000000000000000
#define SATP64_ASID 0x0FFFF00000000000
#define SATP64_PPN 0x00000FFFFFFFFFFF
#define SATP_MODE_OFF 0
#define SATP_MODE_SV32 1
#define SATP_MODE_SV39 8
#define SATP_MODE_SV48 9
#define SATP_MODE_SV57 10
#define SATP_MODE_SV64 11
#define PMP_R 0x01
#define PMP_W 0x02
#define PMP_X 0x04
#define PMP_A 0x18
#define PMP_L 0x80
#define PMP_SHIFT 2
#define PMP_TOR 0x08
#define PMP_NA4 0x10
#define PMP_NAPOT 0x18
#define IRQ_S_SOFT 1
#define IRQ_H_SOFT 2
@ -127,9 +151,8 @@
#define IRQ_HOST 13
#define DEFAULT_RSTVEC 0x00001000
#define DEFAULT_NMIVEC 0x00001004
#define DEFAULT_MTVEC 0x00001010
#define CONFIG_STRING_ADDR 0x0000100C
#define CLINT_BASE 0x02000000
#define CLINT_SIZE 0x000c0000
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
@ -150,14 +173,16 @@
#ifdef __riscv
#ifdef __riscv64
#if __riscv_xlen == 64
# define MSTATUS_SD MSTATUS64_SD
# define SSTATUS_SD SSTATUS64_SD
# define RISCV_PGLEVEL_BITS 9
# define SATP_MODE SATP64_MODE
#else
# define MSTATUS_SD MSTATUS32_SD
# define SSTATUS_SD SSTATUS32_SD
# define RISCV_PGLEVEL_BITS 10
# define SATP_MODE SATP32_MODE
#endif
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
@ -171,30 +196,18 @@
__tmp; })
#define write_csr(reg, val) ({ \
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
else \
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
asm volatile ("csrw " #reg ", %0" :: "rK"(val)); })
#define swap_csr(reg, val) ({ unsigned long __tmp; \
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
else \
asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
__tmp; })
#define set_csr(reg, bit) ({ unsigned long __tmp; \
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
else \
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
__tmp; })
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
else \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
__tmp; })
#define rdtime() read_csr(time)
@ -208,7 +221,7 @@
#endif
#endif
/* Automatically generated by parse-opcodes */
/* Automatically generated by parse-opcodes. */
#ifndef RISCV_ENCODING_H
#define RISCV_ENCODING_H
#define MATCH_BEQ 0x63
@ -391,14 +404,12 @@
#define MASK_URET 0xffffffff
#define MATCH_SRET 0x10200073
#define MASK_SRET 0xffffffff
#define MATCH_HRET 0x20200073
#define MASK_HRET 0xffffffff
#define MATCH_MRET 0x30200073
#define MASK_MRET 0xffffffff
#define MATCH_DRET 0x7b200073
#define MASK_DRET 0xffffffff
#define MATCH_SFENCE_VM 0x10400073
#define MASK_SFENCE_VM 0xfff07fff
#define MATCH_SFENCE_VMA 0x12000073
#define MASK_SFENCE_VMA 0xfe007fff
#define MATCH_WFI 0x10500073
#define MASK_WFI 0xffffffff
#define MATCH_CSRRW 0x1073
@ -457,6 +468,34 @@
#define MASK_FCVT_D_S 0xfff0007f
#define MATCH_FSQRT_D 0x5a000053
#define MASK_FSQRT_D 0xfff0007f
#define MATCH_FADD_Q 0x6000053
#define MASK_FADD_Q 0xfe00007f
#define MATCH_FSUB_Q 0xe000053
#define MASK_FSUB_Q 0xfe00007f
#define MATCH_FMUL_Q 0x16000053
#define MASK_FMUL_Q 0xfe00007f
#define MATCH_FDIV_Q 0x1e000053
#define MASK_FDIV_Q 0xfe00007f
#define MATCH_FSGNJ_Q 0x26000053
#define MASK_FSGNJ_Q 0xfe00707f
#define MATCH_FSGNJN_Q 0x26001053
#define MASK_FSGNJN_Q 0xfe00707f
#define MATCH_FSGNJX_Q 0x26002053
#define MASK_FSGNJX_Q 0xfe00707f
#define MATCH_FMIN_Q 0x2e000053
#define MASK_FMIN_Q 0xfe00707f
#define MATCH_FMAX_Q 0x2e001053
#define MASK_FMAX_Q 0xfe00707f
#define MATCH_FCVT_S_Q 0x40300053
#define MASK_FCVT_S_Q 0xfff0007f
#define MATCH_FCVT_Q_S 0x46000053
#define MASK_FCVT_Q_S 0xfff0007f
#define MATCH_FCVT_D_Q 0x42300053
#define MASK_FCVT_D_Q 0xfff0007f
#define MATCH_FCVT_Q_D 0x46100053
#define MASK_FCVT_Q_D 0xfff0007f
#define MATCH_FSQRT_Q 0x5e000053
#define MASK_FSQRT_Q 0xfff0007f
#define MATCH_FLE_S 0xa0000053
#define MASK_FLE_S 0xfe00707f
#define MATCH_FLT_S 0xa0001053
@ -469,6 +508,12 @@
#define MASK_FLT_D 0xfe00707f
#define MATCH_FEQ_D 0xa2002053
#define MASK_FEQ_D 0xfe00707f
#define MATCH_FLE_Q 0xa6000053
#define MASK_FLE_Q 0xfe00707f
#define MATCH_FLT_Q 0xa6001053
#define MASK_FLT_Q 0xfe00707f
#define MATCH_FEQ_Q 0xa6002053
#define MASK_FEQ_Q 0xfe00707f
#define MATCH_FCVT_W_S 0xc0000053
#define MASK_FCVT_W_S 0xfff0007f
#define MATCH_FCVT_WU_S 0xc0100053
@ -477,8 +522,8 @@
#define MASK_FCVT_L_S 0xfff0007f
#define MATCH_FCVT_LU_S 0xc0300053
#define MASK_FCVT_LU_S 0xfff0007f
#define MATCH_FMV_X_S 0xe0000053
#define MASK_FMV_X_S 0xfff0707f
#define MATCH_FMV_X_W 0xe0000053
#define MASK_FMV_X_W 0xfff0707f
#define MATCH_FCLASS_S 0xe0001053
#define MASK_FCLASS_S 0xfff0707f
#define MATCH_FCVT_W_D 0xc2000053
@ -493,6 +538,18 @@
#define MASK_FMV_X_D 0xfff0707f
#define MATCH_FCLASS_D 0xe2001053
#define MASK_FCLASS_D 0xfff0707f
#define MATCH_FCVT_W_Q 0xc6000053
#define MASK_FCVT_W_Q 0xfff0007f
#define MATCH_FCVT_WU_Q 0xc6100053
#define MASK_FCVT_WU_Q 0xfff0007f
#define MATCH_FCVT_L_Q 0xc6200053
#define MASK_FCVT_L_Q 0xfff0007f
#define MATCH_FCVT_LU_Q 0xc6300053
#define MASK_FCVT_LU_Q 0xfff0007f
#define MATCH_FMV_X_Q 0xe6000053
#define MASK_FMV_X_Q 0xfff0707f
#define MATCH_FCLASS_Q 0xe6001053
#define MASK_FCLASS_Q 0xfff0707f
#define MATCH_FCVT_S_W 0xd0000053
#define MASK_FCVT_S_W 0xfff0007f
#define MATCH_FCVT_S_WU 0xd0100053
@ -501,8 +558,8 @@
#define MASK_FCVT_S_L 0xfff0007f
#define MATCH_FCVT_S_LU 0xd0300053
#define MASK_FCVT_S_LU 0xfff0007f
#define MATCH_FMV_S_X 0xf0000053
#define MASK_FMV_S_X 0xfff0707f
#define MATCH_FMV_W_X 0xf0000053
#define MASK_FMV_W_X 0xfff0707f
#define MATCH_FCVT_D_W 0xd2000053
#define MASK_FCVT_D_W 0xfff0007f
#define MATCH_FCVT_D_WU 0xd2100053
@ -513,14 +570,28 @@
#define MASK_FCVT_D_LU 0xfff0007f
#define MATCH_FMV_D_X 0xf2000053
#define MASK_FMV_D_X 0xfff0707f
#define MATCH_FCVT_Q_W 0xd6000053
#define MASK_FCVT_Q_W 0xfff0007f
#define MATCH_FCVT_Q_WU 0xd6100053
#define MASK_FCVT_Q_WU 0xfff0007f
#define MATCH_FCVT_Q_L 0xd6200053
#define MASK_FCVT_Q_L 0xfff0007f
#define MATCH_FCVT_Q_LU 0xd6300053
#define MASK_FCVT_Q_LU 0xfff0007f
#define MATCH_FMV_Q_X 0xf6000053
#define MASK_FMV_Q_X 0xfff0707f
#define MATCH_FLW 0x2007
#define MASK_FLW 0x707f
#define MATCH_FLD 0x3007
#define MASK_FLD 0x707f
#define MATCH_FLQ 0x4007
#define MASK_FLQ 0x707f
#define MATCH_FSW 0x2027
#define MASK_FSW 0x707f
#define MATCH_FSD 0x3027
#define MASK_FSD 0x707f
#define MATCH_FSQ 0x4027
#define MASK_FSQ 0x707f
#define MATCH_FMADD_S 0x43
#define MASK_FMADD_S 0x600007f
#define MATCH_FMSUB_S 0x47
@ -537,6 +608,14 @@
#define MASK_FNMSUB_D 0x600007f
#define MATCH_FNMADD_D 0x200004f
#define MASK_FNMADD_D 0x600007f
#define MATCH_FMADD_Q 0x6000043
#define MASK_FMADD_Q 0x600007f
#define MATCH_FMSUB_Q 0x6000047
#define MASK_FMSUB_Q 0x600007f
#define MATCH_FNMSUB_Q 0x600004b
#define MASK_FNMSUB_Q 0x600007f
#define MATCH_FNMADD_Q 0x600004f
#define MASK_FNMADD_Q 0x600007f
#define MATCH_C_NOP 0x1
#define MASK_C_NOP 0xffff
#define MATCH_C_ADDI16SP 0x6101
@ -707,23 +786,45 @@
#define CSR_SSTATUS 0x100
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
#define CSR_SBADADDR 0x143
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_SPTBR 0x180
#define CSR_SATP 0x180
#define CSR_MSTATUS 0x300
#define CSR_MISA 0x301
#define CSR_MEDELEG 0x302
#define CSR_MIDELEG 0x303
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MCOUNTEREN 0x306
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MBADADDR 0x343
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
#define CSR_PMPCFG0 0x3a0
#define CSR_PMPCFG1 0x3a1
#define CSR_PMPCFG2 0x3a2
#define CSR_PMPCFG3 0x3a3
#define CSR_PMPADDR0 0x3b0
#define CSR_PMPADDR1 0x3b1
#define CSR_PMPADDR2 0x3b2
#define CSR_PMPADDR3 0x3b3
#define CSR_PMPADDR4 0x3b4
#define CSR_PMPADDR5 0x3b5
#define CSR_PMPADDR6 0x3b6
#define CSR_PMPADDR7 0x3b7
#define CSR_PMPADDR8 0x3b8
#define CSR_PMPADDR9 0x3b9
#define CSR_PMPADDR10 0x3ba
#define CSR_PMPADDR11 0x3bb
#define CSR_PMPADDR12 0x3bc
#define CSR_PMPADDR13 0x3bd
#define CSR_PMPADDR14 0x3be
#define CSR_PMPADDR15 0x3bf
#define CSR_TSELECT 0x7a0
#define CSR_TDATA1 0x7a1
#define CSR_TDATA2 0x7a2
@ -762,8 +863,6 @@
#define CSR_MHPMCOUNTER29 0xb1d
#define CSR_MHPMCOUNTER30 0xb1e
#define CSR_MHPMCOUNTER31 0xb1f
#define CSR_MUCOUNTEREN 0x320
#define CSR_MSCOUNTEREN 0x321
#define CSR_MHPMEVENT3 0x323
#define CSR_MHPMEVENT4 0x324
#define CSR_MHPMEVENT5 0x325
@ -861,17 +960,20 @@
#define CSR_MHPMCOUNTER30H 0xb9e
#define CSR_MHPMCOUNTER31H 0xb9f
#define CAUSE_MISALIGNED_FETCH 0x0
#define CAUSE_FAULT_FETCH 0x1
#define CAUSE_FETCH_ACCESS 0x1
#define CAUSE_ILLEGAL_INSTRUCTION 0x2
#define CAUSE_BREAKPOINT 0x3
#define CAUSE_MISALIGNED_LOAD 0x4
#define CAUSE_FAULT_LOAD 0x5
#define CAUSE_LOAD_ACCESS 0x5
#define CAUSE_MISALIGNED_STORE 0x6
#define CAUSE_FAULT_STORE 0x7
#define CAUSE_STORE_ACCESS 0x7
#define CAUSE_USER_ECALL 0x8
#define CAUSE_SUPERVISOR_ECALL 0x9
#define CAUSE_HYPERVISOR_ECALL 0xa
#define CAUSE_MACHINE_ECALL 0xb
#define CAUSE_FETCH_PAGE_FAULT 0xc
#define CAUSE_LOAD_PAGE_FAULT 0xd
#define CAUSE_STORE_PAGE_FAULT 0xf
#endif
#ifdef DECLARE_INSN
DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
@ -964,10 +1066,9 @@ DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
DECLARE_INSN(uret, MATCH_URET, MASK_URET)
DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
DECLARE_INSN(hret, MATCH_HRET, MASK_HRET)
DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA)
DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
@ -997,17 +1098,34 @@ DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q)
DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q)
DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q)
DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q)
DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q)
DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q)
DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q)
DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q)
DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q)
DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q)
DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S)
DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q)
DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D)
DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q)
DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q)
DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q)
DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q)
DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W)
DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
@ -1015,20 +1133,33 @@ DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q)
DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q)
DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q)
DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q)
DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q)
DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q)
DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X)
DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W)
DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU)
DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L)
DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU)
DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X)
DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ)
DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ)
DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
@ -1037,6 +1168,10 @@ DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q)
DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q)
DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q)
DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q)
DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
@ -1143,23 +1278,45 @@ DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
DECLARE_CSR(sstatus, CSR_SSTATUS)
DECLARE_CSR(sie, CSR_SIE)
DECLARE_CSR(stvec, CSR_STVEC)
DECLARE_CSR(scounteren, CSR_SCOUNTEREN)
DECLARE_CSR(sscratch, CSR_SSCRATCH)
DECLARE_CSR(sepc, CSR_SEPC)
DECLARE_CSR(scause, CSR_SCAUSE)
DECLARE_CSR(sbadaddr, CSR_SBADADDR)
DECLARE_CSR(stval, CSR_STVAL)
DECLARE_CSR(sip, CSR_SIP)
DECLARE_CSR(sptbr, CSR_SPTBR)
DECLARE_CSR(satp, CSR_SATP)
DECLARE_CSR(mstatus, CSR_MSTATUS)
DECLARE_CSR(misa, CSR_MISA)
DECLARE_CSR(medeleg, CSR_MEDELEG)
DECLARE_CSR(mideleg, CSR_MIDELEG)
DECLARE_CSR(mie, CSR_MIE)
DECLARE_CSR(mtvec, CSR_MTVEC)
DECLARE_CSR(mcounteren, CSR_MCOUNTEREN)
DECLARE_CSR(mscratch, CSR_MSCRATCH)
DECLARE_CSR(mepc, CSR_MEPC)
DECLARE_CSR(mcause, CSR_MCAUSE)
DECLARE_CSR(mbadaddr, CSR_MBADADDR)
DECLARE_CSR(mtval, CSR_MTVAL)
DECLARE_CSR(mip, CSR_MIP)
DECLARE_CSR(pmpcfg0, CSR_PMPCFG0)
DECLARE_CSR(pmpcfg1, CSR_PMPCFG1)
DECLARE_CSR(pmpcfg2, CSR_PMPCFG2)
DECLARE_CSR(pmpcfg3, CSR_PMPCFG3)
DECLARE_CSR(pmpaddr0, CSR_PMPADDR0)
DECLARE_CSR(pmpaddr1, CSR_PMPADDR1)
DECLARE_CSR(pmpaddr2, CSR_PMPADDR2)
DECLARE_CSR(pmpaddr3, CSR_PMPADDR3)
DECLARE_CSR(pmpaddr4, CSR_PMPADDR4)
DECLARE_CSR(pmpaddr5, CSR_PMPADDR5)
DECLARE_CSR(pmpaddr6, CSR_PMPADDR6)
DECLARE_CSR(pmpaddr7, CSR_PMPADDR7)
DECLARE_CSR(pmpaddr8, CSR_PMPADDR8)
DECLARE_CSR(pmpaddr9, CSR_PMPADDR9)
DECLARE_CSR(pmpaddr10, CSR_PMPADDR10)
DECLARE_CSR(pmpaddr11, CSR_PMPADDR11)
DECLARE_CSR(pmpaddr12, CSR_PMPADDR12)
DECLARE_CSR(pmpaddr13, CSR_PMPADDR13)
DECLARE_CSR(pmpaddr14, CSR_PMPADDR14)
DECLARE_CSR(pmpaddr15, CSR_PMPADDR15)
DECLARE_CSR(tselect, CSR_TSELECT)
DECLARE_CSR(tdata1, CSR_TDATA1)
DECLARE_CSR(tdata2, CSR_TDATA2)
@ -1198,8 +1355,6 @@ DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
@ -1299,15 +1454,18 @@ DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
#endif
#ifdef DECLARE_CAUSE
DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH)
DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS)
DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD)
DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS)
DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE)
DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS)
DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT)
DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT)
DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT)
#endif

View File

@ -1,18 +1,79 @@
#ifndef TARGET__RISCV__GDB_REGS_H
#define TARGET__RISCV__GDB_REGS_H
// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
// its source tree. We must interpret the numbers the same here.
/* gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
* its source tree. We must interpret the numbers the same here. */
enum gdb_regno {
GDB_REGNO_XPR0 = 0,
GDB_REGNO_X0 = GDB_REGNO_XPR0 + 0,
GDB_REGNO_ZERO = GDB_REGNO_XPR0 + 0,
GDB_REGNO_S0 = GDB_REGNO_XPR0 + 8,
GDB_REGNO_S1 = GDB_REGNO_XPR0 + 9,
GDB_REGNO_XPR31 = GDB_REGNO_XPR0 + 31,
GDB_REGNO_ZERO = 0, /* Read-only register, always 0. */
GDB_REGNO_RA = 1, /* Return Address. */
GDB_REGNO_SP = 2, /* Stack Pointer. */
GDB_REGNO_GP = 3, /* Global Pointer. */
GDB_REGNO_TP = 4, /* Thread Pointer. */
GDB_REGNO_T0,
GDB_REGNO_T1,
GDB_REGNO_T2,
GDB_REGNO_S0 = 8,
GDB_REGNO_FP = 8, /* Frame Pointer. */
GDB_REGNO_S1,
GDB_REGNO_A0 = 10, /* First argument. */
GDB_REGNO_A1 = 11, /* Second argument. */
GDB_REGNO_A2,
GDB_REGNO_A3,
GDB_REGNO_A4,
GDB_REGNO_A5,
GDB_REGNO_A6,
GDB_REGNO_A7,
GDB_REGNO_S2,
GDB_REGNO_S3,
GDB_REGNO_S4,
GDB_REGNO_S5,
GDB_REGNO_S6,
GDB_REGNO_S7,
GDB_REGNO_S8,
GDB_REGNO_S9,
GDB_REGNO_S10,
GDB_REGNO_S11,
GDB_REGNO_T3,
GDB_REGNO_T4,
GDB_REGNO_T5,
GDB_REGNO_T6,
GDB_REGNO_XPR31 = GDB_REGNO_T6,
GDB_REGNO_PC = 32,
GDB_REGNO_FPR0 = 33,
GDB_REGNO_FPR31 = GDB_REGNO_FPR0 + 31,
GDB_REGNO_FT0 = GDB_REGNO_FPR0,
GDB_REGNO_FT1,
GDB_REGNO_FT2,
GDB_REGNO_FT3,
GDB_REGNO_FT4,
GDB_REGNO_FT5,
GDB_REGNO_FT6,
GDB_REGNO_FT7,
GDB_REGNO_FS0,
GDB_REGNO_FS1,
GDB_REGNO_FA0,
GDB_REGNO_FA1,
GDB_REGNO_FA2,
GDB_REGNO_FA3,
GDB_REGNO_FA4,
GDB_REGNO_FA5,
GDB_REGNO_FA6,
GDB_REGNO_FA7,
GDB_REGNO_FS2,
GDB_REGNO_FS3,
GDB_REGNO_FS4,
GDB_REGNO_FS5,
GDB_REGNO_FS6,
GDB_REGNO_FS7,
GDB_REGNO_FS8,
GDB_REGNO_FS9,
GDB_REGNO_FS10,
GDB_REGNO_FS11,
GDB_REGNO_FT8,
GDB_REGNO_FT9,
GDB_REGNO_FT10,
GDB_REGNO_FT11,
GDB_REGNO_FPR31 = GDB_REGNO_FT11,
GDB_REGNO_CSR0 = 65,
GDB_REGNO_TSELECT = CSR_TSELECT + GDB_REGNO_CSR0,
GDB_REGNO_TDATA1 = CSR_TDATA1 + GDB_REGNO_CSR0,

View File

@ -5,16 +5,19 @@
#define S0 8
#define S1 9
static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo)
{
return (value >> lo) & ((1 << (hi+1-lo)) - 1);
}
static uint32_t bit(uint32_t value, unsigned int b) {
static uint32_t bit(uint32_t value, unsigned int b)
{
return (value >> b) & 1;
}
static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
static uint32_t jal(unsigned int rd, uint32_t imm) {
static uint32_t jal(unsigned int rd, uint32_t imm)
{
return (bit(imm, 20) << 31) |
(bits(imm, 10, 1) << 21) |
(bit(imm, 11) << 20) |
@ -24,7 +27,8 @@ static uint32_t jal(unsigned int rd, uint32_t imm) {
}
static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrsi(unsigned int csr, uint16_t imm) {
static uint32_t csrsi(unsigned int csr, uint16_t imm)
{
return (csr << 20) |
(bits(imm, 4, 0) << 15) |
MATCH_CSRRSI;
@ -107,7 +111,8 @@ static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
}
static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
static uint32_t csrw(unsigned int source, unsigned int csr) {
static uint32_t csrw(unsigned int source, unsigned int csr)
{
return (csr << 20) | (source << 15) | MATCH_CSRRW;
}
@ -121,17 +126,20 @@ static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
}
static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
static uint32_t csrr(unsigned int rd, unsigned int csr) {
static uint32_t csrr(unsigned int rd, unsigned int csr)
{
return (csr << 20) | (rd << 7) | MATCH_CSRRS;
}
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) {
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr)
{
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRS;
}
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) {
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr)
{
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRW;
}
@ -173,12 +181,12 @@ static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
MATCH_FLD;
}
static uint32_t fmv_x_s(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_x_s(unsigned dest, unsigned src)
static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_x_w(unsigned dest, unsigned src)
{
return src << 15 |
dest << 7 |
MATCH_FMV_X_S;
MATCH_FMV_X_W;
}
static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused));
@ -189,12 +197,12 @@ static uint32_t fmv_x_d(unsigned dest, unsigned src)
MATCH_FMV_X_D;
}
static uint32_t fmv_s_x(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_s_x(unsigned dest, unsigned src)
static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused));
static uint32_t fmv_w_x(unsigned dest, unsigned src)
{
return src << 15 |
dest << 7 |
MATCH_FMV_S_X;
MATCH_FMV_W_X;
}
static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused));
@ -206,9 +214,15 @@ static uint32_t fmv_d_x(unsigned dest, unsigned src)
}
static uint32_t ebreak(void) __attribute__ ((unused));
static uint32_t ebreak(void) { return MATCH_EBREAK; }
static uint32_t ebreak(void)
{
return MATCH_EBREAK;
}
static uint32_t ebreak_c(void) __attribute__ ((unused));
static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
static uint32_t ebreak_c(void)
{
return MATCH_C_EBREAK;
}
static uint32_t wfi(void) __attribute__ ((unused));
static uint32_t wfi(void) { return MATCH_WFI; }
@ -229,7 +243,8 @@ static uint32_t lui(unsigned int dest, uint32_t imm)
/*
static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrci(unsigned int csr, uint16_t imm) {
static uint32_t csrci(unsigned int csr, uint16_t imm)
{
return (csr << 20) |
(bits(imm, 4, 0) << 15) |
MATCH_CSRRCI;

View File

@ -11,78 +11,57 @@
#include "asm.h"
#include "encoding.h"
riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr);
int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
/* Program interface. */
int riscv_program_init(struct riscv_program *p, struct target *target)
{
memset(p, 0, sizeof(*p));
p->target = target;
p->instruction_count = 0;
p->data_count = 0;
p->writes_memory = 0;
p->target_xlen = riscv_xlen(target);
for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i) {
for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i)
p->writes_xreg[i] = 0;
p->in_use[i] = 0;
}
for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
for (size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
p->debug_buffer[i] = -1;
if (riscv_debug_buffer_enter(target, p) != ERROR_OK) {
LOG_ERROR("unable to write progam buffer enter code");
return ERROR_FAIL;
}
return ERROR_OK;
}
int riscv_program_write(struct riscv_program *program)
{
for (unsigned i = 0; i < program->instruction_count; ++i) {
LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", program, i, program->debug_buffer[i]);
if (riscv_write_debug_buffer(program->target, i,
program->debug_buffer[i]) != ERROR_OK)
return ERROR_FAIL;
}
return ERROR_OK;
}
/** Add ebreak and execute the program. */
int riscv_program_exec(struct riscv_program *p, struct target *t)
{
keep_alive();
if (riscv_debug_buffer_leave(t, p) != ERROR_OK) {
LOG_ERROR("unable to write program buffer exit code");
return ERROR_FAIL;
}
riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1];
for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) {
for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) {
if (p->writes_xreg[i]) {
LOG_DEBUG("Saving register %d as used by program", (int)i);
saved_registers[i] = riscv_get_register(t, i);
int result = riscv_get_register(t, &saved_registers[i], i);
if (result != ERROR_OK)
return result;
}
}
if (p->writes_memory && (riscv_program_fence(p) != ERROR_OK)) {
LOG_ERROR("Unable to write fence");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", (int)i, (long)p->debug_buffer[i], (long)p->debug_buffer[i]);
abort();
return ERROR_FAIL;
}
if (riscv_program_ebreak(p) != ERROR_OK) {
LOG_ERROR("Unable to write ebreak");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", (int)i, (long)p->debug_buffer[i], (long)p->debug_buffer[i]);
abort();
return ERROR_FAIL;
}
for (unsigned i = 0; i < riscv_debug_buffer_size(p->target); ++i) {
if (i < p->instruction_count) {
LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", p, i, p->debug_buffer[i]);
riscv_write_debug_buffer(t, i, p->debug_buffer[i]);
}
if (i >= riscv_debug_buffer_size(p->target) - p->data_count) {
LOG_DEBUG("%p: debug_buffer[%02x] = 0x%08x", p, i, p->debug_buffer[i]);
riscv_write_debug_buffer(t, i, p->debug_buffer[i]);
}
}
if (riscv_program_write(p) != ERROR_OK)
return ERROR_FAIL;
if (riscv_execute_debug_buffer(t) != ERROR_OK) {
LOG_ERROR("Unable to execute program %p", p);
@ -90,259 +69,56 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
}
for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
if (i >= riscv_debug_buffer_size(p->target) - p->data_count)
if (i >= riscv_debug_buffer_size(p->target))
p->debug_buffer[i] = riscv_read_debug_buffer(t, i);
for (size_t i = GDB_REGNO_XPR0; i <= GDB_REGNO_XPR31; ++i)
for (size_t i = GDB_REGNO_ZERO; i <= GDB_REGNO_XPR31; ++i)
if (p->writes_xreg[i])
riscv_set_register(t, i, saved_registers[i]);
return ERROR_OK;
}
riscv_addr_t riscv_program_alloc_data(struct riscv_program *p, size_t bytes)
{
riscv_addr_t addr =
riscv_debug_buffer_addr(p->target)
+ riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])
- p->data_count * sizeof(p->debug_buffer[0])
- bytes;
while (addr % bytes != 0) addr--;
riscv_addr_t ptop =
riscv_debug_buffer_addr(p->target)
+ p->instruction_count * sizeof(p->debug_buffer[0]);
if (addr <= ptop) {
LOG_ERROR("unable to allocate %d bytes", (int)bytes);
return RISCV_PROGRAM_ALLOC_FAIL;
}
p->data_count =
+ riscv_debug_buffer_size(p->target)
- (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
return addr;
}
riscv_addr_t riscv_program_alloc_x(struct riscv_program *p)
{
return riscv_program_alloc_data(p, p->target_xlen / 8);
}
riscv_addr_t riscv_program_alloc_d(struct riscv_program *p)
{
return riscv_program_alloc_data(p, 8);
}
riscv_addr_t riscv_program_alloc_w(struct riscv_program *p)
{
return riscv_program_alloc_data(p, 4);
}
riscv_addr_t riscv_program_alloc_h(struct riscv_program *p)
{
return riscv_program_alloc_data(p, 2);
}
riscv_addr_t riscv_program_alloc_b(struct riscv_program *p)
{
return riscv_program_alloc_data(p, 1);
}
riscv_insn_t riscv_program_read_ram(struct riscv_program *p, riscv_addr_t addr)
{
if (addr < riscv_debug_buffer_addr(p->target))
return -1;
if ((size_t)addr > riscv_debug_buffer_addr(p->target) + (riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])))
return -1;
int off = (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
return p->debug_buffer[off];
}
void riscv_program_write_ram(struct riscv_program *p, riscv_addr_t addr, uint64_t d)
{
if (addr < riscv_debug_buffer_addr(p->target))
return;
if ((size_t)addr > riscv_debug_buffer_addr(p->target) + (riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])))
return;
int off = (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
p->debug_buffer[off] = d;
}
int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, sw(d, b, offset));
}
int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, sh(d, b, offset));
}
int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, sb(d, b, offset));
}
int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, lw(d, b, offset));
}
int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, lh(d, b, offset));
}
int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{
p->writes_memory = 1;
return riscv_program_insert(p, lb(d, b, offset));
}
int riscv_program_lx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
switch (p->target_xlen) {
case 64: return riscv_program_ld(p, d, addr);
case 32: return riscv_program_lw(p, d, addr);
}
LOG_ERROR("unknown xlen %d", p->target_xlen);
abort();
return -1;
}
int riscv_program_ld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, ld(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lw(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lh(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lb(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_sx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
switch (p->target_xlen) {
case 64: return riscv_program_sd(p, d, addr);
case 32: return riscv_program_sw(p, d, addr);
}
LOG_ERROR("unknown xlen %d", p->target_xlen);
abort();
return -1;
}
int riscv_program_sd(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sd(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sw(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sh(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sb(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr)
{
assert(csr >= GDB_REGNO_CSR0);
return riscv_program_insert(p, csrrs(d, GDB_REGNO_X0, csr - GDB_REGNO_CSR0));
assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
return riscv_program_insert(p, csrrs(d, GDB_REGNO_ZERO, csr - GDB_REGNO_CSR0));
}
int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr)
{
assert(csr >= GDB_REGNO_CSR0);
return riscv_program_insert(p, csrrw(GDB_REGNO_X0, s, csr - GDB_REGNO_CSR0));
}
int riscv_program_csrrw(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, enum gdb_regno csr)
{
assert(csr >= GDB_REGNO_CSR0);
return riscv_program_insert(p, csrrw(d, s, csr - GDB_REGNO_CSR0));
return riscv_program_insert(p, csrrw(GDB_REGNO_ZERO, s, csr - GDB_REGNO_CSR0));
}
int riscv_program_fence_i(struct riscv_program *p)
@ -357,156 +133,25 @@ int riscv_program_fence(struct riscv_program *p)
int riscv_program_ebreak(struct riscv_program *p)
{
struct target *target = p->target;
RISCV_INFO(r);
if (p->instruction_count == riscv_debug_buffer_size(p->target) &&
r->impebreak) {
return ERROR_OK;
}
return riscv_program_insert(p, ebreak());
}
int riscv_program_lui(struct riscv_program *p, enum gdb_regno d, int32_t u)
{
return riscv_program_insert(p, lui(d, u));
}
int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t u)
{
return riscv_program_insert(p, addi(d, s, u));
}
int riscv_program_fsx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
assert(d >= GDB_REGNO_FPR0);
assert(d <= GDB_REGNO_FPR31);
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
uint32_t instruction;
switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) {
case 64:
instruction = fsd(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
case 32:
instruction = fsw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
default:
return ERROR_FAIL;
}
if (riscv_program_insert(p, instruction) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
assert(d >= GDB_REGNO_FPR0);
assert(d <= GDB_REGNO_FPR31);
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
uint32_t instruction;
switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) {
case 64:
instruction = fld(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
case 32:
instruction = flw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
default:
return ERROR_FAIL;
}
if (riscv_program_insert(p, instruction) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_li(struct riscv_program *p, enum gdb_regno d, riscv_reg_t c)
{
if (riscv_program_lui(p, d, c >> 12) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_addi(p, d, d, c & 0xFFF) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_dont_restore_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 0;
return ERROR_OK;
}
int riscv_program_do_restore_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 1;
return ERROR_OK;
}
void riscv_program_reserve_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
assert(p->in_use[r] == 0);
p->in_use[r] = 1;
}
enum gdb_regno riscv_program_gettemp(struct riscv_program *p)
{
for (size_t i = GDB_REGNO_S0; i <= GDB_REGNO_XPR31; ++i) {
if (p->in_use[i]) continue;
riscv_program_do_restore_register(p, i);
p->in_use[i] = 1;
return i;
}
LOG_ERROR("You've run out of temporary registers. This is impossible.");
abort();
}
void riscv_program_puttemp(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->in_use[r] = 0;
}
/* Helper functions. */
riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr)
{
return addr >> 12;
}
riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr)
{
if (addr > 0) {
return (addr & 0x7FF);
} else {
return 0;
}
}
int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
riscv_addr_t ah = riscv_program_gah(p, addr);
if (ah == 0)
return ERROR_OK;
return riscv_program_lui(p, d, ah);
}
int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
riscv_addr_t al = riscv_program_gal(p, addr);
if (al == 0)
return ERROR_OK;
return riscv_program_addi(p, d, d, al);
}
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
{
if (p->instruction_count + p->data_count + 1 > riscv_debug_buffer_size(p->target)) {
if (p->instruction_count >= riscv_debug_buffer_size(p->target)) {
LOG_ERROR("Unable to insert instruction:");
LOG_ERROR(" instruction_count=%d", (int)p->instruction_count);
LOG_ERROR(" data_count =%d", (int)p->data_count);
LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target));
return ERROR_FAIL;
}

View File

@ -15,23 +15,12 @@ struct riscv_program {
uint32_t debug_buffer[RISCV_MAX_DEBUG_BUFFER_SIZE];
/* The debug buffer is allocated in two directions: instructions go at
* the start, while data goes at the end. When they meet in the middle
* this blows up. */
/* Number of 32-bit instructions in the program. */
size_t instruction_count;
size_t data_count;
/* Side effects of executing this program. These must be accounted for
* in order to maintain correct executing of the target system. */
bool writes_xreg[RISCV_REGISTER_COUNT];
bool writes_memory;
/* When a register is used it will be set in this array. */
bool in_use[RISCV_REGISTER_COUNT];
/* Remembers the registers that have been saved into dscratch
* registers. These are restored */
enum gdb_regno dscratch_saved[RISCV_DSCRATCH_COUNT];
/* XLEN on the target. */
int target_xlen;
@ -40,6 +29,9 @@ struct riscv_program {
/* Initializes a program with the header. */
int riscv_program_init(struct riscv_program *p, struct target *t);
/* Write the program to the program buffer. */
int riscv_program_write(struct riscv_program *program);
/* Executes a program, returning 0 if the program successfully executed. Note
* that this may cause registers to be saved or restored, which could result to
* calls to things like riscv_save_register which itself could require a
@ -60,83 +52,24 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i);
* memory. */
int riscv_program_save_to_dscratch(struct riscv_program *p, enum gdb_regno to_save);
/* Allocates data of various sizes. Either returns the absolute physical
* address or RISCV_PROGRAM_ALLOC_FAIL on failure. */
riscv_addr_t riscv_program_alloc_data(struct riscv_program *p, size_t bytes);
riscv_addr_t riscv_program_alloc_x(struct riscv_program *p);
riscv_addr_t riscv_program_alloc_d(struct riscv_program *p);
riscv_addr_t riscv_program_alloc_w(struct riscv_program *p);
riscv_addr_t riscv_program_alloc_h(struct riscv_program *p);
riscv_addr_t riscv_program_alloc_b(struct riscv_program *p);
#define RISCV_PROGRAM_ALLOC_FAIL ((riscv_addr_t)(-1))
/* Reads a word of memory from this program's internal view of the debug RAM.
* This is what you want to use to get data back from the program after it
* executes. */
riscv_insn_t riscv_program_read_ram(struct riscv_program *p, riscv_addr_t addr);
void riscv_program_write_ram(struct riscv_program *p, riscv_addr_t a, uint64_t d);
/* Helpers to assembly various instructions. Return 0 on success. These might
* assembly into a multi-instruction sequence that overwrites some other
* register, but those will be properly saved and restored. */
int riscv_program_lx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_ld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_sx(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sd(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sw(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sh(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sb(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_lxr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_sxr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_sdr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_swr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_shr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_sbr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr);
int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr);
int riscv_program_csrrw(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, enum gdb_regno csr);
int riscv_program_fence_i(struct riscv_program *p);
int riscv_program_fence(struct riscv_program *p);
int riscv_program_ebreak(struct riscv_program *p);
int riscv_program_lui(struct riscv_program *p, enum gdb_regno d, int32_t u);
int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t i);
int riscv_program_fsx(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
/* Assembler macros. */
int riscv_program_li(struct riscv_program *p, enum gdb_regno d, riscv_reg_t c);
int riscv_program_la(struct riscv_program *p, enum gdb_regno d, riscv_addr_t a);
/* Register allocation. The user is expected to have obtained temporary
* registers using these fuctions. Additionally, there is an interface for
* reserving registers -- it's expected that this has been called as the first
* thing in the program's execution to reserve registers that can't be touched
* by the program's execution. */
void riscv_program_reserve_register(struct riscv_program *p, enum gdb_regno r);
enum gdb_regno riscv_program_gettemp(struct riscv_program *p);
void riscv_program_puttemp(struct riscv_program *p, enum gdb_regno r);
/* Executing a program usually causes the registers that get overwritten to be
* saved and restored. Calling this prevents the given register from actually
* being restored as a result of all activity in this program. */
int riscv_program_dont_restore_register(struct riscv_program *p, enum gdb_regno r);
int riscv_program_do_restore_register(struct riscv_program *p, enum gdb_regno r);
/* Addressing functions. */
riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ enum riscv_halt_reason {
RISCV_HALT_INTERRUPT,
RISCV_HALT_BREAKPOINT,
RISCV_HALT_SINGLESTEP,
RISCV_HALT_UNKNOWN
};
typedef struct {
@ -59,7 +60,11 @@ typedef struct {
/* The register cache points into here. */
uint64_t reg_cache_values[RISCV_MAX_REGISTERS];
/* Single buffer that contains all register names, instead of calling
* malloc for each register. Needs to be freed when reg_list is freed. */
char *reg_names;
/* It's possible that each core has a different supported ISA set. */
int xlen[RISCV_MAX_HARTS];
@ -72,32 +77,31 @@ typedef struct {
* target controls, while otherwise only a single hart is controlled. */
int trigger_unique_id[RISCV_MAX_HWBPS];
/* The address of the debug RAM buffer. */
riscv_addr_t debug_buffer_addr[RISCV_MAX_HARTS];
/* The number of entries in the debug buffer. */
int debug_buffer_size[RISCV_MAX_HARTS];
/* This avoids invalidating the register cache too often. */
bool registers_initialized;
/* This hart contains an implicit ebreak at the end of the program buffer. */
bool impebreak;
/* Helper functions that target the various RISC-V debug spec
* implementations. */
riscv_reg_t (*get_register)(struct target *, int hartid, int regid);
void (*set_register)(struct target *, int hartid, int regid,
int (*get_register)(struct target *target,
riscv_reg_t *value, int hid, int rid);
int (*set_register)(struct target *, int hartid, int regid,
uint64_t value);
void (*select_current_hart)(struct target *);
bool (*is_halted)(struct target *target);
void (*halt_current_hart)(struct target *);
void (*resume_current_hart)(struct target *target);
void (*step_current_hart)(struct target *target);
void (*on_halt)(struct target *target);
void (*on_resume)(struct target *target);
void (*on_step)(struct target *target);
int (*halt_current_hart)(struct target *);
int (*resume_current_hart)(struct target *target);
int (*step_current_hart)(struct target *target);
int (*on_halt)(struct target *target);
int (*on_resume)(struct target *target);
int (*on_step)(struct target *target);
enum riscv_halt_reason (*halt_reason)(struct target *target);
void (*debug_buffer_enter)(struct target *target, struct riscv_program *program);
void (*debug_buffer_leave)(struct target *target, struct riscv_program *program);
void (*write_debug_buffer)(struct target *target, unsigned index,
int (*write_debug_buffer)(struct target *target, unsigned index,
riscv_insn_t d);
riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index);
int (*execute_debug_buffer)(struct target *target);
@ -115,6 +119,9 @@ extern int riscv_command_timeout_sec;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
extern int riscv_reset_timeout_sec;
extern bool riscv_use_scratch_ram;
extern uint64_t riscv_scratch_ram_address;
/* Everything needs the RISC-V specific info structure, so here's a nice macro
* that provides that. */
static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused));
@ -138,7 +145,7 @@ int riscv_openocd_resume(
struct target *target,
int current,
target_addr_t address,
int handle_breakpoints,
int handle_breakpoints,
int debug_execution
);
@ -169,6 +176,8 @@ int riscv_resume_one_hart(struct target *target, int hartid);
* then the only hart. */
int riscv_step_rtos_hart(struct target *target);
bool riscv_supports_extension(struct target *target, char letter);
/* Returns XLEN for the given (or current) hart. */
int riscv_xlen(const struct target *target);
int riscv_xlen_of_hart(const struct target *target, int hartid);
@ -197,10 +206,12 @@ bool riscv_has_register(struct target *target, int hartid, int regid);
/* Returns the value of the given register on the given hart. 32-bit registers
* are zero extended to 64 bits. */
void riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
void riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
riscv_reg_t riscv_get_register(struct target *target, enum gdb_regno i);
riscv_reg_t riscv_get_register_on_hart(struct target *target, int hid, enum gdb_regno rid);
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
int riscv_get_register(struct target *target, riscv_reg_t *value,
enum gdb_regno r);
int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
int hartid, enum gdb_regno regid);
/* Checks the state of the current hart -- "is_halted" checks the actual
* on-device register. */
@ -215,15 +226,9 @@ int riscv_count_triggers_of_hart(struct target *target, int hartid);
/* These helper functions let the generic program interface get target-specific
* information. */
size_t riscv_debug_buffer_size(struct target *target);
riscv_addr_t riscv_debug_buffer_addr(struct target *target);
int riscv_debug_buffer_enter(struct target *target, struct riscv_program *program);
int riscv_debug_buffer_leave(struct target *target, struct riscv_program *program);
riscv_insn_t riscv_read_debug_buffer(struct target *target, int index);
riscv_addr_t riscv_read_debug_buffer_x(struct target *target, int index);
int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn);
int riscv_write_debug_buffer_x(struct target *target, int index, riscv_addr_t data);
int riscv_execute_debug_buffer(struct target *target);
void riscv_fill_dmi_nop_u64(struct target *target, char *buf);
@ -246,4 +251,6 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint);
int riscv_remove_watchpoint(struct target *target,
struct watchpoint *watchpoint);
int riscv_init_registers(struct target *target);
#endif

2219
src/target/stm8.c Normal file

File diff suppressed because it is too large Load Diff

75
src/target/stm8.h Normal file
View File

@ -0,0 +1,75 @@
/*
OpenOCD STM8 target driver
Copyright (C) 2017 Ake Rehnman
ake.rehnman(at)gmail.com
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENOCD_TARGET_STM8_H
#define OPENOCD_TARGET_STM8_H
struct target;
#define STM8_COMMON_MAGIC 0x53544D38
#define STM8_NUM_CORE_REGS 6
struct stm8_common {
uint32_t common_magic;
void *arch_info;
struct reg_cache *core_cache;
uint32_t core_regs[STM8_NUM_CORE_REGS];
/* working area for fastdata access */
struct working_area *fast_data_area;
bool swim_configured;
bool bp_scanned;
uint8_t num_hw_bpoints;
uint8_t num_hw_bpoints_avail;
struct stm8_comparator *hw_break_list;
uint32_t blocksize;
uint32_t flashstart;
uint32_t flashend;
uint32_t eepromstart;
uint32_t eepromend;
uint32_t optionstart;
uint32_t optionend;
bool enable_step_irq;
bool enable_stm8l;
uint32_t flash_cr2;
uint32_t flash_ncr2;
uint32_t flash_iapsr;
uint32_t flash_dukr;
uint32_t flash_pukr;
/* cc value used for interrupt flags restore */
uint32_t cc;
bool cc_valid;
/* register cache to processor synchronization */
int (*read_core_reg)(struct target *target, unsigned int num);
int (*write_core_reg)(struct target *target, unsigned int num);
};
static inline struct stm8_common *
target_to_stm8(struct target *target)
{
return target->arch_info;
}
const struct command_registration stm8_command_handlers[];
#endif /* OPENOCD_TARGET_STM8_H */

View File

@ -105,6 +105,7 @@ extern struct target_type nds32_v3m_target;
extern struct target_type or1k_target;
extern struct target_type quark_x10xx_target;
extern struct target_type quark_d20xx_target;
extern struct target_type stm8_target;
extern struct target_type riscv_target;
static struct target_type *target_types[] = {
@ -137,6 +138,7 @@ static struct target_type *target_types[] = {
&or1k_target,
&quark_x10xx_target,
&quark_d20xx_target,
&stm8_target,
&riscv_target,
#if BUILD_TARGET64
&aarch64_target,
@ -204,10 +206,6 @@ static const Jim_Nvp nvp_target_event[] = {
{ .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" },
{ .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" },
{ .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
{ .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" },
{ .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" },
{ .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" },
{ .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" },
{ .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" },
{ .value = TARGET_EVENT_RESET_END, .name = "reset-end" },
@ -2742,21 +2740,23 @@ COMMAND_HANDLER(handle_reg_command)
i < cache->num_regs;
i++, reg++, count++) {
/* only print cached values if they are valid */
if (reg->valid) {
value = buf_to_str(reg->value,
reg->size, 16);
command_print(CMD_CTX,
"(%i) %s (/%" PRIu32 "): 0x%s%s",
count, reg->name,
reg->size, value,
reg->dirty
if (reg->exist) {
if (reg->valid) {
value = buf_to_str(reg->value,
reg->size, 16);
command_print(CMD_CTX,
"(%i) %s (/%" PRIu32 "): 0x%s%s",
count, reg->name,
reg->size, value,
reg->dirty
? " (dirty)"
: "");
free(value);
} else {
command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")",
count, reg->name,
reg->size) ;
free(value);
} else {
command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")",
count, reg->name,
reg->size) ;
}
}
}
cache = cache->next;
@ -2830,8 +2830,8 @@ COMMAND_HANDLER(handle_reg_command)
retval = reg->type->set(reg, buf);
if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't set register %s.", reg->name);
free (buf);
LOG_DEBUG("Couldn't set register %s.", reg->name);
free(buf);
return retval;
}
@ -3697,7 +3697,7 @@ COMMAND_HANDLER(handle_bp_command)
addr = 0;
return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
}
/* fallthrough */
case 4:
hw = BKPT_HARD;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);

View File

@ -253,10 +253,6 @@ enum target_event {
TARGET_EVENT_RESET_ASSERT_POST,
TARGET_EVENT_RESET_DEASSERT_PRE,
TARGET_EVENT_RESET_DEASSERT_POST,
TARGET_EVENT_RESET_HALT_PRE,
TARGET_EVENT_RESET_HALT_POST,
TARGET_EVENT_RESET_WAIT_PRE,
TARGET_EVENT_RESET_WAIT_POST,
TARGET_EVENT_RESET_INIT,
TARGET_EVENT_RESET_END,

View File

@ -0,0 +1,7 @@
# config for ESPRESSObin from
# Globalscale Technologies Inc.
# srst is isolated through missing resistor
reset_config trst_only
source [find target/marvell/88f3720.cfg]

View File

@ -3,6 +3,8 @@
source [find interface/ftdi/openrd.cfg]
source [find target/feroceon.cfg]
adapter_khz 2000
$_TARGETNAME configure \
-work-area-phys 0x10000000 \
-work-area-size 65536 \

View File

@ -0,0 +1,22 @@
#
# Be sure you include the speed and interface before this file
# Example:
# -c "adapter_khz 5000" -f "interface/ftdi/olimex-arm-usb-tiny-h.cfg" -f "board/sifive-e31arty.cfg"
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
flash protect 0 64 last off
echo "Ready for Remote Connections"

View File

@ -0,0 +1,22 @@
#
# Be sure you include the speed and interface before this file
# Example:
# -c "adapter_khz 5000" -f "interface/ftdi/olimex-arm-usb-tiny-h.cfg" -f "board/sifive-e51arty.cfg"
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
flash protect 0 64 last off
echo "Ready for Remote Connections"

View File

@ -0,0 +1,34 @@
adapter_khz 10000
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0008 0x001b
ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020
#Reset Stretcher logic on FE310 is ~1 second long
#This doesn't apply if you use
# ftdi_set_signal, but still good to document
#adapter_nsrst_delay 1500
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
init
#reset -- This type of reset is not implemented yet
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
#Wait for the reset stretcher
#It will work without this, but
#will incur lots of delays for later commands.
sleep 1500
}
halt
flash protect 0 64 last off

View File

@ -6,7 +6,7 @@
# STM32F091RC
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260944
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -1,7 +1,7 @@
# This is an ST NUCLEO F103RB board with a single STM32F103RBT6 chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -1,7 +1,7 @@
# This is an ST NUCLEO F334R8 board with a single STM32F334R8T6 chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260004
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
# STM32F411RET6
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260320
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -0,0 +1,10 @@
# This is an ST NUCLEO-H743ZI board with single STM32H743ZI chip.
# http://www.st.com/en/evaluation-tools/nucleo-h743zi.html
source [find interface/stlink-v2-1.cfg]
transport select hla_swd
source [find target/stm32h7x_dual_bank.cfg]
reset_config srst_only

View File

@ -1,7 +1,7 @@
# This is an ST NUCLEO L152RE board with a single STM32L152RET6 chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260002
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -1,7 +1,7 @@
# This is a ST NUCLEO L476RG board with a single STM32L476RGT6 chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF261636
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
#
# This is for using the onboard STLINK/V2
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
#
# This is for using the onboard STLINK/V2
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
#
# This is for using the onboard STLINK/V2
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
#
# This is for using the onboard STLINK/V2
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -4,7 +4,7 @@
#
# This is for using the onboard STLINK/V2
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -1,7 +1,7 @@
# This is an STM32F0 discovery board with a single STM32F051R8T6 chip.
# http://www.st.com/internet/evalboard/product/253215.jsp
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -1,7 +1,7 @@
# This is an STM32F3 discovery board with a single STM32F303VCT6 chip.
# http://www.st.com/internet/evalboard/product/254044.jsp
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -3,7 +3,7 @@
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF259090
#
source [find interface/stlink-v2-1.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

View File

@ -3,7 +3,7 @@
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF259090
#
source [find interface/stlink-v2.cfg]
source [find interface/stlink.cfg]
transport select hla_swd

Some files were not shown because too many files have changed in this diff Show More