KEIL 調(diào)試方法,到底該怎么使用這些方法呢?這篇文章將介紹個(gè)人的調(diào)試經(jīng)驗(yàn)。 本節(jié)分為如下幾部分內(nèi)容: 1) 虛擬串口 2) 變量使用 3) 數(shù)組輸出 4) 時(shí)間獲取 5) LOG 輸出 6) 注意事項(xiàng)(KEIL 調(diào)試的缺陷)虛擬串口首先是虛擬串口,為什么要虛擬串口,這里的虛擬串口又是什么意思? 在線仿真的時(shí)候我們根本不需要虛擬串口,因?yàn)?a target="_blank">單片機(jī)一般來(lái)說(shuō)都有串口,所以不需要虛擬的串口,但是在軟件仿真情況下又該如何呢? 有些時(shí)候我們可能沒(méi)有開(kāi)發(fā)板,但項(xiàng)目很急,需要提前做,該怎么辦?KEIL 的軟件仿真可以幫你解決大部分問(wèn)題,它可以幫你驗(yàn)證程序邏輯問(wèn)題,也能驗(yàn)證硬件配置是否正確,相當(dāng)不錯(cuò)的功能。比如你的串口配置是否有問(wèn)題,進(jìn)入仿真模式:
從上面的仿真圖你可以了解到在軟件仿真模式下,你可以正常使用 printf(),scanf()函數(shù),輸入輸出操作由串口窗口進(jìn)行,所以還是很方便的,但是需要注意的是:即使是軟件仿真,它的發(fā)送時(shí)間和你的設(shè)定波特率也是有關(guān)系的,即發(fā)送完一個(gè)字節(jié)后,必須延時(shí)后才能在串口窗口看到數(shù)據(jù),這個(gè)時(shí)間和現(xiàn)實(shí)時(shí)間可能不匹配(即 115200 不一定是 1 秒就發(fā)送 115200 個(gè) bit,可能更多,也可能更少),但道理是一樣,因?yàn)樗鼘?duì)串口的工作過(guò)程進(jìn)行了完全模擬。在這里你還可以選擇顯示方式。
這里看到我之前寫的一個(gè)注釋:
但實(shí)際測(cè)試發(fā)現(xiàn)并不會(huì)丟失最后一個(gè)字符,不知道當(dāng)時(shí)咋測(cè)試的。 繼續(xù)正題。 有一個(gè)問(wèn)題,如果說(shuō)你想把這個(gè)數(shù)據(jù)傳給其他上位機(jī)呢? 比如你想把串口數(shù)據(jù)傳輸?shù)揭粋€(gè)虛擬示波器顯示(事實(shí)上 KEIL 也能顯示波形,但是功能比較簡(jiǎn)單),又該怎么辦? 這個(gè)時(shí)候你可以虛擬一個(gè) COM 口,將串口數(shù)據(jù)綁定到 COM 中:
在命令行中輸入紅色方框中的內(nèi)容,既可達(dá)到目的。當(dāng)然你可以將其保存為.ini 文件,具體使用方法請(qǐng)看魚(yú)鷹相關(guān)筆記。 上面的命令參考鏈接: http://www.keil.com/support/man/docs/uv4cl/uv4cl_cm_assign.htm?_ga=2.225757210.1084600666.1557148734-475076243.1554469739 完成綁定后,KEIL 軟件的串口 1 數(shù)據(jù)除了會(huì)發(fā)送到 KEIL 串口窗口中(【View】【Serial Windows】),也會(huì)發(fā)送到 COM1 口中(當(dāng)然數(shù)據(jù)輸入也是從 COM1 中進(jìn)行輸入的)。 但是因?yàn)?KEIL 對(duì) COM1 進(jìn)行了綁定,也就是你的 KEIL 正在使用 COM1 口,那么其他軟件肯定是無(wú)法打開(kāi)這個(gè) COM1 口的,那么這樣又該怎么查看 COM1 的數(shù)據(jù)呢? 此時(shí)你可以使用一個(gè)軟件虛擬兩個(gè)串口,這里我用 vspd.exe 軟件虛擬 COM1 和 COM2,并且將 COM1 和 COM2 進(jìn)行了連接,這里就是說(shuō) COM1 發(fā)送的數(shù)據(jù)會(huì)被 COM2 接收,接收同理,這樣一來(lái),KEIL 中的串口數(shù)據(jù)就能發(fā)送到 COM2 中了,因?yàn)?COM2 并沒(méi)有被任何軟件所使用,所以你可以使用串口助手打開(kāi)(其他串口軟件類似)。
因?yàn)樵谶@里是虛擬的串口,所以說(shuō)你的波特率參數(shù)并沒(méi)有用處,即你的串口配置成 115200,你的上位機(jī)以 9600 接收也是可以的。 但是你會(huì)發(fā)現(xiàn),這個(gè)中文支持不如 KEIL 自帶的窗口好用,但通過(guò)將串口綁定到其他 COM 口的方法能擴(kuò)展它的串口仿真功能,還是相當(dāng)不錯(cuò)的。 事實(shí)上,KEIL 除了仿真串口,也能仿真 I2C、CAN,比如下面的:
對(duì)此感興趣的可以參考鏈接: http://www.keil.com/support/man/docs/uv4/uv4_sm_can_communication.htm變量使用在前面公布的文章中,魚(yú)鷹曾經(jīng)說(shuō)過(guò)一個(gè)詞,顛覆認(rèn)知: 打了多年的單片機(jī)調(diào)試斷點(diǎn)到底應(yīng)該怎么設(shè)置?| 顛覆認(rèn)知 也說(shuō)過(guò)一個(gè)串口通訊的問(wèn)題: KEIL 調(diào)試的 ini 文件有什么用? 通過(guò)運(yùn)用上面的知識(shí),總算是解決了項(xiàng)目串口通信的問(wèn)題,測(cè)試多天,不再出現(xiàn)這個(gè)問(wèn)題了。 那么魚(yú)鷹是如何解決的呢?且聽(tīng)魚(yú)鷹道來(lái)。 這個(gè)通信錯(cuò)誤的現(xiàn)象是,前一個(gè)數(shù)據(jù)幀尚未發(fā)送完成,后面又來(lái)一個(gè)數(shù)據(jù)幀,導(dǎo)致傳輸數(shù)據(jù)錯(cuò)亂了,這種現(xiàn)象在多任務(wù)中很常見(jiàn),所以魚(yú)鷹很早就對(duì)它進(jìn)行了研究: 信號(hào)量保護(hù)之禁止中斷 因?yàn)轸~(yú)鷹知道,資源互斥的現(xiàn)象很平常,只有深刻理解了其中的原理,你才能更好的掌握它。而這個(gè)通信過(guò)程的互斥資源有兩個(gè),第一個(gè)是發(fā)送緩存數(shù)組的資源,另一個(gè)就是串口。在這里因?yàn)闆](méi)有采用隊(duì)列的方式發(fā)送數(shù)據(jù),所以緩存數(shù)組和串口是綁定在一起的,也就是說(shuō),一旦數(shù)組中含有發(fā)送數(shù)據(jù),那么馬上就開(kāi)始進(jìn)行發(fā)送,中間不應(yīng)該斷開(kāi),所以可以把數(shù)組和串口當(dāng)成一個(gè)資源使用(特別需要注意的是,一定要在對(duì)數(shù)組賦值之前獲得互斥鎖,而不是在串口發(fā)送前獲取,因?yàn)橹灰@樣,才能保證你發(fā)出的數(shù)組數(shù)據(jù)不會(huì)被其他程序修改)。 很明顯,這個(gè)資源是互斥的,所以可以使用一個(gè)變量作為訪問(wèn)該資源的鎖,每次訪問(wèn)之前看資源是否被使用,如果被使用了就等待。而鎖的釋放是由發(fā)送完成中斷完成的,即只有將全部數(shù)據(jù)發(fā)送完成之后這把鎖才能釋放,進(jìn)而由其他任務(wù)使用。 那么如何利用上面提到的技能查找這類問(wèn)題呢? 這里的關(guān)鍵點(diǎn)還是在鎖,因?yàn)槿绻@把鎖被正確使用的話,是不應(yīng)該出現(xiàn)兩個(gè)數(shù)據(jù)幀混亂的情況的,需要對(duì)這把鎖重點(diǎn)關(guān)注,那么該如何關(guān)注呢? 就是用前面的斷點(diǎn)窗口,對(duì)這個(gè)變量(鎖)設(shè)置寫入訪問(wèn)斷點(diǎn),如下:
這里要說(shuō)明一點(diǎn),單片機(jī)所有的全局變量都是可以在命令行直接獲取數(shù)據(jù)的(事實(shí)上如果你將斷點(diǎn)設(shè)置在函數(shù)內(nèi)部,也可以獲取局部變量的值),比如你在命令行直接輸入 lock,那么結(jié)果如下:
0x00000001 就是這個(gè)全局變量 lock 的值。 回到剛才鎖的話題。在斷點(diǎn)窗口設(shè)置之后,你就會(huì)在 Command 命令窗口中得到如下消息:
正常的 lock 數(shù)據(jù)流程應(yīng)該是這樣,1~0~1~0~1……也就是上鎖、釋放鎖交替進(jìn)行的,但是魚(yú)鷹在觀察有錯(cuò)誤通信的代碼發(fā)現(xiàn),出現(xiàn)了 1~0~0 這種情況,也就是說(shuō)一次上鎖之后,出現(xiàn)了兩次釋放鎖的過(guò)程,那這是怎么回事? 魚(yú)鷹前面說(shuō)過(guò),釋放鎖的位置在串口發(fā)送完成中斷中(此處是 DMA 傳輸完成中斷),難道有其他位置對(duì)它進(jìn)行了清零操作?為了確定這個(gè)位置繼續(xù)增加調(diào)試信息(注意如果重新設(shè)置了一個(gè)新斷點(diǎn),需要把之前的斷點(diǎn)刪除):
這次將寫入時(shí)的 PC 指針打印出來(lái)(需要注意,ST-LINK 不能實(shí)時(shí)更新這個(gè) PC 數(shù)據(jù),但 CMSIS-DAP 可以,暫時(shí)未找到解決辦法),你會(huì)發(fā)現(xiàn)清零的位置是一樣的(沒(méi)有實(shí)際環(huán)境,模擬的情況):
可以看到,清零操作時(shí)的 PC 指針都是一樣的,也就是說(shuō),釋放鎖的過(guò)程確實(shí)只有一處,那么為什么會(huì)出現(xiàn)兩次釋放呢?那肯定是啟動(dòng)了兩次 DMA 傳輸,導(dǎo)致兩次進(jìn)入傳輸完成中斷,從而釋放了兩次鎖。 這里再說(shuō)一點(diǎn),怎么通過(guò) PC 指針找到對(duì)應(yīng)源代碼的位置:
之后輸入你的 PC 指針即可:
但是按理來(lái)說(shuō),如果上鎖操作正常的話,應(yīng)該不會(huì)出現(xiàn)兩次啟動(dòng) DMA 傳輸?shù)倪^(guò)程才是,所以由此可以判斷出,肯定有至少一處地方?jīng)]有上鎖而直接使用了互斥資源,才最終導(dǎo)致了異常情況。 通過(guò)對(duì)互斥資源在整個(gè)系統(tǒng)的使用情況,發(fā)現(xiàn)確實(shí)有一個(gè)地方使用了互斥資源,但是卻沒(méi)有對(duì)互斥資源上鎖(當(dāng)時(shí)由于某種原因,只對(duì)鎖是否可用進(jìn)行了判斷,但判斷完成后,并沒(méi)有對(duì)它加鎖)。當(dāng)加上了這把鎖之后,通信就此正常了(實(shí)際情況要比這個(gè)更復(fù)雜一些)。 為什么說(shuō)顛覆認(rèn)知,就是因?yàn)檎莆樟诉@個(gè)技能后,很多問(wèn)題可以迎刃而解。就比如項(xiàng)目中有一個(gè)變量莫名奇妙的變化了,通過(guò)對(duì)每一次寫入操作的監(jiān)控,發(fā)現(xiàn)了數(shù)據(jù)變化順序出現(xiàn)了問(wèn)題,不該出現(xiàn)的變化卻出現(xiàn)了,從而深入下去找到變化的原因,并最終解決了這個(gè)項(xiàng)目問(wèn)題??梢哉f(shuō)掌握了這個(gè)技能,魚(yú)鷹用它解決了很多以前難以解決的問(wèn)題,所以我才會(huì)對(duì)它推崇備至! 從前面講述的內(nèi)容可以知道,原來(lái) printf 函數(shù)不僅可以打印一些字符串,還能獲取運(yùn)行在單片機(jī)上所有的數(shù)據(jù)(包括你定義的全局變量、靜態(tài)變量、外設(shè)寄存器、CPU 寄存器),了解了這個(gè),你再也不用在你原來(lái)的代碼中添加調(diào)試代碼后再刪除了,使用這個(gè)方法有以下幾點(diǎn)好處: 1、命令行中的 printf 函數(shù)打印數(shù)據(jù)比串口打印速度更快,極大地減少了調(diào)試語(yǔ)句對(duì)原本代碼的影響。 2、再也不會(huì)忘記刪除代碼了,因?yàn)檫@些語(yǔ)句根本就沒(méi)有下載到單片機(jī)中,只要退出調(diào)試模式,就不會(huì)對(duì)程序造成任何影響。 3、只要你使用 KEIL,有一個(gè)可以設(shè)置斷點(diǎn)的調(diào)試器(不管是 ST-LINK、CMSIS-DAP、還是 J-LINK)都可以采用這種方式調(diào)試,極大的方便了開(kāi)發(fā)。 說(shuō)到程序的變量,事實(shí)上我們也可以在 KEIL 內(nèi)部定義一個(gè)變量,即使用 DEFINE 命令定義一個(gè)變量名,這個(gè)變量不存在于單片機(jī)中,而只存在 KEIL 軟件中,所以不用擔(dān)心存儲(chǔ)空間不夠的問(wèn)題,但是因?yàn)閱纹瑱C(jī)和 KEIL 共用同一套符號(hào)系統(tǒng),所以,你定義的變量名不能和單片機(jī)的全局變量名相同。至于你定義的這個(gè)變量用來(lái)干什么,那完全就是你自己的事情了。數(shù)組輸出前面的內(nèi)容說(shuō)了程序中的變量都可以通過(guò) printf 函數(shù)打印出來(lái),但在公眾號(hào)公布的文章說(shuō)過(guò),它畢竟不是標(biāo)準(zhǔn)的 C 語(yǔ)言函數(shù),所以它不支持指針,所以也不支持?jǐn)?shù)組,那么我們?cè)撊绾屋敵鰯?shù)組呢? 這個(gè)時(shí)候其實(shí)要用到公眾號(hào)公布的另一篇關(guān)于 ini 的使用問(wèn)題的文章。 看完那篇文章之后,在 ini 文件中輸入以下代碼,并編譯執(zhí)行:
然后,在你的程序中添加如下代碼:
這里的 OspreyARR 數(shù)組是我們準(zhǔn)備輸出的數(shù)據(jù),OspreyPointer 這個(gè)數(shù)據(jù)用于保存數(shù)組的地址。因?yàn)椴恢С种羔槪荒軗Q種方式來(lái)達(dá)到相同的效果了。 然后對(duì)上面的斷點(diǎn)設(shè)置如下:
事實(shí)上我們也可以設(shè)置成這樣:
這里的 0x2000 004E 就是數(shù)組的地址,但是因?yàn)槊看尉幾g之后,數(shù)組的地址可能都不一樣,所以使用一個(gè)變量 OspreyPointe 實(shí)時(shí)保存這個(gè)地址,這樣你需要顯示什么數(shù)據(jù),只要修改這個(gè)變量的值即可,不需要修改斷點(diǎn)窗口的值。
全速運(yùn)行之后,你就可以獲得如下結(jié)果:
可以看到,數(shù)組中的所有數(shù)據(jù)都打印出來(lái)了,同時(shí)將當(dāng)前打印的地址、長(zhǎng)度信息也打印出來(lái)了。 數(shù)組查看這個(gè)技能有什么好處?下位機(jī)和上位機(jī)通信是很正常的是,而通信錯(cuò)誤再正常不過(guò)了,那么怎么實(shí)時(shí)獲取通信過(guò)程的數(shù)據(jù)呢,以前靠串口 printf,現(xiàn)在靠更高級(jí)的 KEIL printf,就是這么簡(jiǎn)單,串口助手都省了。 除此之外,我們還可以對(duì)接收或者發(fā)送的數(shù)據(jù)進(jìn)行解析,方便閱讀,比如下面的是我在工作中根據(jù)自己的通信協(xié)議做的一個(gè)簡(jiǎn)單解析:
時(shí)間獲取上面介紹了獲取數(shù)據(jù)的方法,但是很多時(shí)候,我們不僅需要數(shù)據(jù)進(jìn)行分析,還需要獲取數(shù)據(jù)時(shí)間,有時(shí)候時(shí)間是很關(guān)鍵的一環(huán)。 那么該如何獲取時(shí)間呢? 以前一般使用 SysTick 獲取時(shí)間,但是當(dāng)你使用操作系統(tǒng)的時(shí)候,你會(huì)發(fā)現(xiàn)這個(gè)時(shí)鐘被操作系統(tǒng)占用了,那么怎么辦?搶嗎?肯定不行,那么只能找替代方案了,那么找誰(shuí),普通定時(shí)器?高級(jí)定時(shí)器?都不是,這里魚(yú)鷹推薦 DWT。 為什么推薦它呢? 1、很多 STM32 單片機(jī)都集成了這個(gè)模塊 2、它的精度是 CPU 運(yùn)行周期,即它是由 CPU 系統(tǒng)時(shí)鐘驅(qū)動(dòng)的,即你的內(nèi)核時(shí)鐘頻率是 72 M,那么它的頻率也是如此,所以精度很高。 當(dāng)我們使用定時(shí)器中斷的時(shí)候,如果需要看你的定時(shí)中斷是否及時(shí)處理了(如果沒(méi)有及時(shí)處理,那么兩次進(jìn)入定時(shí)中斷的時(shí)間肯定是不同的),那么使用 DWT 是不二人選,因?yàn)榧词鼓愕闹袛嘌舆t了一個(gè)指令的執(zhí)行時(shí)間,它也能發(fā)現(xiàn),因?yàn)槎噙\(yùn)行一條指令,那么 DWT 的計(jì)數(shù)器必然會(huì)增加,所以如果時(shí)間要求高的話,可以直接獲取計(jì)數(shù)器的值。 但很多時(shí)候,可能并不需要那么精準(zhǔn)的時(shí)間,而只需要大概的實(shí)際時(shí)間,而且為了方便使用,魚(yú)鷹使用相對(duì)時(shí)間(即上次和這次執(zhí)行時(shí)間之差),所以可以使用下面的這個(gè)函數(shù)(上面這個(gè)函數(shù)用于直接獲取計(jì)數(shù)器的值,0xE0001004 為 DWT 計(jì)數(shù)器的地址,事實(shí)上 DWT 使用是需要初始化配置的,但 KEIL 在進(jìn)入 Debug 模式后會(huì)自行配置,不需要你操心):
并且為了和正常時(shí)間匹配,對(duì) DWT 時(shí)間進(jìn)行了換算,單片機(jī)系統(tǒng)時(shí)間設(shè)置為 72M,所以我這里除以 72 用于換算成 us 時(shí)間,另外為了更加精確,使用了浮點(diǎn)型數(shù)據(jù)(關(guān)于為什么加 0xFFFF FFFF 請(qǐng)看公眾號(hào)相關(guān)文章,魚(yú)鷹就不在此詳述了)。 那么該怎么使用呢?我在公眾號(hào)的視頻中其實(shí)已經(jīng)展示了這個(gè)方法,現(xiàn)在詳細(xì)介紹這個(gè)方法: 首先設(shè)置一個(gè)你需要的斷點(diǎn),然后在 Command 里面輸入你的 printf()調(diào)試信息:
這樣就可以了(前提是你已經(jīng)使用 ini 文件包含了上述內(nèi)容)。 其實(shí)單純獲取時(shí)間信息是用處不大的,你還可以結(jié)合前面的變量和數(shù)組數(shù)據(jù)顯示,一起輸出到命令窗口,這樣你就能獲得這個(gè)斷點(diǎn)的執(zhí)行頻率和變量的數(shù)據(jù),但是這里需要說(shuō)明一點(diǎn)的就是,魚(yú)鷹在 KEIL V5.14 下用調(diào)試器 CMSIS-DAP 可以同時(shí)在 Watch 窗口和命令窗口中實(shí)時(shí)刷新數(shù)據(jù),但是使用 ST-LINK 時(shí)發(fā)現(xiàn)命令窗口的數(shù)據(jù)變量值是不能實(shí)時(shí)刷新,也就是說(shuō)這個(gè)變量始終是一個(gè)數(shù)據(jù),并沒(méi)有改變。但是后來(lái)在使用 V5.25 版本時(shí),CMSIS-DAP 調(diào)試下,命令窗口能刷新,Watch 窗口卻不能刷新了,所以各種情況需要道友自行分析,不能認(rèn)為數(shù)據(jù)不變就是真的不變了,很可能是軟件或調(diào)試器的問(wèn)題,但能確定的一點(diǎn)就是,當(dāng)你將程序暫停時(shí),Watch 還是會(huì)刷新數(shù)據(jù)的,這個(gè)時(shí)候的數(shù)據(jù)是可以信任的。
(關(guān)于這個(gè)還有一篇文章KEIL 下如何準(zhǔn)確測(cè)量代碼執(zhí)行時(shí)間?)LOG 輸出不知道你是否羨慕別人的上位機(jī)程序能夠?qū)崟r(shí)的打印 LOG 數(shù)據(jù),是否夢(mèng)想著自己的嵌入式程序有一天也能實(shí)現(xiàn)?事實(shí)上真的可以。 在嵌入式開(kāi)發(fā)時(shí),受單片機(jī)資源的限制,很多時(shí)候都是用串口打印數(shù)據(jù),高級(jí)一點(diǎn)的用 J-Scope 之類的工具,但是用串口有比較多限制: 1. 需要實(shí)現(xiàn)串口驅(qū)動(dòng)程序,并占用為數(shù)不多的串口資源 2. 串口速度比較慢 3. 需要一個(gè)類似串口助手的上位機(jī) 4. 數(shù)據(jù)接收后需要自己保存這些數(shù)據(jù) 5. 不能設(shè)置斷點(diǎn),調(diào)試受到很大的限制 6. 調(diào)試代碼在調(diào)試完之后得刪除,萬(wàn)一忘記了,就會(huì)影響性能 但是用了 KEIL 自帶的 LOG 打印功能,就不存在這些問(wèn)題,它的輸出速度就是調(diào)試器的速度,調(diào)試器多快,你的打印就有多塊(但是打印數(shù)據(jù)也別太多,需要針對(duì)性的打印,后面會(huì)說(shuō)原因),而調(diào)試器速度一般都是 M 級(jí)別的,對(duì)于一般情況完全夠用了。 現(xiàn)在看怎么使用,使用的話,其實(shí)很簡(jiǎn)單,就是幾條指令的事情,在你的 ini 文件最后輸入以下命令:
這樣從這條命令以下的所有內(nèi)容都會(huì)保存在 DEBUG_LOG_OUT.txt 中(所以如果你不想把 ini 文件的其他內(nèi)容保存在 LOG 中的話,那么就把這條命令放在 ini 文件最后即可)。 現(xiàn)在解釋一下這幾條命令,LOG OFF 表示將 LOG 文件關(guān)閉,即使你沒(méi)有打開(kāi)一個(gè) LOG 文件,執(zhí)行該命令也不會(huì)出錯(cuò),這條命令主要是防止一個(gè) LOG 文件重復(fù)打開(kāi)的錯(cuò)誤,加上這條命令就不會(huì)了。 第二條命令,即將 Command 窗口的數(shù)據(jù)保存在 DEBUG_LOG_OUT.txt 中,注意這里有個(gè) > ,而 DEBUG_LOG_OUT 這個(gè)文件名就隨你意了,但是實(shí)驗(yàn)的時(shí)候按這個(gè)來(lái),等你確定會(huì)了之后就可以隨便取你喜歡的名字了,出了問(wèn)題自己對(duì)比一下就知道了。
然后再說(shuō)一點(diǎn),這里使用的是相對(duì)路徑,即你的工程文件下的路徑,如果你想往上一層,你可以使用 ../ 表示在這個(gè)工程上的一個(gè)文件夾下輸出 LOG 文件。 當(dāng)退出調(diào)試模式之后,KEIL 將自動(dòng)保存 Command 數(shù)據(jù)到文件中(也就是說(shuō)在此之前你是看不到這些調(diào)試數(shù)據(jù)的),現(xiàn)在看看我的調(diào)試 LOG:
一次設(shè)定之后,LOG 打印就不需要你操心了,即使調(diào)試器通信錯(cuò)誤,它也會(huì)把之前輸出的數(shù)據(jù)保存下來(lái)的。 看到這里,你應(yīng)該知道 ini 文件到底有多重要了吧,你的所有調(diào)試命令都可以用它保存并在進(jìn)入調(diào)試模式后自動(dòng)執(zhí)行,比如說(shuō)你有一個(gè)斷點(diǎn),很復(fù)雜,不想每次設(shè)置,那么你可以在設(shè)置完一次后,從命令窗口將這個(gè)命令復(fù)制到 ini 文件中,比如像這樣:
這樣你每次進(jìn)入調(diào)試模式后,那些斷點(diǎn)就會(huì)被自動(dòng)設(shè)置了,根本不用你操心,而且如果需要修改的話,也是直接在編輯器中修改后重新編譯就行,馬上就能生效,不再需要從斷點(diǎn)窗口設(shè)置了。 而這里有個(gè)刪除所有斷點(diǎn)的命令,這是為了防止和之前設(shè)置的斷點(diǎn)沖突,所以一次性全部刪除了(事實(shí)上,可以刪除某一個(gè)斷點(diǎn),但需要斷點(diǎn)序號(hào),而斷點(diǎn)序號(hào)每一次都可能不一樣,所以選擇直接全部刪了方便)。而為了更好的配合這些功能,可以把下面的 Breakpoints 勾選去掉,這樣它就不會(huì)保存關(guān)于斷點(diǎn)的設(shè)置了,而為了讓 Toolbox 在關(guān)閉后還能每次自動(dòng)顯示出來(lái),也可以去掉 Toolbox 的勾選。
另外再說(shuō)一點(diǎn),KEIL 支持把某一塊內(nèi)存數(shù)據(jù)保存成文件,這個(gè)命令是 SAVE,感興趣的話可以去官網(wǎng)了解一下。注意事項(xiàng)上面說(shuō)了 KEIL 命令調(diào)試的很多優(yōu)點(diǎn),現(xiàn)在說(shuō)說(shuō)它的缺點(diǎn): 1、KEIL 命令調(diào)試不支持指針,這個(gè)已經(jīng)多次強(qiáng)調(diào)了,要實(shí)現(xiàn)指針的功能,只能間接使用。 2、對(duì)程序運(yùn)行造成一定的影響(事實(shí)上這個(gè)不關(guān) KEIL 的事,是調(diào)試系統(tǒng)本身的問(wèn)題) 前面說(shuō)過(guò),調(diào)試器可以說(shuō)是第三方監(jiān)視器,雖然幾乎沒(méi)有侵入性(事實(shí)上對(duì) CPU 還是有影響的),但是它還是會(huì)竊取 CPU 時(shí)鐘的,而且在執(zhí)行斷點(diǎn)的時(shí)候,雖然由 ini 文件定義的函數(shù)由 KEIL 執(zhí)行了,實(shí)際上上執(zhí)行這些函數(shù)也是需要時(shí)間的,那這個(gè)時(shí)間怎么來(lái),就是通過(guò)暫停 CPU 后去執(zhí)行這些代碼,這個(gè)你可以通過(guò) DWT 計(jì)數(shù)器看出來(lái),因?yàn)橹挥?CPU 執(zhí)行了 DWT 才會(huì)計(jì)數(shù),但是你會(huì)發(fā)現(xiàn)在執(zhí)行這些代碼時(shí),DWT 是沒(méi)有進(jìn)行計(jì)數(shù)的(在 KEIL 函數(shù)的前后獲取 DWT 計(jì)數(shù),可以發(fā)現(xiàn)計(jì)數(shù)值不變):
也就是說(shuō) CPU 和 KEI 是在交替使用系統(tǒng)時(shí)鐘的。平常來(lái)看,由于 KEIL 執(zhí)行速度很快,看不出來(lái)問(wèn)題,但到中斷的時(shí)候卻會(huì)出現(xiàn)問(wèn)題。 情況是這樣的,驅(qū)動(dòng)步進(jìn)電機(jī)時(shí),魚(yú)鷹使用了這種調(diào)試方法打印每次進(jìn)入定時(shí)器中斷的時(shí)間,發(fā)現(xiàn)即使使用最高精度的情況下(CPU 運(yùn)行時(shí)鐘),每次進(jìn)入中斷的時(shí)間看似都是固定的,但步進(jìn)電機(jī)還是表現(xiàn)出失步情況,也就是說(shuō)系統(tǒng)內(nèi)部時(shí)間看起來(lái)每次進(jìn)入中斷時(shí)間一樣,但是實(shí)際情況是,已經(jīng)丟失了時(shí)間(好好理解這句話),這個(gè)時(shí)間損耗就在運(yùn)行這些命令上,而一旦把這些命令輸出刪去,就會(huì)發(fā)現(xiàn)電機(jī)不再出現(xiàn)失步了。 這是一個(gè)比較大的缺陷,但是在一般情況下是不會(huì)有多大問(wèn)題的,因?yàn)橐话闱闆r下竊取一點(diǎn) CPU 時(shí)間也不會(huì)對(duì)整個(gè)系統(tǒng)有太大影響,前提是你別竊取太多了。
-
keil
+關(guān)注
關(guān)注
68文章
1212瀏覽量
166705 -
虛擬串口
+關(guān)注
關(guān)注
3文章
62瀏覽量
13866
原文標(biāo)題:KEIL 調(diào)試經(jīng)驗(yàn)總結(jié)
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論