Skip to content

Conversation

@xobs
Copy link
Contributor

@xobs xobs commented Nov 13, 2022

Detailed description

This is a rewrite of the main loop as suggested in #1281. Rather
than constantly sitting inside gdb_main(), the program's main loop does its own polling of the target. This enables
a host to do its own waiting without needing to insert hooks in various functions.

This prevents WDT triggers on ESP32 where RTT blocks the IDLE thread from running. The IDLE thread is responsible for resetting the WDT. It can also be used inside the main loop to regulate hosts such as PC_HOSTED where constant USB polling is undesirable.

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

@xobs xobs marked this pull request as draft November 13, 2022 13:21
@xobs
Copy link
Contributor Author

xobs commented Nov 13, 2022

This has not been tested -- I have only confirmed that it builds, so there may be issues.

I've created this PR to get feedback, to ensure this is the approach you were describing in #1281.

@koendv
Copy link
Contributor

koendv commented Nov 13, 2022

I've tried rtt on black pill v2 and hosted on arm64, seems ok. Flashing works, speed unchanged. Not bad.
How does it run on esp32? What's your opinion of the way the code looks now?

@xobs
Copy link
Contributor Author

xobs commented Nov 14, 2022

It seems to work fine. I started on a refactor of Farpatch to support multiple clients attaching at once, and nearly got something working. I backed out those changes for another day, but I can confirm that this approach allows me to insert delays as necessary. Overall, I think this approach is sound.

I am, however, concerned with the fact that RP2040 debugging appears to have broken slightly. Though if you're not seeing it on your target, then perhaps it's either something on my platform or something due to flash changes recently.

@koendv
Copy link
Contributor

koendv commented Nov 15, 2022 via email

@xobs
Copy link
Contributor Author

xobs commented Nov 15, 2022

I just checked, and it seems that RP2040 support is just weird even on main. For example:

[4:47:17 pm] E:/Code/Farpatch/farpatch> & 'E:\Software\gcc\6 2017-q2-update\bin\arm-none-eabi-gdb.exe' mdi-gateway.elf
GNU gdb (GNU Tools for ARM Embedded Processors 6-2017-q2-update) 7.12.1.20170417-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from mdi-gateway.elf...done.
(gdb) tar ext \\.\COM54
Remote debugging using \\.\COM54
(gdb) mon s
Target voltage: 3.3V
Available Targets:
No. Att Driver
 1      Raspberry RP2040 M0+
 2      Raspberry RP2040 M0+
 3      Raspberry RP2040 Rescue (Attach to reset!)
(gdb) att 1
Attaching to program: E:\Code\Ion\mdi-gateway.elf, Remote target
0x10002340 in tud_suspended () at /opt/Pico/pico-sdk/lib/tinyusb/src/device/usbd.c:372
372     /opt/Pico/pico-sdk/lib/tinyusb/src/device/usbd.c: No such file or directory.
(gdb) load
Loading section .boot2, size 0x100 lma 0x10000000
Loading section .text, size 0x61e8 lma 0x10000100
Loading section .rodata, size 0x8b8 lma 0x100062e8
Loading section .binary_info, size 0x24 lma 0x10006ba0
Loading section .data, size 0x2a8 lma 0x10006bc4
Start address 0x100001e8, load size 28268
Transfer rate: 47 KB/sec, 883 bytes/write.
(gdb) c
Continuing.

Program received signal SIGINT, Interrupt.
0x102f29d0 in ?? ()
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: mdi-gateway.elf

Program received signal SIGINT, Interrupt.
0x000020f0 in ?? ()
(gdb) bt
#0  0x000020f0 in ?? ()
#1  0x000002b2 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: mdi-gateway.elf

Program received signal SIGINT, Interrupt.
0x000020f0 in ?? ()
(gdb) bt
#0  0x000020f0 in ?? ()
#1  0x000002b2 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) b main
Breakpoint 1 at 0x100004b0: file main.c, line 59.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: mdi-gateway.elf
Note: automatically using hardware breakpoints for read-only addresses.

Program received signal SIGINT, Interrupt.
0x000020f0 in ?? ()
(gdb) x 0x10002000
0x10002000 <_hw_endpoint_buffer_control_update32+56>:   0x00000000
(gdb) disassemble main
Dump of assembler code for function main:
   0x100004b0 <+0>:     movs    r0, r0
   0x100004b2 <+2>:     movs    r0, r0
   0x100004b4 <+4>:     movs    r0, r0
   0x100004b6 <+6>:     movs    r0, r0
   0x100004b8 <+8>:     movs    r0, r0
   0x100004ba <+10>:    movs    r0, r0
   0x100004bc <+12>:    movs    r0, r0
   0x100004be <+14>:    movs    r0, r0
   0x100004c0 <+16>:    movs    r0, r0
   0x100004c2 <+18>:    movs    r0, r0
   0x100004c4 <+20>:    movs    r0, r0
   0x100004c6 <+22>:    movs    r0, r0
   0x100004c8 <+24>:    movs    r0, r0
   0x100004ca <+26>:    movs    r0, r0
   0x100004cc <+28>:    movs    r0, r0
   0x100004ce <+30>:    movs    r0, r0
   0x100004d0 <+32>:    movs    r0, r0
   0x100004d2 <+34>:    movs    r0, r0
   0x100004d4 <+36>:    movs    r0, r0
   0x100004d6 <+38>:    movs    r0, r0
   0x100004d8 <+40>:    movs    r0, r0
   0x100004da <+42>:    movs    r0, r0
   0x100004dc <+44>:    movs    r0, r0
   0x100004de <+46>:    movs    r0, r0
   0x100004e0 <+48>:    movs    r0, r0
   0x100004e2 <+50>:    movs    r0, r0
   0x100004e4 <+52>:    movs    r0, r0
   0x100004e6 <+54>:    movs    r0, r0
   0x100004e8 <+56>:    movs    r0, r0
   0x100004ea <+58>:    movs    r0, r0
   0x100004ec <+60>:    movs    r0, r0
   0x100004ee <+62>:    movs    r0, r0
   0x100004f0 <+64>:    movs    r0, r0
   0x100004f2 <+66>:    movs    r0, r0
   0x100004f4 <+68>:    movs    r0, r0
   0x100004f6 <+70>:    movs    r0, r0
   0x100004f8 <+72>:    movs    r0, r0
   0x100004fa <+74>:    movs    r0, r0
   0x100004fc <+76>:    movs    r0, r0
   0x100004fe <+78>:    movs    r0, r0
   0x10000500 <+80>:    movs    r0, r0
   0x10000502 <+82>:    movs    r0, r0
   0x10000504 <+84>:    movs    r0, r0
   0x10000506 <+86>:    movs    r0, r0
   0x10000508 <+88>:    movs    r0, r0
   0x1000050a <+90>:    movs    r0, r0
   0x1000050c <+92>:    movs    r0, r0
   0x1000050e <+94>:    movs    r0, r0
   0x10000510 <+96>:    movs    r0, r0
   0x10000512 <+98>:    movs    r0, r0
End of assembler dump.
(gdb) p main
$1 = {int (void)} 0x100004b0 <main>
(gdb) x main
0x100004b0 <main>:      0x00000000
(gdb) load
Loading section .boot2, size 0x100 lma 0x10000000
Loading section .text, size 0x61e8 lma 0x10000100
Loading section .rodata, size 0x8b8 lma 0x100062e8
Loading section .binary_info, size 0x24 lma 0x10006ba0
Loading section .data, size 0x2a8 lma 0x10006bc4
Start address 0x100001e8, load size 28268
Transfer rate: 106 KB/sec, 883 bytes/write.
(gdb) p main
$2 = {int (void)} 0x100004b0 <main>
(gdb) x 0x100004b0
0x100004b0 <main>:      0x00000000
(gdb) mon erase_mass
Erasing device Flash: done
(gdb) mon ver
Black Magic Probe v1.8.0-709-g5092cd14, Hardware Version 6
Copyright (C) 2022 Black Magic Debug Project
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
(gdb)

From this point, the board has stopped responding. Examining memory returns all zeroes. Doing an erase_mass returns immediately rather than performing a mass erase. The board doesn't actually work unless I hard power-cycle it.

It's just coincidence that it's the board I was testing my patches with. Perhaps it's damaged. At any rate, the STM32G49 test board I've got works just fine under both JTAG and SWD, so I'd consider the rpi weirdness a separate issue.

@xobs xobs marked this pull request as ready for review November 15, 2022 08:53
@dragonmux
Copy link
Member

That behaviour indicates issues with getting the RP2040 to run its exit-XIP and enter-XIP sequences (rp_flash_prepare, rp_flash_resume). It's possible this is a bug in your RP2040's ROM routines, or it could indicate an issue with BMP's own implementations of those same routines..

There are two #if 0 blocks in the RP2040 support routines guarding rp_flash_* routines, if you remove the preprocessor magic, and replace the prepare and resume routines' calls to the ROM table with:

rp_flash_connect_internal(t);
rp_flash_exit_xip(t);

and

rp_flash_flush_cache(t);
rp_flash_enter_xip(t);

for prepare and resume respectively.. please let us know how that goes in a follow-up issue report

@xobs
Copy link
Contributor Author

xobs commented Nov 18, 2022

I think this is what you were looking for:

diff --git a/src/target/rp.c b/src/target/rp.c
index c27a0a58..06b8ec6e 100644
--- a/src/target/rp.c
+++ b/src/target/rp.c
@@ -207,7 +207,7 @@ static bool rp_mass_erase(target *t);
 // Our own implementation of bootloader functions for handling flash chip
 static void rp_flash_exit_xip(target *const t);
 static void rp_flash_enter_xip(target *const t);
-#if 0
+#if 1
 static void rp_flash_connect_internal(target *const t);
 static void rp_flash_flush_cache(target *const t);
 #endif
@@ -225,6 +225,7 @@ static void rp_add_flash(target *t)
                return;
        }

+       rp_flash_connect_internal(t);
        rp_flash_exit_xip(t);

        spi_parameters_s spi_parameters;
@@ -236,6 +237,7 @@ static void rp_add_flash(target *t)
                spi_parameters.sector_erase_opcode = SPI_FLASH_CMD_SECTOR_ERASE;
        }

+       rp_flash_flush_cache(t);
        rp_flash_enter_xip(t);

        DEBUG_INFO("Flash size: %uMiB\n", spi_parameters.capacity / (1024U * 1024U));
@@ -612,7 +614,7 @@ static void rp_spi_read(
        target_mem_write32(t, RP_SSI_ENABLE, ssi_enabled);
 }

-#if 0
+#if 1
 // Connect the XIP controller to the flash pads
 static void rp_flash_connect_internal(target *const t)
 {
@@ -769,7 +771,7 @@ static void rp_flash_exit_xip(target *const t)
        target_mem_write32(t, RP_GPIO_QSPI_CS_CTRL, 0);
 }

-#if 0
+#if 1
 // This is a hook for steps to be taken in between programming the flash and
 // doing cached XIP reads from the flash. Called by the bootrom before
 // entering flash second stage, and called by the debugger after flash

However, it's still behaving Oddly. Since this is orthogonal to this patch, I can move this into another issue and we can discuss it there.

Is there anything else that needs to happen in order to merge this change?

@dragonmux
Copy link
Member

That is indeed, please do move that into a new issue ticket. A trace of what you're seeing would be fantastic to help debug but otherwise we mostly need to recreate your situation to see what's going on

@xobs
Copy link
Contributor Author

xobs commented Nov 18, 2022

I opened #1295 which is at least rather reproducible

@xobs
Copy link
Contributor Author

xobs commented Nov 18, 2022

Rebased to latest main to keep it mergable.

Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of times we found on a cursory initial code review. We'll dive deeper once the cleanup work is all merged

@xobs xobs force-pushed the main-loop-invert branch 3 times, most recently from 448422a to 37498c8 Compare November 20, 2022 02:47
@xobs
Copy link
Contributor Author

xobs commented Nov 20, 2022

Rebased to latest main to keep it mergable.

@xobs
Copy link
Contributor Author

xobs commented Nov 29, 2022

Rebased to merge latest changes on main

@xobs xobs requested a review from dragonmux December 1, 2022 05:09
@xobs
Copy link
Contributor Author

xobs commented Dec 29, 2022

Rebased to fix conflicts with latest main

@dragonmux dragonmux added this to the v1.10 milestone Dec 30, 2022
@dragonmux dragonmux added the Enhancement General project improvement label Dec 30, 2022
@xobs xobs force-pushed the main-loop-invert branch from 72dfe68 to 06b5794 Compare January 1, 2023 16:14
@xobs
Copy link
Contributor Author

xobs commented Jan 1, 2023

Rebased again to fix conflicts with latest main

@xobs xobs force-pushed the main-loop-invert branch 2 times, most recently from aa85558 to 94e77c3 Compare January 1, 2023 16:28
@dragonmux
Copy link
Member

We will try to get this reviewed today now the v1.10 merge window is open

Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of stylistic/formatting things to resolve, and we'd like an explanation on one or two things the change set is doing so we can better understand it, but this is shaping up nicely. With the stylistic/formatting items resolved this looks ready to merge.

src/gdb_main.c Outdated
default:
gdb_putpacket_f("T%02X", GDB_SIGTRAP);
}
if (cur_target)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this not need to call the new gdb_poll_target() before sending back a W00 or no-response? If not, please add documentation as to why this otherwise disjointed-seeming approach works and what the new logic is

src/main.c Outdated
TRY_CATCH (e, EXCEPTION_ALL) {
gdb_main();
SET_IDLE_STATE(false);
while (gdb_target_running && cur_target) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to flatten this out a bit by making this while loop the outer while loop?

@xobs xobs force-pushed the main-loop-invert branch from eb80a0a to ad0b905 Compare January 31, 2023 05:43
@xobs
Copy link
Contributor Author

xobs commented Jan 31, 2023

I've made the requested changes, except I'm not sure what you mean by flattening out that bit.

Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this should be the last round of changes. Next review should be approve-to-merge.

To explain what we meant about flattening the main loop out a bit: currently there's a while loop inside which there's a "try-catch", inside which another while loop - this is a lot of levels of indentation, and especially as the outer most is while true.

What we were thinking is if it's possible to push the inner while condition out to the outer while loop, making the inner while body a part of the try-catch scope instead, removing a layer indentation. If not, it might be worth extracting the inner while loop into its own function to reduce the indentation level and improve readability instead?

@xobs
Copy link
Contributor Author

xobs commented Feb 3, 2023

Alright, both of those requested changes have been made. I can't figure out how to de-indent those without adding a goto, so I opted to pull it into its own function instead.

dragonmux
dragonmux previously approved these changes Feb 3, 2023
Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, we'll give this a test locally just to make sure nothing broke on native, then merge. Many thanks xobs!

While we do, could we get you to rebase the PR so the gdb_main.c conflict is resolved? We'll aim to merge this today so this should be the last rebase

@dragonmux dragonmux added the Bug Confirmed bug label Feb 3, 2023
@dragonmux
Copy link
Member

Testing says this works well on both RP2040 and Tiva-C, so this is ready for merge once the branch conflict has been sorted

xobs added 8 commits February 3, 2023 14:57
This is an attempt to invert the main loop. Rather than spending
the majority of time executing within `gdb_main()`, turn it into
a state machine that gets polled. This will improve behaviour on
PC_HOSTED platforms as well as platforms such as ESP32 where the
main loop needs to pause occasionally.

Signed-off-by: Sean Cross <[email protected]>
These macros were previously empty, which made them unusable in if()
statements without braces. Add an empty do{}while(0) statement that
allows these statements to be used in such locations.

Signed-off-by: Sean Cross <[email protected]>
Add a parameter to `pbuf_size`, since `sizeof(pbuf)` now always returns
the size of a pointer.

Signed-off-by: Sean Cross <[email protected]>
The function was indented bceause it used to have a loop around it.
Deindent the entire function now that the `while()` is gone.

Signed-off-by: Sean Cross <[email protected]>
Use newer C standard variable initialization.

Signed-off-by: Sean Cross <[email protected]>
Remove extra braces and an extra, now-unnecessary cast.

Signed-off-by: Sean Cross <[email protected]>
In order to prevent super indentation, move the main poll loop into its
own function.

Signed-off-by: Sean Cross <[email protected]>
This typedef exists, so we might as well use it.

Signed-off-by: Sean Cross <[email protected]>
@dragonmux dragonmux merged commit 5cf0dd2 into blackmagic-debug:main Feb 3, 2023
@dragonmux dragonmux mentioned this pull request Feb 13, 2023
dragonmux added a commit that referenced this pull request Apr 3, 2023
…o a hidden UB declaration of gdb_main_loop()
@dragonmux dragonmux mentioned this pull request Apr 3, 2023
6 tasks
esden pushed a commit that referenced this pull request Apr 4, 2023
…o a hidden UB declaration of gdb_main_loop()
@ALTracer ALTracer mentioned this pull request Nov 19, 2023
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Confirmed bug Enhancement General project improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants