Failed to execute callback function in timer's handler

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
User avatar
xidameng
Posts: 9
Joined: Fri Jul 24, 2020 2:08 pm

Failed to execute callback function in timer's handler

Post by xidameng » Wed Sep 30, 2020 6:33 am

Hi I am currently working on porting MicroPython to Realtek’s RTL8722 WiFi+ BLE dev. board, and it has been mostly done except the Timer module which takes in a callback function but never returns.

here is the C code I wrote for Timer:

Code: Select all

STATIC mp_obj_t timer_start(mp_uint_t n_args, const mp_obj_t *args) {
    enum { ARG_self, ARG_duration, ARG_callback, ARG_type };
    timer_obj_t *self = args[ARG_self];
    uint32_t duration = mp_obj_get_int(args[ARG_duration]);

    if (!MP_OBJ_IS_FUN(args[ARG_callback]) && (args[ARG_callback] != mp_const_none))
        mp_raise_ValueError("Error function type");

    uint8_t type = mp_obj_get_int(args[ARG_type]);

    if (type == TIMER_PERIODICAL)
        gtimer_start_periodical(&(self->obj), duration, mp_obj_timer_irq_handler,
                self);  // MBED api that controls timer 
    else if (type == TIMER_ONESHOT)
        gtimer_start_one_shout(&(self->obj), duration, mp_obj_timer_irq_handler,
                self);  // MBED api that controls timer
    else
        mp_raise_ValueError("Invalid TIMER type");
    
    self->callback = args[ARG_callback];

    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(timer_start_obj, 4, 4,  timer_start);
Because it takes in a callback function which executes whenever timer triggers, I pass the callback function to my timer object using,
self->callback = args[ARG_callback];
And write a timer handler called “mp_obj_timer_irq_handler” as such,

Code: Select all

void mp_obj_timer_irq_handler(timer_obj_t *self) {

    if (self->callback != mp_const_none) {
        gc_lock();
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_call_function_0(self->callback);
            nlr_pop();
        } else {
            self->callback = mp_const_none;
            mp_printf(&mp_plat_print, "Uncaught exception in callback handler");
            if (nlr.ret_val != MP_OBJ_NULL)
                mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
        }
        gc_unlock();
    }
}
And here is my python script:

Code: Select all

>>> from machine import Timer
>>> t = Timer(0) # Create a timer obj on timer 0
>>> t.init() # init it
>>> t.start(2000000, lambda x: print(”test”), t.PERIODICAL)  # period at 2s, callback only print, trigger periodically

It looks and works all good until the last line of the script where I started the timer and then it gets stuck and cannot exit until I manually reset the hardware.

After some trial and error, it appears to me that my C handler never even gets trigger when I pass the python lambda function into the API as an argument

It will mean tremendously to me if someone can give me some suggestions on what is going wrong with my code and how to correctly trigger another handler inside a handler, thanks!

miltmobley
Posts: 30
Joined: Mon Mar 07, 2016 11:44 pm

Re: Failed to execute callback function in timer's handler

Post by miltmobley » Thu Nov 05, 2020 7:13 am

Try replacing the lambda with an actual function. Most examples of lambda compute expressions and return some value.
They are not supposed to contain statements, which your print probably is.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Failed to execute callback function in timer's handler

Post by pythoncoder » Fri Nov 06, 2020 7:54 am

The lambda looks OK to me:

Code: Select all

>>> a = lambda : print('rats')
>>> a()
rats
>>> 
Peter Hinch
Index to my micropython libraries.

Post Reply