jdolinay / avr_debug

Source level debugger for Arduino - GDB stub for Atmega328 microcontroller used in Arduino Uno.
GNU Lesser General Public License v3.0
142 stars 33 forks source link

Global objects init won't allow a call for debug_init() #49

Open emaayan opened 1 year ago

emaayan commented 1 year ago

if i understand correctly, debug_init() must always be called first before any objects.

but in the event i have any other objects defined globally, that may never happen as those objects maybe call other objects upon init.

image

jdolinay commented 1 year ago

I would say debug_init () must be called before you can communicate with the debugger. There should be no problem if you call it in main() or setup() in Arduino. I am not aware of any relationship between debug_init() and global objects in your program. Is there any specific problem you encounter?

The debugger is in fact just a library added to your program, it's not like real hardware debugger which can control the program from the very beginning. Only after you call debug_init() it starts to listen for serial communication and your IDE can connect with the debugger. The debugged program actually runs until the IDE connects and you insert a breakpoint or break (pause) the program. So you are connecting to a running program. You can use the breakpoint() function to insert a breakpoint right after call to debug_init() to stop the program at that point, but this will be typically in main() or in setup() in Arduino programs, after the global objects are initialized. If you need to debug the code in the constructor of some object, it could be possible to call debug_init() from the constructor of that object instead of calling it from main/setup. I never thought about this scenario but it could work.

emaayan commented 1 year ago

yes i've encountered situations where even after debug_init is called first in in the setup method, the debugger stil won't be able to connect ( i get a message something about bogus trace i think) this happens when a global object is being initialized and it's constructor contains statements.

On Tue, Dec 27, 2022 at 1:43 PM Jan Dolinay @.***> wrote:

I would say debug_init () must be called before you can communicate with the debugger. There should be no problem if you call it in main() or setup() in Arduino. I am not aware of any relationship between debug_init() and global objects in your program. Is there any specific problem you encounter?

The debugger is in fact just a library added to your program, it's not like real hardware debugger which can control the program from the very beginning. Only after you call debug_init() it starts to listen for serial communication and your IDE can connect with the debugger. The debugged program actually runs until the IDE connects and you insert a breakpoint or break (pause) the program. So you are connecting to a running program. You can use the breakpoint() function to insert a breakpoint right after call to debug_init() to stop the program at that point, but this will be typically in main() or in setup() in Arduino programs, after the global objects are initialized. If you need to debug the code in the constructor of some object, it could be possible to call debug_init() from the constructor of that object instead of calling it from main/setup. I never thought about this scenario but it could work.

— Reply to this email directly, view it on GitHub https://github.com/jdolinay/avr_debug/issues/49#issuecomment-1365842286, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADGP5MB6KT7YZYCNPNEGMGLWPLI4JANCNFSM6AAAAAATISQPWA . You are receiving this because you authored the thread.Message ID: @.***>

jdolinay commented 1 year ago

The bogus trace message indicates some problems with serial communication, it should not be related with global objects. I would try to look for some side effects of the global object, maybe there is not enough RAM, or it uses the pins which are used for serial line, or disables interrupts (try to put sei() after call to debug_init() to make sure interrupts are enabled)...

It should be OK to call the debug_init() anywhere in setup, it does not have to be first.

Looking at your screenshot one more time, what is the debug("some text") function doing? Perhaps it uses serial line to send the message - it would not work with the debugger, the debugger needs to use the serial line for itself.

emaayan commented 1 year ago

the debug did contain serial, but i commented it out at the time, because that won't even compile (because of the debugger, that's why i have conditional defines), in addition to that that's doesn't even get called. what does get called are methods for RTC DS3231 and i2c display calls, when i moved them away from the constructor to their own method (which is called after the debug_init) then it worked. i usually get the bogus method i debug without the debug_init being called. image

jdolinay commented 1 year ago

OK, I see. It makes sense that without the debug_init() being called the bogus message is reported. I guess it is not safe to call communication libraries like I2C from a constructor because one cannot be sure that the objects used in these libraries were already initialized. So I think it is better that you moved them to separate methods and call them later. I don't have much experience with C++ in embedded programs, but I guess it may be a good idea to use methods like "begin" or "init" to execute any hardware-related code rather than put it into constructors. And call these begin/init functions from setup().

So I think the problem was not actually related to calling debug_init(); it was in calling the RTC and display in constructor which was too early and the libraries failed to work or the program crashed. Now when you call them from setup(), when all the C++ objects and C runtime are initialized, it works.