PSoC Creator Debug

1.目的

在撰寫單晶片程式的時候假使專案龐大時(上千行、甚至更大時),C語言是一種具有結構性的程式語言,除了透過結構性的程式語言使其較容易管理外,變數的管理也顯得格外重要。

在C語言中,我們可以透過Scope(視域、可視範圍)來管理變數,但在複雜專案中,經常性的會使用到pointer(指標)的功能,當在程式中使用指標時,可以增加程式運作的效率,降低程式複雜度等優點,但也因為指標具有一定的便利性,使得水能載舟亦能覆舟,往往因為指標的操作錯誤會使得在程式除錯上的難度更為增加。

除了指標以外,必須注意當使用陣列操作時,當索引溢位的時候,也會產生不可預期的錯誤結果,陣列可以想像成是一個穿了衣服後的指標,所以破壞力也是不容小覷的。

每個程式開發軟體(IDE)都會提供相當的除錯工具,不外乎變數監看,單步執行等功能,而只要能夠多加利用這些功能,便可提高程式除錯的效率。此篇針對PSoC Creator中樣除錯好用的功能作為介紹,相信其他工具軟體也一定有這樣的功能。

2.錯誤的種類

微控制器程式的錯誤種類可以歸納出以下三種可能

a.由語法引發的錯誤

通常指的就是程式設計師本身的語法使用錯誤,例如少個括號")"或者少了分號";"等這類的語意錯誤,這通常是很容易發現的,現在IDE開發軟體通常會在背景不停的檢查語法錯誤,當發現語法錯誤的時候,則會即時的反應出來。

20150827-1

b.由邏輯引發的錯誤

邏輯錯誤通常是指程式設計師對於邏輯的設計上出現瑕疵,使得結果不如預期,而邏輯錯誤也有可能是與語法的使用錯誤有關係,通常重新檢查過程邏輯都可以將問題排除。

20150827-2

c.由記憶體操作而引發的錯誤

由記憶體操作引發的錯誤通常就是在程式中使用了具有記憶體操作功能的語法,例如陣列、指標等功能,就有機會造成此種錯誤,通常症狀是不定期的可能會出現程式當機(異常失控,大陸地區有所謂跑飛的說法)、短暫性的異常(例如指示燈閃了一下或畫面抖動一下等任何可能的情況),通常由記憶體產生問題的錯誤比較難解決,原因是程式設計師可能會在多處使用指標操作,而指標操作在C語言中是一種合法的工具,然而對於記憶體的保護就並沒有辦法很嚴謹,所以通常只要編譯成功後,就可執行,但是對於微控制器來說,他只是忠實的反映了程式碼的執行動作,並無法判斷所操作的記憶體是否正確。

通常由記憶體錯誤引發的問題,就在於操作記憶體時沒有明確的檢查邏輯,例如指標中的操錯地址錯誤,變更到不再預期中應該被變更的對象,也有可能是使用陣列時,錯誤的陣列索引值,導致變更到其他位址的記憶體,都會產生嚴重的錯誤。

不管任何程式語言,其工作時都與記憶體有關,不管任何的變數都是存放在記憶體當中,所以透過記憶體除錯是必要的技巧,更尤其當由指標變數、陣列變數所引起的錯誤時,更需要透過記憶體上的監視才能夠更快的找出錯誤。

3.PSoC Creator Debug介面

PSoC Creator Debug介面提供常見單的執行控制、變數監看視窗、Call stack(呼叫堆疊)、中斷點管理等功能。

20150827-3

a.流程控制

用於控制程式運行的控制按鈕

b.特殊暫存器監看視窗

可檢視微控制器內部特殊暫存器之數值

c.特定變數監看視窗

可直接指定欲監看的變數,通常可用來監看全域變數。

d.區域變數監看視窗

於中斷點內,所在的程式區段中內的所有變數會呈列於此(區域變數)

e.記憶體監看視窗

微控制器內所有記憶體均在此視窗內,可以說是記憶體的最原始樣貌。

f.Call Stack監看視窗

C語言中每呼叫一個副程式就會產生一次堆疊,而這個堆疊的過程,就會呈列在Call Stack視窗中,可用於追溯程式執行時的前後關係。

g.中斷點管理視窗

可用於管理目前所有的中斷點位置、觸發條件等。

4.Debug技巧

PSoC Creator要進行Debug的話必須有實際的硬體存在,並無法使用模擬的方式進行,此乃一大遺憾(我實在很懷念MPLAB Sim的功能)。

為什麼要Debug?一定就是程式執行的結果不如預期,而我們要如何進行Debug?就是必須在程式執行過程中,找出錯誤的地方,通常我們可以循著邏輯,找到錯誤,我們可以使用中斷點控制,使程式跑到特定的位置,檢視相關的變數(透過變數監看視窗),來檢查變數內容是否符合預期的結果,當不符合時,則必須查看是否因為語法、邏輯錯誤造成變數內容不正確。

PSoC Creator Debug設定中斷點的方式有很多種,如下:

a.設定執行到特定行數時中斷

只要在Source code的編輯視窗內在行號的旁邊點一下就可以設定中斷點,當Debug模式下運行到該行號的時候,就會進入Debug中斷,此時CPU工作將會暫停執行。

20150827-4

b.針對變數操作而產生中斷點

我們可以針對特定的變數設定中斷點,可以指定該變數讀取、寫入、或存取時進入中斷。

20150827-5

這個功能相當好用,尤其是針對全域變數的除錯時,可以採用這種條件式的中斷。

c.針對記憶體位址操作時而產生中斷點

與變數操作不同,此處是針對記憶體位址產生了操作行為,可設定讀取、寫入或存取時而產生中斷。

20150827-6

與變數中斷不同的是,使用記憶體設定條件的時候,只要針對該記憶體有操作行為時,就可產生中斷,例如當使用指標操作的時候,所處理的對象是地址而不是變數,所以當由記憶體引發的錯誤時,就必須透過監視記憶體內容而來除錯。

例如:

當程式某處有個變數宣告為 static uint8 cnt; 其位址在 0x0000112處

如果使用變數監看設定該變數寫入時產生中斷則下面敘述句會引起中斷停止:

cnt += 10;

但是由記憶體位址改變的時候,則不會產生,例如:

uint8 *ptr;

ptr = 0x0000112;

*ptr = 0xAA;

此處透過變數設定中斷條件時並不會觸發,必須透過直接設定記憶體中斷條件時才會觸發。

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料