2010年1月20日 星期三

NUC501初探

沒想到過了這麼久,大金還是對GPS的應用念念不忘!之前有試作一台GPS軌跡記錄器,用22Mhz的標準8051、GBA專案剩下的半硬體半軟體的SD介面晶片、國產便宜的GPS接收器、二顆LED,以及32K RAM及ROM組成,完全以便宜為考量的機器。

為了能在這顆效能貧脊的8051(由於指令需12 clock,效能最快只有1.83MIPS而已),順暢的執行GPS接收、寫入SD卡,花了許久的時間改進程式碼的效率,透過檢查編譯器(SDCC)所編出的組合語言,找出能讓編譯器產出最佳的程式寫法。無法改進的部份,就直接用組合語言來加速!導致專案大半時間都耗在最佳化上(很愚蠢吧),最後雖然能夠順暢的執行所有工作,但受到半硬半軟SD介面的限制,儲存的資料偶而會有錯誤的問題!8051剩餘效能也無法進行複雜的資料分析作業。此外還有定位慢、燈號意思不易記(只有二顆LED呀,是要怎麼閃才容易記?)等問題。最重要的,就是沒有技術去開發電腦端的整合方案,最後這個專案淪為練功用,唯一受益的,就是讓之後用到8051的專案,比以前更容易搾出效能啦!

這次又因為公司的大方向還沒出來(哪次有出來?),需要多方面發展才能提供給客戶選擇。結果大金又提GPS的東西,就跟大金明說了,裝置方面應該不是問題,最大的難題在電腦端的應用,需要花很多時間去搞懂一些規格,才能寫得出像樣的應用程式,大金也說了可以跟其他廠商合作(雖然每次都這麼說,最後還不是拿些理由要我自己做...)。既然如此,就順便進讒言說想換個高階一點的CPU,不要每次都用8051。另外,裝置上也要有黑白的(彩色更讚)液晶螢幕,才像目前市面上在賣的軌跡記錄器嘛!是不是?!說不定之後還能以此架構為基底,發展出不同的應用呢!

哀求了很久,終於大金挖到Nuvoton的NUC501來作為系統的心臟!這是一顆ARM7TDMI架構的CPU,與GBA使用的相同,並不陌生,運作頻率最快可以達到108Mhz。更神奇的是,這顆CPU的報價竟然只要美金1元左右,太有競爭力了!本以為大金能同意用高效能8-bit晶片(如AVR),或16-bit的CPU就謝天謝地了。想想自從開始寫裝置系統以來,除GBA外,還沒真的在專案上使用32-bit的CPU耶~~

興奮之餘,也稍微研究了一下NUC501的規格。啥米!RAM竟然只有32KB,程式則是放在SpiROM上,且沒有直接的擴充介面。也就是說,要嘛就把程式全部放在RAM裡面,這樣可以發揮108Mhz的最大威力,但是只能寫小程式。不然就要用NUC501的特異功能,讓程式直接在SpiROM上執行,但這樣卻會受限於SPI的頻寬而折損效能。我只能說為了降低售價,真是委屈這顆ARM7TDMI的核心了。雖然有跟大金抱怨過擴充的問題,不過大金還是用一貫的藉口「成本考量」來打發了,再加上NUC501上的週邊可以說是應有盡有(COM埠、I2C、SD等),為了避免最後大金反悔,又打回8-bit的時代,只好努力用看看了。

雖經歷一番波折才拿到開發板,裡面卻沒有開發工具,大金也說ICE太貴不肯買。還好開發板有附GCC版本的程式庫原始程式,也有makefile可以參考,所以只要自己生一套GCC的開發系統,然後把開發板的程式庫重新編譯就行了。除錯方面,程式庫已經寫好方便的RS-232訊息輸出,可以稍微彌補沒有ICE的缺憾(不過有ICE才能比較快了解硬體運作的細節呀~~")。在網路上搜尋了一下,這顆晶片還沒有什麼應用實例出來,也沒有直接可以用的GCC,還好NUC501的架構與GBA一樣,讓我想到以前寫GBA時候用的DevKitPro這套開發系統,裡面就有可以編譯ARM code的GCC,或許可以拿來用哦!

在修改範例程式的makefile,並嘗試make後,雖然有warning訊息,但還是編譯成功了!把binary code燒到開發板的SpiROM上,並設定SpiROM執行後,哇!看到訊息了,還好可以執行,不然就要傷腦筋了,呵呵。接下來的工作就是整合開發環境了。

由於懶惰寫那個麻煩的makefile,在GBA時代是借用DevC++,這套IDE軟體是整合MINGW版的GCC,編譯前會自動生成簡單的makefile,並呼叫make來編譯,也可以另外指定編譯器。雖然很方便,可是DevC++主要是開發Windows的程式,所以產生的makefile自然與ARM的編譯方式有些許差異,所以需要寫個front-end來解決DevKitPro與DevC++本質上不相容的問題。

為了這個問題,以前是寫個叫做ACC(Advanced C Compiler)的front-end解決,將DevC++執行make時所傳來的編譯參數加料,補上ARM編譯所需的-mcpu -march等,然後再把加料過的參數丟給ARM的GCC去執行。除此之外,link時期還要偷偷的補上DevC++沒做的步驟,如objcopy等。所以到目前為止,已經用這個技倆讓DevC++相容Dark Fader DevKitAdv (GBA)、DevKitPro (GBA/NDS)、SDCC (8051)以及CC65 (VT1682)了,沒想到懶惰的怨念,竟然間接擴充DevC++能支援的編譯器,哈哈。還好DevKitPro原本就在支援之列,所以ACC的修改工作還算容易,在編譯好開發板附的程式庫,參考範例程式製作一個合用的crt0,整合好開發環境,就可以開始寫程式囉!

弄完IDE後稍微試了一下NUC501的效能,在SpiROM上面執行程式如預期真的有點慢,雖然我認同Nuvoton在節省產品成本的努力,而且這介面能很神奇的讓CPU核心等待SPI序列轉並列,然後才執行轉好的程式碼,但程式不是循序執行的,這使得SpiROM的缺點曝露出來。

基於SpiROM必須先下序列位址,然後才能序列讀取資料,整合成32-bit的資料後交給CPU執行,所以當程式亂序執行時,便需要經常重新執行序列位址輸出,讀取序列資料交給CPU的動作。如果要執行的指令在下一個位址還好,不是的話又得重新執行,CPU才能拿到要執行的資料。這一來一往就會浪費不少時間週期在等待,遇到經常性間接參考讀取資料的指令(這可是ARM的強項)就會慢到不行,即使SpiROM已經跑72Mhz的速度也無法即時餵飽CPU。所以應用指南有說明SpiROM可以用在「不Critical」的程式上,哇!我不想再做最佳化的苦力了!

不過NUC501有個簡單的MMU機能,可以把內部的SRAM分割成16個2K區塊,並能將區塊隨意的放置在512MB (0x00000000~0x1FFFFFFF)的位址空間上,就某些程度而言,或許可以利用這個MMU及ARM7TDMI的ABORT例外,實作虛擬記憶體來解決SpiROM頻寬不足的問題。目前想到的方法是在512MB區段找個空間當ROM區,當CPU執行到此區域時,會因記憶體不存在而引發ABORT例外,這時就從SpiROM上複製該空間的資料到RAM上,並將該RAM mapping到要執行的位址,如此程式就能繼續執行。如果使用這個方法執行程式,SpiROM造成的效能衝擊就可大幅降低,程式可以執行的更快、也更省電!不過目前也只是想想,還需要做些實驗才知道這個方法是否有用了。

7 則留言:

  1. 看了你對NUC501的評論, 可以感覺到你的用心 , 你對NUC501的瞭解可能比Nuvoton 內部的工程人員都還要多一些 .

    回覆刪除
  2. 感謝您的回文與鼓勵!小弟只是苦力程式一員,懂一些皮毛啦~~

    回覆刪除
  3. 再目前這樣的環境之下, 願意用苦力換取經驗的工程師不多了 , 希望未來 Nuvoton 還有與你一起合作的機會 .

    回覆刪除
  4. 這麼說...原來您是Nuvoton的大人!這真不好意思,小弟有些班門弄斧了。不過有機會的話,也希望能與貴公司合作!

    回覆刪除
  5. 其實有你的文章中, 已經將NUC501的幾個特點都說的很清楚了. 因為很多NUC501的case 都是代理商去處理 , Nuvoton 這邊沒有介入 , 不知道你方便告知你是哪一家廠商嗎?或者提供你的 email給我, 以後有新產品也會通知你知道 .
    我的Email 是 cfwu0@nuvoton.com

    回覆刪除
  6. 您好,我想和您做技術交流,方便給我聯絡方式嗎?
    pome2000.tw@yahoo.com.tw

    回覆刪除
  7. pome2000.tw您好,已將聯絡方式mail到您指定的信箱

    回覆刪除