gdb (over pyocd) displays stale memory contents

67 Views Asked by At

I am using an SWD probe to write a memory location in a MAX32660 while the following program is running.

  while (true)
    {
      DEBUG("x=%d", *(int volatile*)0x20017000);
      Tick_Delay_US(1000000);
    }

It is working; the program displays the values written by the probe:

92503131 main.c:81      x=125300000
93503118 main.c:81      x=125400000
94503104 main.c:81      x=125600000
95503090 main.c:81      x=125700000
96503077 main.c:81      x=125900000
97503063 main.c:81      x=126100000
98503050 main.c:81      x=126200000
99503036 main.c:81      x=126400000

Unfortunately, GDB (over pyocd server) seems to be able to read the value from memory only once after each time the program is stopped:

(gdb) print *(int volatile*)0x20017000
$1 = 178700000
(gdb) print *(int volatile*)0x20017000
$2 = 178700000
(gdb) print *(int volatile*)0x20017000
$3 = 178700000
(gdb) print *(int volatile*)0x20017000
$4 = 178700000
(gdb) print *(int volatile*)0x20017000
$5 = 178700000
(gdb) print *(int volatile*)0x20017000
$6 = 178700000
(gdb) print *(int volatile*)0x20017000
$7 = 178700000
(gdb) cont
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x000003aa in Tick_Reached (target=<optimized out>) at ../../max/Tick.h:60
60      {while (!Tick_Reached(target));}
(gdb) print *(int volatile*)0x20017000
$8 = 180800000
(gdb) print *(int volatile*)0x20017000
$9 = 180800000
(gdb) print *(int volatile*)0x20017000
$10 = 180800000
(gdb) print *(int volatile*)0x20017000
$11 = 180800000

I looked at the probe log, and saw that GDB was reading the value (via the MEM-AP's TAR/DRW registers) only the first time I asked for it.

This is unexpected and not very useful. What does the program's running have to do with memory caching? (Also, even if they were related, I don't see the point. I thought maybe it was trying to snapshot memory when the program stops. But it's not. It's reading the value on demand... but only the first time you ask for it).

Apart from continuing the program, is there any way to force GDB to read the value from memory again?

1

There are 1 best solutions below

3
personal_cloud On

I turned on DEBUG logging in pyocd, and saw the following message correlated with GDB's getting the new value:

DEBUG:Probe:WRITE TAR (AP0.04) <- 0xe000edf0
DEBUG:Probe:READ  DRW (AP0.0c), now=False, uid=rd75
DEBUG:Probe:  rd75 = 0x01010001
DEBUG:pyocd.cache.memory:core is running; invalidating cache
DEBUG:Probe:WRITE TAR (AP0.04) <- 0x20017000
DEBUG:Probe:READ  DRW (AP0.0c), now=True, uid=rd76
DEBUG:Probe:  rd76 = 0x049791b4
DEBUG:Probe:FLUSH

pyocd.cache.memory seems to be saying it's invalidating the cache because the core is running. (Which seems like a flawed heuristic.)

I disabled pyocd.cache.memory by adding an unconditional call to self._reset_cache() in memory.MemoryCache._check_cache(). Now GDB is working as expected:

(gdb) print *(int*)0x20017000
$1 = 207094350
(gdb) print *(int*)0x20017000
$2 = 207323100
(gdb) print *(int*)0x20017000
$3 = 207425550
(gdb) print *(int*)0x20017000
$4 = 207484200
(gdb) print *(int*)0x20017000
$5 = 207542850
(gdb) print *(int*)0x20017000
$6 = 207581550

Is there a cleaner solution?

It would be nice if one could disable caching without hacking the pyocd library itself. If the cache is actually useful for something, then we'd want to select the memory regions to enable it on. Otherwise turning it off algother would be fine.

Some versions of pyocd have a cache.enable_memory option. The description:

Enable the memory read cache. Affects memory accesses made through the target debug context, including the gdbserver.

(Emphasis on including the gdbserver is mine.)

Unfortunately this option doesn't seem to do anything in the version I am using (0.26.1). It appears that the pyocd library does not even contain the string enable_memory.