Using GDB with Teensy without hardware debugger, first Beta

I updated Github today with these fixes:

1. Reduce serial polling to 0.5 milliseconds. This should increase responsiveness. Will look at alternatives @defragster suggested.
2. Fix `p func()` that allows you to call most functions from GDB when it is stopped.
3. Improve install script.
4. Fix numerous bugs with SP and stack handling. It now steps into and over function calls more consistently.

It only really works with Teensy 4. I'm not going to bother getting Teensy 3 working.

Pulled code into github desktop to glance at changes - what fun.

This is semi-redundant but harmless since delay() as noted calls yield() - in gitstub.cpp:
Code:
    delay(1);
    yield();
Even if the yield could call processGDB() - it might just call too often? ... see below.

This works to Assert - but just breaks/halts printing the next line - no msg as to why : #define ASSERT(expr) if (!(expr)) {asm volatile("svc #0x11");}

Changing this to 100us from 500 gave the prior 'ERROR' sooner and didn't run much faster (maybe 70/sec instead of 60) : #define GDB_POLL_INTERVAL_MICROSEC 1000
> so the slowdown may be PC side processing as well as multiple msg/parts to process? - setting to 1000us as above still runs at 54 loop()/sec - and 'ignore 1 10000' still results in GDB fail - 'Remote connection closed'
> Not sure if calling processGDB() too fast is bad? Being called on IntercalTimer_isr - it should be blocked from calling itself twice? - but if called from user code the timer could cause re-rentry?
> So adding yield()/polling calling may be bad - as the timer would still be needed to run in case it gets in a tight loop ... or lost.

Getting it working well on T_4.x's 1062 seems good given any trouble/differences on T_3.x family. Perhaps Paul will evolve his plan for debug if Arduino moves that way ... or everyone will just buy 1062's :)
 
Anybody running on linux that could try:

void setup() {
Serial.begin(19200);
debug.begin(SerialUSB1);
delay(1000);
halt();
}

This often causes gbd to not connect. Works fine without the delay(). Also works fine if I get gdb connected during the delay period.

Is there a way for teensy code to determine if gdb is connected? For example, below would solve my problem

if (gdb_connected()) halt();
 
If anyone is debugging a teensy that is not connected via dual serial USB (eg, hardware serial port), this should be useful:

gdb_out_print(const char *msg)

It causes gdb to display a string.

PS - looks like a declaration for this is missing from TeensyDebug.h.
 
Last edited:
If anyone is debugging a teensy that is not connected via dual serial USB (eg, hardware serial port), this should be useful:

gdb_out_print(const char *msg)

It causes gdb to display a string.

PS - looks like a declaration for this is missing from TeensyDebug.h.

It wasn't documented (I just added it), but object `debug` inherits from class `Print`. Thus it supports print, println, etc. to print to the GDB console.

Code:
debug.print(testvalue, HEX);
 
This works to Assert - but just breaks/halts printing the next line - no msg as to why : #define ASSERT(expr) if (!(expr)) {asm volatile("svc #0x11");}

This is a bug with the shenanigans I have to pull to get GDB to work calling code dynamically. I just committed some changes that may fix this most of the time.

Getting it working well on T_4.x's 1062 seems good given any trouble/differences on T_3.x family. Perhaps Paul will evolve his plan for debug if Arduino moves that way ... or everyone will just buy 1062's

As for the T3, I had a plan using FP_REMAP and associated functions and it's mostly coded and works so-so. I would devote more time to it if I thought it had a future. But it seems the T3 is an obsolete platform with the Teensy 4 being the same size, roughly the same price and so much better in everything except a DAC.
 
the T3 is an obsolete platform with the Teensy 4 being the same size, roughly the same price and so much better in everything except a DAC.

I don't know what Paul thinks about it, but I have to say I prefer 3.x to 4.x unfortunately.
4.x has too much power draw for most of my projects, even at lower clock speeds, and the powersave/sleep modes are not efficient.
I'll resort to 4.x when high speed is a must, but I'm not moving my stuff to them, as much as I would have liked to.
 
Everything is working well for me now. Thanks, this will definitely speed up debugging.
This works amazingly easily and well - if only for a quick enable to detect code Faults! Rather than a mystery hang - you end up on a line of code with some ability to examine the system and backtrace.
So nice the needed GDB tool already installed and easy to activate. There is some overhead of course.

I don't know what Paul thinks about it, but I have to say I prefer 3.x to 4.x unfortunately.
4.x has too much power draw for most of my projects, even at lower clock speeds, and the powersave/sleep modes are not efficient.
I'll resort to 4.x when high speed is a must, but I'm not moving my stuff to them, as much as I would have liked to.

prior note was to make the 1062 debug the best it can be - which seems to be mostly done - at least proven functional - get some runtime on it and either work for T_3.x might come along - or Paul might be inspired to relate/implement the PJRC debug scheme - given popularity and how well it works. It might follow along with this and expose any missing parts - or be wholly different with use of SWD hardware the bootloader owns.
 
This is a bug with the shenanigans I have to pull to get GDB to work calling code dynamically. I just committed some changes that may fix this most of the time.

As for the T3, I had a plan using FP_REMAP and associated functions and it's mostly coded and works so-so. I would devote more time to it if I thought it had a future. But it seems the T3 is an obsolete platform with the Teensy 4 being the same size, roughly the same price and so much better in everything except a DAC.

With today's github code it seems to be fixed: #define ASSERT(expr) if (!(expr)) { asm volatile("svc #0x11");}
Code:
Reading symbols from T:\TEMP\\arduino_build_testOut.ino\testOut.ino.elf...done.
(gdb) target remote \\.\com26
Remote debugging using \\.\com26
0x00000000 in _stext ()
[B][U](gdb) c[/U][/B]
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x000001b8 in loop () at T:\tCode\TLAjr\testOut/testOut.ino:34
34                              ASSERT(0 == Serial);
[B][U](gdb) l[/U][/B]
29                      lTime = 0;
30                      lCnt = 0;
31              }
32                      if ( Serial.available() ) {
33                              Serial.read();
34                              [B]ASSERT(0 == Serial);[/B]
35                      }

Would be nice if there is a usable way to get it to work on the T_3.x's.
 
I learned that on linux I can install "gdb-multiarch" and then use this newer version (V8.1) of gdb. Maybe this effects how the call function issue should be resolved.
 
@ftrias - Having problems installing TeeensyDebug on My Linux laptop.Using Ubuntu 4.4.0. Running './install-linux.sh -i=/home/wwatson/arduino-1.8.13' I got this:

Code:
wwatson@wwatsonl1:~/TeensyDebug$ ./install-linux.sh -i=/home/wwatson/arduino-1.8.13
Install GDB in Teensyduino
[Errno 2] No such file or directory: '/usr/local/bin/arduino'
Press Enter to close

It does not seem to be picking up the provided path and defaults to '/usr/local/bin/arduino'.

What am I missing? I did get it installed from the zip file on one of my desktops.

Thanks

Edit: I usually do not install Arduino into '/usr/local/bin/arduino'. I run directly out of home directory.
 
Last edited:
wwatson:

As a possible work-around, could you just create a softlink in /usr/local/bin/arduino that points to your actual location ?? Something like this (probably have to be root to do it):

Code:
ln -s /home/wwatson/arduino-1.8.13/arduino /usr/local/bin/arduino

Note: I have not installed or run arduino on any of my linux machines, so adjust the command if/as needed if the arduino executable is not directly under your /home/wwatson/arduino-1.8.13 folder.

Good luck & have fun !!

Mark J Culross
KD5RXT
 
wwatson:

As a possible work-around, could you just create a softlink in /usr/local/bin/arduino that points to your actual location ?? Something like this (probably have to be root to do it):

Code:
ln -s /home/wwatson/arduino-1.8.13/arduino /usr/local/bin/arduino

Note: I have not installed or run arduino on any of my linux machines, so adjust the command if/as needed if the arduino executable is not directly under your /home/wwatson/arduino-1.8.13 folder.

Good luck & have fun !!

Mark J Culross
KD5RXT

Thanks for the work around. That worked:)
 
It's a bug. I updated the install script to accommodate a missing /usr/local/bin/arduino.

I have it working now and changed the terminal program from xterm to mate-terminal in 'teensy_debug'. My eye's need bigger fonts:)
Anyway it's working and now have to refresh my memory on using gdb. It's been years since I used it.
 
I have it working now and changed the terminal program from xterm to mate-terminal in 'teensy_debug'. My eye's need bigger fonts:)
Anyway it's working and now have to refresh my memory on using gdb. It's been years since I used it.

For what it's worth, this is not too bad: https://www.gdbgui.com/

You can create a file `customize.py` in the `....hardware/tools` directory with the below (changing the path for 'g') and it should start that up instead of the xterm.

Code:
import os
def customRun(gdb, dev, elf):
  g = "/Users/ftrias/.local/bin/gdbgui"
  cmd = "'%s' -g '%s' '%s' --gdb-args \"-ex 'target remote %s'\" &" % (g, gdb, elf, dev)
  os.system(cmd)
 
For what it's worth, this is not too bad: https://www.gdbgui.com/

You can create a file `customize.py` in the `....hardware/tools` directory with the below (changing the path for 'g') and it should start that up instead of the xterm.

Code:
import os
def customRun(gdb, dev, elf):
  g = "/Users/ftrias/.local/bin/gdbgui"
  cmd = "'%s' -g '%s' '%s' --gdb-args \"-ex 'target remote %s'\" &" % (g, gdb, elf, dev)
  os.system(cmd)

Thanks for the link. I will definitely check this out. I remember using 'DDD' as front end to GDB. I also remember using 'make' from within GDB.
 
@ftrias - This is so awesome!! It all comes up and works:) The gdbgui pops up in my Firefox browser after compiling and when I type in step in the command line I see 'mark =' values increasing in the terminal window. Can't wait to learn how to fully utilize this resource and see what it can do.

Nice work:)
 
I fixed support for Teensy 3 to git. It should work now using the Flash Patch feature to set/clear breakpoints in Flash. You can have a maximum of 5 breakpoints. Stepping line-by-line over the end of a function (and returning to the previous one) does not seem to work reliably. Stepping within functions should work.
 
Hi !
Looking at this thread, i find this really excellent.
Am I making a too quick assumption thinking i can get inline debug capability within Vscode/Platformio, which to my knowledge is based on gdb for the debugger?
Thanks.
 
@ftrias - Thanks again, Just starting to play again. Also trying to get it to work with the VisualMicro.
I will ask more on their thread or forum... Like how to setup to use with libraries (again). Although a lot of what I am debugging is in my set of Arduino sketch tabs.

A couple of notes: Took me awhile to find again how to connect to the sketch: target remote \\.\COM32

But am able to breakpoint in servo library which is great...

It is also interesting if I use the: #pragma GCC optimize ("O0")
The sketch will NOT build with USBHost code as the link will fail as not finding VTables for some of the base classes.

Also note: I am getting several compiler warnings: (T4.1) 1.8.13 ...
Code:
"C:\\arduino-1.8.13\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -c -Og -g -DGDB_DUAL_SERIAL -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=153 -DARDUINO=10813 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_DUAL_SERIAL -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_142095/pch" "-IC:\\arduino-1.8.13\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\TeensyDebug" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\LSS_Library_Arduino\\src" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\SoftwareSerial" "-IC:\\arduino-1.8.13\\hardware\\teensy\\avr\\libraries\\EEPROM" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\USBHost_t36" "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\TeensyDebug\\gdbstub.cpp" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_142095\\libraries\\TeensyDebug\\gdbstub.cpp.o"
In file included from C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:19:0:
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp: In function 'int isValidAddress(uint32_t, int)':
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:36:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define RAM_START ((void*)0x00000020)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:534:15: note: in expansion of macro 'RAM_START'
   if (addr >= RAM_START && addr <= RAM_END) {
               ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:37:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define RAM_END   ((void*)0x20280000)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:534:36: note: in expansion of macro 'RAM_END'
   if (addr >= RAM_START && addr <= RAM_END) {
                                    ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:36:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define RAM_START ((void*)0x00000020)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:535:22: note: in expansion of macro 'RAM_START'
     if (addr+sz-1 >= RAM_START && addr+sz-1 <= RAM_END) {
                      ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:37:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define RAM_END   ((void*)0x20280000)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:535:48: note: in expansion of macro 'RAM_END'
     if (addr+sz-1 >= RAM_START && addr+sz-1 <= RAM_END) {
                                                ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:34:39: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define FLASH_START ((void*)0x60000000)
                                       ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:539:20: note: in expansion of macro 'FLASH_START'
   else if (addr >= FLASH_START && addr <= FLASH_END) {
                    ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:35:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define FLASH_END ((void*)0x601f0000)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:539:43: note: in expansion of macro 'FLASH_END'
   else if (addr >= FLASH_START && addr <= FLASH_END) {
                                           ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:34:39: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define FLASH_START ((void*)0x60000000)
                                       ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:540:22: note: in expansion of macro 'FLASH_START'
     if (addr+sz-1 >= FLASH_START && addr+sz-1 <= FLASH_END) {
                      ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\TeensyDebug.h:35:37: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
 #define FLASH_END ((void*)0x601f0000)
                                     ^
C:\Users\kurte\Documents\Arduino\libraries\TeensyDebug\gdbstub.cpp:540:50: note: in expansion of macro 'FLASH_END'
     if (addr+sz-1 >= FLASH_START && addr+sz-1 <= FLASH_END) {
But this will be very helpful, so again THANKS
 
I saw speed increase when removing this from sketch :: #pragma GCC optimize ("O0") ... noted in prior post.

>> But sample debug was unaffected in that case without that :: #pragma GCC optimize ("O0")

so much GUI for too long ... cmdLine remembering "target remote" and then finding correct "\\.\COM32" value takes effort - especially when using two Teensy at once :)

Very cool that VisualMicro watched and picked up on it! Good luck getting it to work.
 
Hi Guys,

Has anyone managed to get "Take over serial" to work?

In GDB I see:
Code:
[no_device]: No such file or directory.

I cannot see the serial device available either.

The only way to get flashing working after this is to close the teensy flashing app, next time it reloads flashing works again.

I have Dual Serial working fine but am using the audio/midi usb and only have one serial.

Thanks

Andy
 
Back
Top