loboris / MicroPython_ESP32_psRAM_LoBo

MicroPython for ESP32 with psRAM support
Other
831 stars 344 forks source link

Does not run web server with asyncio #148

Open KostSvitlana opened 6 years ago

KostSvitlana commented 6 years ago

Hi, I got the error when try running web server with asyncio on ESP-WROOM-32, ESP32-WROVER and firmware ESP32_LoBo_v3.2.17 - 2018-05-16. When I use firmware MicroPython v1.9.4-33-g94a79f34 there is no error and server run correct.

Traceback (most recent call last):
  File "<stdin>", line 20, in <module>
  File "/flash/lib/uasyncio/core.py", line 154, in run_forever
  File "/flash/lib/uasyncio/core.py", line 109, in run_forever
  File "/flash/lib/uasyncio/__init__.py", line 249, in start_server
OSError: [Errno 110] ETIMEDOUT

More information about ESP-WROOM-32

Internal FS (SPIFFS): Mounted on partition 'internalfs' [size: 1048576; Flash address: 0x170000]
----------------
Filesystem size: 956416 B
           Used: 512 B
           Free: 955904 B
----------------

FreeRTOS running on BOTH CORES, MicroPython task started on App Core (1).

 Reset reason: Power on reset
    uPY stack: 19456 bytes
     uPY heap: 80000/6384/73616 bytes

MicroPython ESP32_LoBo_v3.2.17 - 2018-05-16 on ESP32 board with ESP32

about ESP32-WROVER

Internal FS (SPIFFS): Mounted on partition 'internalfs' [size: 1048576; Flash address: 0x210000]
----------------
Filesystem size: 956416 B
           Used: 32000 B
           Free: 924416 B
----------------

FreeRTOS running on BOTH CORES, MicroPython task started on App Core (1).

 Reset reason: RTC WDT reset
    uPY stack: 19456 bytes
     uPY heap: 3073664/6320/3067344 bytes (in SPIRAM using heap_caps_malloc)

MicroPython ESP32_LoBo_v3.2.17 - 2018-05-16 on ESP32 board with ESP32
loboris commented 6 years ago

Which webserver are you trying to run? microWebSrv is supported and included as frozen module. An example of how to use is available in .../micropython/esp32/modules_examples/webserver. It is designed to run in a thread.

KostSvitlana commented 6 years ago

I tried webserver picoweb and this example https://github.com/micropython/micropython-lib/blob/master/uasyncio/example_http_server.py In both case traceback is similar

loboris commented 6 years ago

I'm sorry, but I can't provide help related to uasyncio, as I recommend using the threads instead (not that I have anything against using uasyncio, I just think it is not needed on this MicroPython port).

mzdaniel commented 6 years ago

Just tried MicroPython ESP32_LoBo_v3.2.18 - 2018-06-04 on ESP32 board with ESP32 with this tiny picoweb 1.4.1 hello world and seems to be working for at least small usecases now:

import picoweb

http_template = '''\
HTTP/1.0 200 OK\r
Content-Type: text/html\r
\r
Hello world
'''

async def index(req, resp):
    await resp.awrite(http_template)

ROUTES = [("/", index)]

app = picoweb.WebApp(__name__, ROUTES)
app.run('0.0.0.0', debug=True)

For completeness, I notice the following message in the first request (but not subsequents:

ERROR:picoweb:<StreamReader <socket> <socket>>: EOF on request start

Also the watchdog timeout is called every ~15 seconds with this message

Task watchdog got triggered. The following tasks did not reset the watchdog in time:
 - mp_task (CPU 1)
Tasks currently running:
CPU 0: IDLE
CPU 1: IDLE

None of the messages seems to affect picoweb to properly function in this small testcase so far.

loboris commented 6 years ago

The dafault settings enables the FreeRTOS Idle tasks to be watched by Watchdog timer. Watching the MicroPython task is also enabled by default.

If this option is enabled, the Task Watchdog Timer will watch the CPU0 (and/or CPU1) Idle Task. Having the Task Watchdog watch the Idle Task allows for detection of CPU starvation as the Idle Task not being called is usually a symptom of CPU starvation. Starvation of the Idle Task is detrimental as FreeRTOS household tasks depend on the Idle Task getting some runtime every now and then.

The watchdog reset in this port is handled by many MicroPython functions, like time.wait*, waiting for uart input, etc. uasyncio runs in a loop which takes all the CPU time and the Idle task cannot be executed. It should be probably modified to execute at least one time.wait_ms(3) function before watchdog timeout (default: 15 sec) expires.

You can disable the MicroPython task watching in menuconfig: → MicroPython → System settings → Enable WatchDog for MicroPython task

You can also disable the Idle tasks watching in menuconfig: → Component config → ESP32-specific → Watch CPU0 Idle Task → Component config → ESP32-specific → Watch CPU0 Idle Task

but it is not recommended.

kevinkk525 commented 6 years ago

It's true that a very long uasyncio delay will trigger the watchdog but the problem here is most likely the utimeq library that currently works in reverse, so that the coroutine that should be executed last will be executed first, resulting in a really long delay. So use the file in #150 or wait for the update. Depending on your other coroutines it might still be neccessary to either feed the watchdog or disable it.

Personally I do not have any watchdog problem using uasyncio (with the utimeq file from #150) although not calling time.slee_ms(). I guess using a socket is enough to feed the watchdog as I don't have another explanation.

loboris commented 6 years ago

utimeq was updated yesterday.

mzdaniel commented 6 years ago

@loboris: I found https://loboris.eu/forum/Thread-Bug-report-uasyncio-V2-0-status that discuss exactly this issue. At first I thought watchdog triggering was bad, but it really depends on the settings. It seems that the default is effectivelly just a debug message inconvenience that can be ignored and can be easily disabled from python side with:

def uasync_watchdog():
    'Feed watchdog'
    from machine import resetWDT
    from uasyncio import core, sleep, get_event_loop

    async def reset_watchdog():
        while True:
            yield from sleep(14)
            resetWDT()

    get_event_loop()
    core.Task(reset_watchdog())

uasync_watchdog()

Doesnt seems better to create a little convenience function/module to do just that than patch an 'standard' library?

In any case, it's great that the watchdog options can be customized. Hopefully at some point in the future these options could be done at runtime too (if I understand correctly menuconfig options cannot be customized in python)

@kevinkk525: So far I didn't found execution issues with watchdog being triggered aside the inconvenience of those console messages (though this likely would affect applications that heavily depends on the console output)

@KostSvitlana: Is the new release ESP32_LoBo_v3.2.18 working for you?

loboris commented 6 years ago

All task watchdog options can be enabled/disabled/configured at runtime. I'll test it and probably add the needed functions to the machine module.

mzdaniel commented 6 years ago

All task watchdog options can be enabled/disabled/configured at runtime.

That was fast! I'll be happy to help with testing efforts.

By the way, Peter's Hinch test, https://loboris.eu/forum/Thread-Bug-report-uasyncio-V2-0-status?pid=395#pid395 is flawlessly running (zero console output and more than 11500 UART messages in 6:30 hours). I'll keep it running for at least 2 days.

kevinkk525 commented 6 years ago

I'm using uasyncio on esp32 without problems. Sometimes one unit gets a cpu halted error but I guess it's because of a faulty flash/psram unit (it gives me an error on boot but works fine apart from that) while the other unit seems to be doing fine just running Peter Hinch's mqtt library (I don't use the included one as my program is supposed to run on esp8266 as well) for many days. In my opinion uasyncio is now stable on this port.

KostSvitlana commented 6 years ago

With uasyncio there is no problem and mzdaniel's function helps to avoid problems with watchdog. Thanks