Debuging the micropython core
-
- Posts: 5
- Joined: Thu Jun 10, 2021 9:38 pm
Debuging the micropython core
Dear MicroPython People!
I am currently preparing a MicroPython Core enhancement to framebuf https://github.com/micropython/micropython/issues/7750 .
But I am new to the micropython core and may be have missed some briefings .
I have a complete esp32 cross-compile platform running for my controller. So changes on my C-Core-Code are well reflected in the behavior of my esp32 controller. My new core functions for framebuf are working but not as intended.
So how can I debug these functions? Is their any IDE that supports debugging Micropython?
If not:
How can I print a simple message to the python console from my C-Core-code?
Any help appreciated
Volker
I am currently preparing a MicroPython Core enhancement to framebuf https://github.com/micropython/micropython/issues/7750 .
But I am new to the micropython core and may be have missed some briefings .
I have a complete esp32 cross-compile platform running for my controller. So changes on my C-Core-Code are well reflected in the behavior of my esp32 controller. My new core functions for framebuf are working but not as intended.
So how can I debug these functions? Is their any IDE that supports debugging Micropython?
If not:
How can I print a simple message to the python console from my C-Core-code?
Any help appreciated
Volker
Re: Debuging the micropython core
I'll let others answer the 'how to debug C code on an ESP32' aspect, but here's an other idea: framebuf is mostly platform agnostic anyway, so provide an implementation which works for the unix port (either a dummy one which just provides a piece of memory for the pixels, or an actual one; it used to be possible to get a framebuf i.e. raw pointer to display memory on standard linux distros) and you can use any debugger you like.
Re: Debuging the micropython core
You can printf() from c code and it will printed to the REPL console. Another thing that can help is to add a monitor target in ports/esp32/Makefile.
This will let you connect to the REPL over the usb com port and if your code crashes it will automatically print a stack trace for the code that was running. If you compile with DEBUG=1 the trace will show source code line numbers as well.
I haven't found a way to compile user c modules with line number information. I do not know CMake very well, so it could be something I'm not doing correctly.
Code: Select all
deploy:
idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) flash
monitor:
idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) monitor
erase:
idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) erase_flash
Code: Select all
make monitor
- reanimator
- Posts: 2
- Joined: Fri Sep 10, 2021 6:32 pm
Debuging the micropython core / ITM trace
Hi there,
I would like to ask a question relevant to mp-core debugging topic too. I ask the question here since exactly the thread has been already created now.
Currently I am working on porting the circuitpython on NXP LPC series MCUs.
In order to debug memory allocation issues (it turned to be my fault) I added ITM-trace support and implemented DEBUG_printf to redirect debug information to SWO channel. It worked out quite well except one piece of code in mp_builtin___import__.
The problem is that the mp_obj_print still uses stdout (i.e. REPL-console).
Is there any easy, clean way to elaborate the code (e.g. of mp_obj_print function?) to inject the custom printer support?
What about MP_PYTHON_PRINTER?
Here is the call stack to have complete picture:
I would like to ask a question relevant to mp-core debugging topic too. I ask the question here since exactly the thread has been already created now.
Currently I am working on porting the circuitpython on NXP LPC series MCUs.
In order to debug memory allocation issues (it turned to be my fault) I added ITM-trace support and implemented DEBUG_printf to redirect debug information to SWO channel. It worked out quite well except one piece of code in mp_builtin___import__.
Code: Select all
mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
#if DEBUG_PRINT
DEBUG_printf("__import__:\n");
for (size_t i = 0; i < n_args; i++) {
DEBUG_printf(" ");
mp_obj_print(args[i], PRINT_REPR);
DEBUG_printf("\n");
}
#endif
Is there any easy, clean way to elaborate the code (e.g. of mp_obj_print function?) to inject the custom printer support?
What about MP_PYTHON_PRINTER?
Here is the call stack to have complete picture:
Re: Debuging the micropython core
I think that's an oversight, instead of mp_obj_print that should be mp_obj_print_helper(MICROPY_DEBUG_PRINTER or similar
If you'd change the code anyway you could create a pull request for it?
If you'd change the code anyway you could create a pull request for it?
- reanimator
- Posts: 2
- Joined: Fri Sep 10, 2021 6:32 pm
Debuging the micropython core
Thanks for you reply!
Sounds reasonable, but I am not completely sure how to proceed.
The new printer MICROPY_DEBUG_PRINTER is going to another be mp_stream_adaptor, right?
mp_print_strn function calls print_strn functor of new printer of mp_print_t type:
Code: Select all
if (len) {
print->print_strn(print->data, str, len);
total_chars_printed += len;
}
Code: Select all
void mp_stream_write_adaptor(void *self, const char *buf, size_t len) {
mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, MP_STREAM_RW_WRITE);
}
Code: Select all
void mp_stream_write_adaptor(void *self, const char *buf, size_t len) {
mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, (MP_STREAM_RW_WRITE | MP_STREAM_DEBUG));
}
Code: Select all
mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode, byte flags) {
byte *buf = buf_;
typedef mp_uint_t (*io_func_t)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
io_func_t io_func;
const mp_stream_p_t *stream_p = mp_get_stream(stream);
if (flags & MP_STREAM_RW_WRITE) {
io_func = (io_func_t)stream_p->write;
} else {
io_func = stream_p->read;
}
Code: Select all
mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode, byte flags) {
byte *buf = buf_;
typedef mp_uint_t (*io_func_t)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
io_func_t io_func;
const mp_stream_p_t *stream_p = mp_get_stream(stream);
if (flags & MP_STREAM_RW_WRITE) {
if (flags & MP_STREAM_DEBUG) {
io_func = (io_func_t)stream_p->dbg_write;
} else {
io_func = (io_func_t)stream_p->write;
}
} else {
io_func = stream_p->read;
}
In this case mp_stream_p_t has to be modified. Isn't it too much code to alter?
Re: Debuging the micropython core
I'm not really following - have a look at how other ports implement MICROPY_DEBUG_PRINTER: you don't have to modify how printing with it works, MICROPY_DEBUG_PRINTER is only used for debug printing anyway. Also see shared/libc/printf.c: you don't have to write your own DEBUG_printf, instead you only have to provide an mp_print_t object which prints to whatever you want, in this case that SWO channel. So you only need something like this:
Code: Select all
//somewhere in a .c file
STATIC void swo_print_strn(void *env, const char *str, size_t len) {
(void)env;
//print str to SWO here
}
const mp_print_t mp_swo_print = {NULL, swo_print_strn};
//and in mpconfigoprt:
#define MICROPY_DEBUG_PRINTER (&mp_swo_print)
Re: Debuging the micropython core
See https://github.com/micropython/micropython/pull/7834
Wit this e.g. the unix port will properly print the arguments etc to mp_stderr_print (which is what it uses by default for MICROPY_DEBUG_PRINTER)
Wit this e.g. the unix port will properly print the arguments etc to mp_stderr_print (which is what it uses by default for MICROPY_DEBUG_PRINTER)