2020年11月10日 星期二

在 Linux mint 上玩 ATmega328P

先安裝好 binutils-avr  gcc-avr  avr-libc:

      sudo apt-get install binutils-avr  gcc-avr  avr-libc

使用 open source 的 grbl 當範例程式(官網 https://github.com/gnea/grbl/releases), 下載解壓縮後, 進入主目錄並編譯 :

      wget  https://github.com/grbl/grbl/archive/master.zip  && unzip master.zip

      cd grbl-master  && make 

安裝燒程式:

      sudo apt-get install  avrdude

參考資料:https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266AVRISP 

空的 avr uP 必須先透過 ICP (in-circuit programing) 的方式預先燒錄一段內建 ISP(n-System programing)的 bootloader, 之後才能透過 serial port 來更新軔體(Firmaware), 另一種是花錢買 ICSP (in-circuit serial programming)燒器,  而 AVR 的 uP 像是 ATmega328P 能透過 SPI 介面來燒內部的 flash.

我之前買過一個 ESP8266 的開發板, 本身也可以拿來當作 AVR ICSP 的燒, 安裝完 ESP8266 的 arduino 後, 打開位在 ~/home/mint/.arduino15/packages/esp8266/hardware/esp8266/2.7.4/libraries/ESP8266AVRISP, 可以將他複製到專案裏,稍作修改, 編譯後再燒到 ESP8266, 他就變成一個名副其實的無線 AVRISP 燒錄器. 燒錄 AVR uP流程要使用 avrdude 命令, 把 Hex 檔案傳送給 ESP8266, 由 ESP8266 用自身的 SPI 介面燒寫到 ATmega328P 的 flash 上, 命令列執行格式:

  avrdude -C avrdude.conf -c avrisp -p ATmega328P -P net:avrisp -U flash:w:grbl.hex:i

上述 -C avrdude.conf avrdude 的事前設定檔(可以將參數放在檔案裏面), 而 -P net: 參數中的 avrisp 是 esp8266 執行 mdns 的 localhost:port(例如用 -P net:esp8266.local:328), 或是直接用 -P net:ip:port, 例如 -P net:192.168.1.12:328, 至於 grbl.hex 正是前面編譯 grbl 完, 要燒的軔體程式(hex 格式檔),至於 esp8266 與 ATmega328P 接線方式要參考 AVRISP 原始碼裡面的 README.rst 說明

-----------------+-------------
|ESP8266 IO/JTAG |AVR
ICSP/SPI|
|================+============|
| GPIO14(D5/TMS)>| SCK        |
|----------------+------------|
| GPIO12(D6/TDI)<| MISO       |
|----------------+------------|
| GPIO13(D7/TCK)>| MOSI       |
|----------------+------------|
| GPIO16(D0)    >| RESET      |
-----------------+-------------


AVR ICSP SPI(Slave)/ESP8266 SPI(Master):
  MISO  --|1 2|-- VCC
  SCK   --|3 4|-- MOSI
  RESET --|5 6|-- GND

ESP8266 的 GPIO12(TDI), GPIO13(TCK), GPIO14(TMS), GPIO15(TDO) 是內建的 SPI/JTAG 硬體介面, 我改用 GPIO16(D0) 作為 RESET 腳, 要注意的是 ESP8266 是 3.3V 的裝置, 介面之間的邏輯準位若電壓太高恐會把 IC 弄壞或是造成無法開機. 而 MISO (GPIO12)對於 ESP8266 來說是輸入接腳, 可以簡單用 1k 串聯 2k 下地電阻的分壓器(Voltage divider)作為 Level shifter 來連接, 另外因為在 Arduino UNO( ATmega328P) 板子上的 RESET 接腳有個 10k Ohm 提升電阻拉到 5V, 為免影響 ESP8266 開機,可以在 ESP8266 端加個電晶體(buffer)把它隔開, 亦或是簡單用 1.5k 下地電阻把把它拉到 0.7V 以下.

以下執行命令不使用 -C avrdude.conf, 而是直接下命令燒錄 grbl.hex, 假設 esp8266 在區域網路獲得的 ip 位址是 192.168.12.106, 而 service tcp port 是 328, 執行 avrdude 燒錄:

   avrdude -c avrisp -p ATmega328P -P net:192.168.12.106:328 -U flash:w:grbl.hex:i

警告:使用 avrdude 直接燒錄若下的參數錯誤, 恐會造成無法再燒錄的悲劇, 因為可能會清掉原來的 bootloader, 若是內部的 fuse 燒入錯誤, 將造成無法透過 SPI 再更新軔體若真的想要燒入內部 fuse 可先參考

   https://www.engbedded.com/fusecalc

燒錄程序畫面截錄:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "grbl.hex"
avrdude: writing flash (29864 bytes):

Writing | ################################################## | 100% 8.66s

avrdude: 29864 bytes of flash written
avrdude: verifying flash memory against grbl.hex:
avrdude: load data flash data from input file grbl.hex:
avrdude: input file grbl.hex contains 29864 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 7.34s

avrdude: verifying ...
avrdude: 29864 bytes of flash verified

avrdude: safemode: Fuses OK (E:FD, H:DA, L:FF)

avrdude done.  Thank you.

 

後記:

使用 arduino SDK 修改 AVRISP 程式啟用 TCP port 328 當 sevice port, 以及 GPIO16 作為 RESET 腳:

  #include <ESP8266AVRISP.h>

  ESP8266AVRISP avrISP(328, 16);

  void setup(){

    Serial.begin(115200);

    // ...

    avrISP.begin(); 

  }

  void loop() {

    // ... 

    static AVRISPState_t last_state = AVRISP_STATE_IDLE;
    AVRISPState_t new_state = avrISP.update();
    if (last_state != new_state) {
      switch (new_state) {
        case AVRISP_STATE_IDLE: Serial.printf("[AVRISP] idle\n");
            break;         
        case AVRISP_STATE_PENDING:Serial.printf("[AVRISP] pending\n");
            break;         
        case AVRISP_STATE_ACTIVE:
            Serial.printf("[AVRISP] programming\n");
            break;
        default: break;         
      }
      last_state = new_state;
    }
    if (last_state != AVRISP_STATE_IDLE) avrISP.serve();

  }

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...