Page 1 of 1

Software interrupt on nRF52832

Posted: Wed Mar 08, 2017 9:44 am
by chrizztus
Hi,
for a nordic based pcb I'd like to implement micropython callbacks to be triggered once a button was pressed/released.
Similar to the stmhal hardware interrupt in usrsw.c, I'd like to register a button callback in micropython which can be triggered from a software interrupt coming from nordics button driver implementation where I can register several function pointers that will be called on (debounced) short/long pressed/released events.
Since I'm quiet new to micropython I'd appreciate if someone can give me a hint if it's possible to pass function pointers from a micropython module to the button dirver implementation in order to trigger the python callback function.

Best
Christian

Re: Software interrupt on nRF52832

Posted: Wed Mar 08, 2017 8:28 pm
by dhylands

Re: Software interrupt on nRF52832

Posted: Tue Mar 21, 2017 1:43 pm
by chrizztus
Hey,
thanks for your support and the example code. I meanwhile got it working so far.
Now I'm facing another issue which might be related to the garbage collector or maybe not. The problem occurs when I'm trying to increment a global variable within a C callback function. I can read and print the value of that variable but once I start writing to it I get the python error: "NameError:"
This is how the C function looks like:
[code]
void ext_button_released_callback(uint8_t button_id, bool long_press)
{
pb_button_obj_t *self = MP_STATE_PORT(pb_button_objects)[button_id];
if(mp_const_none != self->callback)
{
gc_lock();
nlr_buf_t nlr;
if(0 == nlr_push(&nlr))
{
mp_call_function_1(self->callback,mp_obj_new_bool(long_press));
nlr_pop();
}
else
{
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
gc_unlock();
}
}
[/code]
Is it somehow possible to modify a global var within a callback function?
Christian

PS: Sorry for the bad formatting. Obviously BBCode is not enabled for my account.

Re: Software interrupt on nRF52832

Posted: Tue Mar 21, 2017 8:16 pm
by dhylands
The formatting will automagically start to work for you after you have enough posts to no longer require moderation.

I don't see any code trying to increment a global. Are you trying to increment a C global? or a python global?

Are you getting the NameError from within the callback? Can you share your python code?

Re: Software interrupt on nRF52832

Posted: Wed Mar 22, 2017 8:21 am
by chrizztus
Sorry for the lack of information. What I'm trying to do is to increase/decrease the duty time for a LED pwm.
For this I first create an instance of the button and the LED and register a callback as follows:

Code: Select all

import pb
#instantiatte led and buttons
red = pb.LED(0)
record = pb.BUTTON(2)
duty=50

#button callback function
def record_pressed(long_press):
	#printing the duty works well
	print(duty)
	#changing the duty cycle gives error
	duty = (duty + 5) % 100
	#set the new duty for red LED 
	red.brightness(duty)

red.callback(record_pressed)
When I comment the line "duty = (duty + 5) % 100" in the callback function everything works. The duty value is printed and the led value is set. Once I uncomment it I get the following error:

Code: Select all

>>> NameError:
For sake of readablity I'll attach the C callback function that'll be called on pushing a button:

Code: Select all

void ext_button_released_callback(uint8_t button_id, bool long_press)
{
  pb_button_obj_t *self = MP_STATE_PORT(pb_button_objects)[button_id];
  if(mp_const_none != self->callback)
  {
    gc_lock();
    nlr_buf_t nlr;
    if(0 == nlr_push(&nlr))
    {
      mp_call_function_1(self->callback,mp_obj_new_bool(long_press));
      nlr_pop();
    }
    else
    {
      mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
    }
    gc_unlock();
  }
}
Maybe there is something wrong/missing here. I recycled it from stmhal/timer.c implementation.

Re: Software interrupt on nRF52832

Posted: Wed Mar 22, 2017 8:59 am
by pythoncoder
You need

Code: Select all

def record_pressed(long_press):
	global duty
If you assign to a variable in a Python function, and it is not declared as global, Python creates it as a local variable. However your code requires the value to be read, so you get "NameError: local variable referenced before assignment".

Note that a global declaration is not needed if you only intend to read a global variable. If Python fails to find a name in the local namespace it then looks in global.

This is a perennial source of confusion to people new to Python.

Re: Software interrupt on nRF52832

Posted: Wed Mar 22, 2017 2:04 pm
by chrizztus
pythoncoder wrote:You need
However your code requires the value to be read, so you get "NameError: local variable referenced before assignment".

Note that a global declaration is not needed if you only intend to read a global variable. If Python fails to find a name in the local namespace it then looks in global.

This is a perennial source of confusion to people new to Python.
Thanks Peter,
except a few (slight) contacts with python I'm learning python by implementing the modules needed for my custom board ;)
Although I might have used the keyword in the past, I couldn't assign the error since it only says "NameError:" without the meaningful description you pointed out. It would have helped me a lot.
Nevertheless with your suggestion the code is working and I don't need to debug any further. Thank you for that.
Best
Christian

Re: Software interrupt on nRF52832

Posted: Thu Mar 23, 2017 7:15 am
by pythoncoder
chrizztus wrote:... I couldn't assign the error since it only says "NameError:" without the meaningful description you pointed out. It would have helped me a lot...
Error reporting on the ESP8266 still leaves a lot to be desired and it sounds like the nRF52832 has the same problem. It is confusing. On other MicroPython platforms you get the full message.