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.
Callback from a different FreeRTOS task
Re: Callback from a different FreeRTOS task
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#L1189robdobson wrote: ↑Tue Jun 07, 2022 3:57 pmI'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).
(Essentially we acquire the GIL in the task, which pauses the VM task, then take over it's thread safe temporarily)
-
- Posts: 144
- Joined: Mon Jul 25, 2022 9:45 pm
Re: Callback from a different FreeRTOS task
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.
Re: Callback from a different FreeRTOS task
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.Jibun no kage wrote: ↑Thu Aug 18, 2022 4:22 pmWhy 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.
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.
-
- Posts: 144
- Joined: Mon Jul 25, 2022 9:45 pm
Re: Callback from a different FreeRTOS task
Ah, in C... missed that. Ok.