Line 17... |
Line 17... |
pre-built binaries can be obtained for example from https://www.sifive.com/software[SiFive]
|
pre-built binaries can be obtained for example from https://www.sifive.com/software[SiFive]
|
|
|
.OCD Security Note
|
.OCD Security Note
|
[IMPORTANT]
|
[IMPORTANT]
|
Access via the OCD is _always authenticated_ (`dmstatus.authenticated` == `1`). Hence, the
|
Access via the OCD is _always authenticated_ (`dmstatus.authenticated` == `1`). Hence, the
|
_whole system_ can always be accessed via the on-chip debugger.
|
_whole system_ can always be accessed via the on-chip debugger. Currently, there is no option
|
|
to disable the OCD via software. The OCD can only be disabled by disabling implementation
|
|
(setting _ON_CHIP_DEBUGGER_EN_ generic to _false_).
|
|
|
[NOTE]
|
[NOTE]
|
The OCD requires additional resources for implementation and _might_ also increase the critical path resulting in less
|
The OCD requires additional resources for implementation and _might_ also increase the critical path resulting in less
|
performance. If the OCD is not really required for the _final_ implementation, it can be disabled and thus,
|
performance. If the OCD is not really required for the _final_ implementation, it can be disabled and thus,
|
discarded from implementation. In this case all circuitry of the debugger is completely removed (no impact
|
discarded from implementation. In this case all circuitry of the debugger is completely removed (no impact
|
Line 350... |
Line 352... |
|
|
.`command` - abstract command register - "access register" commands only
|
.`command` - abstract command register - "access register" commands only
|
[cols="^1,^2,<8"]
|
[cols="^1,^2,<8"]
|
[options="header",grid="rows"]
|
[options="header",grid="rows"]
|
|=======================
|
|=======================
|
| Bit | Name [RISC-V] | Description / required value
|
| Bit | Name [RISC-V] | R/W | Description / required value
|
| 31:24 | `cmdtype` | `00000000` to indicate "access register" command
|
| 31:24 | `cmdtype` | -/w | `00000000` to indicate "access register" command
|
| 23 | _reserved_ | reserved, has to be `0` when writing
|
| 23 | _reserved_ | -/w | reserved, has to be `0` when writing
|
| 22:20 | `aarsize` | `010` to indicate 32-bit accesses
|
| 22:20 | `aarsize` | -/w | `010` to indicate 32-bit accesses
|
| 21 | `aarpostincrement` | `0`, postincrement is not supported
|
| 21 | `aarpostincrement` | -/w | `0`, postincrement is not supported
|
| 18 | `postexec` | if set the program buffer is executed _after_ the command
|
| 18 | `postexec` | -/w | if set the program buffer is executed _after_ the command
|
| 17 | `transfer` | if set the operation in `write` is conducted
|
| 17 | `transfer` | -/w | if set the operation in `write` is conducted
|
| 16 | `write` | `1`: copy `data0` to `[regno]`; `0` copy `[regno]` to `data0`
|
| 16 | `write` | -/w | `1`: copy `data0` to `[regno]`; `0` copy `[regno]` to `data0`
|
| 15:0 | `regno` | GPR-access only; has to be `0x1000` - `0x101f`
|
| 15:0 | `regno` | -/w | GPR-access only; has to be `0x1000` - `0x101f`
|
|=======================
|
|=======================
|
|
|
|
|
:sectnums!:
|
:sectnums!:
|
===== **`abstractauto`**
|
===== **`abstractauto`**
|
Line 491... |
Line 493... |
|
|
[IMPORTANT]
|
[IMPORTANT]
|
The CPU _debug mode_ requires the `Zicsr` and `Zifencei` CPU extension to be implemented (top generics _CPU_EXTENSION_RISCV_Zicsr_
|
The CPU _debug mode_ requires the `Zicsr` and `Zifencei` CPU extension to be implemented (top generics _CPU_EXTENSION_RISCV_Zicsr_
|
and _CPU_EXTENSION_RISCV_Zifencei_ = true).
|
and _CPU_EXTENSION_RISCV_Zifencei_ = true).
|
|
|
The CPU debug mode is entered when one of the following events appear:
|
.Hardware Watchpoints and Breakpoints
|
|
[NOTE]
|
|
The NEORV32 CPU _debug mode_ does not provide a hardware "trigger module" (which is optional in the RISC-V debug spec). However, gdb
|
|
provides a native _emulation_ for code (breakpoints using `break` instruction) and data (polling data watchpoints in automated
|
|
single-stepping) triggers.
|
|
|
|
The CPU debug-mode is entered when one of the following events appear:
|
|
|
[start=1]
|
[start=1]
|
. executing `ebreak` instruction (when `dcsr.ebreakm` is set and in machine mode OR when `dcsr.ebreaku` is set and in user mode)
|
. executing `ebreak` instruction (when `dcsr.ebreakm` is set and in machine mode OR when `dcsr.ebreaku` is set and in user mode)
|
. debug halt request from external DM (via CPU signal `db_halt_req_i`, high-active, triggering on rising-edge)
|
. debug halt request from external DM (via CPU signal `db_halt_req_i`, high-active, triggering on rising-edge)
|
. finished executing of a single instruction while in single-step debugging mode (enabled via `dcsr.step`)
|
. finished executing of a single instruction while in single-step debugging mode (enabled via `dcsr.step`)
|
|
|
From a hardware point of view, these "entry conditions" are special synchronous (`ebreak` instruction) or asynchronous
|
From a hardware point of view, these "entry conditions" are special synchronous (`ebreak` instruction) or asynchronous
|
(single-stepping "interrupt"; halt request "interrupt") traps, that are handled invisibly by the control logic.
|
(single-stepping "interrupt"; halt request "interrupt") traps, that are handled invisibly by the control logic.
|
|
|
Whenever the CPU **enters debug mode** it performs the following operations:
|
.WFI instruction
|
|
[WARNING]
|
|
The wait-for-interrupt instruction `wfi` puts the CPU into sleep mode. The CPU will resume normale operation
|
|
when at least one interrupt source becomes pending (= at least one bit in `mip` CSR is set).
|
|
However, the CPU will _also resume_ from sleep mode if there is a halt request from the debug module (DM).
|
|
|
|
Whenever the CPU **enters debug-mode** it performs the following operations:
|
|
|
* move `pc` to `dpcs`
|
* move `pc` to `dpcs`
|
* copy the hart's current privilege level to `dcsr.prv`
|
* copy the hart's current privilege level to `dcsr.prv`
|
* set `dcrs.cause` according to the cause why debug mode is entered
|
* set `dcrs.cause` according to the cause why debug mode is entered
|
* **no update** of `mtval`, `mcause`, `mtval` and `mstatus` CSRs
|
* **no update** of `mtval`, `mcause`, `mtval` and `mstatus` CSRs
|
* load the address configured via the CPU _CPU_DEBUG_ADDR_ generic to the `pc` to jump to "debugger park loop" code in the debug module (DM)
|
* load the address configured via the CPU _CPU_DEBUG_ADDR_ generic to the `pc` to jump to "debugger park loop" code in the debug module (DM)
|
|
|
When the CPU **is in debug mode** the following things are important:
|
When the CPU **is in debug-mode** the following things are important:
|
|
|
* while in debug mode, the CPU executes the parking loop and the program buffer provided by the DM if requested
|
* while in debug mode, the CPU executes the parking loop and the program buffer provided by the DM if requested
|
* effective CPU privilege level is `machine` mode, PMP is not active
|
* effective CPU privilege level is `machine` mode, any PMP configuration is bypassed
|
* if an exception occurs
|
* the `wfi` instruction acts as a `nop` (also during single-stepping)
|
* if the exception was caused by any debug-mode entry action the CPU jumps to the _normal entry point_
|
* if an exception occurs:
|
( = _CPU_DEBUG_ADDR_) of the park loop again (for example when executing `ebreak` in debug mode)
|
** if the exception was caused by any debug-mode entry action the CPU jumps to the _normal entry point_
|
* for all other exception sources the CPU jumps to the _exception entry point_ ( = _CPU_DEBUG_ADDR_ + 4)
|
(= _CPU_DEBUG_ADDR_) of the park loop again (for example when executing `ebreak` _in_ debug-mode)
|
|
** for all other exception sources the CPU jumps to the _exception entry point_ ( = _CPU_DEBUG_ADDR_ + 4)
|
to signal an exception to the DM and restarts the park loop again afterwards
|
to signal an exception to the DM and restarts the park loop again afterwards
|
* interrupts are disabled; however, they will be remain pending and will get executed after the CPU has left debug mode
|
* interrupts are disabled; however, they will remain pending and will get executed after the CPU has left debug mode
|
* if the DM makes a resume request, the park loop exits and the CPU leaves debug mode (executing `dret`)
|
* if the DM makes a resume request, the park loop exits and the CPU leaves debug mode (executing `dret`)
|
|
|
Debug mode is left either by executing the `dret` instruction footnote:[`dret` should only be executed _inside_ the debugger
|
Debug mode is left either by executing the `dret` instruction footnote:[`dret` should only be executed _inside_ the debugger
|
"park loop" code (-> code ROM in the debug module (DM).)] (_in_ debug mode) or by performing
|
"park loop" code (-> code ROM in the debug module (DM).)] (_in_ debug mode) or by performing
|
a hardware reset of the CPU. Executing `dret` outside of debug mode will raise an illegal instruction exception.
|
a hardware reset of the CPU. Executing `dret` outside of debug mode will raise an illegal instruction exception.
|