吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

很全面的嵌入式開發與學習的入門知識

NJ90_gh_bee81f8 ? 2018-02-08 16:55 ? 次閱讀

在剛剛涉足嵌入式開發的時候,總想找到這樣一本書,它可以解決我一些這樣那樣的疑惑。但是遺憾的是,到現在也沒有這樣一本書面世,而且我想永遠也不可能面世了。因為我的疑惑太多太雜了。

這些疑惑在教科書中又難以尋找到答案。C 教程注重講C的語法,編譯原理注重講語法,語義的分析。每一門教科書都是有它的注重,所以那些交叉的問題便成了三不管。市場上的那些自稱為《XX 寶典》、《XX 圣經》的書卻總是說一些可能連作者自己也沒搞清楚的問題。于是我想,我想了解的也許是大家都想了解的吧,那么把我學到的一點東西寫出來,大家也許就可以少花點時間在上面,留出寶貴的腦力資源去做更有意義的事。

語言選擇,C 還是其他

剛剛涉及嵌入式開發者總是先閱讀一些指導類型文章,然后就開始對開發語言的選擇躊躇不決。是C還是C++?還是好像更熱門的JAVA?不用猶豫,至少目前看來C還是你的選擇。嵌入式開發的本質是訂制開發,硬件平臺林林總總,處理能力高下不同,如果想保護你學習精力投資的話,C是最好的“優績股”。C++的優點在于它的代碼重用,但是效率比C低很多,最重要的是,并非所有芯片的編譯器都能支持C++。JAVA就更不用提及,在一個虛擬平臺上開發的優點是不用關心具體的硬件細節,但這不是一個嵌入式開發者的作風,換一種說法,這種開發不能稱之為嵌入式開發。

C被稱為高級語言中的低級語言,低級語言中的高級語言,這是因為其一方面有高級語言所具有的接近于人類思想的語言體系,另一方面同時支持地址與位操作。可以方便的與硬件打交道。嵌入式開發必然要操作IO、硬件地址,沒有位操作和指針你又如何方便做到?

嵌入式開發一般流程

嵌入式開發的流程與高層開發大體類似,編碼——編譯、鏈接——運行。中間當然可以有聯機調試,重新編碼等遞歸過程。但有一些不同之處。

首先,開發平臺不同。受嵌入式平臺處理能力所限,嵌入式開發一般都采用交叉編譯環境開發。所謂交叉編譯就是在A平臺上編譯B平臺上運行的目標程序。在A平臺上運行的B平臺程序編譯器就被稱為交叉編譯器。一個初入門者,建立一套這樣的編譯環境也許就要花掉幾天的時間。

其次,調試方式不同。我們在Windows或者Linux上開發的程序可以馬上運行察看運行結果,也可以利用IDE來調試運行過程,但是嵌入式開發者卻至少需要作一系列工作才能達到這種地步。

目前最流行的是采用JTAG方式連接到目標系統上,將編譯成功的代碼下載運行,高級的調試器幾乎可以像VC環境一樣任意的調試程序。再者,開發者所了解層次結構不同。高層軟件開發者把工作的重點放在對應用需求的理解和實現上。

嵌入式開發者對整個過程細節必須比高層開發者有更深的認識。最大不同之處在于有操作系統支持的程序不需要你關心程序的運行地址以及程序鏈接后各個程序塊最后的位置。像Windows,Linux這類需要MMU支持的操作系統,其程序都是放置在虛擬地址空間的一個固定的內存地址。不管程序在真正RAM空間的地址位置在哪里,最后都由MMU映射到虛擬地址空間的一個固定的地址。

為什么程序的運行與存放的地址要相關呢?學過匯編原理,或者看過最后編譯成機器碼程序的人就知道,程序中的變量、函數最后都在機器碼中體現為地址,程序的跳轉,子程序的調用,以及變量調用最后都是CPU通過直接提取其地址來實現的。嵌入式學習企鵝意義氣嗚嗚吧久零就易。編譯時指定的TEXT_BASE就是所有一切地址的參考值。如果你指定的地址與最后程序放置的地址不一致顯然不能正常運行。

但也有例外,不過不尋常的用法當然要付出不尋常的努力。有兩種方法可以解決這個問題。

一種方法是在程序的最起始編寫與地址無關的代碼,最后將后面的程序自搬移到你真正指定的TEXT_BASE然后跳轉到你將要運行的代碼處。

另一種方法是,TEXT_BASE指定為你程序的存放地址,然后將程序搬移到真正運行的地址,有一個變量將后者的地址記錄下來作為參考值,在以后的符號表地址都以此值作為參考與偏移值合成為其真正的地址。

聽起來很拗口,實現起來也很難,在后面的內容中有更好的解決辦法——用一個BootLoader支持。另外,一個完整的程序必然至少有三個段TEXT (正文,也就是最后用程序編譯后的機器指令)段、BSS(未初始變量)段DATA(初始化變量)段。前面講到的TEXT_BASE只是TEXT段的基址,對于另外的BSS段和DATA段,如果最后的整個程序放在RAM中,那么三個段可以連續放置,但是,如果程序是放置在ROM或者FLASH這種只讀存儲器中,那么你還需要指定你的其他段的地址,因為代碼在運行中是不改變的,而后兩者卻不同。這些工作都是在鏈接的時候完成,編譯器必然為你提供了一些手段讓你完成這些工作。

還是那句話,有操作系統支持的編程屏蔽了這些細節,讓你完全不用考慮這些頭痛的問題。但是嵌入式開發者沒有那么幸運,他們總是在一個冷冰冰的芯片上從頭做起。CPU上電復位總是從一個固定的地址去找程序,開始其繁忙的工作。對于我們的PC來說這個地址就是我們的BIOS程序,對于嵌入式系統,一般沒有BIOS支持,RAM不能在掉電情況下保留你的程序,所以必須將程序存放在ROM或FLASH中,但是一般來講,這些存儲器的寬度和速度都無法與RAM相提并論。

程序在這些存儲器上運行會降低運行速率。大多數的方案是在此處存放一個BootLoader,BootLoader所完成的功能可多可少,一個基本的BootLoader只完成一些系統初始化并將用戶程序搬移到一定地址,然后跳轉到用戶程序即交出CPU控制權,功能強大的BootLoad還可以支持網絡、串口下載,甚至調試功能。但不要指望有一個像PC BIOS那樣通用的BootLoader供你使用,至少你需要作一些移植工作使其符合你的系統,這個移植工作也是你開發的一個部分,作為嵌入式開發個入門者來講,移植或者編寫一個BootLoader會使你受益匪淺。

沒有BootLoader行不行?當然可以,要么你就犧牲效率直接從ROM中運行,要么你就自己編寫程序搬移代碼去RAM運行,最主要的是,開發過程中你要有好的調試工具支持在線調試,否則你就得在改動哪怕一個變量的情況下都要去重新燒片驗證。繼續程序入口的話題,不管過程如何,程序最后在執行時都是變成了機器指令,一個純的執行程序就是這些機器指令的集合。像我們在操作系統上的可運行程序都不是純的執行程序,而是帶有格式的。一般除了包含上面提到的幾個段以外,還有程序的長度,校驗以及程序入口——就是從哪兒開始執行用戶程序。

為什么有了程序地址還需要有程序的入口呢?這是因為你要真正開始執行的代碼并非一定放置在一個文件的最開始,就算放在最開始,除非你去控制鏈接,否則在多文件的情況下,編譯器也不一定將你的這段程序放置在最后程序的最頂端。像我們一般有操作系統支持的程序,只需在你的代碼中有一個main作為程序入口——注意這個main只是大多數編譯器約成定俗的入口,除非你利用了別人的初始化庫,否則程序入口可以自行設定——即可。顯然,帶有格式的這種執行文件使用更加靈活,但需要BootLoader的支持。有關執行文件格式的內容可以看看ELF文件格式。

編譯預處理

首先看看文件包含,從我們的第一個C程序Hello World!開始,我們就使用頭文件包含,但是另人驚奇的是,很多人在做了很長時間的開發以后仍然對文件的包含沒有正確的認識或者是概念不清,有更多的人卻把頭文件和與之相關聯的庫混淆。

為了照顧這些初學者,這里羅嗦一下,其實文件包含的本質就是把一個大的文件截成幾個小文件便于管理和閱讀,如果你包含了那個文件,那么你把這個文件的所有內容原封不動的復制到你包含其的文件中,效果是完全一樣的,另一方面,如果你編譯了一些中間代碼,如庫文件,可以通過提供頭文件來告知調用者你的庫包含的函數和調用格式,但是真正的代碼已經變成了目標代碼以庫文件形式存在了。至于包含文件的后綴如.h只是告訴使用者,這是一個頭文件,你用任何別的名字,編譯器都一般不會在意。

那些對頭文件和庫還混淆的朋友應該恍然大悟了吧,其實頭文件只能保證你的程序編譯不出現語法錯誤,但是直到最后鏈接的時候才會真正使用到庫,那些只把一個頭文件拷貝來就想擁有一個庫的人再也不要犯這樣的錯誤了。如果你的工程中源程序數目繁多令你覺得管理困難,把他們全部包含在一個文件中也未嘗不可。

另一個初學者常常遇到的問題就是由于重復包含引起的困惑。如果一個文件中包含了另一個文件兩次或兩次以上很可能引起重復定義的問題,但是沒有人蠢到會重復包含兩次同一個文件的,這種問題都是隱式的重復包含,比如A文件中包含了B文件和C文件,B文件中又包含了C文件,這樣,A文件實際上已經包含了C文件兩次。不過一個好的頭文件巧妙的利用編譯預處理避免了這種情況。在頭文件中你可能發現這樣的一些預處理:

#ifndef __TEST_H__

#define __TEST_H__

… …

#endif /* __TEST_H__ */

這三行編譯預處理前兩行一般位于文件最頂端,最后文件位于文件最末端,它的意思是,如果沒有定義__TEST_H__那么就定義__TEST_H__同時下面的代碼一直到#endif前參與編譯,反之不參與編譯。多么巧妙的設計,有了這三行簡潔的預處理,這個文件即使被包含幾萬次也只能算一次。

我們再來看看宏的使用。初學者在看別人代碼的時候總是想,為什么用那么多宏呢?看得人一頭霧水,的確,有時候宏的使用會降低代碼的可讀性。但有時宏也可以提高代碼的可讀性,看看下邊這兩段代碼:

1)

#define SCC_GSMRH_RSYN 0x00000001 /* receive sync timing */

#define SCC_GSMRH_RTSM 0x00000002 /* RTS* mode */

#define SCC_GSMRH_SYNL 0x0000000c /* sync length */

#define SCC_GSMRH_TXSY 0x00000010 /* transmitter/receiver sync*/

#define SCC_GSMRH_RFW 0x00000020 /* Rx FIFO width */

#define SCC_GSMRH_TFL 0x00000040 /* transmit FIFO length */

#define SCC_GSMRH_CTSS 0x00000080 /* CTS* sampling */

#define SCC_GSMRH_CDS 0x00000100 /* CD* sampling */

#define SCC_GSMRH_CTSP 0x00000200 /* CTS* pulse */

#define SCC_GSMRH_CDP 0x00000400 /* CD* pulse */

#define SCC_GSMRH_TTX 0x00000800 /* transparent transmitter */

#define SCC_GSMRH_TRX 0x00001000 /* transparent receiver */

#define SCC_GSMRH_REVD 0x00002000 /* reverse data */

#define SCC_GSMRH_TCRC 0x0000c000 /* transparent CRC */

#define SCC_GSMRH_GDE 0x00010000 /* glitch detect enable */

*(int *)0xff000a04 = SCC_GSMRH_REVD | SCC_GSMRH_TRX | SCC_GSMRH_TTX |

SCC_GSMRH_CDP | SCC_GSMRH_CTSP | SCC_GSMRH_CDS | SCC_GSMRH_CTSS;

2)

*(int *)0xff000a04 = 0x00003f80;

這是對某一個寄存器的賦值程序,兩者完成的是完全相同的工作。第一段代碼略顯冗長,第二段代碼很簡潔,但是如果你如果想改動此寄存器的設置的時候顯然更喜歡看到的是第一段代碼,因為它現有的值已經很清楚,要對那些位賦值只要用相應得宏定義即可,不必每次改變都拿筆再重新計算一次。這一點對于嵌入式開發者很重要,有時我們調試一個設備的時候,一個關鍵寄存器的值也許會被我們修改很多次,每一次都計算每一位所對應得值是一件很頭疼的事。

另外利用宏也可以提高代碼的運行效率,子程序的調用需要壓棧出棧,這一過程如果過于頻繁會耗費掉大量的CPU運算資源。所以一些代碼量小但運行頻繁的代碼如果采用帶參數宏來實現會提高代碼的運行效率,比如我們常常用到的對外部IO賦值的操作,你可以寫一個類似下邊的函數來實現:

void outb(unsigned char val, unsigned int *addr)

{

*addr = val;

}

僅僅是一句語句的函數,卻要調用一個函數,如果不用函數呢,重復寫上面的語句又顯得羅嗦。不如用下面的宏實現。

#define outb(b, addr) (*(volatile unsigned char *)(addr) = (b))

由于不需要調用子函數,宏提高了運行效率,但是浪費了程序空間,這是由于凡是用到此宏的地方,都要替換為一句其代替的語句。開發者需要根據系統需求取舍時間與空間。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5092

    文章

    19177

    瀏覽量

    307650
  • C語言
    +關注

    關注

    180

    文章

    7614

    瀏覽量

    137704

原文標題:嵌入式大拿站在初學者角度談嵌入式開發與學習

文章出處:【微信號:gh_bee81f890fc1,微信公眾號:面包板社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    嵌入式開發入門之旅

    嵌入式開發這個技術新領域,讓學員領略嵌入式技術的魅力,使學員對嵌入式開發過程有一個大致的了解,了解嵌入式開發所需要的知識
    發表于 07-09 16:57

    嵌入式開發學習路線 零基礎入門嵌入式技術知識

      創客學院嵌入式開發培訓講師通過和嵌入式開發學員的交流了解到,一般零基礎學習嵌入式開發技術的小白,在入門
    發表于 06-30 13:45

    嵌入式開發要學什么

    、大咖篇。入門嵌入式工程師  此階段主要是前期的入門過程,主要針對入行沒多久的新人。其實成功沒有捷徑,所以打好基礎才是關鍵。嵌入式開發要學什么主要包含以下4個方
    發表于 01-18 06:36

    嵌入式開發入門知識點大合集

    嵌入式開發八大入門知識
    發表于 11-16 06:33

    嵌入式開發的基礎知識入門必要步驟

    ARM嵌入式開發嵌入式開發領略比較熱門的技術,本文針對ARM嵌入式開發入門者給出嵌入式開發的基礎知識
    發表于 12-14 07:32

    嵌入式開發入門知識

    嵌入式開發入門知識:1 前言在剛剛涉足嵌入式開發的時候,總想找到這樣一本書,它可以解決我一些這樣那樣的疑惑。但是遺憾的是,到現在也沒有這樣一本書面世,而且我想永
    發表于 09-25 15:50 ?72次下載

    嵌入式開發

    嵌入式開發就是指在嵌入式操作系統下進行開發嵌入式Linux是以Linux為基礎的嵌入式作業系統。這里提供了
    發表于 12-20 13:21
    <b class='flag-5'>嵌入式開發</b>

    嵌入式開發入門_學嵌入式開發需要看哪些書籍

    現在嵌入式開發越來越吃香,很多人都想要學習卻不知道要從何下手。本文分析了學習嵌入式軟件開發需要具備哪些基本
    的頭像 發表于 04-04 10:25 ?2.7w次閱讀

    嵌入式開發(一):嵌入式開發新手入門

    本篇文章整理下嵌入式開發中一些入門的基礎技能,都是根據以往的工程經驗整理,適用于之前沒做過嵌入式開發的新手。嵌入式開發流程一般如下,一般是在PC機的Windows系統下安裝Ubuntu
    發表于 10-14 10:58 ?79次下載
    <b class='flag-5'>嵌入式開發</b>(一):<b class='flag-5'>嵌入式開發</b>新手<b class='flag-5'>入門</b>

    嵌入式開發資料免費分享

    嵌入式開發資料免費分享嵌入式工程師經驗分享:如何學習嵌入式開發截取文檔部分學習嵌入式工程師經驗分
    發表于 10-21 11:07 ?47次下載
    <b class='flag-5'>嵌入式開發</b>資料免費分享

    零基礎學習嵌入式開發難嗎?嵌入式開發需要學習什么

    對于零基礎剛開始學習嵌入式的同學很多都會有這樣的一個想法,嵌入式開發需要學習什么?如果是電子或計算機專業的人,相對來說,會比較容易入門;而非
    發表于 11-02 20:21 ?13次下載
    零基礎<b class='flag-5'>學習</b><b class='flag-5'>嵌入式開發</b>難嗎?<b class='flag-5'>嵌入式開發</b>需要<b class='flag-5'>學習</b>什么

    linux嵌入式系統開發知識分享,嵌入式開發教程哪家好?

    嵌入式入門你知多少?對于一些初入門的初學者而言,對嵌入式入門的一些知識有助于后期的
    發表于 11-02 20:51 ?13次下載
    linux<b class='flag-5'>嵌入式</b>系統<b class='flag-5'>開發</b>小<b class='flag-5'>知識</b>分享,<b class='flag-5'>嵌入式開發</b>教程哪家好?

    VScode嵌入式開發入門教程

    VScode嵌入式開發入門教程1.VScode進行單片機嵌入式開發教程2.單片機開發環境的搭建3.相關技巧與設置
    發表于 11-03 09:51 ?44次下載
    VScode<b class='flag-5'>嵌入式開發</b>之<b class='flag-5'>入門</b>教程

    嵌入式開發教程哪家好?linux嵌入式系統開發

    嵌入式入門你知多少?對于一些初入門的初學者而言,對嵌入式入門的一些知識有助于后期的
    發表于 11-03 09:51 ?17次下載
    <b class='flag-5'>嵌入式開發</b>教程哪家好?linux<b class='flag-5'>嵌入式</b>系統<b class='flag-5'>開發</b>

    嵌入式開發入門學習

    電子發燒友網站提供《嵌入式開發入門學習.doc》資料免費下載
    發表于 10-26 09:37 ?1次下載
    <b class='flag-5'>嵌入式開發</b><b class='flag-5'>入門</b><b class='flag-5'>學習</b>
    如何看百家乐的玩法技巧和规则| ea百家乐官网打水| 赢家百家乐的玩法技巧和规则| 百家乐官网导航网| 大发888真钱娱乐下载| 贵族百家乐官网的玩法技巧和规则| 百家乐赌场| 百家乐官网娱乐优惠| bet365体育| 百家乐技巧何为百家乐之路| 百家乐官网定位膽技巧| 大发888真钱娱乐下载| 最新百家乐游戏机| 百家乐官网真人大头贴| 大发888真钱游戏下载365| 百家乐怎么会赢| gt百家乐官网平台假吗| 德州扑克看牌器| 澳门百家乐官网登陆网址| 大发888赌博违法吗| 网上百家乐开户送现金| 百家乐官网百胜注码法| 盈丰娱乐| 广发百家乐的玩法技巧和规则| 千亿娱百家乐官网的玩法技巧和规则 | 百家乐官网美女荷官| 大发888技巧| 网络百家乐最安全| 老k百家乐官网游戏| 真人娱乐城| 大发888娱乐城范本| 至尊百家乐20111110| 百家乐官网出老千视频| 曲周县| 大发888官网免费58| 百家乐蓝盾有赢钱的吗| 百家乐官网路单下| 百家乐官网投注办法| 德州扑克高级教程| 网上百家乐赌城| 百家乐系统足球博彩通|