發表文章

目前顯示的是 5月, 2016的文章

文章總列表

假日嵌入式系統工程師:SEGGER RTT (3)

圖片
假日嵌入式系統工程師:SEGGER RTT (3) 專業的Trace系統 在前面的文章[1][2],我介紹怎麼用SEGGER RTT搭配printf()。這個方法有幾個明顯的缺點: printf()需要Data memory存format字串,在SRAM受限的場合會很傷腦筋 printf()需要花時間產生字串 舉例來說,產生十進位數值(%d)一定不是瑣碎的工作 回頭看SEGGER RTT,既然已經有路能送字串,為什麼不直接送binary values,由PC產生字串就好?以下面這段code為例: printf("idx1=%d, idx2=%d\n", idx1, idx2); 上面的code,format string起碼要 >16 bytes,而且MCU要花cycles來產生字串,最後字串也要 >16 bytes;還不包括code size的開銷。如果丟binary values就可以只傳必要的資訊 (12 bytes) ID碼,表示format string是哪一個 ID=1 -> “idx1=%d, idx2=%d\n” 參數 idx1 idx2 這篇文章介紹怎麼在MCU/PC實作這個idea。另外我認為 SEGGER SystemView 實作的方法也是同一招,底層都是RTT,只是PC端的程式換另外一套。 MCU-Side 程式 和所有通訊系統一樣,發送端比較簡單。我們定義一道macro來產生ID,裡面包括magic number來讓PC偵測trace起點,以及trace-ID本體。程式的主體是一個loop,透過SEGGER_RTT_Write不停送出 {ID, i, i<<16}。如果接收端能正確解出來,那我們就成功了。 #define MK_TRACE_HEADER(id) ((0xABCD<<16) | ((id)<<0)) int main(void) { unsigned int buf_idx = 0; while(1) { unsigned int i; for(i=0; i<256; i++) { unsigned in

假日嵌入式系統工程師:SEGGER RTT (2)

圖片
假日嵌入式系統工程師:SEGGER RTT (2) 簡介 這篇文章介紹我怎麼在WINDOWS平台跑起SEGGER-RTT。看完以後,你大概會發現這東西比想像還要容易設定。因為SEGGER RTT Viewer只提供WINDOWS版,所以這篇文章沒得選;不過下一篇SEGGER RTT (3)就會介紹怎麼在Linux/ Mac使用。而且這個形式是我個人最滿意的Log system的樣貌。 再聊一下SEGGER JLINK 我用中國做的NRF51822板子,上面有謎版的JLINK。我有買一顆JLINK-EDU,也算是合法使用吧。SEGGER的JLINK是相當出色的工具,基礎版的JLINK-EDU價格殺到2400NTD,值得投資一套。另一個合法管道是買 NRF51-DK ,上面也有JLINK on board。 RTT 程式碼 安裝完SEGGER driver以後,可以在底下目錄找到壓縮檔 /c/Program Files (x86)/SEGGER/JLink_V50i/Samples/SEGGER_RTT_V510i.zip 解壓縮以後,把裡面的這些檔案拷貝到自己的MCU projects裡: RTT/SEGGER_RTT.c RTT/SEGGER_RTT.h RTT/SEGGER_RTT_Conf.h RTT/SEGGER_RTT_printf.c 我用的NRF SDK (nRF51_SDK_10.0.0_dc26b5e)也有RTT library,路徑是 $(NRF51_SDK)/components/drivers_ext/segger_rtt/ 編譯 RTT 程式 把上面四個C file加到MCU project某個目錄,應該很容易就能編譯過。我用了GCC & KEIL-C都沒問題。 SEGGER RTT Library提供一個簡化版的printf() int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 我們在MCU寫一個簡單的程式: unsigned int buf_idx = 0; while(1) { unsigned int i; for(i=0; i<256; i++) {

假日嵌入式系統工程師:SEGGER RTT (1)

圖片
假日嵌入式系統工程師:SEGGER RTT (1) UART真的很麻煩 (Target-Side) 從我學C語言開始,我認定最好用的debug工具叫printf()。在嵌入式系統的世界,一般我們會用UART (Universal Asynchronous Receiver/Transmitter)來印出printf()。幾年下來,學的東西稍微多一點以後,我實在是越來越討厭這東西。 首先UART很慢,9600bps傳1byte大概要0.1ms。如果CPU跑在16Mhz,代表1byte需要1600 CPU cycles。 一般的UART硬體緩衝區都少得可憐( 16550 UART , 16bytes),一般embedded MCU只有4bytes這種數量級。如果用polling簡單實作的UART driver,MCU跑BLE這種應用時,根本不可能透過UART丟訊息。 另一招是UART-IRQ功能,在buffer快光的時候打中斷出來,然後再塞資料給他。這需要額外的工作去搞定這個模式。而且還需要設計一個ring buffer來當write buffer存字串。 為了要有(3)描述的 先進 功能,我們還得逐一搞定UART HW。更天怒人怨的是:這東西每顆晶片玩都還不一樣。 最後一點和UART無關,只是printf()合成字串也要花不少時間,沒準還得準備個小型的C library,不然Code size可能無法接受。 UART在PC更麻煩 1994年USB推出以後,配備COM port的電腦大概已經絕跡了15年以上了。其實也不是絕跡, 想要還是有的 。不要問我怎麼讓他會動,很麻煩的!現代流行的貨色是UART轉USB的晶片,有家叫 FTDI 的公司,或著台灣的 旺玖 也有做這種產品。2016年買得到的開發板,上面都會有這種晶片。不過這個解法還是不夠完美。 要看到開發版丟出的資訊,一般會開個叫做"TeraTerm"的程式,人類需要設定底下的參數: UART速度 COM port編號 Start bits數目 Data bits數目 End bits數目 Parity bit是否存在 這些參數真的很不直覺,開發嵌入式系統這麼多年了,每次我都會遲疑。這裡面最討厭的是COM port編號,就算是同一片板子,只要插的USB孔不一

SEGGER RTT (3)

圖片
SEGGER RTT (3) Let’s Build a Trace System In previous article articles [1][2], I’ve introduced how to use SEGGER RTT as conventional printf method. I’m not fully satisfied with this method as I mentioned in [2]. Because it had several drawbacks printf() requires SRAM to store format string, which may be a problem is SRAM size is limited printf() takes cycles to generate string It must not be trivial job to generate decimal value (%d) Since a channel (SEGGER RTT) already exists to transmit string, why not reuse the channel to transmit essential values and do string composing in PC-side. Take following code as an example: printf("idx1=%d, idx2=%d\n", idx1, idx2); In legacy method, it may require >16bytes and MCU does string formatting. In proposed method, one could only transmit essential values (12bytes) An ID code which indicates the format string ID=1 -> “idx1=%d, idx2=%d\n” Parameters idx1 idx2 The article would introduce how to implement the