Page 1 of 1

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

Posted: Tue Sep 24, 2019 2:13 am
by manseekingknowledge
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.

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

Posted: Tue Sep 24, 2019 3:53 am
by jimmo
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).

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

Posted: Tue Sep 24, 2019 8:42 am
by stijn
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

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

Posted: Tue Sep 24, 2019 1:21 pm
by manseekingknowledge
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

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

Posted: Tue Sep 24, 2019 1:52 pm
by jimmo
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.

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

Posted: Tue Sep 24, 2019 2:02 pm
by stijn
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 :)

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

Posted: Tue Sep 24, 2019 5:33 pm
by manseekingknowledge
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.

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

Posted: Tue Sep 24, 2019 5:56 pm
by stijn
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
>>>

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

Posted: Tue Sep 24, 2019 6:26 pm
by manseekingknowledge
Works like a charm! Thanks man!

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

Posted: Wed Sep 25, 2019 7:40 am
by stijn
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) },
    ....