星期二, 3月 13, 2018

ESP8266 MicroPython 使用 poll() 出現 Fatal exception 28(LoadProhibitedCause)

由於 MicroPython 預設並沒有像是 ESP8266 Arduino Core 提供有 ESP8266WebServer 程式庫那樣的簡易 Web Server, 所以打算撰寫一個超級簡易版來用。在設計的過程中, 發現 socket 的 accept() 在沒有新連線的情況下並不會返回, 這樣程式流程就會被凍結在這裡無法進行其他的工作, 根據 MicroPythono 文件的說明, 建議你改用 uselect 模組的 poll 類別, 於是我大概寫了這樣的程式:
server.bind(('0.0.0.0', port))
server.listen(1)
poller.register(server, uselect.POLLIN)

where True:
  res = poller.poll(0)
  if res:
    (socket, sockaddr) = server.accept()
    handle(socket)
    ...
程式運作基本上都很好, 但是會在某個沒有規律的神奇時間出現嚴重例外而重置, 出現以下訊息:
Fatal exception 28(LoadProhibitedCause):
epc1=0x4025681d, epc2=0x00000000, epc3=0x00000000, 
excvaddr=0x00000010, depc=0x00000000

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)
...
經過反覆實驗, 發現只要叫用 poll() 時不要給 0 作為 timeout, 就可以避免了。因此最後修改的程式就把 poll(0) 改為 poll(1) 即可。

我寫好的 Web Server 可以參考這裡