輕鬆上手:以VS Code, SDCC, Git建立新唐8051編譯環境

 這是003Clock系列的第二篇文章,第一篇還沒跟上的趕快回追一下~

(一)製作新唐N76E003白光LED電子時鐘套件
(二)以VS Code, SDCC, Git建立新唐8051編譯環境
(三)新唐N76E003白光LED電子時鐘套件韌體技巧說明
(四)免用燒錄器更新韌體:NuMicro ISP Programming Tool

2018年前後,新唐推出了這顆N76E003,主打著只要台幣7塊錢的增強型8051,與STM8S003 pin-to-pin相容,機械週期只有1個clock cycle、內建了18KB的程式記憶體、兩組UART、ADC、I2C、SPI、PWM等齊全的功能,要接什麼感測器都很方便,Arduino UNO有的它都有,於是就入手了一堆N76E003。

朋友們如果有新的設計,推薦使用今年新出的N76S003啊!因為N76E003目前已調漲到台幣10塊錢。新出的N76S003大概是用了更成熟的技術來生產,所以還能維持在台幣7塊錢(聽說是e-store Nuvoton Direct獨賣),除了更便宜之外還多了SPROM的功能。我現在還在用N76E003是因為當年買的那一堆庫存還沒用完XD 但請各位放心,這兩個型號新唐掛保證是完全pin-to-pin、code-to-code相容的,原廠提供的BSP也完全共用。

https://direct.nuvoton.com/n76s003-series

由於Keil C51、IAR之類的商用軟體,免費版本是有code size限制的,印象中Keil C51是限制在2KB,那麼N76E003的18KB豈不是用不完!因此當時就轉向使用open source、無code size limit的SDCC (Small Device C Compiler) 來開發。SDCC只是一套工具鏈(俗稱編譯器),而非整合型的開發環境(Integrated Development Environment, IDE)。

那時候自己看了一下SDCC的手冊,就能將新唐原廠提供的BSP (Board Support Package) 修改成SDCC支援的格式,用Windows內建的記事本或Notepad++編輯主程式,再開一個「命令提示字元」一一敲進編譯、組譯和鏈結的指令,把執行檔編出來。後來當然學聰明了,將這些步驟寫成.bat的批次檔,修改程式後只要執行這個批次檔就能自動產生執行檔了。

後來工作時用新唐Arm系列的MCU做了一些open source專案,當時VS Code正流行起來,就順勢建了一個VS Code + Git + Makefile + ARM-GCC的環境,掌握了一些VS Code的使用技巧。我這套評價還不錯,如同Arduino IDE一般,按個按鈕就會把執行檔編出來,只是在這邊是下一行指令「make」。日後有機會的話再來介紹Makefile。

直到最近新唐原廠推出自家的NuEclipse 8051 IDE的同時,將1T 8051 的BSP增加了對SDCC的支援,這也意味著現在我也可以用類似的方法,從OpenNuvoton用Git來管理整個開發環境了!

自己的建環境真的有太多優點啦,真的要用過比過才會懂 …

SDCC和商用軟體相比之下的優點:SDCC免費且無code size限制,想寫多少就寫多少, N76S003、N76E003的18KB可以盡情地用。

VS Code和商用軟體相比之下的優點:介面簡潔,編譯器的路徑以文字檔存放於實體路徑下的.vscode/setting.json,這個是VS Code原生提供的功能,不必安裝擴充套件,亦無擴充套件相容性問題,整個韌體專案的資料夾移到別台電腦去完全不用重新設定,相當容易使用Git管理專案。

使用Makefile或批次檔的優點:沒有複雜的按鈕、選項要設定,讀懂compiler的手冊即可依照自己的需求進行設定,compiler加了哪些參數、編了哪些內容全部以文字檔寫在Makefile或批次檔裡面清楚明瞭;由於也是文字檔,同樣容易使用Git管理。

綜合上述幾點,自建的環境優勢在於:

1. 免費且無code size limit
2. Windows, Linux跨平台支援
3. Open source軟體
4. 可攜式的開發環境
5. 易於使用Git管理、容易與他人協作

不過,缺點就是目前我還沒有把debug的功能整合進去。如果有debug、單步執行的需求,可以使用新唐原廠推出的NuEclipse 8051,新版BSP中有詳細說明建立專案的步驟,使用之前一定要先讀一下,有心得、疑問、建議,歡迎到NuForum發文!

https://github.com/OpenNuvoton/N76E003_BSP/blob/3d205357fbbab48122c25cdd4f66e7ca3aeb3b6c/NuEclipse SDCC quick start_EN.pdf

NuEclipse可以在這裡下載到,記得要先登入新唐帳號才能下載唷:https://www.nuvoton.com/tool-and-software/ide-and-compiler/


好啦,設計理念的部分說明完畢,接下來就要進入實作的部分,建環境有以下幾個步驟:

一、安裝文字編輯器:VS Code
二、安裝工具鏈(編譯器):SDCC (Small Device C Compiler)
三、安裝Git Bash
四、燒錄軟體NuMicro ICP或ISP Programming Tool
五、編譯
六、燒錄

看起來很繁瑣嗎? 不用擔心,一 ~ 三安裝起來,第四步ISP燒錄為免安裝軟體,只要下載解壓縮。我在GitHub已經放了完整專案,直接在Git Bash中輸入下面這行指令,clone下來之後用VS Code開啟專案的目錄即可使用!VS Code裡面看到的檔案就和實體路徑完全一樣,清楚明瞭!

git clone https://github.com/danchouzhou/003Clock.git --recurse-submodules

一、安裝文字編輯器:VS Code

可以在這裡下載到VS Code:https://code.visualstudio.com/download

安裝VS Code時到了這步會建議把這兩個選項勾起來,以便日後能在檔案總管右鍵選單中,直接開啟專案的目錄或檔案。

將[以Code開啟]動作加入Windows檔案總管檔案的操作功能表中
將[以Code開啟]動作加入Windows檔案總管目錄的操作功能表中


有勾選這兩個選項,右鍵選單就會像這樣有「以Code開啟」的選項:


安裝完畢以後我會在設定中搜尋update把VS Code自動更新通通關閉。


二、安裝工具鏈(編譯器):SDCC (Small Device C Compiler)

可以在這裡下載到SDCC,在這邊我們先下載這一個版本「sdcc-4.2.0-x64-setup.exe」,因為其它版本我還沒有測試過,不清楚會不會遇到其它的問題。開發東西要記得,用了沒問題就繼續用;用了遇到問題有繞過解決了就好,下次也可以用相同方式繞過。尤其是這種免費open source的軟體,不要去追求最新版XD

https://sourceforge.net/projects/sdcc/files/sdcc-win64/4.2.0/

安裝的路徑不要更動它,照著步驟安裝即可。


安裝完成之前還會問要不要將sdcc加入環境變數中,在這邊不用勾選,因為我們待會會在.vscode/setting.json中告訴VS Code SDCC放在哪裡。


三、安裝Git Bash

可以在這邊下載到Git Bash:https://git-scm.com/downloads

基本上照著步驟下一步下一步裝完就可以了。


四、燒錄軟體NuMicro ICP或ISP Programming Tool

新唐的燒錄軟體都集中在這裡:https://www.nuvoton.com/tool-and-software/software-tool/programmer-tool/

將編出來的執行檔(ex. *.bin, *.hex) 要經由燒錄軟體、通訊介面燒進晶片內由快閃記憶體組成的程式記憶體(code memory)。

如果您手邊有新唐8051開發板,或是有Nu-Link燒錄器的話,請安裝Nu-Link_Command_Tool,可以直接在VS Code裡面執行flash.bat燒錄。

如果想更動晶片細部設定,或是同時燒錄LDROM (bootloader)與APROM,可以下載有GUI的版本NuMicro_ICP_Programming_Tool。安裝好軟體以後,選擇晶片系列「1T 8051」,可以在Help/說明的欄位中找到使用手冊。

如果您只是為我出的003Clock時鐘套件增加新功能,可以下載NuMicro_ISP_Programming_Tool。這個就不用Nu-Link燒錄器,因為003Clock我包貨時都已經幫MCU燒好ISP bootloader,只需要用USB to UART,連接在N76E003/N76S003的UART1上,就可以用ISP Programming Tool更新APROM中的程式。操作方式詳見GitHub的README.md。


五、編譯

再來若想要編譯,要在VS Code裡面開啟一個終端機。


終端機開啟之後將目錄切換到source code的資料夾裡面:

cd firmware/003Clock

接著執行批次檔:

./build.bat

沒有出現任何錯誤訊息即是編譯完成,執行檔會在這裡

firmware/003Clock/Objects/main.bin


六、燒錄

如果是用Nu-Link燒錄,在終端機裡面執行 ./flash.bat 就會將main.bin燒錄到MCU當中。

./flash.bat

沒有Nu-Link的朋友不用擔心,找一條USB to UART接到時鐘上:


然後可以用NuMicro ISP Programming Tool以UART燒錄新的程式,操作方式就是選好COM Port以後先按燒錄軟體上的Connect,再送電給時鐘,由於我燒錄時已設定從LDROM開機,因此就會跑裡面燒好的ISP程式了,此時ISP Tool應該會顯示連線成功,勾選APROM和Reset and Run,最後按右下角的Start,就可以燒錄並執行APROM。


對於環境使用到的技巧細節有興趣的朋友,可以繼續往下看。

一、./vscode/setting.json

剛剛在安裝SDCC時提到,可以不用將sdcc加入環境變數中,原因是我們透過VS Code原生的功能使內建的終端機讀取SDCC安裝的路徑。所以假設剛剛安裝SDCC時有去變更預設的路徑,就要更改setting.json裡面記載的路徑。

關於setting.json設定環境變數參考的相關資料:
Configure environment of terminal sessions
Terminal Configuring profiles

{
    "terminal.integrated.env.windows": {
        "PATH": "${env:PATH};C:\\Program Files\\SDCC\\bin;C:\\Program Files (x86)\\Nuvoton Tools\\NuLink Command Tool;"
    }
}

透過下面的實驗可以驗證,先單獨開啟一個PowerShell,分別輸入sdcc -v以及echo ${env:PATH},可以看到PowerShell是找不到sdcc的,且PATH也沒有列出所安裝的路徑。


再來用VS Code開啟包含./vscode的這個專案目錄,然後在裡面開啟一個終端機,一樣執行sdcc -v和echo ${env:PATH}。在VS Code裡面就可以看到sdcc可以被執行,且列出的環境變數中是有setting.json裡面所記載的路徑。


二、./vscode/c_cpp_properties.json

c_cpp_properties.json這個設定檔實際上是給C/C++ IntelliSense使用的,這不是VS Code原生提供的功能,而是個extension,它可以幫助我們閱讀C語言,但不是編譯必須的。

有安裝IntelliSense的朋友可以試試看,如果把c_cpp_properties.json檔名暫時改掉,例如:我先把它改成c_cpp_properties.json.bk,讓IntelliSense讀不到這個設定檔,main.c一點開就會冒出一堆錯誤的紅色毛毛蟲。原因是SDCC比較冷門,IntelliSense沒支援,認不得它的語法XD


新唐很讚,已經在BSP當中幫我們定義好SDCC用到的關鍵字,我們看看BSP中的fuction_define_n76e003.h可以發現,如果預先定義__CDT_PARSER__,就會利用標準C語言的#define列出SDCC的關鍵字,讓不管是IntelliSense或是Eclipse都能夠認得它們。

#ifdef __CDT_PARSER__         /* For __SDCC__ */
  #define __data
  #define __near
  #define __idata
  #define __xdata
  #define __far
  #define __pdata
  #define __code
  #define __bit
  #define __sfr
  #define __sbit
  #define __critical
  #define __at(x)             /* use "__at (0xab)" instead of "__at 0xab" */
  #define __using(x)
  #define __interrupt(x)
  #define __naked
#endif

除此之外numicro_8051.h也要定義__SDCC__,才會去讀n76e003_sdcc.h這個include files。(同樣的道理,可以去看build.bat也有-D __SDCC__指定去讀SDCC用的include files)

/* for Keil */
#if defined __C51__
#include "n76e003_keil.h"

/* for IAR */
#elif defined __ICC8051__
#include "n76e003_iar.h"

/* for SDCC */
#elif defined __SDCC__
#include "n76e003_sdcc.h"

#endif

因此我們可以在c_cpp_properties.json中定義它們,這麼一來可以讓IntelliSense在搜尋時認得這些關鍵字。

{
    "configurations": [
        {
            "name": "NuMicro 8051",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [
                "__SDCC__",
                "__CDT_PARSER__"
            ],
            "browse": {
                "path": [
                    "${workspaceFolder}/**"
                ],
                "limitSymbolsToIncludedHeaders": true
            }
        }
    ],
    "version": 4
}


三、Git submodules

Open source其中的重要精神就是:衍生著作要公開透明,並且保留原著的完整性。Git submodule就可以很好地做到這件事。我們在專案中使用到新唐提供的BSP,以submodule的方式從新唐BSP的repository匯入到本專案中。

Git Submodules的文件可以參考這裡:
https://git-scm.com/book/en/v2/Git-Tools-Submodules

我在建git的時候是這麼做的:

git init
git submodule add https://github.com/OpenNuvoton/N76E003_BSP.git firmware/N76E003_BSP

如此就可以在firmware這個目錄中新增新唐的BSP。

我會再建立其他的目錄來放自己的程式與函式庫,比方在這個時鐘專案中,firmware/003Clock擺的就是時鐘的程式碼 (APROM),firmware/ISP_UART1擺的就是ISP (LDROM)的程式碼,兩份程式編譯時都會呼叫到N76E003_BSP的driver。

留言

這個網誌中的熱門文章

無法被取代的指針型三用電表(一):前言

關於新唐科技NuMicro ISP的介紹和使用方式

新唐火神板開箱實作(一):NuMaker-Volcano與NuEclipse IDE入門篇