Language

Tuesday, November 6, 2012

如何用星座圖偵錯數位通訊系統

人類天生就是視覺與聽覺的動物, 而抽象思考能力是比較晚才發展起來的, 因此不同工程的偵錯技巧都類似, 最好使用視覺或聽覺來輔助, 才能做最有效率的偵錯。上次講「在 SoC debug 的藝術」時筆者並沒有提到這個非常重要的偵錯技巧: 視覺化! 通訊系統偵錯如果用視覺化來輔助, 可以大幅提升工作效率, 我們今天就來談談通訊系統視覺化偵錯技巧。1

首先來看什麼是星座圖。天文學上的星座圖是一組一組的星星合起來看的, 在通訊系統裡面, 星座圖就是在頻域上看解調出來的 symbol 值, 繪製在一個平面上, 將所有出現的 symbol 值同時繪製在上面的時候, 看起來就像是天文學上的星座圖, 所以就有了這個名字。不過我們並沒有把一個點稱之為星星。:-)

為什麼我們能夠把真實傳輸的訊號看作是星座圖上的一點?這牽涉到 signal space 的證明, 在這裡我們就不詳細證明了, 有興趣的可以翻閱數位通訊系統的書, 有兩本數位通訊對於 signal space 有比較詳細的證明。2

筆者打從一開始從事通訊產業就開始使用星座圖來偵錯通訊系統, 深深的為這樣的偵錯技巧著迷, 最近看到一本書3有詳盡的介紹這個偵錯技巧, 接下來我們就來看在星座圖上能夠看到通訊系統什麼樣的問題。全部的圖例都是以 16 QAM 為例子。

Carrier Recovery Loop Phase Offset

From Constellations
上圖可以看到 16 QAM 的星座點以原點為圓心, 逆時針旋轉了 8 度, 是由於 carrier recovery loop 裡面殘留的相位差所致。

Carrier Recovery Loop Unlocked

From Constellations

上圖可以看到 16 QAM 的星座點隨著時間旋轉, 這是由於 carrier recovery loop 完全沒有鎖到對方發射器的相位。通常脫鎖的話, 旋轉方向是一樣的, 也就是說你的鎖相迴路頻率比對方發射機快或是慢, 如果是一下往順時針, 然後很快就往逆時針(或是相反情況), 而且一去不回頭, 那也是脫鎖, 這有可能是一開始雙方頻率差異過大, 超過鎖相迴路能夠處理的頻寬。

Poor Phase Noise

From Constellations
上圖可以看到星座點以原點為圓心, 以正負平均 3 度的差異旋轉, 這是由於鎖相迴路的相位雜訊過大而來。正負平均(rms) 三度就可以在星座點造成這樣明顯的軌跡了。

Coherent Carrier Interference(同步載波干擾)

From Constellations
上圖是 16 QAM 的星座點受到跟接收機同步的另一個載波干擾所產生的, 受到干擾的點圍繞著理想的星座點旋轉。同步載波干擾會導致錯誤率的增加, 因為相鄰兩個星座點的距離被縮小了。

Multipath

From Constellations
上圖可以看到在多重路徑干擾下的 16 QAM 星座點。多重路徑干擾是由於對方發射機的訊號被衰減並延遲, 而接收機收到兩組或兩組以上的訊號所致。解調器會收到並且鎖住比較大的訊號, 但是在星座點上會顯示另一組衰減的星座點。在每一個理想的星座點上都可以看到完整的縮小版 16 QAM 星座點, 由於延遲的關係旋轉某一個角度。上圖的多重路徑訊號是原來訊號傳輸功率的十分之一。

IQ Phase Imbalance(IQ 相位不平衡)

From Constellations
IQ 相位不平衡(IQ Phase Imbalance) 是由於調變器或解調器的功能出問題, 當訊號區分 I 跟 Q 頻道的時候, 兩組線路的相位差異不是正好 90 度。上圖的 IQ 頻道相位差為 10 度。

IQ Amplitude Imbalance(IQ 振幅不平衡)

From Constellations
IQ 振幅不平衡(IQ Amplitude Imbalance) 也是調變器或解調器線路問題, 當訊號區分 I 與 Q 頻道後, 兩者的增益不一樣, 就會導致 IQ 振幅不平衡。

Gain Compression(增益壓縮)

From Constellations
外圈星座點相對於內圈有比較高的瞬時功率, 如果系統上有增益壓縮的問題, 外圈的星座點會被拉往內圈, 而內圈的星座點會被稍稍從理想星座點位置拉離圓心。

這個問題也會導致解調的錯誤率增加, 因為星座點之間的距離縮短了。

Improper Amounts of Gain

From Constellations
上圖所顯示的是增益太大, 使得 16 QAM 星座點往外長。

From Constellations
上圖所顯示的是增益太小, 使得 16 QAM 星座點往內縮。

Amplitude Variation beyond Automatic Gain Control Bandwidth

From Constellations
上圖可以看出來, 每一個星座點都有振幅變化, 這是由於接收機的自動增益控制趕不上訊號的振幅變化, 無法將振幅變化消除。上圖的星座點都是沿著圓心作直線變化, 表示接收機的鎖相迴路鎖得很精準。

結語

今天介紹了如何用視覺化的方式, 透過對星座點的觀察, 偵錯數位通訊系統, 這是筆者一直以來覺得非常有效率與威力的偵錯方式。在這篇文章中介紹了通訊系統會在星座點出現的現象, 但平面的文章沒辦法表現的是人類對於視覺的快速反應, 在面對 symbol rate 很快的系統, 仍然能夠很快速的反應, 讓我們很容易能夠抓出也許只有一兩個 symbol 的瞬間錯誤。在很多數位通訊儀器上面, 也都內建這種偵錯的方式, 可以好好利用。

Footnotes:

1 除了視覺化偵錯之外, 如果許可的話也可以利用聽覺, 比如說在偵錯語音頻帶數據機、業餘無線電數據機的時候, 因為頻寬在聲音頻寬內(小於 20 kHz), 所以很適合用聲音來偵錯。這樣你就知道為什麼以前的電話撥接數據機在剛開始連線的時候會開啟喇叭讓你聽到一連串的高低音了吧。

2 Wozencraft, John M., and Jacobs, Irwin Mark, "Principles of Communication Engineering," John Wiley & Sons, 1965.

Gallager, Robert G., "Principles of Digital Communication," Cambridge University Press, 2008. 可以由 http://goo.gl/glkdQ 下載。

3 McClaning, Kevin, "Wireless Receiver Design for Digital Communications, " 2/ed, SciTech Publishing Inc., 2012.


--

阿姆斯壯之死

第一個登陸月球的那個阿姆斯壯(全名是 Neil Armstrong) 逝世於 2012 年 8 月 25 日。他的身軀是死了, 但是他的精神(spirit) 卻永遠與我們同在, 我們永遠會記得他登陸月球時講過的話:「這是一個人的一小步,卻是全人類的一大步」。而另一個阿姆斯壯, Lance Armstrong, 在單車環法賽奪得了七次冠軍的那個阿姆斯壯, 他還活著。

一個單車選手要能夠奪得單車環法賽冠軍就已經很不容易了, 而 Lance Armstrong 不但奪得七次單車環法賽冠軍, 而且還是在他罹患癌症並且痊癒之後奪得, 這樣的故事可以激勵多少人心, 鼓勵多少人向上, 也因此, 他出了一本書, 書名是 "It's Not About The Bike: My Journey Back To Life" 多年前我開始騎單車的時候, 買了一本。

運動選手之所以常常是被人們所崇敬的對象, 正是因為他們秉持運動家精神, 即便目標是多麼艱難, 從不輕言放棄, 也不用不公平的方式贏得比賽。筆者還記得有一年環法賽, Lance Armstrong 長年的冠軍競爭對手, 來自德國的 Jan Ulrich 被撞倒在地上, Lance Armstrong 並沒有利用這個機會趕緊大幅超前, 而是在 Ulrich 的附近等待他再度上路之後, 才一起出發。這一幕被多少媒體與網路文章傳頌, 至今仍讓人津津樂道。這正是運動家精神表現的極致: 堅持與對手公平競爭。

Lance Armstrong 曾經罹患癌症, 但他並未放棄他熱愛的單車運動, 反而在痊癒後, 不放棄自己的訓練計畫, 也不管癌症治療後身體是多麼的虛弱, 他還是堅持奮戰不懈, 積極的訓練, 終能在 2005 年獲得第七次環法賽冠軍, 並且宣布退休。這也是運動家永遠不放棄的精神。

因為上述兩項運動家精神極致的表現, Lance Armstrong 是現任的 Apple 執行長 Tim Cook 常常掛在嘴邊的效法對象, 如果時光就停留在 2005 年的話, 一切看起來是那麼的完美: Lance Armstrong, 一個罹患癌症之後仍然奮戰不懈的鬥士, 一個贏得七次單車環法賽冠軍的英雄, 一個堅持與對手公平競爭的謙謙君子, 他的運動家精神放眼當今這個世界, 沒有幾個人能夠與他匹敵。

今年七月美國反禁藥協會(United States Anti-Doping Agency, or USADA) 以 2009 至 2010 年的血液樣本以及 Lance Armstrong 在美國郵政車隊的前隊友的證詞, 指控 Lance Armstrong 使用禁藥以提升運動表現, 並要求撤銷其七次單車環法賽的冠軍頭銜。而 Lance Armstrong 在八月底正式放棄任何上訴, 也意味著他默認了他使用禁藥的指控。

此刻, Lance Armstrong 的書很諷刺的躺在我的書架上, 還沒有機會被我閱讀, 就已經充滿了汙穢。登陸月球的阿姆斯壯, 身軀是死了, 精神卻與我們同在; 而單車英雄阿姆斯壯, 還非常健康, 精神卻已經死了。


--

Sunday, November 4, 2012

台鐵老舊車廂警報器

週日要從新竹到台北, 一時興起改搭台鐵莒光號, 當天旅客人數不少, 座位坐滿之餘走道仍有一些旅客站立。車行至楊梅一帶, 突然第七車廂廁所有人誤觸警報器, 一時間鈴聲大作, 許久都沒有人來關掉警報器, 至少十分鐘之後, 車廂有一名旅客及筆者在互相不知道的情況下先後依照警報器旁邊的告示指示, 走去第一車的車長室通知車長來處理, 在旅客人數不少的情況下, 筆者從七車走到三車時便遇到迎面而來已經被通知的列車長。列車長表示由於是老舊車廂, 警報器沒有辦法連線到車長室, 只能由旅客主動通知列車長來處理。這要是真有緊急事件, 這麼一來一回, 恐怕會失掉處理機會吧?再者, 只要車廂門關起來, 相鄰的車廂是聽不到警報器聲音的, 真的發生事情而該車廂又剛好沒有其他人, 那麼恐怕會產生莫大的遺憾。

台鐵目前積極購置全新車組淘汰舊有車廂, 但是以目前淘汰的速度來看, 舊有車廂恐怕要再用上好幾年, 在這些老舊車廂淘汰之前, 難道就只能放任這種規劃不良的警報系統繼續使用嗎? 筆者在接下來的旅程便發揮了工程師愛解決問題的毛病, 開始思考這個問題。筆者認為其實可以用低廉的價格便可以將這些警報器全部升級成為可以通報車長室的現代化連線警報器。

空話不多說, 來發想解決方案吧。

首先就是如何連線? 根據列車長所言, 看來是牽電纜有窒礙難行之處, 那麼想當然爾, 就來用無線的方式吧!但是無線的方式如何是成本最低廉的呢?台鐵列車之間的無線電通訊早已進入全面數位化的時代, 使用的是 TETRA 的數位中繼無線電系統, 原有的類比式(應該是 FM 調頻式無線電)的機器以及頻率都沒有在使用。筆者想到的其實就是使用這些頻率, 用 AFSK 1200bps1 的傳輸方式, 每一節車廂廁所警報器都配上一台 modem, 或是我們一般稱之為 TNC(Terminal Node Controller) 的無線電數據機, 每一節車廂都配上一台。當警報器響的時候, 就開始每隔一段時間傳送一個封包, 裡面包含了列車號碼、車廂號碼與警報器的型態(也許將來要擴充傳送其他訊息)等資訊, 業餘無線電裡有一個通訊協定是 AX.25, 這個通訊協定會把 TNC 收到的封包, 再廣播出去, 當然會用某種機制避免封包氾濫。如此, 每一個車廂的數據機都會幫上一個車廂的數據機的封包傳送出去, 讓下一個車廂的數據機收到, 如此層層轉送, 很快就可以送到列車長室。這樣的系統成本非常低廉, 甚至有可能利用原有以淘汰的無線電對講設備來使用, 在這些車廂淘汰之前, 至少讓旅客覺得台鐵有可靠且安全的服務。

Footnotes:

1 AFSK 是一種用兩種頻率的聲音來代表 0 與 1 的調變方式, 只要用接上對講機使用聲音發射即可, 構造簡單成本極低, 在 VHF/UHF 可以達到 1200 bps 以上的速度。


--

Friday, November 2, 2012

在 SoC debug 的藝術

今天要談一下, 在 SoC(System-on-Chip) debug 的藝術, 首先我先界定一下何謂 SoC, Wikipedia 對於 "System on a chip" 的解釋是 "A system on a chip or system on chip (SoC or SOC) is an integrated circuit (IC) that integrates all components of a computer or other electronic system into a single chip." 對於在 SoC 上面寫程式與 debug, 我認為最大的特點是:

  • 任何地方都有可能會錯

讀者可能會想, 我在任何地方寫程式的特性也是這樣啊, 但是 SoC 還有一個很致命的缺點, 即便是處理器已經驗證過, 都仍然有可能會發生指令集的錯誤, 尤其是組合語言程式設計師每個人的寫法都不一樣, 很有可能會踩到之前沒有驗證過的指令集組合而發生錯誤!

是的, 在 SoC 上寫程式, 驗證工具不管做得再好, 都只是減少錯誤發生的機率而已, 實際上遇到的問題, 還是要有這樣的心態來面對會比較正確。因為在一般的情況下, 我們會把 CPU/DSP 當做已經驗證沒有問題來寫程式, 但是在 SoC 上面, CPU/DSP 非常有可能會因為在新的設計上, 某個或某些組合的 CPU/DSP instruction 在某一級 pipeline 發生問題, 而導致錯誤的結果。即便是大廠如 AMD, 經過了很多的驗證程序之後, 還是有可能出現問題, 如: AMD processor incorrectly updates the stack pointer

在這樣的 SoC 上面寫程式與 debug, 需要有一些藝術與技巧, 筆者就來分享一下我的經驗。筆者分享的是筆者在通訊 SoC 晶片上發展的經驗, 但我想很多部分都可以類推到其他系統晶片上。一般說來, 在這樣的 SoC 上面會出現的錯誤來源有幾個:

  • 自己的程式
  • CPU/DSP instruction 的邏輯錯誤
  • CPU/DSP instruction 的時序錯誤
  • IC 硬體區塊的錯誤
  • IC 內部 Bus 傳輸錯誤
  • IC 與 IC 之間外部 Bus 傳輸錯誤
  • 別家晶片上對於通訊訊號或協定上的錯誤

由於通訊基頻系統大部分都含有一顆或多顆 DSP 負責基頻訊號處理, 所以 DSP programmer 常常身負驗證各個 functional block 的責任, 或是在使用的過程中由奇特的現象來發現驗證團隊之前沒有發現到的錯誤。不管錯誤來源有多少, 解錯誤的首要, 就是先把整個系統以及演算法的原理搞清楚, 清楚之後, 就要依據錯誤出現的現象, 猜測問題出現的點, 然後設計實驗來確認錯誤發生的地方。猜測問題發生的點, 依靠的是對於這個系統的直覺, 而這個直覺是透過你對系統的了解與經驗累積而來的。另外, 就是需要重建錯誤發生時所發生的事情。如果有 simulator 可以使用, 那麼常常在 simulator 上就可以觀察到錯誤的前後發生的事情, 但是像是通訊訊號或協定上的錯誤, 則常常需要有時序上的事件紀錄來重建錯誤發生當時的原貌, 或是有時候沒有現成的分析工具, 就要自己寫一些程式來記錄與觀察變數的變化與事件的流程; 而選擇觀察的物件, 也反映了你對於系統的了解程度。

第一個就是要確定自己的程式沒有問題, 程式可能出錯的來源有兩種: 一種是程式設計師自己寫錯, 另一個是 CPU/DSP instructions 出錯導致程式有錯。前者有很多的程式設計相關書籍都有提到如何避免, 以筆者的經驗, 在寫任何 DSP 程式, 特別是組合語言之前, 一定要先想好怎麼測試自己所寫的程式, 以及怎麼樣算是測試成功及失敗。這部分的觀念, 筆者後來發現軟體業界早已經講了很多, 讀者有興趣的話可以參考 TDD(Test Driven Development) 的觀念。TDD 的導入也能夠幫助我們找到第二、三個 CPU/DSP 指令集上的錯誤。

程式出錯另一個來源就是 CPU/DSP 指令集上的錯誤, 可以略分成兩種: 一種是指令集邏輯上的錯誤, 另一種是指令集時序上的錯誤。一般來說如果 CPU/DSP 有 test pattern 的話, 前者邏輯上的錯誤應該都已經抓完, 剩下的時序上的錯誤, 也就是指令前後組合的問題, 由於樣本數太大, 一般都只能隨機測試, 所以後者時序上的錯誤是 DSP programmer 比較容易遇到的地雷。如果 DSP programmer 是用組合語言撰寫程式, 而不是 C 語言, 那麼踩到地雷的機會更大。如果有編譯器的話, 通常編譯器就可以當作是一個測試的程式, 可以抓到某些編譯器 codegen 愛用的組合語言時序組合的 bug, 但是組合語言程式設計師每個人愛用的組合語言寫法都不同, 就很容易在某個人的寫法上就踩到地雷。而時序上的錯誤其實也是比較難抓的問題, 通常只能依靠 DSP programmer 在使用上的時候, 發現某些奇特的現象, 把搜尋範圍縮小之後才能夠找到。上一節講的 TDD 就能夠幫助 programmer 找到那些奇特的現象在哪裡。另外, 一般來說, 通訊 SoC 的計畫時程短則三年, 長則五年以上, 要求把整本 DSP 架構讀得滾瓜爛熟不也是很合理的嗎? 對於 CPU/DSP 架構的熟悉程度, 也會幫助你可以很快的找到指令時序上的錯誤。

前三項都確定沒問題之後, 接下來要排除的錯誤才是困難的開始, 在此, 筆者建議大家一定要維持寫實驗記錄或是工作記錄的習慣, 筆者常常遇到一解就是一兩週的 bug, 常常解到後來需要與一兩週之前的結果一起比較才能判斷錯誤在哪裡, 因此工作記錄非常重要, 而且有了工作記錄之後, 每天回家才不會心裡一直掛念這件事。要排除這邊的錯誤, 通常是已經有一個錯誤發生了, 這個錯誤也許要做很多次才能重複, 但是一定要確定如何能夠重複這個錯誤, 這點很重要, 因為接下來你會需要一直讓這個錯誤發生才能夠 debug. 讓錯誤發生是一個「點」, 要找出錯誤發生真正的原因(root cause), 常常需要其他的「點」, 讓你連成數條線才能夠把搜尋範圍變小找到真正發生的原因。

找 root cause 的過程, 我個人覺得就像是 binary search 一樣, 不斷的找一個點做判斷, 決定要往左跑, 還是往右跑。當然, 有的時候還是會判斷錯誤, 跑錯方向, 所以就要回溯到當初的切割點, 知道當時的實驗資料是什麼, 為什麼做這樣的判斷, 才能對整個問題有更全面性的了解。這時候仰賴的還是當初的實驗記錄, 所以實驗記錄很重要吧!

除了解單一錯誤以外, 有的時候會需要解多重錯誤。筆者碰觸到的大部分是通訊或訊號處理的問題, 穩定度很重要, 多重錯誤常常會表現在穩定度上, 所以我們常常要記錄錯誤率, 才能知道自己是否已經解完所有的錯誤, 或是剛剛解掉的那個錯誤是否佔的比例最大。另外, 我覺得在這樣的系統上 debug, 還要「大膽的假設,小心的求證」, 有的時候, 我們需要處理的是通訊 physical layer 或是 protocol layer 的問題, 需要猜測對方怎麼做, 這時候就需要大膽的假設, 然後小心的求證。有的時候, 錯誤的可能是另一家公司的晶片, 因此「大膽的假設,小心的求證」是必要的。在這個情況下, 考驗的就是你對整個通訊系統以及原理的掌握程度了。另外, 晶片內部的錯誤, 也是需要「大膽的假設,小心的求證」, 因為這時候, 能夠觀察的工具變少了, 有時候需要猜測。還有, 對已知事物的掌握程度, 也會影響到猜測的精準度, 比如說各個硬體的規格, 使用到的演算法的原理, 通訊 physical layer or protocl layer 的原理, 通訊系統的規格, CPU/DSP instruction set, 等等, 都能夠提昇猜測的效率。對已知事物掌握程度高, 才能夠專心的面對未知的事物。

在此, 筆者試圖將我的經驗整理成幾點原則:

  • 先想清楚 test plan
  • 熟悉 CPU/DSP 架構
  • 熟悉待測物的功能、規格、演算法
  • 確保知道如何重複產生 bug
  • 知道 bug 發生點之後, 嘗試往前一級測試問題
  • 紀錄所有測試數據以及判斷的依據, 以便回頭仔細檢視

身為一個使用組合語言的通訊 DSP 程式設計師, 除了通訊演算法以外, debug 大概就佔掉絕大多數的時間, 真正寫 code 反而是這些工作裡面佔比例最少的。因此, debug 的效率與正確性, 對於程式甚至是晶片的品質, 有著決定性的影響。每個人都有每個人的方法, 筆者在這一篇文章裡, 試圖分享我個人的方法與經驗, 希望能對即將跨入或剛剛跨入這一個領域的工程師有點幫助, 而在這個領域很有經驗的工程師也歡迎大家一起交流心得。


--