pyocd / pyOCD

Open source Python library for programming and debugging Arm Cortex-M microcontrollers
https://pyocd.io
Apache License 2.0
1.13k stars 483 forks source link

Improve RTT support #1580

Open tyalie opened 1 year ago

tyalie commented 1 year ago

I've successfully setup Seggers RTT for my Zephyr project using an MCULink debug probe on an LPC55S16 (I know - the irony :D)

I really do love that the support is available, but along the way I've run into a few issues regarding usability, namely:

1. the default settings of pyocd rtt were not able to find the control block, because it searched in the wrong RAM

The memory is ordered as follows:

 Region     Type   Start       End         Size        Access  Sector      Page       
 nsflash    Flash  0x00000000  0x0003d7ff  0x0003d800  rx      0x00000200  0x00000200 
 nsrom      Rom    0x03000000  0x0301ffff  0x00020000  rx      -           -          
 nscoderam  Ram    0x04000000  0x04003fff  0x00004000  rwx     -           -          
 sflash     Flash  0x10000000  0x1003d7ff  0x0003d800  rx      0x00000200  0x00000200 
 srom       Rom    0x13000000  0x1301ffff  0x00020000  srx     -           -          
 scoderam   Ram    0x14000000  0x14003fff  0x00004000  srwx    -           -          
 nsram      Ram    0x20000000  0x2000ffff  0x00010000  rwx     -           -          
 sram       Ram    0x30000000  0x3000ffff  0x00010000  srwx    -           -          

Because pyocd only searches in the first RAM section by default (here nscoderam) it couldn't find the block which is hidden in nsram. Additionally the search range is by default far to short (4096B, but block is at 0x20002300).

Afterwards the pyocd rtt command runs smoothly.

In comparison Seggers J-Link directly finds the block without issues.

2. enabling RTT over the gdbserver could be greatly improved

This has taken me the longest. The help messages if one inputs the wrong command / wrong length are basically useless. And there is no explanation for what the arguments even are (besides rtt {setup|start|stop|server}).

Additionally there are no default presets and the choice of what can be adjusted is rather interesting. Especially being able to configure the control block identity code is ...

3. gdbserver's rtt start should have more information

If rtt start completed successfully, one only receives a notification of "Control block found". I think it would really be helpful here to have some more information so that one can verify if that is plausible (e.g. number of channels, ...)

4. missing quick configurations

https://github.com/pyocd/pyOCD/issues/1417 is already mentioning this. But always being forced to type in the monitor rtt commands is tedious at best...

5. using RTT with gdbserver doesn't work immediately

at least for Zephyr, the initialization of RTT occurs delayed. This is a feature of the SEGGER library so I presume it's an issue everywhere. That means, that the chip won't have RTT loaded when e.g. Zephyr stops the processor directly at the entry point (the SEGGER SDK has not been executed at this point).

JLinks gdbserver doesn't seem to have any problems with that. I'm not sure how they do it, but their gdbserver automatically starts an RTT server in the background even before the control block has been initialized. When continuing the SEGGER will automatically connect the RTT backend.

I think pyOCD would greatly benefit from something similar.

tyalie commented 1 year ago

I'm btw happy to help here out. Especially 2 and 3 are easy to fix. For the first one I'm unsure. Is there maybe a way to find out where the control block could be located, or is it stored per device, ...?

flit commented 1 year ago

Hi @tyalie, there's definitely a lot that can be improved about pyocd's RTT support. I'll have to reply fully this weekend, but I wanted to let you know I agree and am on board.

Quick answer for your question: we can probably find the control block without searching if we have the ELF by looking for the appropriate symbol. There's already an --elf argument for pyocd gdb, so it makes sense to add one for the rtt subcommand too.

tyalie commented 1 year ago

we can probably find the control block without searching if we have the ELF by looking for the appropriate symbol.

I'm not fully sure if that is possible, because the SEGGER SDK builds the control block during initialization and reorders it from what exists in code. That is probably quite clever as otherwise the control block would be found in the code section, but it makes it harder for us to find it just through the elf.

flit commented 1 year ago

It should be fine. The location of the _SEGGER_RTT symbol is what we need. And whether the acID member contains the "SEGGER RTT" string tells us whether it's initialised.

I'm not sure if that will solve the issues you describe with initialisation, though. There is also the possibility of a stale RTT CB being left in RAM. Something similar can happen for RTOS structures. The gdbserver thread reporting docs describe how this is handled for the RTOS case.

For the gdbserver we don't even need the ELF file since we can ask gdb for the value of symbols (during a specific phase when gdb connects to the gdbserver).

For the other changes, let's break them down in order of priority.

  1. Fixes/improvements to finding the CB.
    1. Fixing #1553 is top priority.
    2. While this is fixed, widening the default search range to all RAM regions seems reasonable.
    3. Adding ELF support for finding the CB.
  2. gdbserver CB initialization sync/race condition
  3. Config file and session options (#1417)
  4. gdbserver rtt command improvements
  5. Docs would be nice!!

Beyond the first item, the priorities don't really matter to me. It's just an attempt to put them in some order. 😄

Btw, honestly, I haven't really used the RTT support much. It was all written by other folks, so I'm not even all that familiar with the code. But I'd definitely like to improve it.

tdasika commented 1 year ago

Raised a PR to fix this issue https://github.com/pyocd/pyOCD/issues/1553 , https://github.com/pyocd/pyOCD/pull/1583

alanfans commented 1 year ago

image Work on (https://github.com/zhenruyan/DAPLINK_C6T6) daplink v1 downloaded from stm32f103c6t6 minimum system board

TunaBicim commented 5 months ago

Hi all, I am trying to pass rtt start to gdbserver and I can't seem to get it working. Does anyone have an example on how to enable rtt through gdbserver like mentioned on bullet point 3?