[SOLVED] JLinkExe: Improper behavior of "step" and "stepover" commands on RISC-V

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • [SOLVED] JLinkExe: Improper behavior of "step" and "stepover" commands on RISC-V

    Hello,

    when working with a RISC-V target (RV32 core with RISC-V debug interface 0.13) using J-Link Commander V6.50, I could observe the following behavior of "step" and "stepover" commands which I believe is not correct.


    "step" command

    Issuing "step" command on RISC-V target apparently does not start the processor. Instead, the instructions being stepped are simulated/interpreted within J-Link commander using cached values of registers. Only when the core is resumed (command "g"), the newly computed values of registers are written back to the processor code (including incremented DPC), which gives the illusion the stepping really took place.

    Issues with this approach is that certain aspects of execution probably cannot be reliably simulated:
    • exceptions
    • interrupts
    • custom instructions (beyond RISC-V spec)
    • ... perhaps more
    A solution to this problem would be to implement stepping via the "step" bit in "dcsr" register - per the RISC-V debug spec 0.13.

    I have not tried the "step" command on different targets than RISC-V, so I am not sure if the above is a limitation of the RISC-V implementation only or general limitation of JLinkExe.


    "stepover" command

    The "stepover" command, per my observations, emulates the single-step feature on RISC-V using HW breakpoints (RISC-V triggers). I have seen the "stepover" algorithm fail on "ret" instruction - JLinkExe did not place the breakpoint at the return address but instead at the next instruction in the program.

    Concrete example:

    In the program below, stepping over ("stepover") command over instruction "ret" at address 0x11cc causes JLinkExe to place the breakpoint at address 0x11d0 (0x11cc + 4), which does not correspond to the return address from the subroutine (in our case 0x1218).

    Source Code

    1. long subroutine(long arg)
    2. {
    3. 10d0: fd010113 addi sp,sp,-48
    4. 10d4: 02812623 sw s0,44(sp)
    5. 10d8: 03010413 addi s0,sp,48
    6. ...
    7. ...
    8. 11c0: 00078513 mv a0,a5
    9. 11c4: 02c12403 lw s0,44(sp)
    10. 11c8: 03010113 addi sp,sp,48
    11. 11cc: 00008067 ret
    12. 000011d0 <main>:
    13. int main(int argc, char *argv[])
    14. {
    15. 11d0: fd010113 addi sp,sp,-48
    16. 11d4: 02112623 sw ra,44(sp)
    17. 11d8: 02812423 sw s0,40(sp)
    18. ...
    19. ...
    20. 120c: 00078513 mv a0,a5
    21. 1210: 00000097 auipc ra,0x0
    22. 1214: ec0080e7 jalr -320(ra) # 10d0 <subroutine>
    23. 1218: 00050793 mv a5,a0
    24. ...
    25. ...
    Display All


    In conclusion, both issues with "step" and "stepover" could be solved by letting the hardware itself do the single-stepping using the "step" bit from RISC-V "dcsr" register.

    Is there any way how to enable this behavior in current J-Link Commander version?
    If not, is please this feature on roadmap of J-Link Commander?


    Thank you, regards

    Jan
  • Hello Jan,

    Thank you for your inquiry.
    We received your inquiry in parallel via our Support System. To make sure no information is lost between different channels this thread will be locked now.

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.