Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
manseekingknowledge
Posts: 61
Joined: Sun Oct 29, 2017 5:14 pm

Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by manseekingknowledge » Tue Sep 24, 2019 2:13 am

There is #define in mpconfigport.h I want to know the value of in my Python code. I know I can make a new C module to get access I want, but I was hoping there was some easier way.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by jimmo » Tue Sep 24, 2019 3:53 am

Unfortunately there's no way to do this other than (like you say) something along the lines of making it a constant on a class or a module.

There's no automatic "get all the config variables and put them into the firmware by name" (that would be a lot of ROM to store all their names). You might be able to observe the effect of the variable (i.e. if it enabled/disabled something though).

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by stijn » Tue Sep 24, 2019 8:42 am

Which definition? As jimmo says some of these can be tested one way or another. Just an example, this tests whether MICROPY_PY_BUILTINS_MEMORYVIEW is enabled:

Code: Select all

try:
  memoryview
  has_memoryview = 1
except:
  has_memoryview = 0

manseekingknowledge
Posts: 61
Joined: Sun Oct 29, 2017 5:14 pm

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by manseekingknowledge » Tue Sep 24, 2019 1:21 pm

I change MICROPY_PY_OS_DUPTERM from its default value of 2 to 1 to regain 8 bbs and also only run this bit of code in main.c if the value is 2:

Code: Select all

#if MICROPY_PY_OS_DUPTERM == 2
    dupterm_task_init();

    // Activate UART(0) on dupterm slot 1 for the REPL
    {
        mp_obj_t args[2];
        args[0] = MP_OBJ_NEW_SMALL_INT(0);
        args[1] = MP_OBJ_NEW_SMALL_INT(115200);
        args[0] = pyb_uart_type.make_new(&pyb_uart_type, 2, 0, args);
        args[1] = MP_OBJ_NEW_SMALL_INT(1);
        extern mp_obj_t os_dupterm(size_t n_args, const mp_obj_t *args);
        os_dupterm(2, args);
    }
#endif

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by jimmo » Tue Sep 24, 2019 1:52 pm

Extending on what stjin said, looking at the implementation of dupterm:

Code: Select all

STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
    mp_int_t idx = 0;
    if (n_args == 2) {
        idx = mp_obj_get_int(args[1]);
    }

    if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
        mp_raise_ValueError("invalid dupterm index");
    }
So I guess you could do something like work backwards from a higher index until you find one that succeeds. Then you'd know how many are available, and do the necessary cleanup.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by stijn » Tue Sep 24, 2019 2:02 pm

Only looked briefly but I don't immediately see a way to access that value directly. The closest thing accessible from within python is that the dupterm function checks it's second argument is smaller than MICROPY_PY_OS_DUPTERM, meaning if you would call it with e.g. 3 it would raise a ValueError. So to figure out the value you'd have to loop until it doesn't raise an exception, but at that point you'll also have effectively called it and so have side effects..
Since you modify main.c anyway, you could store the value as an integer in globals() so no need for a module?

edit jimmo beat me to it :)

manseekingknowledge
Posts: 61
Joined: Sun Oct 29, 2017 5:14 pm

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by manseekingknowledge » Tue Sep 24, 2019 5:33 pm

stijn wrote:
Tue Sep 24, 2019 2:02 pm
Since you modify main.c anyway, you could store the value as an integer in globals() so no need for a module?
Can you expand on this a bit? I did some searching for "globals" and I do see some functions of interest like mp_load_global() and mp_globals_set(). Unfortunately the term "globals" is used a lot in the MicroPython code base and comments aren't, so it is difficult to determine what I'm targeting.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by stijn » Tue Sep 24, 2019 5:56 pm

Something like this in main.c, after initialization and before the REPL or file execution:

Code: Select all

    mp_store_global(QSTR_FROM_STR_STATIC("dupterm_value"), mp_obj_new_int(MICROPY_PY_OS_DUPTERM));
then when you enter the REPL or in a file, dupterm_value is in the global scope so you can acces it e.g.

Code: Select all

MicroPython v1.11-240-g519746cae-dirty on 2019-09-24; win32 version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> dupterm_value
2
>>>

manseekingknowledge
Posts: 61
Joined: Sun Oct 29, 2017 5:14 pm

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by manseekingknowledge » Tue Sep 24, 2019 6:26 pm

Works like a charm! Thanks man!

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Is there an easy way to expose the value of a #define from mpconfigport.h to Python code?

Post by stijn » Wed Sep 25, 2019 7:40 am

Note it's just a quick hack, using global variables like that has disadvantages. Out of scope to explain all of that here, but there's plenty of information on the internet. Already a cleaner solution would be to add the information in a more logical place like the uos module itself by defining a function in moduos.c:

Code: Select all

STATIC mp_obj_t mp_micropython_dupterm_value(void) {
    return mp_obj_new_int(MICROPY_PY_OS_DUPTERM);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_dupterm_value_obj, mp_micropython_dupterm_value);

STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
    { MP_ROM_QSTR( MP_QSTR_dupterm_value), MP_ROM_PTR(&mp_micropython_dupterm_value_obj) },
    ....

Post Reply