Merge remote-tracking branch 'origin/riscv' into HEAD
commit
5cf705d360
33
.travis.yml
33
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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"], [
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
|
@ -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
|
|
@ -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]
|
||||
|
|
|
@ -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
|
149
doc/openocd.texi
149
doc/openocd.texi
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ®_val);
|
||||
ret = efm32x_read_reg_u32(bank, 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(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */
|
||||
init_reg_param(®_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");
|
||||
|
|
|
@ -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(®_params[0], "x10", xlen, PARAM_OUT);
|
||||
init_reg_param(®_params[1], "x11", xlen, PARAM_OUT);
|
||||
init_reg_param(®_params[0], "a0", xlen, PARAM_OUT);
|
||||
init_reg_param(®_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));
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
/** */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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, ®_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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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]
|
|
@ -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 \
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue