-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
Description
Hi,
I have made a custom build MPY 1.16 ESP32 port, esp-idf v3.3.5, no SPIRAM, to integrate into Arduino. I use the whole core 1 for MPY thread. On core 1, there are only 2 extra system threads: IDLE1, ipc1. I have created another MPY thread in C code, MPThreadCMesh, besides MPY main thread.
My detail issue is here. The issue is still there.
peterhinch/micropython-async#60
However, my new issue is different, related to running sync code, so I report here.
Yesterday I had found new update for esp32 port here: #5344
This update is good. I see better performance. Before the update, I got some random exceptions, especially BREAK like my async issue. With the new update, I ran my test 3 times, got the same exception. It will help to find out the cause, rather than random exception found before.
Here is my actual test on my final application. The test is incrementing variable _cntButton up to element 0 of array N, N[0], then reset to zero. Here its value is 10. I do sleep with 50ms. I make this test to make more computations on MPY. The test failed after from 30 minutes to several hours (2, 3). I run this code inside REPL. While this code run in REPL, thread MPThreadCMesh doing only delay using mp_hal_delay_ms(1), and checking FreeRTOS queue to get new message from C side. "cmo20.o" is a class, inherit from dict, class DObj(dict)
.
def test_push(period):
cmo20 = cmo(20)
while 1:
try:
cmo20.o._cntButton = 0 if not hasattr(cmo20.o, '_cntButton') or cmo20.o._cntButton >= N[0] else cmo20.o._cntButton + 1
parse_in_post_demo(cmo20, 1);
time.sleep_ms(period)
except Exception as e:
print(str(e))
def parse_in_post_demo(cmobj, args):
is_send = 0
if args is None:
if cmobj.o.contact:
if hasattr(cmobj.o, '_cntButton'):
cmobj.o._cntButton = cmobj.o._cntButton + 1 if cmobj.o._cntButton < N[0] else 0
else:
cmobj.o._cntButton = 0
is_send = 1
elif args == 1:
is_send = 1
if is_send:
x = {"apitype": "ext", "command": "cmesh/set", "group":10, "data": {"quiet":1, "data": [[20, 0, {'_cntButton': cmobj.o._cntButton}]]}}
_cconn(x)
N[0] = 10
test_push(50)
The exception here, luckily it's not BREAK instr:
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x401d4d66 PS : 0x00060030 A0 : 0x8008aa74 A1 : 0x3ffd70d0
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x3ffc985c A5 : 0x00000001
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x801d3b92 A9 : 0x3ffccef0
A10 : 0x00000001 A11 : 0x3f42b654 A12 : 0x3ffc9c38 A13 : 0x00000044
A14 : 0x3ffcd020 A15 : 0x3ffccf80 SAR : 0x0000001e EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
ELF file SHA256: 0000000000000000
Backtrace: 0x401d4d66:0x3ffd70d0 0x4008aa71:0x3ffd70f0 0x401d951d:0x3ffd7130 0x401d93d1:0x3ffd7150 0x400fa4e8:0x3ffd7180 0x401d97cc:0x3ffd71a0 0x401d9441:0x3ffd7240 0x4008ac62:0x3ffd7260
0x401d5062: mp_execute_bytecode at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/py/vm.c line 1436
0x4008aa71: xQueueGenericReceive at /home/cuongbh/esp32/arduino_build/lib_335/esp-idf/components/freertos/queue.c line 1592
0x401d9819: mp_thread_mutex_lock at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 230
0x401d96cd: mp_hal_delay_ms at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mphalport.c line 231
0x400fa704: MPThreadCMesh(size_t, size_t, mp_obj_t const*) at C:\Users\cuongbh\AppData\Local\Temp\arduino_build_557899\sketch\mpy.cpp line 405
0x401d9ac8: app_thread_entry at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 327
0x401d973d: freertos_entry at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 151
0x4008ac62: vPortTaskWrapper at /home/cuongbh/esp32/arduino_build/lib_335/esp-idf/components/freertos/port.c line 143
The exception occurs while getting GIL. I google portYIELD_WITHIN_API, often related to interrupt. I dont understand that there is any relation between portYIELD_WITHIN_API and its effect on executing mp_execute_bytecode. LoadProhibited due to access "->type" reading at address 0x00000000 (specified by EXCVADDR). I guess that.
mphalport.c line 231: MP_THREAD_GIL_ENTER();
mpthreadport.c line 230: return pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0);
queue.c line 1592: portYIELD_WITHIN_API();
vm.c line 1436: if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
If using simple dict like this, it's always running (above 7 hours). I guess that it's due to simpler code execution, not face corner situtation.
x = {}
def test_exception2(period):
while 1:
try:
x['_cntButton'] = 0 if '_cntButton' not in x or x['_cntButton'] >= N[0] else x['_cntButton'] + 1
y = {"apitype": "ext", "command": "cmesh/set", "group":10, "data": {"quiet":1, "data": [[20, 0, {'_cntButton': x['_cntButton']}]]}}
_cconn(y)
time.sleep_ms(period)
except Exception as e:
print(str(e))
Thank you,
Cuong.