AttributeError on restarting MicroPython Task

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
User avatar
chrizztus
Posts: 13
Joined: Thu Feb 23, 2017 3:59 pm

AttributeError on restarting MicroPython Task

Post by chrizztus » Fri Jan 18, 2019 9:47 pm

Dear community,
since days I try to get rid of this issue every now and then.
I'm running MicroPython as a FreeRTOS task on a nrf52832 dk. When I power the board my (frozen) main.py runs as intended. main.py itself depends on several (frozen) modules for playing sound, handle button events, blinking leds and stuff like that.
But every now and then I need to restart the python task. This (from what I thought) could be done easily with FreeRTOS by calling:

Code: Select all

vTaskDelete( taskHandleMpyRepl );
and as second step (re)creating the same task which was created on startup:

Code: Select all

xTaskCreate(mpy_task, "REPL", 800, NULL, 0, &taskHandleMpyRepl);

Code: Select all

static uint32_t heap[MP_HEAP_SIZE];
static char *stack_top;
void mpy_task(void *pvParameter)
{
  SEGGER_RTT_printf(0, "mpy :: task\n");
  volatile uint32_t sp;
  stack_top = (char *) &sp;

  mp_stack_set_top((void *)&sp);
  gc_init(heap, heap + MP_HEAP_SIZE);
  mp_init();

  mpy_exec();
}
void mpy_exec(void)
{
  pyexec_frozen_module("main.py");
}
Although the task is starting, when the main.py is executed I only get a Python traceback:

Code: Select all

main
Traceback (most recent call last):
  File "main.py", line 57, in <module>
  File "main.py", line 51, in main
AttributeError: no such attribute

Code: Select all

[...]
# main loop
def main():
  print('main') #this is printed
  #play ON melody on startup
  snd.play_melody(on_melody) #this is line 51 where traceback starts

  #fsm.run() runs an infinite loop
  fsm_init()

if __name__ == "__main__":
  main()
Seems as if micorpython does not recognize the frozen modules any more. But wait, main.py is a frozen module too. I don't know where to look any more. May somebody else can give me the decisive hint.

Thanks for hanging on to this line ;)
Chris

User avatar
dhylands
Posts: 3011
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: AttributeError on restarting MicroPython Task

Post by dhylands » Fri Jan 18, 2019 10:04 pm

When micropython starts the bss is normally cleared. I suspect what might be happening is that the bss has old non-zero data in it and this is causing some code to not be executed when you restart micropython.

You'll need to be careful here and only clear the micropython portion of the bss and not all of it.

You might also need to reload the data section from its initial state stored in flash.

User avatar
chrizztus
Posts: 13
Joined: Thu Feb 23, 2017 3:59 pm

Re: AttributeError on restarting MicroPython Task

Post by chrizztus » Fri Jan 18, 2019 11:54 pm

dhylands wrote:
Fri Jan 18, 2019 10:04 pm
When micropython starts the bss is normally cleared. I suspect what might be happening is that the bss has old non-zero data in it and this is causing some code to not be executed when you restart micropython.
I suspected this as well and tried a

Code: Select all

memset(heap,0,MP_HEAP_SIZE);
before calling gc_init() and mp_init() in order to clear the data. The heap variable is declared static (see above) and should have the same address (in bss) during runtime. Unfortunately it did not work either.
You'll need to be careful here and only clear the micropython portion of the bss and not all of it.

You might also need to reload the data section from its initial state stored in flash.
Thought I was doing this by calling gc_init() and mp_init(). Seems I forgot something of importance.
How would you wipe micropythons bss portion and releoad the data section?

Thank you in advance
Chris

User avatar
dhylands
Posts: 3011
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: AttributeError on restarting MicroPython Task

Post by dhylands » Sat Jan 19, 2019 12:39 am

I've not looked at the .map file when using micropython with freertos, so all I can do is provide some hints.

Normally, there is startup code which is called before main which does the bss clearing/data copying. For bare metal pyboard you can find this here: https://github.com/micropython/micropyt ... 32f4.s#L86

Since you're linking micropython with FreeRTOS and presumably some other app, you want to ensure that you only clear micropythons's BSS and copy micropython's data. To do this will most likely require a special linker .ld file so that you can tell which bss belongs where.

For the bare metal pyboard, this is the linker script which describes the .bss and data sections: https://github.com/micropython/micropyt ... n_basic.ld

Splitting the .bss and .data for just micropython will depend on exactly what your build process is and what linker script you're using.

You might be better off to restart MicroPython by doing the equivalent of a soft-reset, which basically means causing your execution of main,py to return here:
https://github.com/micropython/micropyt ... ain.c#L725

This can be done from the python code by calling machine.soft_reset(). If you need to do it from C, then you can do the same thing that the machine_soft_reset function does:
https://github.com/micropython/micropyt ... #L244-L245

User avatar
chrizztus
Posts: 13
Joined: Thu Feb 23, 2017 3:59 pm

[Solved] Re: AttributeError on restarting MicroPython Task

Post by chrizztus » Sat Jan 19, 2019 10:46 pm

Hi Dave,
thanks again for your reply and the detailed information.
I had a quick look at the map file and found one entry which I think might be of interest:

Code: Select all

COMMON         0x000000002000de04      0x1c8 ./libmicropython.a(mpstate.o)
               0x000000002000de04                mp_state_ctx
Luckily on memsetting this address (actually its a structure) to zero did the trick for me.
Now I can restart the micropython task and keep the bluetooth connection at the same time. I'm so happy and (as always) I'm asking myself why I didn't use this great forum earlier.
Nevertheless, the seemingly easier approach by doing a 'soft-reset' didn't work as expected with my rather large main.py. Smaller main.py files doing just a 'print' worked though. My assumption is that the allocated memory is not sweeped entirely on a soft-reset. So for me restarting the task seems to be the better solution.
Now I will do some further tests since I concurrently updated to v1.9.4.

Thank you again
Chris

Post Reply