RISC-V debugging: data and instruction cache handling

  • Hello,

    I'm working on a debug unit for a custom RISC-V CPU and would like to get it working with the SEGGER J-Link debug probe and tools. Currently, the debug unit works fine with OpenOCD + GDB. Also with JLinkExe, I can successfully connect, downloading files, halt the CPU, and step through code. Setting breakpoints and more complicated operations don't work or are buggy and it appears that the reason might be the fact that the data cache is not flushed and that the instruction cache is not invalidated after memory writes. I know that there is no standardized way of doing this, e.g., OpenOCD uses a combination of fence and fence.i instructions.

    I'm just curious how the SEGGER debugger is handling caches in general and how I could add the flush/invalidation myself. This must be quite a common problem for other RISC-V CPUs as well, so maybe there is an elegant way to handle this.

    Thank you!

  • Hey fsiegle!

    I could not help but notice we may be having similar issues, if you still frequent this forum, would you be willing to upload what you ended up doing in your .jlinkscript file?

  • Hi Evan,

    For now, I did the following (which feels a bit hacked but seems to work):

    • After memory write access: Executing a fence.i and fence instruction. In my implementation, fence.i invalidates the instruction cache and fence flushes the data cache. This is mainly required to ensure that software breakpoints are visible to the CPU.
    • Before memory read access: Executing a fence instruction to ensure that the debugger reads fresh data from memory when looking at memory content. I added a check to see if the CPU is halted or not because it seems the hook is also called when doing background memory reads using the SBA.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!