Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: memwatch: read memory while running #1655

Closed
wants to merge 1 commit into from
Closed

feature: memwatch: read memory while running #1655

wants to merge 1 commit into from

Conversation

koendv
Copy link
Contributor

@koendv koendv commented Oct 24, 2023

Detailed description

memwatch - read memory while target running

This PR introduces a new monitor command, memwatch.
The memwatch command reads target memory while the target is running.
Inspecting memory without halting the target is useful when debugging hard real time systems.

The arguments to "mon memwatch" are names, formats (/d, /u, /f, /x, /t), and memory addresses. Up to 8 memory addresses may be monitored at the same time. The "mon memwatch" command can be applied to Arm Cortex-M targets only.

Example

Assume target firmware contains a variable called "counter". In gdb:

(gdb) p &counter
$1 = (<data variable, no debug info> *) 0x20000224 <counter>
(gdb) mon memwatch counter /d 0x20000224
0x20000224
(gdb) r

When the variable changes, output is written to the usb serial:

counter 0
counter 1
counter 2
counter 3
counter 4

To switch off, enter "mon memwatch" without arguments.

(gdb) mon memwatch

Compiling

To compile bmp with memwatch support, add ENABLE_MEMWATCH=1 to the command line. E.g.:

git clone https://github.com/blackmagic-debug/blackmagic
cd blackmagic
wget https://github.com/blackmagic-debug/blackmagic/pull/1655.patch
patch -p 1 -i 1655.patch
make PROBE_HOST=blackpill-f411ce ENABLE_MEMWATCH=1

Pre-built binaries.

Arguments

The command arguments in detail:

mon memwatch [/t] [[NAME] [/d|/u|/f|/x] ADDRESS]...

Up to 8 addresses of watchpoints may be specified.

mon memwatch x1 /d 0x20000224 x2 0x20000228 x3 0x2000022c x4 0x20000230 x5 0x20000234 x6 0x20000238 x7 0x2000023c x8 0x20000240

NAME begins with a letter a-z A-Z. NAME is printed on every line of output. If NAME has been omitted, the address is printed instead:

(gdb) mon memwatch /d 0x20000224

prints

0x20000224 0
0x20000224 1
0x20000224 2
0x20000224 3
0x20000224 4

Format is one of

  • /d signed 32-bit integer
  • /u unsigned 32-bit integer
  • /f 32-bit float
  • /x hex 32-bit integer
  • /t timestamp in ms

If format is not given, default is hex, or the last used format.

(gdb) mon memwatch counter 0x20000224

prints

counter 0x0
counter 0x1
counter 0x2
counter 0x3
counter 0x4

Address is a hexadecimal number. The address is the minimum necessary to define a watchpoint.

(gdb) mon memwatch 0x20000224

prints

0x20000224 0x0
0x20000224 0x1
0x20000224 0x2
0x20000224 0x3
0x20000224 0x4

The '/f' format prints IEEE754 32-bit single-precision "float":

(gdb) mon memwatch counter /d 0x20000224 root /f 0x20000248

prints

counter 0
root 0
counter 1
root 1
counter 2
root 1.41421
counter 3
root 1.73205
counter 4
root 2                                          

On the Black Magic Probe firmware probes /f defaults to printing all significant digits, without any rounding.
On the pc-based Black Magic Debug App /f defaults to printing to 6 decimal places "%.6g".
Optionally, /f may be followed by a digit, indicating the number of decimal places.
Example: /f4 prints floating point numbers to four decimal places.

The '/t' format prints a timestamp in milliseconds:

(gdb) mon memwatch /t counter /d 0x20000224

prints

20601 counter 0
20613 counter 1
21613 counter 2
22613 counter 3
23613 counter 4

With both target and bmp running on a stm32f411, memory is polled 1000 times per second.

Your checklist for this pull request

  • I've read the Code of Conduct
  • I've read the guidelines for contributing to this repository
  • It builds for hardware native (make PROBE_HOST=native)
  • It builds as BMDA (make PROBE_HOST=hosted)
  • I've tested it to the best of my ability
  • My commit messages provide a useful short description of what the commits do

Closing issues

fixes #1532

@koendv
Copy link
Contributor Author

koendv commented Nov 2, 2023

float

memwatch prints 32-bit int and float.
memwatch prints float using this ftoa(). The main advantage is small size. With support for printing int and float, memwatch needs around 3 kbyte flash.

platform core flash
f072 Cortex-M0 3488
native Cortex-M1 2992
blackpill-f411ce Cortex-M4 2704

To decrease flash use, printing float can be omitted. Without support for printing float, memwatch needs only 850 bytes flash. This is similar to the flash needed to implement a new target.

When building bmp using make:

make option
ENABLE_MEMWATCH=1 print 32-bit int and float
ENABLE_MEMWATCH=2 print 32-bit int only

Example:

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (xPack GNU Arm Embedded GCC x86_64) 12.2.1 20221205
$ make PROBE_HOST=native ENABLE_MEMWATCH=1
...
  LD      blackmagic.elf
Memory region         Used Size  Region Size  %age Used
             rom:      130624 B       128 KB     99.66%
             ram:        4136 B        20 KB     20.20%
$ make clean
$ make PROBE_HOST=native ENABLE_MEMWATCH=2
...
  LD      blackmagic.elf
Memory region         Used Size  Region Size  %age Used
             rom:      128516 B       128 KB     98.05%
             ram:        4136 B        20 KB     20.20%

Pre-built binaries here.

testing

memwatch is designed to work on Arm Cortex-M.
In the grid below, a row is a target, and a column is a black magic probe platform. Some combinations have already been tested, others not yet. If you have test results of interest, please add a comment below.
I'm especially interested in finding out if there are Arm Cortex-M targets where memwatch does not work.
Thank you.

black magic→
target↓
stm32f072 stm32f103 stm32f411
stm32f4 ok f411 ok f411 ok f411
stm32f7
stm32h7 ok h743

@koendv koendv closed this Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Read memory while running
1 participant