D:\test>ampy --port COM4 put main.py
Traceback (most recent call last):
File "c:\python36\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Python36\Scripts\ampy.exe\__main__.py", line 9, in <module>
File "c:\python36\lib\site-packages\click\core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "c:\python36\lib\site-packages\click\core.py", line 697, in main
rv = self.invoke(ctx)
File "c:\python36\lib\site-packages\click\core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "c:\python36\lib\site-packages\click\core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\python36\lib\site-packages\click\core.py", line 535, in invoke
return callback(*args, **kwargs)
File "c:\python36\lib\site-packages\ampy\cli.py", line 208, in put
board_files.put(remote, infile.read())
File "c:\python36\lib\site-packages\ampy\files.py", line 139, in put
self._pyboard.exec_("f.write({0})".format(chunk))
File "c:\python36\lib\site-packages\ampy\pyboard.py", line 257, in exec_
raise PyboardError('exception', ret, ret_err)
ampy.pyboard.PyboardError: ('exception', b'', b'Traceback (most recent call last):\r\n File "<stdin>", line 1, in <module>\r\nOSError: 28\r\n')
也有人跟我遇到一樣的問題, 但他的是 OSError 5 :
# I can not copy files to the board #21
這仁兄說他不確定是檔案系統出問題還是韌體壞了, 總之重灌韌體就解決問題了 :
"I have solved the problem by updating MicroPython v1.8.7-672-g11a9620 on 2017-04-28. I'm not sure if it was the file system or bad firmware, maybe a bad parameter when uploading the firmware."
但我遇到的這個 OSError 28 是啥意思呢? 我在下面這篇文章中查到這似乎是 "No space left on device" 之意, 應該跟檔案系統有關, 可以從 os.statvfs('') 指令查看個檔案的 block size 大小 :
# https://forum.micropython.org/viewtopic.php?t=2615
所以我也決定重灌, 果真重灌後 ampy 就恢復正常可以上傳檔案了. 我猜應該是我的 ESP-01 檔案系統又完蛋了, 導致 ampy 要上傳檔案時發現檔案系統無可用空間就發生錯誤了.
重灌後我用 os.statvfs('') 查詢記憶體空間狀態結果如下 :
MicroPython v1.9.1-8-g7213e78d on 2017-06-12; ESP module with ESP8266
Type "help()" for more information.
>>> import os
>>> os.statvfs('')
(4096, 4096, 92, 90, 90, 0, 0, 0, 0, 255)
此函數是一個查詢指定路徑之檔案系統狀態之系統呼叫, 傳回值為 10 個元素的元組 :
(f_bsize, f_frsize, f_blocks, f_bfree, f_bavail, f_files, f_ffree, f_favail, f_flag, f_namemax)
其定義是 :
f_bsize: 希望的檔案系統 block 數 (資料區塊)
f_frsize: 基本的檔案系統 block 數
f_blocks: 檔案系統全部 block 數
f_bfree: 可用的 block 數
f_bavail: 一般使用者可用之 block 數
f_files: file node 總數 (節點)
f_ffree: 可用之 file node 總數
f_favail: 一般使用者可用之 file node 數
f_flag: 掛載旗標
f_namemax: 檔案名稱最長長度 (字元)
所以重灌後 (4096, 4096, 92, 90, 90, 0, 0, 0, 0, 255) 全部區塊數為 92 個, 可用為 90 個.
參考 :
# https://www.tutorialspoint.com/python/os_statvfs.htm
# https://docs.python.org/3.4/library/os.html
不過我在 Python 2.x 版文件中卻看到 os.statvfs() 已經被棄置不用了 :
"Deprecated since version 2.6: The statvfs module has been removed in Python 3."
奇怪, MicroPython 是 Python 3 也還有這個函數哩!
MicroPython 的檔案系統還可以用 os.stat() 來觀察, 例如 :
for f in os.listdir():
print('File: {} stats: {}'.format(f, os.stat(f)))
這裡利用拜訪 os.listdir() 傳回的串列, 將其元素 (檔案名稱) 傳給 os.stat() 即可顯示該檔案之狀態. 測試結果如下 :
>>> for f in os.listdir():
... print('File: {} stats: {}'.format(f, os.stat(f)))
...
...
...
File: boot.py stats: (32768, 0, 0, 0, 0, 0, 160, 5346, 5346, 5346)
File: webrepl_cfg.py stats: (32768, 0, 0, 0, 0, 0, 16, 5346, 5346, 5346)
File: main.py stats: (32768, 0, 0, 0, 0, 0, 394, 602, 602, 602)
File: lib stats: (16384, 0, 0, 0, 0, 0, 0, 6288, 6288, 6288)
File: test.txt stats: (32768, 0, 0, 0, 0, 0, 5, 9522, 9522, 9522)
參考 :
# https://forum.micropython.org/viewtopic.php?t=2615
# https://docs.python.org/3/library/os.html#os.stat
2017-06-26 補充 :
如果重灌韌體後於 REPL 中使用 os.listdir() 指令查看檔案列表發現有一堆 \x00 如下 :
>>> import os
>>> os.listdir()
['\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00', '\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00',
....... (一堆 \x00)
這表示檔案系統已經局部毀損了, 重灌韌體並無法解決檔案系統受損問題, 必須利用下列程式碼重建檔案系統 :
>>> from flashbdev import bdev
>>> uos.VfsFat.mkfs(bdev)
>>> vfs=uos.VfsFat(bdev)
>>> with open("/boot.py", "w") as f:
... f.write("""\
... import gc
... gc.collect()
... """)
... f.close()
...
...
重建完成後, 那些 \x00 就不見了, 檔案系統下就只有一個 boot.py :
>>> import os
>>> os.listdir()
['boot.py']
boot.py 內容為 :
import gc
gc.collect()
然後上傳基本架構的 main.py :
#main.py
import network
def connect_wifi(ssid, pwd):
wlan=network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network ...')
wlan.connect(ssid, pwd)
while not wlan.isconnected():
pass
print('Connected:', wlan.ifconfig())
def get_ip():
return (network.WLAN(network.STA_IF).ifconfig()[0],
network.WLAN(network.AP_IF).ifconfig()[0])
def ap_on():
network.WLAN(network.AP_IF).active(True)
def ap_off():
network.WLAN(network.AP_IF).active(False)
參考 :
# MicroPython v1.9.1 版韌體測試
沒有留言 :
張貼留言