Callback from a different FreeRTOS task

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
robdobson
Posts: 6
Joined: Mon Sep 28, 2020 9:23 am

Callback from a different FreeRTOS task

Post by robdobson » Tue Jun 07, 2022 3:57 pm

I'm working on an ESP32 project in which FreeRTOS is used. I have a communications system which isn't integrated into Micropython and this generates messages on a different task than then one Micropython runs on. I am trying to handle an inbound message (which is asynchronous to Micropython operation).

My code does this:

void messageCallback(const uint8_t* pCallbackData, uint32_t callbackLen) {
mp_obj_t arg = mp_obj_new_str(callbackData, callbackLen);
mp_sched_schedule(callbackObj, arg);
}

In the past (Micropython <= v1.16) this seemed to work ok - although I'm not sure why as I assume mp_obj_new_str() isn't thread safe.

Anyhow, currently (Micropython v.1.8) it crashes.

Is there a way to create a string object (that is garbage collected later) on this alternate task (thread) and then pass this to mp_sched_schedule() ?

Or should I try to find a workaround?

I noticed in the extint.c file that this passes (as the arg to mp_sched_schedule) a pointer to a static called pyb_extint_callback_arg and there is a comment there about "no need to scan by GC". So maybe this approach is possible although I have a string of variable length.

Another option I guess would be to pass a pointer to self - it seems that machine_i2c.c and machine_timer.c do this. In this case I guess I could add the message to a FreeRTOS queue (or similar) and the callback could act as a hint that the python code should go and fetch from the queue?

Any suggestions warmly received.

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

Re: Callback from a different FreeRTOS task

Post by jimmo » Wed Aug 17, 2022 12:17 pm

robdobson wrote:
Tue Jun 07, 2022 3:57 pm
I'm working on an ESP32 project in which FreeRTOS is used. I have a communications system which isn't integrated into Micropython and this generates messages on a different task than then one Micropython runs on. I am trying to handle an inbound message (which is asynchronous to Micropython operation).
Unfortunately this is a bit complicated, but to see an example of how we do this in the BLE stack, see https://github.com/micropython/micropyt ... th.c#L1189

(Essentially we acquire the GIL in the task, which pauses the VM task, then take over it's thread safe temporarily)

Jibun no kage
Posts: 144
Joined: Mon Jul 25, 2022 9:45 pm

Re: Callback from a different FreeRTOS task

Post by Jibun no kage » Thu Aug 18, 2022 4:22 pm

Why not use a list object? It is on the heap, which is shared, across threads/processors. You then convert the list to string at point of need? I you need to modify the list, use memoryview to isolate the list. I use a list object as a UART buffer for example. It is just a global in MP. Yes, you need to ensure locking on writes, but that is expected right? Old C programming trick, if you keep reference to first byte of anything, and you know the struct/data structure, it is locked or de-referenced (MacOS), you have safe access.

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

Re: Callback from a different FreeRTOS task

Post by jimmo » Thu Aug 18, 2022 11:52 pm

Jibun no kage wrote:
Thu Aug 18, 2022 4:22 pm
Why not use a list object? It is on the heap, which is shared, across threads/processors. You then convert the list to string at point of need? I you need to modify the list, use memoryview to isolate the list. I use a list object as a UART buffer for example. It is just a global in MP. Yes, you need to ensure locking on writes, but that is expected right? Old C programming trick, if you keep reference to first byte of anything, and you know the struct/data structure, it is locked or de-referenced (MacOS), you have safe access.
Because the task that is appending to the list doesn't have the ability to allocate on the heap. Also note that the OP is asking about doing this from C not Python.

The only way to do this is if all the shared memory is pre-allocated, e.g. a ringbuffer. We also do this in a few places in MicroPython.

Jibun no kage
Posts: 144
Joined: Mon Jul 25, 2022 9:45 pm

Re: Callback from a different FreeRTOS task

Post by Jibun no kage » Fri Aug 19, 2022 6:23 pm

Ah, in C... missed that. Ok.

Post Reply