Sleeping to disable C_DEBUGEN

Status
Not open for further replies.

ftrias

Well-known member
I was hoping that the Debug Monitor ISR would help with a low level project. After reading https://forum.pjrc.com/threads/26358-Software-Debugger-Stack and https://forum.pjrc.com/threads/28058-Teensyduino-1-22-Features?highlight=C_DEBUGEN. I'm having difficulty following the instructions to turn off C_DEBUGEN. It says to sleep for 100 ms or more.

Here is my code:

Code:
#include <Snooze.h>

#define ARM_DHCSR (*(uint32_t*)0xE000EDF0)

SnoozeTimer timer;
SnoozeBlock config_teensy(timer);

void setup() {
  pinMode(13, OUTPUT);

#ifdef __MK20DX128__
  return;
#endif
  delay(1000);

  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
#ifdef __IMXRT1062__
  timer.setTimer(1);
#else
  timer.setTimer(500);
#endif
  Snooze.sleep(config_teensy);
  digitalWrite(13, HIGH);
}

void loop() {
  delay(1000);
  Serial.print("DHCSR=");Serial.println(ARM_DHCSR, HEX);
}

Running on a Teensy 3.2, the C_DEBUGEN bit is never disabled. Here is the output:

Code:
DHCSR=3010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001

What am I doing wrong?
 
I was hoping that the Debug Monitor ISR would help with a low level project. After reading https://forum.pjrc.com/threads/26358-Software-Debugger-Stack and https://forum.pjrc.com/threads/28058-Teensyduino-1-22-Features?highlight=C_DEBUGEN. I'm having difficulty following the instructions to turn off C_DEBUGEN. It says to sleep for 100 ms or more.

Here is my code:

Code:
#include <Snooze.h>

#define ARM_DHCSR (*(uint32_t*)0xE000EDF0)

SnoozeTimer timer;
SnoozeBlock config_teensy(timer);

void setup() {
  pinMode(13, OUTPUT);

#ifdef __MK20DX128__
  return;
#endif
  delay(1000);

  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
#ifdef __IMXRT1062__
  timer.setTimer(1);
#else
  timer.setTimer(500);
#endif
  Snooze.sleep(config_teensy);
  digitalWrite(13, HIGH);
}

void loop() {
  delay(1000);
  Serial.print("DHCSR=");Serial.println(ARM_DHCSR, HEX);
}

Running on a Teensy 3.2, the C_DEBUGEN bit is never disabled. Here is the output:

Code:
DHCSR=3010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001
DHCSR=1010001

What am I doing wrong?

Not Sure. It did not work for me, too-and Paul said it's not implemented o the T4 so I lost interest and will look again when it is ported to the T4
 
That's unfortunate. The previous threads also suggested using Flash Patch Control Register FP_REMAP to do something similar to a breakpoint by remapping the instruction to a fault of some sort (or, it occurs to me, to the SVC instruction). However, the Cortex M7 that the Teensy 4 uses does not support that. So is doing any sort of live debugging on the Teensy a dead end? It seems like such a practical feature if only you could disable C_DEBUGEN. Sometimes print statements just aren't practical.
 
GDB stubs on Teensy proposal

I gave this some thought over the weekend and I think live debugging is possible even if C_DEBUGEN cannot be changed. The idea is to use a GDB stub to remotely debug the Teensy and instead of using BKPT, using SVC. This proposal will enable limited breakpoints and live examination of data.

First, I'll explain GDB stubs a little. Then I'll discuss how to use it. I'm writing this here to see if this has already been done and to get feedback.

GDB stubs

GDB stubs provides a simple interface between GDB and a remote target via a serial interface, such as a socket, pipe, UART, USB, etc. It works like this:

[PC running GDB looking at ELF file] <----(serial)----> [Teensy running GDB stub]

Teensyduino comes with a GDB executable that supports ARM. The ELF file contains debugging info if compiled with the "Debug" option that Teensyduino provides. Thus, GDB loads up the ELF and knows all the symbols and sees the source code. GDB queries Teensy for information like memory data and registers as needed. It also sends Teensy breaking and execution commands.

This is how it would work with Teensy:

1. By using interrupts or the EventResponder, the Teensy listens to GDB commands from a serial device.

2. When it gets commands like memory queries, memory sets and things that don't require halting, it responds with the data requested.

3. When it receives a halt command, Teensy will just go into a loop querying for commands and responding. It won't return to it's caller until GDB tells it to do so. Thus, execution of the main thread will stop but interrupts will continue. Because interrupts continue, on the plus side, the Teensy won't die and USB and other features will stay active. On the other hand, sometimes you just the want the system to halt. Perhaps there could be an option to halt all interrupts as well or change the priority. Keeping interrupts going is probably easier for beginners and models what desktop apps do (when an apps stops, the OS keeps going).

So far, this will enable us to do simple live debugging. You can't set breakpoints yet, but you'll be able to stop execution and examine the state.

4. Provide a special "breakpoint" instruction that you can insert into your code. Each breakpoint will have a flag in RAM to determine if it is enabled or not. If enabled, when execution reaches it, it will execute an interrupt (software or SVC). If disabled, execution just keeps going. Breakpoints are enabled/disabled based on commands received from GDB.

So far, this provides fixed hardcoded breakpoints. You can stop the code at any place and examine/change variables, stack, etc.

5. If a function is placed in RAM with the FASTRAM option, you can dynamically insert/remove SVC calls in the code, in the same way that standard debuggers work. Thus, if you want arbitrary breakpoints in certain code, just specify FASTRAM. Again, breakpoints like this can be set and enabled/disabled by GDB.

In theory, most code can be placed in RAM by changing the gcc compile options, or by linking with an alternative LD file. Perhaps Teensyduino can provide a feature to do this in the future? The Teensy 4 has plenty of RAM to store most programs. You can store some parts, like core code, in flash and all user code in RAM.

6. On the Teensy 3.1/3.2, we could as well use the Flash Patch Block to set and remove SVC calls using patching. Thus, you can dynamically set breakpoints in flash. Teensy 4 doesn't support this.

Other considerations

The serial connection can be anything. To start it's probably best to use a UART but in theory it could be USB Serial, CAN, network, Raw connection, etc.

Right now, running GDB will have to be done manually. But in the future, GDB could be piped to Arduino's serial monitor. Both GDB's output and Teensy's serial output could be sent to the display. GDB can receive commands from the Send window. If, in addition to this, we use USB for the serial connection to GDB, then Teensy will have onboard live debugging available with no special setup or hardware required.

If C_DEBUGEN can be disabled, then the Teensy 4 can also have dynamic breakpoints in flash and everything else becomes somewhat simpler to implement.

Any thoughts?
 
No doubt there have been times when a debugger would have saved me some time. #1 and #2 are easy. I'd make some use of a monitor program that allowed halt/read-write global variable/resume through a second serial port (physical or the new USB1 virtual serial). Might as well make it easy to read/set/clear hardware pins too. Like ArduinoMonitor.
 
Last edited:
I
5. If a function is placed in RAM with the FASTRAM option, you can dynamically insert/remove SVC calls in the code, in the same way that standard debuggers work. Thus, if you want arbitrary breakpoints in certain code, just specify FASTRAM. Again, breakpoints like this can be set and enabled/disabled by GDB.

I just realized that the Teensy 4 places all user code in RAM so setting breakpoints in this way should work fine.
 
No doubt there have been times when a debugger would have saved me some time. #1 and #2 are easy. I'd make some use of a monitor program that allowed halt/read-write global variable/resume through a second serial port (physical or the new USB1 virtual serial). Might as well make it easy to read/set/clear hardware pins too. Like ArduinoMonitor.

Everything is doable except to set/clear hardware pins. The gdb remote protocol (https://sourceware.org/gdb/current/...ml#File_002dI_002fO-Remote-Protocol-Extension) doesn't seem to support anything like arbitrarily running code on the target. However, it does seem to support running code on the _host_ (that is the PC) with the 'F' command. Thus, Teensy could read/write files on the host computer. This might also be useful.
 
But set/clear pins is only a matter of writing to a memory location - which gdb can do. Would be nice if someone ported even a minimal implementation of gdbstub to teensy. I'd even use it if it wasn't interrupt based and it needed to be called periodically (cooperative multitasking).

Summary - lots of useful gdb functionality doesn't need C_DEBUGEN.

Info about ArduinoMonitor (some similar functions, implemented without the gdb protocol):
https://n.mtng.org/ele/arduino/arduinomon.html
 
Would be nice if someone ported even a minimal implementation of gdbstub to teensy.

That's what I'm hoping to do. I've got something minimal working and it's all looking very doable on the Teensy 4. Hopefully I will put it on github over the weekend for testing/feedback.

I also figured out the hardware pings. We can use the "monitor" command to trigger the Teensy to do things.
 
Great, I look forward to trying it. IMO, many will want to use SerialUSB1 (second virtual port) vs a hardware serial port.
 
I put together some code that allows GDB to perform source-level debugging on the Teensy without an external debug interface (no need for SWD, etc). It uses GDB's Remote Serial Protocol to communicate with Teensy over a Serial connection (hardware or USB). This is a beta release for comments and testing. It works (mostly) on Teensy 4 and 3.2. Tested on Mac. Highlights:

* Set/remove breakpoints on most places in your code
* Examine and change memory and registers
* View call stack
* Halt code at any time
* Next/step working minimally, but not across functions.

To emulate breakpoints the library first takes over the SVC interrupt (like I did in TeensyThreads). The Teensy 4 places most code in RAM so to activate a breakpoint it just replaces the original instructions with SVC calls. On Teensy 3.2, setting breakpoints uses the Cortex-M4's features to "patch" parts of flash by pointing it to RAM.

The library is enabled by including the header. On Macs, there is a python script that adds a menu option and configures Arduino to open GDB automatically after uploading your program. On other platforms, you run GDB manually and use `target remote` to connect to the serial port used by the GDB interface. However, the python script is simple and could easily be ported to Windows (or rewritten in C).

To read more and try it out visit: http://github.com/ftrias/TeensyDebug

Any comments or code would be greatly appreciated!
 
Excellent! Nice instructions - getting the example program running is easy and it works.

On my linux system:

gdb is at ~/arduino/arduino-1.8.12/hardware/tools/arm/bin/arm-none-eabi-gdb
The .elf is at /tmp/arduino_build_282047/XXX.ino.elf
Serial port is at /dev/ttyACM1

There is a mark vs mark1 typo.
 
I just realized that there is a tool "arm-none-eabi-gdb-py", which is GDB with an embedded Python interpreter. If `run.command` (the Python component that adds the menu & opens GDB automatically on a Mac) can be ported to this, then all external dependencies can be removed.
 
Just went back to TSET building on Windows now that no active PJRC TD beta and TyCommander was updated for T_4.1 and working. May need to update TSET - as my local copy had TyComm REM'd out to force using TeensyLoader as the T_4.1 evovled.

With a chance to see this on Windows I could integrate the startup into TSET perhaps.

Indeed posted TSET had TyComm REM'd - now restored if anyone cares to look: github.com/Defragster/Tset/blob/master/TSet.cmd2
 
ftrias's gdbstub is working well. I strongly believe that:

a) a debugger speeds program development - no painful "think of debug idea, insert debug statements, recompile, start over".
b) it's a bad idea that many people learn to program without even knowing what a debugger is

Imagine a problem that only occurs rarely - a single cycle of a) can take hours.
 
Not seeing this in the README - as far as I read ... added as an issue on github:
GDB is :: "T:\arduino-1.8.12\hardware\tools\arm\bin\arm-none-eabi-gdb.exe"

Com port ( as found by TyComm ) given as :: (gdb) target remote \.\com21

not yet done reading the README - but those are the first two notes for WINDOWS 10
 
What's the deal with Python? Needed/Expected? On Windows there are two GDB exe's with the second '...gdb-py.exe' Without the "-py" I get GDB as below. When I add the -py the system wants for 'python27.dll' - but that isn't a file in the python27 installed here and may not be on the path.

Using this example code: ...\libraries\TeensyDebug\examples\breakpoint_test\breakpoint_test.ino

Not sure if this is close but what follows in TSET giving me this in a DOS box:
Code:
Reading symbols from [B]T:\TEMP\\arduino_build_breakpoint_test.ino\breakpoint_test.ino.elf[/B]...done.
(gdb) [B]target remote \\.\com21[/B]
Remote debugging using \\.\com21
[U]Ignoring packet error, continuing...
warning: unrecognized item "timeout" in "qSupported" response
Ignoring packet error, continuing...
Ignoring packet error, continuing...
Bogus trace status reply from target: timeout
[/U](gdb) p mark
[B][COLOR="#FF0000"]$1 = 45[/COLOR][/B]  [U]// it is really :: [B]mark=5[/B][/U]
(gdb) b level1
Breakpoint 1 at 0x108: file T:\tCode\libraries\TeensyDebug\examples\breakpoint_test/breakpoint_test.ino, line 30.
(gdb) c
[B][COLOR="#FF0000"]The program is not being run.[/COLOR][/B]
(gdb)

In the TSET batch file I have - SublimeText was collecting GDB as console output until the 'start' was added to exec a secondary batch file:
Code:
  if "%errorlevel%"=="0" {
    "%TyTools%\TyCommanderC.exe" upload --autostart --wait  "%temp1%\%sketchname%.%model%.hex"
    "%arduino%\hardware\tools\arm\bin\arm-none-eabi-gcc-nm.exe" -n "%temp1%\%sketchname%.elf" | "%tools%\imxrt_size.exe"
    start "%tools%\GDB.cmd" "%arduino%\hardware\tools\arm\bin\arm-none-eabi-gdb.exe" "%temp1%\%sketchname%.elf"
  }

Secondary batch file GDB.cmd currently gave the above:
Code:
echo Start GDB debugger
%1 %2
pause


Pushed updates to Windows TSET :: github.com/Defragster/Tset
From Command line of appropriate Editor { like SublimeText } Board Params set with
> Running TSet.cmd for T_4.1, 600 MHz, Fastest, Dual Serial, Yes save is :: 711my
> Running TSet.cmd for DEBUG T_4.1, 600 MHz, Fastest, Dual Serial, DEBUG save is :: 711md
Then run local copy of Compile.cmd acts accordingly, then for DEBUG Teensy USB is given to (gdb) as :: target remote \\.\com21

Except something isn't right yet with GDB usage ???
 
What's the deal with Python? Needed/Expected? On Windows there are two GDB exe's with the second '...gdb-py.exe' Without the "-py" I get GDB as below. When I add the -py the system wants for 'python27.dll' - but that isn't a file in the python27 installed here and may not be on the path.

I was really excited when I first saw gdb-py. It's too bad it is missing the python library, as you noticed. It probably should have been statically linked. It's useless as it stands. Python is not strictly needed. It was just easier for now to code the wrapper that uploads the code and then launches GDB. I suppose it should really be in C and compiled for each platform. Ideally, it could be integrated into Teensyduino's teensy_post_compile.

Anyway, I'm not familiar with TSET so I can't comment too much on that. However your gdb complains:

Code:
warning: unrecognized item "timeout" in "qSupported" response

"timeout" is not in the code. gdbstub.cpp only replies PacketSize to the qSupported query. Did you modify the code? Or do you have another debugger running on com21. Plus your designation of "\\.\com21" is weird (but then again, I don't use Windows). Have you tried just "com21"?

You may also want to pull new code as I made changes today.
 
...designation of "\\.\com21" is weird...

ftrias:

I have seen that type of character-escaping used as a universal way of allowing serial port names to work across platforms (Windows, linux, etc.). Character escaping of filenames & URLs is done the same way & for the same reason. Just my guess . . .

Mark J Culross
KD5RXT
 
Just pulled UPDATED TeensyDebug ... will update with any changes ...

I was really excited when I first saw gdb-py. It's too bad it is missing the python library, as you noticed. It probably should have been statically linked. It's useless as it stands. Python is not strictly needed. It was just easier for now to code the wrapper that uploads the code and then launches GDB. I suppose it should really be in C and compiled for each platform. Ideally, it could be integrated into Teensyduino's teensy_post_compile.

Anyway, I'm not familiar with TSET so I can't comment too much on that. However your gdb complains:

Code:
warning: unrecognized item "timeout" in "qSupported" response

"timeout" is not in the code. gdbstub.cpp only replies PacketSize to the qSupported query. Did you modify the code? Or do you have another debugger running on com21. Plus your designation of "\\.\com21" is weird (but then again, I don't use Windows). Have you tried just "com21"?

You may also want to pull new code as I made changes today.

Windows ... is Windows ... using that " \\.\com21 " is the way to pass comport ID's over 9 and seems to universally work - it is how TyCommander displays it and on the CmdLine doing a "C_code.exe" for the PJRC lines per second test is how the port is passed.

In the end it does 'connect' as noted by the 'p' and 'b' commands - there is just some intermediate 'delay and noise' "timeout" ????
> The 'arm-none-eabi-gdb.exe' is used as installed - not modified.
> TyCommander sees and reports the TWIN T_4.1 comports ( #21 and #22 ) - and the default output 'mark=5' appears on #22, then the #21 port is selected for "Serial Disable" to free the port. { assume that is right with "debug.begin(Serial1);" in the code }

Windows** only TSET just triggers an IDE build from the command line - IDE never started, works well with TyCommander for multiple Teensy and Sermon instances - TSET sets the vars for the board that the IDE sets and it runs a normal build. It works with TeensyLoader or TyCommander for MultiSerMon and Upload. I created it from Frank_B's 'work' finding the command line details. I just put batch file wrappers to create the required board settings in a batch file with other batch files.
> Step one create Compile.cmd batch file for :: Desired Teensy. Speed, Optimize, Serial, SAVE
> Step two - just run the batch file as needed to (re)build with those settings.
And just added was the alternative to encapsulate the GDB debug exec as desired after the build completes.
Using SublimeText editor of choice captures build console output and denotes and links to errors 'like an IDE' using F4 to jump to the line in the code.

** Windows only - somebody might find easy mod to have linux script do the same? in :: github.com/Defragster/Tset/blob/master/TSet.cmd2
 
Seems connected - with 'timeout' noise - but still :: "The program is not being run."
Here is complete console output - from Windows 10 with IDE 1.81 and TD 1.52 installed::
Code:
GNU gdb (GNU Tools for ARM Embedded Processors) 7.10.1.20160923-cvs
Copyright (C) 2015 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 T:\TEMP\\arduino_build_breakpoint_test.ino\breakpoint_test.ino.elf...done.
(gdb) [B]target remote \\.\com21[/B]
Remote debugging using \\.\com21
Ignoring packet error, continuing...
warning: unrecognized item "timeout" in "qSupported" response
Ignoring packet error, continuing...
Ignoring packet error, continuing...
Bogus trace status reply from target: timeout
(gdb) [B]p mark[/B]
$1 = 45
(gdb) [B]b loop[/B]
Breakpoint 1 at 0x158: file T:\tCode\libraries\TeensyDebug\examples\breakpoint_test/breakpoint_test.ino, line 54.
(gdb) [B]c[/B]
[B][COLOR="#FF0000"]The program is not being run.[/COLOR][/B]
(gdb)

I found this : wikidll.com/python-software-foundation/python27-dll
Placing the 64 bit version python27.dll with GDB.exe gave a subsequent error - as other stuff is missing as well ...
 
Last edited:
Ignoring packet error, continuing...
warning: unrecognized item "timeout" in "qSupported" response
Ignoring packet error, continuing...
Ignoring packet error, continuing...
Bogus trace status reply from target: timeout
(gdb) p mark
$1 = 45
(gdb) b loop
Breakpoint 1 at 0x158: file T:\tCode\libraries\TeensyDebug\examples\breakpoint_test/breakpoint_test.ino, line 54.
(gdb) c
The program is not being run.
(gdb)[/CODE]

That extra "noise" could be some other library sending data over the serial port that GDB is using.

In any case, I moved the discussion to it's own thread since the origin of this thread is not not very relevant: https://forum.pjrc.com/threads/6137...dware-debugger-first-Beta?p=243219#post243219
 
It works - example code was coded to use Serial1 not SerialUSB1 - changing that works!
Posted on new thread ...
 
Status
Not open for further replies.
Back
Top