OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [userguide/] [debugging_with_ocd.adoc] - Diff between revs 69 and 72

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 69 Rev 72
Line 2... Line 2...
:sectnums:
:sectnums:
== Debugging using the On-Chip Debugger
== Debugging using the On-Chip Debugger
 
 
The NEORV32 on-chip debugger allows _online_ in-system debugging via an external JTAG access port from a
The NEORV32 on-chip debugger allows _online_ in-system debugging via an external JTAG access port from a
host machine. The general flow is independent of the host machine's operating system. However, this tutorial uses
host machine. The general flow is independent of the host machine's operating system. However, this tutorial uses
Windows and Linux (Ubuntu on Windows) in parallel.
Windows and Linux (Ubuntu on Windows / WSL) in parallel running the upstream version of OpenOCD and the
 
RISC-V _GNU debugger_ `gdb`.
 
 
[TIP]
[NOTE]
See datasheet section https://stnolting.github.io/neorv32/#_on_chip_debugger_ocd[On Chip Debugger (OCD)]
See datasheet section https://stnolting.github.io/neorv32/#_on_chip_debugger_ocd[On Chip Debugger (OCD)]
for more information.
for more information regarding the actual hardware.
 
 
[NOTE]
[NOTE]
This tutorial uses `gdb` to **directly upload an executable** to the processor. If you are using the default
 
processor setup _with_ internal instruction memory (IMEM) make sure it is implemented as RAM
 
(_INT_BOOTLOADER_EN_ generic = true).
 
 
 
[IMPORTANT]
 
The on-chip debugger is only implemented if the _ON_CHIP_DEBUGGER_EN_ generic is set _true_. Furthermore, it requires
The on-chip debugger is only implemented if the _ON_CHIP_DEBUGGER_EN_ generic is set _true_. Furthermore, it requires
the `Zicsr` and `Zifencei` CPU extension to be implemented (top generics _CPU_EXTENSION_RISCV_Zicsr_
the `Zicsr` and `Zifencei` CPU extension to be implemented (top generics _CPU_EXTENSION_RISCV_Zicsr_ = _true_
and _CPU_EXTENSION_RISCV_Zifencei_ = true).
and _CPU_EXTENSION_RISCV_Zifencei_ = _true_).
 
 
 
 
:sectnums:
:sectnums:
=== Hardware Requirements
=== Hardware Requirements
 
 
Make sure the on-chip debugger of your NEORV32 setups is implemented (_ON_CHIP_DEBUGGER_EN_ generic = true).
Make sure the on-chip debugger of your NEORV32 setup is implemented (_ON_CHIP_DEBUGGER_EN_ generic = true). This
 
tutorial uses `gdb` to **directly upload an executable** to the processor. If you are using the default
 
processor setup _with_ internal instruction memory (IMEM) make sure it is implemented as RAM
 
(_INT_BOOTLOADER_EN_ generic = true).
 
 
Connect a JTAG adapter to the NEORV32 `jtag_*` interface signals. If you do not have a full-scale JTAG adapter, you can
Connect a JTAG adapter to the NEORV32 `jtag_*` interface signals. If you do not have a full-scale JTAG adapter, you can
also use a FTDI-based adapter like the "FT2232H-56Q Mini Module", which is a simple and inexpensive FTDI breakout board.
also use a FTDI-based adapter like the "FT2232H-56Q Mini Module", which is a simple and inexpensive FTDI breakout board.
 
 
.JTAG pin mapping
.JTAG pin mapping
[cols="^3,^2,^2"]
[cols="^3,^2,^2"]
Line 39... Line 39...
| `jtag_tms_i`       | TMS         | D3
| `jtag_tms_i`       | TMS         | D3
| `jtag_trst_i`      | TRST        | D4
| `jtag_trst_i`      | TRST        | D4
|=======================
|=======================
 
 
[TIP]
[TIP]
The low-active JTAG _test reset_ (TRST) signals is _optional_ as a reset can also be triggered via the TAP controller.
The low-active JTAG tap reset `jtag_trst_i` signals is _optional_ as a reset can also be triggered via the TAP controller
If TRST is not used make sure to pull the signal _high_.
issuing special commands. If `jtag_trst_i` is not connected make sure to pull the signal _high_.
 
 
 
 
:sectnums:
:sectnums:
=== OpenOCD
=== OpenOCD
 
 
The NEORV32 on-chip debugger can be accessed using the https://github.com/riscv/riscv-openocd[RISC-V port of OpenOCD].
The NEORV32 on-chip debugger can be accessed using the upstream version of OpenOCD. A pre-configured OpenOCD configuration
Prebuilt binaries can be obtained - for example - from https://www.sifive.com/software[SiFive]. A pre-configured
file is provided (`sw/openocd/openocd_neorv32.cfg`) that allows an easy access to the NEORV32 CPU.
OpenOCD configuration file (`sw/openocd/openocd_neorv32.cfg`) is available that allows easy access to the NEORV32 CPU.
 
 
 
[NOTE]
[NOTE]
You might need to adapt `ftdi_vid_pid`, `ftdi_channel` and `ftdi_layout_init` in `sw/openocd/openocd_neorv32.cfg`
You might need to adapt `ftdi vid_pid`, `ftdi channel` and `ftdi layout_init` in `sw/openocd/openocd_neorv32.cfg`
according to your interface chip and your operating system.
according to your interface chip and your operating system.
 
 
[TIP]
[TIP]
If you want to modify the JTAG clock speed (via `adapter speed` in `sw/openocd/openocd_neorv32.cfg`) make sure to meet
If you want to modify the JTAG clock speed (via `adapter speed` in `sw/openocd/openocd_neorv32.cfg`) make sure to meet
the clock requirements noted in https://stnolting.github.io/neorv32/#_debug_module_dm[Documentation: Debug Transport Module (DTM)].
the clock requirements noted in https://stnolting.github.io/neorv32/#_debug_module_dm[Documentation: Debug Transport Module (DTM)].
 
 
To access the processor using OpenOCD, open a terminal and start OpenOCD with the pre-configured configuration file.
To access the processor using OpenOCD, open a terminal and start OpenOCD with the pre-configured configuration file.
 
 
.Connecting via OpenOCD (on Windows)
.Connecting via OpenOCD (on Windows) using the default `openocd_neorv32.cfg` script
[source, bash]
[source, bash]
--------------------------
--------------------------
N:\Projects\neorv32\sw\openocd>openocd -f openocd_neorv32.cfg
N:\Projects\neorv32\sw\openocd>openocd -f openocd_neorv32.cfg
Open On-Chip Debugger 0.11.0-rc1+dev (SiFive OpenOCD 0.10.0-2020.12.1)
Open On-Chip Debugger 0.11.0 (2021-11-18) [https://github.com/sysprogs/openocd]
Licensed under GNU GPL v2
Licensed under GNU GPL v2
For bug reports:
libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3
        https://github.com/sifive/freedom-tools/issues
For bug reports, read
1
        http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
 
Info : Listening on port 4444 for telnet connections
 
Info : clock speed 1000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: neorv32.cpu tap/device found: 0x0cafe001 (mfg: 0x000 (), part: 0xcafe, ver: 0x0)
Info : JTAG tap: neorv32.cpu tap/device found: 0x0cafe001 (mfg: 0x000 (), part: 0xcafe, ver: 0x0)
Info : datacount=1 progbufsize=2
Info : datacount=1 progbufsize=2
Info : Disabling abstract command reads from CSRs.
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 1 harts
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=32, misa=0x40801105
Info :  hart 0: XLEN=32, misa=0x40901107
Info : starting gdb server for neorv32.cpu.0 on 3333
Info : starting gdb server for neorv32.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : Listening on port 3333 for gdb connections
 
Target HALTED.
 
Ready for remote connections.
 
Info : Listening on port 6666 for tcl connections
 
Info : Listening on port 4444 for telnet connections
--------------------------
--------------------------
 
 
OpenOCD has successfully connected to the NEORV32 on-chip debugger and has examined the CPU (showing the content of
OpenOCD has successfully connected to the NEORV32 on-chip debugger and has examined the CPU (showing the content of
the `misa` CSRs). Now you can use `gdb` to connect via port 3333.
the `misa` CSRs). The processor is halted and OpenOCD waits fot `gdb` to connect via port 3333.
 
 
 
 
:sectnums:
:sectnums:
=== Debugging with GDB
=== Debugging with GDB
 
 
Line 104... Line 105...
--------------------------
--------------------------
 
 
.Adding debug symbols to the executable
.Adding debug symbols to the executable
[NOTE]
[NOTE]
`USER_FLAGS+=-g` passes the `-g` flag to the compiler so it adds debug information/symbols
`USER_FLAGS+=-g` passes the `-g` flag to the compiler so it adds debug information/symbols
to the generated ELF file. This is optional but will provide more sophisticated information for debugging
to the generated ELF file. This is optional but will provide more sophisticated debugging information
(like source file line numbers).
(like source file line numbers).
 
 
This will generate an ELF file `main.elf` that contains all the symbols required for debugging.
This will generate an ELF file `main.elf` that contains all the symbols required for debugging.
Furthermore, an assembly listing file `main.asm` is generated that we will use to define breakpoints.
Furthermore, an assembly listing file `main.asm` is generated that we will use to define breakpoints.
 
 
Line 174... Line 175...
(by default, this is the beginning of the instruction memory at `0x00000000`) skipping the bootloader
(by default, this is the beginning of the instruction memory at `0x00000000`) skipping the bootloader
and halting the CPU right before executing the `blink_led` application.
and halting the CPU right before executing the `blink_led` application.
 
 
 
 
:sectnums:
:sectnums:
==== Breakpoint Example
==== Software Breakpoints
 
 
The following steps are just a small showcase that illustrate a simple debugging scheme.
The following steps are just a small showcase that illustrate a simple debugging scheme.
 
 
While compiling `blink_led`, an assembly listing file `main.asm` was generated.
While compiling `blink_led`, an assembly listing file `main.asm` was generated.
Open this file with a text editor to check out what the CPU is going to do when resumed.
Open this file with a text editor to check out what the CPU is going to do when resumed.
Line 202... Line 203...
 
 
[NOTE]
[NOTE]
The address might be different if you use a different version of the software framework or
The address might be different if you use a different version of the software framework or
if different ISA options are configured.
if different ISA options are configured.
 
 
.Adding a GDB breakpoint
.Adding a GDB software breakpoint
[source, bash]
[source, bash]
--------------------------
--------------------------
(gdb) b * 0x690
(gdb) b * 0x690 <1>
Breakpoint 1 at 0x690
Breakpoint 1 at 0x690
--------------------------
--------------------------
 
<1> `b` is an alias for `break`, which adds a _software_ breakpoint.
 
 
.How do breakpoints work?
.How do _software_ breakpoints work?
[TIP]
[TIP]
The NEORV32 on-chip debugger does not provide any hardware breakpoints (RISC-V "trigger modules") that compare an address like the PC
Software breakpoints are used for debugging programs that are accessed from read/write memory (RAM) like IMEM. The debugger
with a predefined value. Instead, gdb will modify the actual executable in IMEM: the actual instruction at the address
temporarily replaces the instruction word of the instruction, where the breakpoint shall be inserted, by a `ebreak` / `c.ebreak`
of the specified breakpoint is replaced by a `break` / `c.break` instruction. Whenever execution reaches this instruction, debug mode is
instruction. Whenever execution reaches this instruction, debug mode is entered and the debugger restores the original
re-entered and the debugger restores the original instruction at this address to maintain original program behavior.
instruction at this address to maintain original program behavior. +
 
 +
 
When debugging programs executed from ROM _hardware-assisted_ breakpoints using the core's trigger module have to be used.
 
See section <<_hardware_breakpoints>> for more information.
 
 
Now execute `c` (= continue). The CPU will resume operation until it hits the break-point.
Now execute `c` (= continue). The CPU will resume operation until it hits the break-point.
By this we can "step" from increment to increment.
By this we can move from one counter increment to another.
 
 
.Iterating from breakpoint to breakpoint
.Iterating from breakpoint to breakpoint
[source, bash]
[source, bash]
--------------------------
--------------------------
Breakpoint 1 at 0x690
Breakpoint 1 at 0x690
Line 234... Line 239...
 
 
Breakpoint 1, 0x00000690 in neorv32_cpu_delay_ms ()
Breakpoint 1, 0x00000690 in neorv32_cpu_delay_ms ()
(gdb) c
(gdb) c
Continuing.
Continuing.
--------------------------
--------------------------
 
 
 
.BREAK instructions in your program code
 
[TIP]
 
If your original application code uses the BREAK instruction (for example for some OS calls/signaling) this
 
instruction will cause an enter to debug mode when executed. These situation cannot be continued using gdb's
 
`c` command and have to be "stepped-over" using the single-step command `s`.
 
 
 
 
 
:sectnums:
 
==== Hardware Breakpoints
 
 
 
Hardware-assisted breakpoints using the CPU's trigger module are required when debugging code that is executed from
 
read-only memory (ROM) as GDB cannot temporarily replace instructions by BREAK instructions.
 
 
 
From a user point of view hardware breakpoints behave like software breakpoints. GDB provides a command to setup
 
a hardware-assisted breakpoint:
 
 
 
.Adding a GDB hardware breakpoint
 
[source, bash]
 
--------------------------
 
(gdb) hb * 0x690 <1>
 
Breakpoint 1 at 0x690
 
--------------------------
 
<1> `hb` is an alias for `hbreak`, which adds a _hardware_ breakpoint.
 
 
 
[NOTE]
 
The CPU's trigger module only provides a single _instruction address match_ type trigger. Hence, only
 
a single `hb` hardware-assisted breakpoint can be used.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.