久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 入門指導 > 閑聊學習嵌入式編程的(de)復雜性

閑聊(liao)學習嵌入式編程的復雜性(xing) 時間:2016-05-04      來源:未(wei)知

能從(cong)PC機器編(bian)程(cheng)去(qu)看嵌(qian)(qian)(qian)入(ru)(ru)式問(wen)題, 那是(shi)第一(yi)(yi)(yi)步(bu);學(xue)會用(yong)嵌(qian)(qian)(qian)入(ru)(ru)式編(bian)程(cheng)思想(xiang),那是(shi)第二步(bu);用(yong)PC的(de)(de)(de)(de)(de)思想(xiang)和(he)嵌(qian)(qian)(qian)入(ru)(ru)式的(de)(de)(de)(de)(de)思想(xiang)結合在(zai)一(yi)(yi)(yi)起,應(ying)用(yong)于實際的(de)(de)(de)(de)(de)項目,那是(shi)第三步(bu)。很多朋友都(dou)(dou)是(shi)從(cong)PC編(bian)程(cheng)轉向嵌(qian)(qian)(qian)入(ru)(ru) 式編(bian)程(cheng)的(de)(de)(de)(de)(de)。在(zai),嵌(qian)(qian)(qian)入(ru)(ru)式編(bian)程(cheng)的(de)(de)(de)(de)(de)朋友很少是(shi)正(zheng)兒(er)八經(jing)(jing)從(cong)計算機專業畢業的(de)(de)(de)(de)(de),都(dou)(dou)是(shi)從(cong)自動控制啊,電子(zi)相關(guan)的(de)(de)(de)(de)(de)專業畢業的(de)(de)(de)(de)(de)。這些(xie)童(tong)鞋們,實踐經(jing)(jing)驗(yan)雄(xiong)厚,但是(shi)理(li)論(lun)知(zhi)(zhi)(zhi) 識(shi)缺(que)乏;計算機專業畢業的(de)(de)(de)(de)(de)童(tong)鞋很大一(yi)(yi)(yi)部(bu)分(fen)去(qu)弄網游(you)、網頁這些(xie)獨立于操作(zuo)系(xi)統的(de)(de)(de)(de)(de)更高層的(de)(de)(de)(de)(de)應(ying)用(yong)了(le)。也不(bu)(bu)太愿意從(cong)事嵌(qian)(qian)(qian)入(ru)(ru)式行(xing)業,畢竟這條路不(bu)(bu)好走。他(ta)們理(li)論(lun)知(zhi)(zhi)(zhi)識(shi) 雄(xiong)厚,但缺(que)乏電路等相關(guan)的(de)(de)(de)(de)(de)知(zhi)(zhi)(zhi)識(shi),在(zai)嵌(qian)(qian)(qian)入(ru)(ru)式里學(xue)習(xi)需要再學(xue)習(xi)一(yi)(yi)(yi)些(xie)具體的(de)(de)(de)(de)(de)知(zhi)(zhi)(zhi)識(shi),比(bi)較難走。

 

雖然沒有做過產業調查,但從我所見和所招聘人員,從事嵌入式行業的工程師,要么缺乏理論知識,要么缺乏實踐經驗。很少兩者兼備的。究其原因,還是的大學 教育的問題。這里不探討這個問題,避免口水戰。我想列出我實踐中的幾個例子。引起大家在嵌入式中做項目時對一些問題的關注。

為什么應屆生想做嵌入式開發需要培訓呢?純理論  NO, 略知皮毛?都干不了這行!

 

第一個問題:

同 事在uC/OS-II下開發(fa)一個(ge)(ge)串(chuan)口的(de)驅(qu)(qu)動(dong)程(cheng)序(xu),驅(qu)(qu)動(dong)和接(jie)口在測(ce)試中均為發(fa)現問題。應用中開發(fa)了(le)個(ge)(ge)通訊程(cheng)序(xu),串(chuan)口驅(qu)(qu)動(dong)提供了(le)一個(ge)(ge)查詢驅(qu)(qu)動(dong)緩沖區字符(fu)的(de)函(han) 數(shu):GetRxBuffCharNum()。 高層需要接(jie)受(shou)一定數(shu)量的(de)字符(fu)以(yi)后才能對包做解析(xi)。一個(ge)(ge)同事撰寫的(de)代(dai)碼,用偽代(dai)碼表示如(ru)下:

bExit = FALSE;

do {

if (GetRxBuffCharNum() >= 30)

bExit = ReadRxBuff(buff, GetRxBuffCharNum());

} while (!bExit);

 

 這段代(dai)碼判斷當前緩(huan)沖區(qu)中(zhong)(zhong)超過30個字(zi)符(fu),就將(jiang)緩(huan)沖區(qu)中(zhong)(zhong)全部字(zi)符(fu)讀到緩(huan)沖區(qu)中(zhong)(zhong),直到讀取成(cheng)功為止。邏輯清楚,思路(lu)也清楚。但這段代(dai)碼是(shi)不(bu)能(neng)正(zheng)常工(gong)作。如果是(shi)在PC機上,定然是(shi)沒有(you)任何問題,工(gong)作的(de)異常正(zheng)常。但在嵌(qian)入式(shi)里真的(de)是(shi)不(bu)得而知了(le)。同事很郁(yu)悶,不(bu)知道為什么。來(lai)請我解決問題,當時我看(kan)到代(dai)碼,就問了(le)他,GetRxBuffCharNum()是(shi)怎么實現的(de)?打(da)開一看(kan):

unsigned GetRxBuffCharNum(void)

{

cpu_register reg;

unsigned num;

reg = interrupt_disable();

num = gRxBuffCharNum;

interrupt_enable(reg);

return (num);

}

很明顯,由于(yu)在循(xun)環(huan)中(zhong)(zhong)(zhong),interruput_disable()和(he)interrupt_enable()之(zhi)間(jian)是(shi)(shi)個(ge)(ge)全局(ju)臨(lin)界(jie)區域,保證gRxBufCharNum的(de)(de)(de)完整性。但是(shi)(shi),由于(yu)在外層的(de)(de)(de)do { } while() 循(xun)環(huan)中(zhong)(zhong)(zhong),CPU頻繁的(de)(de)(de)關(guan)(guan)閉(bi)(bi)中(zhong)(zhong)(zhong)斷(duan)(duan),打開中(zhong)(zhong)(zhong)斷(duan)(duan),這個(ge)(ge)時間(jian)非常(chang)的(de)(de)(de)短。實際上CPU可能(neng)(neng)(neng)不能(neng)(neng)(neng)正(zheng)常(chang)的(de)(de)(de)響應(ying)UART的(de)(de)(de)中(zhong)(zhong)(zhong)斷(duan)(duan)。當然這和(he)uart的(de)(de)(de)波(bo)(bo)特(te)率(lv)(lv)、硬件緩沖區的(de)(de)(de)大(da)小還有CPU的(de)(de)(de)速度都(dou)有關(guan)(guan)系(xi)。我(wo)們使用的(de)(de)(de)波(bo)(bo)特(te)率(lv)(lv)非常(chang)高(gao),大(da)約有3Mbps。uart起始信號和(he)停(ting)止信號占一個(ge)(ge)比(bi)特(te)位(wei)。一個(ge)(ge)字(zi)節需(xu)要消(xiao)耗10個(ge)(ge)周期。3Mbps的(de)(de)(de)波(bo)(bo)特(te)率(lv)(lv)大(da)約需(xu)要3.3us傳(chuan)輸一個(ge)(ge)字(zi)節。3.3us能(neng)(neng)(neng)執行(xing)多少個(ge)(ge)CPU指令(ling)(ling)呢(ni)(ni)?100MHz的(de)(de)(de)ARM,大(da)約能(neng)(neng)(neng)執行(xing)150條(tiao)(tiao)指令(ling)(ling)左右(you)。結果關(guan)(guan)閉(bi)(bi)中(zhong)(zhong)(zhong)斷(duan)(duan)的(de)(de)(de)時間(jian)是(shi)(shi)多長呢(ni)(ni)?一般ARM關(guan)(guan)閉(bi)(bi)中(zhong)(zhong)(zhong)斷(duan)(duan)都(dou)需(xu)要4條(tiao)(tiao)以上的(de)(de)(de)指令(ling)(ling),打開又有4條(tiao)(tiao)以上的(de)(de)(de)指令(ling)(ling)。接收uart中(zhong)(zhong)(zhong)斷(duan)(duan)的(de)(de)(de)代(dai)碼實際上是(shi)(shi)不止20條(tiao)(tiao)指令(ling)(ling)的(de)(de)(de)。所以,這樣下來(lai),就有可能(neng)(neng)(neng)出現丟(diu)失通信數據的(de)(de)(de)Bug,體現在系(xi)統層面(mian)上,就是(shi)(shi)通信不穩定。

 

修改這段代(dai)碼其實很簡(jian)(jian)單(dan),簡(jian)(jian)單(dan)的辦(ban)法是從(cong)高層修改。即:

 

bExit = FALSE;

do {

DelayUs(20); //延時 20us,一般采(cai)用空循環指令實現(xian)

num = GetRxBuffCharNum();

if (num >= 30)

bExit = ReadRxBuff(buff, num);

} while (!bExit);

 

這(zhe)樣,讓CPU有時(shi)(shi)間去執(zhi)行中(zhong)斷(duan)的(de)代碼(ma)(ma)(ma),從而(er)避免(mian)了頻(pin)繁關閉中(zhong)斷(duan)造成的(de)中(zhong)斷(duan)代碼(ma)(ma)(ma)執(zhi)行不及時(shi)(shi),產生(sheng)的(de)信(xin)息丟失(shi)。在(zai)(zai)嵌入式(shi)系(xi)統(tong)里,大部分的(de)RTOS應用都是不帶串口驅動(dong)。自己設計代碼(ma)(ma)(ma)時(shi)(shi),沒(mei)有充分考慮代碼(ma)(ma)(ma)與內(nei)(nei)核的(de)結(jie)合。造成代碼(ma)(ma)(ma)深層(ceng)次(ci)的(de)問(wen)題。RTOS之所以(yi)稱為(wei)RTOS,就是因為(wei)對事件的(de)快速(su)響應;事件快速(su)的(de)響應依賴于CPU對中(zhong)斷(duan)的(de)響應速(su)度。驅動(dong)在(zai)(zai)Linux這(zhe)種系(xi)統(tong)中(zhong)都是與內(nei)(nei)核高度整合,一起運(yun)行在(zai)(zai)內(nei)(nei)核態(tai)。RTOS雖然不能抄襲linux這(zhe)種結(jie)構(gou),但有一定的(de)借鑒意義(yi)。

 

從上(shang)面的例(li)子可以看清(qing)楚,嵌入式需要開發人員對代碼的各(ge)個環節(jie)需要了解清(qing)楚。

 

第二個例子:

同事驅(qu)動一個14094串(chuan)轉并(bing)的(de)(de)芯片。串(chuan)行信(xin)號(hao)是采用(yong)(yong)IO模擬的(de)(de),因為沒有(you)專用(yong)(yong)的(de)(de)硬件。同事就隨手寫了(le)個驅(qu)動,結果調(diao)試了(le)3、4天,仍舊是有(you)問(wen)題。我實(shi)在看(kan)(kan)不(bu)下去了(le),就去看(kan)(kan)了(le)看(kan)(kan),控制的(de)(de)并(bing)行信(xin)號(hao)有(you)時候正(zheng)常有(you)時候不(bu)正(zheng)常。我看(kan)(kan)了(le)看(kan)(kan)代(dai)碼(ma),用(yong)(yong)偽代(dai)碼(ma)大概是:

for (i = 0; i < 8; i++)

{

SetData((data >> i) & 0x1);

SetClockHigh();

for (j = 0; j < 5; j++);

SetClockLow();

}

 

將數據的(de)8個(ge)bit在(zai)每個(ge)高(gao)電平(ping)(ping)從bit0到bit7依(yi)次發(fa)送出去(qu)。應(ying)該是正常的(de)啊。看不出問題在(zai)哪啊?我仔細想(xiang)了想(xiang),有看了14094的(de)datasheet,明白(bai)了。原來,14094要(yao)求clock的(de)高(gao)電平(ping)(ping)持(chi)續10個(ge)ns,低電平(ping)(ping)也要(yao)持(chi)續10個(ge)ns。這段(duan)代碼(ma)之做了高(gao)電平(ping)(ping)時間的(de)延(yan)時,沒有做低電平(ping)(ping)的(de)延(yan)時。如(ru)果中(zhong)斷插在(zai)低電平(ping)(ping)之間工作,那(nei)么這段(duan)代碼(ma)是可(ke)以(yi)的(de)。但是如(ru)果CPU沒有中(zhong)斷插在(zai)低電平(ping)(ping)時執(zhi)行,則(ze)是不能正常工作的(de)。所以(yi)就(jiu)時好時壞。

修改也(ye)比較(jiao)簡單(dan):

 

for (i = 0; i < 8; i++)

{

SetData((data >> i) & 0x1);

SetClockHigh();

for (j = 0; j < 5; j++);

SetClockLow();

for (j = 0; j < 5; j++);

}

 

這樣就(jiu)(jiu)(jiu)完(wan)全正常(chang)了(le)。但是(shi)這個(ge)還(huan)是(shi)不能很好移(yi)植的(de)(de)一(yi)個(ge)代碼,因為編譯(yi)器一(yi)優化,就(jiu)(jiu)(jiu)有可能造成這兩個(ge)延(yan)時循(xun)環的(de)(de)丟失。丟失了(le),就(jiu)(jiu)(jiu)不能保證高電平低電平持續10ns的(de)(de)要求,也(ye)就(jiu)(jiu)(jiu)不能正常(chang)工(gong)作了(le)。所以,真正的(de)(de)可以移(yi)植的(de)(de)代碼,應該(gai)把(ba)這個(ge)循(xun)環做成一(yi)個(ge)納秒級的(de)(de)DelayNs(10);

 

像Linux一(yi)樣,上電時,先測(ce)量一(yi)下,nop指(zhi)令(ling)執行(xing)需要多(duo)長時間(jian)執行(xing),多(duo)少(shao)個nop指(zhi)令(ling)執行(xing)10ns。執行(xing)一(yi)定的nop指(zhi)令(ling)就可以了。利用編(bian)(bian)譯器(qi)防(fang)止(zhi)優化的編(bian)(bian)譯指(zhi)令(ling)或者特殊的關鍵字,防(fang)止(zhi)延時循(xun)環(huan)被編(bian)(bian)譯器(qi)優化掉。如GCC中的

__volatile__ __asm__("nop;\n");

 

從這個例子中(zhong)可以(yi)清(qing)楚的看到,寫好(hao)一段好(hao)代碼,是(shi)需要很多知識支撐的。你說呢?

上一篇:深度解析:嵌入式工程師是如何煉成的

下一篇:太勵志 一個嵌入式工程師成長史

熱點文章(zhang)推(tui)薦
華清(qing)學員就(jiu)業榜(bang)單(dan)
高薪(xin)學員經驗分享
熱(re)點新聞(wen)推薦
前(qian)臺(tai)專線:010-82525158 企業培訓洽談專(zhuan)線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,,京公海網安備11010802025203號

回到頂部