2012/02/21

Arduino在Windows的Cygwin命令列模式下進行編譯與上傳

我的電腦是Windows XP加上Cygwin。
我的Arduino板子是Uno(Rev 3),軟體開發環境為1.0版。

用了Arduino的軟體開發環境一陣子後,就會覺得好慢,每次執行Sketch-Verify/Compile(按鈕是個勾勾)或File-Upload(按鈕是個朝右的箭頭),都要花上一段時間。可以到File-Preferences,勾選Show verbose output during: compilation與upload,就可以清楚地看到它到底執行了哪些動作。

除了要編譯我們寫的程式碼外,它還需要編譯位於hardware\arduino\cores\arduino底下的Arduino核心程式,但是,讓我覺得納悶的是,為什麼每次都還要重新編譯那些核心呢,之前不是已經編譯過了嗎?我並沒有去更動那些東西啊?而且,如果我修改程式後先Sketch-Verify/Compile看看能不能通過編譯,通過後,再File-Upload,它居然又從頭開始執行那些已經執行過的編譯動作,真是夠了。


總之,Arduino的軟體開發環境,實在有點遜遜的,底下要介紹,怎麼在Cygwin命令列下,以make工具與Makefile檔進行編譯與上傳。

首先,還是要安裝Arduino的軟體開發環境,我們只是不用那套視覺化開發環境,改而使用命令列模式(終端機),但仍然需要裡頭各種工具與核心程式碼。

然後,要安裝Cygwin,到這裡下載Cygwin的setup.exe,安裝步驟如下:

執行setup.exe,我們將從網路下載、安裝,所以選第一個Install from Internet。


指定安裝目錄,預設為C:\cygwin,如果沒有特殊需求,就不要更動。


除了安裝,下載回來的東西也會另外存一份。請指定某路徑。


選取網路連線設定,請根據你上網的方式進行設定。


然後,選擇要從哪台伺服器下載,基本上都是國外的,速度慢,可以自行輸入"ftp://ftp.ntu.edu.tw/cygwin/",使用台灣的。


然後選擇要安裝哪些軟體,預設並不會安裝make,所以我們要自己手動勾選。


在Search欄位輸入"make",在Devel分類下,勾選make: The GNU version of the 'make' utility。應該要顯示3.82.90-1或類似的版本編號。


然後就是下載並安裝了,setup.exe可能會提示你,有些具有相依性的套件也要安裝,請選同意安裝。

我因為還灌了很多其他有的沒的,所以安裝後的C:\cygwin目錄共約700 MB。

不過,新版的make不知道為什麼,不能正確處理我底下要介紹的Makefile,所以,要把make改回3.80版。開啟cygwin終端機後,以底下步驟,改為3.80版。

cd /usr/bin
mv make.exe make_382.exe
wget http://geant4.cern.ch/support/extras/cygwin/make.exe
chmod +x make.exe

然後,因為make 3.80版需要某程式庫,所以請再執行一次setup.exe,加裝"libintl2"這個程式庫。


檢查一下,在cygwin終端機上執行make --version,應該要出現3.80字樣。

我已經提供一份範例,可到這裡下載,按下ZIP按鈕可打包下載。接下來我將使用這個範例作說明。


在BlinkMakefile目錄裡,總共有6支檔案BlinkMakefile.cpp、foo.c、foo.h、bar.cpp、bar.h、Makefile。(其他目錄是我的Arduino練習。)

BlinkMakefile.cpp,裡頭的程式就是讓腳位13的LED閃爍,不同的是,我們需要在檔案開頭加上#include <arduino.h>,這是因為,以前,arduino軟體開發環境會幫我們做這件事情,現在要自己來。

為了當示範,所以我還加了一支C程式檔foo.c與它的標頭檔foo.h,裡頭很簡單就是一個叫做delayDuration的函式,固定回傳1000,在BlinkMakefile.cpp裡,會把這個值當做點亮LED的時距。

還加了一支C++程式檔bar.cpp與它的標頭檔bar.h,裡頭就是個ClassBar類別定義,以成員函式getDelayDuration回傳一個值,但這個值每次呼叫會加100,第一次回傳100、第二次回傳200、等等,在BlinkMakefile.cpp裡,會把這個值當做熄滅LED的時距,所以熄滅時間會越來越長。

然後就是主角Makefile了,恕我無法詳細講解其語法了,底下說明你應該修改的地方:

原本Arduino軟體開發環境,程式檔使用.pde或.ino副檔名, 現在請全部改成.cpp。

PROJECT = BlinkMakefile
這是最後產出檔案(.elf、.hex、.eep)的檔名,可以改成任何你想要的名稱。

ifndef PROJ_SOURCE
PROJ_SOURCE := $(wildcard *.c) $(wildcard *.cpp)
endif
上面會找出你專案的原始程式碼(.c與.cpp),請把這些檔案放在跟Makefile同一個目錄裡即可。請不要使用子目錄。

MCU = atmega328p
板子上的微控制器是哪顆,填寫正確編譯器才知道要產出何種機械碼。我的板子是Arduino Uno Rev 3,所以填atmega328p。不僅編譯器需要這個參數,上傳時也需要。

F_CPU = 16000000L
微控制器的時脈。為了相容性,不管什麼板子,好像都是一樣的,所以應該不用改。

ARDUINO_VERSION = 100
Arduino軟體開發環境的版本編號,這會傳入編譯器,就可以在程式碼裡使用這個值。

FORMAT = ihex
輸出格式,應該不用改。

PORT = \\.\COM3
序列埠連接埠號,這就是軟體開發環境Tools-Serial Port的設定。你可能覺得奇怪\\.\是幹嘛的,這跟上傳工具的參數指定、Windows路徑、等等有的沒的有關係,總之這樣寫就不會遇到奇怪的問題。

UPLOAD_RATE = 115200
序列埠連接埠號的傳輸速率,一般都是設9600,但我的板子可以用115200。上傳時需要這個參數。

INSTALL_PATH = D:/Arduino/arduino-1.0
這個路徑要指向Arduino軟體開發環境的最上層目錄。也就是有arduino.exe執行檔、examples目錄、libraries目錄、等等的目錄。請依照你的安裝路徑修改。

CORE = $(INSTALL_PATH)/hardware/arduino/cores/arduino
這個路徑要指向Arduino的核心程式碼檔案的目錄,也就是有Arduino.h、wiring_analog.c、wiring_shift.c等等檔案的目錄。INSTALL_PATH設好後,這個應該就對了。

BUILTINLIB = $(INSTALL_PATH)/libraries
內建程式庫的路徑,裡頭應該含有EEPROM、Ethernet、LiquidCrystal、等目錄。INSTALL_PATH設好後,這個應該就對了。

SKETCHBOOK = D:/Arduino/sketchbook
自己寫的程式碼的路徑。

THIRDPARTYLIB = $(SKETCHBOOK)/libraries
第三方程式庫的路徑,也就是你自己額外安裝的程式庫。SKETCHBOOK設好後,這個應該就對了。

AVRDUDE_PROGRAMMER = arduino
設定要用什麼燒錄器上傳程式,arduino代表要使用微控制器裡的bootloader進行上傳。根據板子不同,可能要改成stk500、stk500v1、或stk500v2。可用參數請參考avrdude這隻工具程式的參數說明,avrdude是負責上傳(燒錄)程式的工具。

若要使用Arduino內建的程式庫,請修改Makefile裡的
BUILTINLIB_ENABLED =
在後面加入程式庫的名稱,例如
BUILTINLIB_ENABLED = EEPROM Ethernet Firmata LiquidCrystal
(需要設定BUILTINLIB指向內建程式庫的目錄)

若要使用額外安裝的程式庫,請修改Makefile裡的
THIRDPARTYLIB_ENABLED =
在後面加入程式庫的名稱,例如
THIRDPARTYLIB_ENABLED = BOUNCE
(當然,你要先下載程式庫、解壓縮、放進THIRDPARTYLIB指向的目錄。)

至於其他的,就屬於make的東西了,有興趣的話請自己看看囉。

接下來,開啟cygwin終端機,切換到BlinkMakefile目錄後,以底下指令進行編譯與上傳:

首先執行
make depend
根據上面設定的檔案與路徑,這會找出.c、.cpp、.h等檔案的相依關係,並附加在Makefile的後面。

make
這會開始編譯、連結,成功的話,最後會出現BlinkMakefile.elf、BlinkMakefile.eep.hex、BlinkMakefile.eep。(以及其他.o檔。)

若再執行一次make,會出現make: Nothing to be done for `all'.,太好啦。

make upload
這會開始上傳,將程式燒錄到板子裡。

make clean
這會把make產生的檔案通通刪除。我這支Makefile,會把中間目的檔.o、以及其他檔案,直接產生在原始程式檔的目錄裡。

這是我執行make的畫面。




這是我執行make upload的畫面。




 完成啦。

不過,有個小問題,原本的Tools-Serial Monitor序列埠監看視窗呢?沒關係,我們可以用Windows裡的超級終端機或是Tera Term取代。

先介紹超級終端機(開始-程式集-附屬應用程式-通訊-超級終端機),開啟後:

嗯,大家上ptt應該都用別的程式吧,這裡請勾選"請不要再詢問我這個問題",然後按"否"。


填入一個名稱,隨便選個圖案。


若要求你輸入區碼,隨便輸入一個數字。
設定連接Arduino的序列埠號。


底下是序列埠的傳輸設定。
每秒傳輸位元,我使用115200,如果不行,請試試看一般的9600設定值。
資料位元,8。
同位檢查,無(N )。
停止位元,1。
流量控制,無。


連線成功後,就可以看到BlinkMakefile傳過來的LED明滅時距,每次點亮固定為1秒,第一次滅掉為0.1秒,每次延長0.1秒,所以熄滅時間會越來越長。


以上步驟成功後,在「開始-程式集-附屬應用程式-通訊」裡會多出一個超級終端機目錄,裡面有將以上設定儲存起來後的捷徑。

成功啦。

不過Windows附的超級終端機HyperTerminal,年久失修,Windows Vista、Windows 7裡頭已經沒有它的身影了。還好,可以用Tera Term。

Tera Term網站下載,我下載的是teraterm-4.72.zip,只要解壓縮後就可使用,不用安裝。

執行ttermpro.exe,選Serial,選你Arduino板的序列埠號。我的是COM3。


畫面看起來怪怪的,因為還沒設定好序列埠的傳輸參數。選Setup-Serial port...進行設定。請根據你的情況設定,跟我不一樣的地方應該會是Port與Baud rate,其他應該都一樣。


成功啦。


然後,選Setup-Save setup...把設定儲存起來,下次執行ttermpro.exe就會直接連接。

還有其他可用的軟體,譬如PuTTY、Roger Meier's CoolTerm


後記:
我因為裝了免費版的avast!防毒軟體,每次執行make、avr-g++、avr-gcc時,都會進行防毒掃描,變得很慢,所以我到avast!的設定裡,將這些執行檔排除在掃描外。(關閉前超過一分鐘,關閉後5秒。)


參考資料:

19 comments:

  1. 感謝,這篇太有用了 !

    ReplyDelete
  2. 不好意思!想請問一下:
    Makefile:283: *** multiple target patterns. Stop.
    這該如何解決?

    ReplyDelete
    Replies
    1. 光這樣看不出所以然。

      Delete
    2. Makefile:https://dl.dropboxusercontent.com/u/65894737/Makefile
      make --version GNU Make 4.0
      能麻煩您幫忙確認一下?
      拜託了!

      Delete
    3. 當初我在嘗試的時候,必須使用make 3.80版才行。
      我沒試過4.0版。

      Delete
    4. 似乎是因為3.80以上的cygwin的make版本,若出現MS-DOS的路徑就會出問題,例如D:/xyz/abc,但若改為cygwin的路徑/cygdrive/d/xyz/abc,這支Makefile裡有些部分又會出問題,必須改寫。
      可到網路上找找,看看有沒有人更新。不過據我所知,似乎還沒有。

      Delete
  3. 您好,我用 Cygwin 下的 make 4.0 可以成功編譯而且上傳。
    我用的是 1.5.7-beta IDE。

    1. 在 Cygwin 的 shell 裡要執行 export PATH=$PATH:/cygdrive/c//hardware/tools/avr/bin

    2. 如您所說 makefile 裡 MS-DOS 型式的路徑要改成 /cygdrive/c/xyz/abc
    在您提供的 BlinkMakefile 裡的 Makefile 有 INSTALL_PATH 也就是 IDE 的路徑,
    還有 SKETCHBOOK 要改成這種方式。

    3. 如果是 1.5.7-beta IDE,還要修改 CORE,
    CORE := $(INSTALL_PATH)/hardware/arduino/cores/arduino
    ->
    CORE := $(INSTALL_PATH)/hardware/arduino/avr/cores/arduino
    如果是用 1.0.5 IDE,這裡就不需要修。大概是 1.5.7-beta 支援其他的晶片吧 ?

    以上改完就可以編譯成功。

    4. 要上傳到板子,也就是您說的 make upload,
    在 COM3 前要多加一個 '\' --> PORT := \\.\\COM3
    在 AVRDUDE_FLAGS 的下一行 (因為加了 \ 所以對 makefile 來說是同一行)
    -C $(INSTALL_PATH)/hardware/tools/avr/etc/avrdude.conf
    讓 avrdude 能讀到 configuration file。

    以上改完就可以上傳成功。

    個人經驗,供您參考

    ReplyDelete
    Replies
    1. Excellent,太棒了!

      多謝提供詳細的步驟。

      Delete
  4. 請問我按照步驟做完後,下達make depend出現以下錯誤:
    /bin/sh: -c: line 0: syntax error near unexpected token `('
    /bin/sh: -c: line 0: `rm -f /cygdrive/c/Program\ Files\ (x86)/Arduino /hardware/arduino/avr/cores/arduino/core.a'
    Makefile:317: recipe for target 'clean' failed
    make: *** [clean] Error 1

    該怎麼解決?

    ReplyDelete
    Replies
    1. 建議
      1. 不要把Arduino安裝、放到含有中文名、空格、長名稱的路徑裡。
      你的路徑... /Arduino /hardware/arduino/avr/ ...其中/Arduino的部份是不是有空格?
      2. 你裝的是1.5.x版吧,我只試過1.0.x版。請參考上一個留言,有人使用1.5.7版並成功。

      Delete
  5. 請問 為什麼選擇範例進行編譯會發生錯誤 我的電腦是 windows vista 32

    ReplyDelete
    Replies
    1. google翻譯:

      AVR-G++:錯誤:CreateProcess的:沒有這樣的文件或目錄
      編譯時發生錯誤

        這份報告的詳情將會在
        “編譯時顯示詳細輸出資訊”
        在檔案>偏好設定裡啟用。

      Delete
    2. > google翻譯
      為什麼要翻譯?

      > 這份報告的詳情...
      既然如此,請開啟「“編譯時顯示詳細輸出資訊”」選項,取得更詳細的錯誤訊息。

      試試在程式裡加上#include "WProgram.h"或#include "Arduino.h"

      Delete
    3. 一樣是編譯時發生錯誤
      詳細資訊:
      D:\arduino-1.6.4\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10604 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -ID:\arduino-1.6.4\hardware\arduino\avr\cores\arduino -ID:\arduino-1.6.4\hardware\arduino\avr\variants\standard C:\Users\yy\AppData\Local\Temp\build7520302592673202118.tmp\Blink.cpp -o C:\Users\yy\AppData\Local\Temp\build7520302592673202118.tmp\Blink.cpp.o
      avr-g++: error: CreateProcess: No such file or directory

      麻煩你了

      Delete
    4. 這篇的Arduino軟體開發環境為1.0版,我沒試過1.5以上的版本。

      Arduino自1.6.6開始提供arduino-builder,可試試。

      Delete
    5. 呃,你是想在命令列模式下(譬如Cygwin)編譯Arduino程式,對吧?

      Delete
    6. 謝謝你的解答 不過我只是個新手 純粹想解決我的電腦不能執行Arduino的問題 ^^

      Delete
    7. 喔。因為你在這篇底下留言,所以...。

      avr-g++: error: CreateProcess: No such file or directory這個錯誤訊息很模糊。

      試試關閉防毒軟體,它可能妨礙Arduino IDE執行其他程式。

      刪除原本的Arduino,下載最新版,再試試看。

      Delete