Using GDB with Teensy without hardware debugger, first Beta

I think my problem was caused by the following:
I'm using Visual Studio Code with a makefile project (created with VisualTeensy)
To get the debugging going I declared GDB_DUAL_SERIAL at the top of my main file. After moving it to the makefile things are looking better.
So thanks for the help, it looks like it was a case of PEBKAC

I'm the module author. Thanks for debugging this setup. If you send me the specific steps you used to get this working I can add it to the README.
The installer is looking for a directory "hardware/teensy" inside your Arduino directory. If it's not there, it complains.

Since you have a non-standard install, it's probably best to just set up manually. Look at the file and follow the steps in "Installing overview".

I ran into the same problem with the install.
The issue was that the ardunio/teensy stuff was installed in a folder like arduino-1.8.15.
Also, the teensy_debug.exe file had to be hand installed in the "libraries" folder in a custom made folder "TeensyDebug".
Then the .exe file has to be run and the special path given to it when it won't find the folder.
By the way the GDB menu items are in the drop down "tools" list near the bottom.
Hello ftrias,

having made a similar debugger in the past, I took a look at your code on github and I have few remarks to improve it:

- too few instructions are decoded in the software single step routine (setBreakPointNext()), 32 bits thumbs instructions are ignored for example.
You could take a look at the thumb_get_next_pcs_raw() function of GDB for a complete (I guess) decoding to manage software single stepping.
Note that by recompiling the GDB client with a minor patch, you can let it doing this work (as done for linux ARM target).
- PacketSize returned in the qSupported response should be in Hex format.
- The ISR context stack size (ISR_STACK_SIZE) is not constant, it depends on Bit[4] of EXC_RETURN (see DAI0298A_cortex_m4f_lazy_stacking_and_context_switching.pdf). EDIT: and stacked PSR[9] if SP not 8-byte aligned.
- You need to check whether it's PSP or MSP that is in use when the program is 'halted' to save the correct value as the top stack. But may be unnecessary if the same stack is used for user and handlers.

And I don't understand why you use a polling-timer to retrieve the GDB data. Using the UART interrupt works perfectly fine, with zero overhead when there is no communication (Note: I don't use Teensy/Arduino).
Last edited:
It is also worth noting that the communication speed between the client and the stub is very dependent on the RX latency of the USB-UART IC driver.

Using an FTDI cable on Windows (did not try on Linux) with the default settings is awful.
Changing the RX buffer latency from 16ms to 1ms will improve the experience
usb lat.png

but a better result can be achieved by using an ST-Link, as found on the Nucleo boards, with j-link driver.

With interrupt based UART communication, running at 921600 bauds, it is equivalent to a hardware debug probe.

And I am pretty sure that we can still improve the performance if we optimize the communication routines in the GDB client.
Last edited:
I've been playing with this library again, as a result of seeing this thread. At first I couldn't reproduce the issue, then I could, and now I can't again! However, I may have made some progress, my observations being:
  • there can be possibly intermittent issues with using the GDB library with I2S audio, specifically the SGTL5000, but
  • it may not be specific to audio - I could provoke it by referencing the Wire library
  • the symptoms are that the Teensy never makes it to setup(), and its USB capabilities don't start up (no COM ports etc)
I've possibly narrowed it down to the first call to resetPFD() in cores/teensy4/startup.c, and more specifically to the setting of CCM_ANALOG_PFD_480. Removing the call altogether, or just the change to that one register, seemed to fix the issue without causing any other side-effects. Note there's a second call to resetPFD(), commented "//TODO: is this really needed?" - obviously if you remove the first call, it probably is needed, and should set both analogue PFD registers' values.

If the issue is occurring, then it looks like the CPU never returns from the first resetPFD() call, which suggests that something deeply nasty has happened to destabilise the core as a result of setting one or more of the PFD values. As I write I don't know which ones, because it's all started working again.

I'll revert to the stock startup.c, use GDB routinely, and try to generate further data if/when the issue occurs again.
Some minor fixes are in PR#19, opened June 1st and just updated to remove some warnings. The author doesn't appear to have been active recently, so if you want them you may just have to grab them direct from my branch.
Problems with large uploads on Teensy 5.1

I am trying to get TeensyDebug working stably on a Teensy 4.1 using vscode and platformio on Linux. Using the latest version of TeensyDebug it works fine on small sketches, but fails on large ones. The 4.1 accomodates much larger sketches (*10) than any previous teensy. This exacerbates the usb enumeration problem of the teensy upload process returning success before the host OS has recognised the existence of the dual usb serial ports.

I have tried numerous ways of fixing this, but with limited success. The problem is that platformio launches gdb before Linux has created the usb serial device nodes in the file system. This means that gdb exits as soon it tries to open the remote debug target.

This is the recommend platformio.ini section.

build_type = debug
; See
build_unflags = -DUSB_SERIAL
build_flags = -DUSB_DUAL_SERIAL
debug_port = /dev/ttyACM1
debug_tool = custom
debug_load_mode = manual
debug_server =
debug_init_cmds =
target extended-remote $DEBUG_PORT
define pio_reset_run_target
tbreak loop
define pio_restart_target
echo Restart is undefined for now.

I have tried inserting a gdb shell command before the target command i.e.
shell sleep 5
shell while ! [ -c $DEBUG_PORT ]; do echo $DEBUG_PORT not found; sleep 2; done

Neither of these stop my test sketch failing. I am beginning to think that something in the sketch might be causing this. I have this at the beginning of the setup() function.

while (!Serial) {} // wait for Serial Monitor to be ready

Serial.printf("Waiting for debugger to attach\n");
while (!SerialUSB1) {
} // wait for Serial Debugger to be ready
Serial.printf("\nSerial debugger ready\n");
halt_cpu(); // stop on startup; if not, Teensy keeps running and you
// have to set a breakpoint or use Ctrl-C.

Has anyone got any ideas?

I can supply much more information if required.


Hi Roger. Do you know if platformio uses the teensy_debug Python script to program the Teensy and launch GDB? That was what prompted me to make some changes (as you say, now pulled in), and the symptoms sound pretty similar - in Windows, programming plus USB enumeration were taking a long time, and GDB was starting and giving up too soon. If the Python is being used, the key change is lines 387-401, where it checks for the "Bootloader" device to disappear; however, I only allowed 10s for that, and assumed that once it was gone no further wait was required. I didn't test with Linux, but maybe it needs a bit of further tweaking.
Hi h4yn0nnym0u5e,

platformio does not use the python script. It uses whatever you put in platformio.ini, .vscode/launch.json and .vscode/tasks.json.

I have been trying to reproduce what you put in the teensy_debug python script. But my knowledge of teensy and platformio is limited. The launch of gdb on the host fails as soon as the target extended-remote $DEBUG_PORT command is executed in gdb. Unfortunately this locks up the debugger window in vscode.

I thought my test for the existence of the required serial device file should be enough, but it appears it is not.

platformio uses binaries it stashed away in ~/.platformio/packages/tool-teensy to do the uploading.

The failure can also leave the teensy in a funny state. This usually requires pressing boot button more than once to get the boot led back to dim. Do you know what 8 flashes of boot led mean (not 9).

I think that a solid fix requires both the fix to the gdb init commands and something on the teensy side.

Any help gratefully received.

I think you'll probably need a PlatformIO and/or Linux expert for this - I'm neither, but there may well be one along in a moment!

The red LED flashes are documented here:

You could try running the teensy_ports utility to monitor your Teensy's enumeration timing. There's some "documentation" at

I did have considerable difficulty combining audio and debug libraries (as have others). An entirely empirical "fix" (which works for me but I don't understand), is to comment out the reset_PFD() call at or about line 92 of /cores/teensy4/startup.c. This may or may not be relevant to your use case.
Thanks for the tips. I have searched for those blink codes without success!

Yes my test sketch uses the audio libraries. So another good tip.

Why the bootloader chip reports bad jtag is puzzling. But may explain why the usb ports do not appear.

Thankyou very much!!!!
Yes, forgot to say, without that change to startup.c the processor gets completely wedged and thus doesn't enumerate, requiring the Program button press. The 8-flash code seems bogus to me, but at least you get some indication that it's all gone horribly wrong...
I did get VSCode and Teensy_Debug to work. But it seems to only work if the USB type is dual_serial. This is set in the platformio.ini file with
build_unflags = -DUSB_SERIAL
build_flags = -DUSB_DUAL_SERIAL

I want to debug an program using the FlightSim USB type.

Has anybody successfully debugged using any other type than Dual Serial?
Yes, but only with USB descriptors which include a CDC serial interface - TeensyDebug checks for these. It looks as if the FlightSim descriptor only has the emulated serial interface; no idea why, it may be a legacy feature or there may be some technical reason the CDC serial doesn’t play nicely with FlightSim.
I'm trying to install the library to debug teensy 4.1 but am having trouble being able to do so.

Auto-installer (teensy_debug) complains about not finding arduino, no matter what directory I provide (the actual ide runtime location or the arduino15 folder with all the packages).
Directory structures seem to no longer fit the instructions provided in, making it hard to follow manual install.
e.g., "hardware/teensy/avr" is now "teensy/hardware/avr"; there is no "hardware/tools" folder, rather "teensy/tools"
Installing all files to these folders changes nothing in the IDE menus...

Am I missing something? (most likely yes)