Five EmbedDev logo Five EmbedDev

An Embedded RISC-V Blog
RISC-V External Debug Support

6 Trigger Module

Triggers can cause a breakpoint exception, entry into Debug Mode, or a trace action without having to execute a special instruction. This makes them invaluable when debugging code from ROM. They can trigger on execution of instructions at a given memory address, or on the address/data in loads/stores. These are all features that can be useful without having the Debug Module present, so the Trigger Module is broken out as a piece that can be implemented separately.

A hart can be compliant with this specification without implementing any trigger functionality at all, but if it is implemented then it must conform to this section. If triggers aren’t implemented, the CSRs may not exist at all and accessing them results in an illegal instruction exception.

Triggers do not fire while in Debug Mode.

6.1 Enumeration

Each trigger may support a variety of features. A debugger can build a list of all triggers and their features as follows:

Write 0 to . If this results in an illegal instruction exception, then there are no triggers implemented.

Read back and check that it contains the written value. If not, exit the loop.

Read .

If that caused an exception, the debugger must read to discover the type. (If is 0, this trigger doesn’t exist. Exit the loop.)

If is 1, this trigger doesn’t exist. Exit the loop.

Otherwise, the selected trigger supports the types discovered in .

Repeat, incrementing the value in .

The above algorithm reads back so that implementations which have 2n triggers only need to implement n bits of .

The algorithm checks and in case the implementation has m bits of but fewer than 2m triggers.

6.2 Actions

Triggers can be configured to take one of several actions when they fire. Table [tab:action] lists all options.

|r|L| Value & Description
& Raise a breakpoint exception into M-Mode. (Used when software wants to use the trigger module without an external debugger attached.) must contain the virtual address of the next instruction that must be executed to preserve the program flow.
& Enter Debug Mode. must contain the virtual address of the next instruction that must be executed to preserve the program flow.

This action is only legal when the trigger’s is 1. Since the tdata registers are WARL, hardware should clear the action field whenever the action field is 1, is cleared, and the new value of the action field would also be 1.
– 5 & Reserved for use by the trace specification.
other & Reserved for future use.

6.3 Priority

Table [tab:priority] lists the synchronous exceptions from the Privileged Spec, and where the various types of triggers fit in. The first 3 columns come from the Privileged Spec, and the final column shows where triggers fit in. Priorities in the table are separated by horizontal lines, so e.g. etrigger and itrigger have the same priority. If this table contradicts the table in the Privileged Spec, then the latter takes precedence.

This table only applies if triggers are precise. Otherwise triggers will fire some indeterminate time after the event, and the priority is irrelevant. When triggers are chained, the priority is the lowest priority of the triggers in the chain.

Priority Exception Description Trigger
Code
Highest 3 etrigger
3 icount
3 itrigger
3 mcontrol after
(on previous instruction)
3 Instruction address breakpoint mcontrol execute address before
12 Instruction page fault
1 Instruction access fault
3 mcontrol execute data before
2 Illegal instruction
0 Instruction address misaligned
8, 9, 11 Environment call
3 Environment break
3 Load/Store/AMO address breakpoint mcontrol load/store address before
3 mcontrol store data before
6 Store/AMO address misaligned
4 Load address misaligned
15 Store/AMO page fault
13 Load page fault
7 Store/AMO access fault
5 Load access fault
Lowest 3 mcontrol load data before

[tab:priority]

When multiple triggers in the same priority fire at once, (if implemented) is set for all of them. If one of these triggers has the “enter Debug Mode” action (1) and another trigger has the “raise a breakpoint exception” action (0), the preferred behavior is to have both actions take place. It is implementation-dependent which of the two happens first. This ensures both that the presence of an external debugger doesn’t affect execution and that a trigger set by user code doesn’t affect the external debugger. If this is not implemented, then the hart must enter Debug Mode and ignore the breakpoint exception. In the latter case, of the trigger whose action is 0 must still be set, giving a debugger an opportunity to handle this case. What happens with trace actions when triggers with different actions are also firing is left to the trace specification.

6.4 Native M-Mode Triggers

Triggers can be used for native debugging. On a fully featured system triggers will be set using or , and when firing they can cause a breakpoint exception to trap to a more privileged mode. It is possible to set triggers natively to fire in M mode as well. In that case there is no higher privilege mode to trap to. When such a trigger causes a breakpoint exception while already in a trap handler, this will leave the system unable to resume normal execution.

On full-featured systems this is a remote corner case that can probably be ignored. On systems that only implement M mode, however, it is recommended to implement one of two solutions to this problem. This way triggers can be useful for native debugging of even M mode code.

The simple solution is to have the hardware prevent triggers with action=0 from firing while in M mode and while in is 0. Its limitation is that interrupts might be disabled at other times when a user might want triggers to fire.

A more complex solution is to implement and in . This solution has the benefit that it only disables triggers during the trap handler.

A user setting M mode triggers that cause breakpoint exceptions will have to be aware of any problems that might come up with the particular system they are working on.

6.5 Trigger Registers

These registers are CSRs, accessible using the RISC-V csr opcodes and optionally also using abstract debug commands.

Almost all trigger functionality is optional. All tdata registers follow write-any-read-legal semantics. If a debugger writes an unsupported configuration, the register will read back a value that is supported (which may simply be a disabled trigger). This means that a debugger must always read back values it writes to tdata registers, unless it already knows already what is supported. Writes to one tdata register may not modify the contents of other tdata registers, nor the configuration of any trigger besides the one that is currently selected.

[hwbp_registers.tex]