DEV Community

codemee
codemee

Posted on

ESP8266 MicroPython reset() 的陷阱

如果你的程式需要強制重置, 像是底下這個簡單的範例:

from machine import reset

count = 0
while True:
    print(count)
    count = count + 1
    if count == 10:
        reset()
Enter fullscreen mode Exit fullscreen mode

你可能會以為執行了 reset() 之後就會重置, 所以也不會再回到 while 迴圈中, 那你就錯了, 實際的執行結果如下:

0
1
2
3
4
5
6
7
8
9
10
11
12
...
278
279
280
281

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 30712, room 16 
tail 8
chksum 0x16
load 0x3ffe8000, len 996, room 0 
tail 4
chksum 0x70
load 0x3ffe83f0, len 1064, room 4 
tail 4
chksum 0xa3
csum 0xa3
��n�r��n|�llll`�rl�l�l`�rl�l�l`�rl$�ll`rl$rl�bbČb�bbr�$b�n'�
MicroPython v1.15 on 2021-04-18; ESP module with ESP8266
Type "help()" for more information.
>>>
Enter fullscreen mode Exit fullscreen mode

計數到 10 時候的確執行了 reset(), 但這只是發出訊號通知系統重置, 實際上你的程式執行從 reset() 返回後還會繼續執行, 你可以看到程式一路列印到 281 才真的重置。

根據 MicroPython 的原始碼

STATIC mp_obj_t machine_reset(void) {
    system_restart();
    return mp_const_none;
}
Enter fullscreen mode Exit fullscreen mode

reset() 實際上會叫用 ESP8266 SDK 的 system_restart, 而 SDK 文件中特別表示:

The ESP8266 will not restart immediately. Please do not call other functions after calling this API.
Enter fullscreen mode Exit fullscreen mode

也就是說系統不會真的立即重置, 而且也不希望在此之後叫用其他函式。為了避免這個問題, 建議在 reset() 後加個無窮迴圈等待系統重置:

from machine import reset

count = 0
while True:
    print(count)
    count = count + 1
    if count == 10:
        reset()
        while True:
            pass
Enter fullscreen mode Exit fullscreen mode

這樣就會正確執行了:

0
1
2
3
4
5
6
7
8
9

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 30712, room 16 
tail 8
chksum 0x16
load 0x3ffe8000, len 996, room 0 
tail 4
chksum 0x70
load 0x3ffe83f0, len 1064, room 4 
tail 4
chksum 0xa3
csum 0xa3
��n�r��n|�llll`�rl�l�l`�rl�l�l`�rl$�ll`rl$rl�2bbČb�bbr�$b�n'�
MicroPython v1.15 on 2021-04-18; ESP module with ESP8266
Type "help()" for more information.
>>> 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)