1. 程式人生 > >嵌入式開發中的一些硬體設計上的坑

嵌入式開發中的一些硬體設計上的坑

做嵌入式系統開發,經常要接觸硬體。做嵌入式開發對數位電路和類比電路要有一定的瞭解。這樣才能深入的研究下去。下面我們簡單的介紹嵌入式開發中的一些硬體相關的概念。 電平(Level) 在數位電路中,分為高電平和低電平,分別用1和0表示。一個數字電路的管腳,總是存在一個電平的,要麼高要麼低,或者說要麼1要到0(其實,還有另一種狀態,後面會提到)。

匯流排(Bus) 在嵌入式系統中一定會有一塊處理器晶片,此外,還有其它的晶片作為外部裝置(後面簡稱外設),這些晶片與處理器協作實現產品的功能。複雜的產品往往是由大量的晶片組成的。那麼不可避免的是我們需要將所有的外設與處理器進行相連,最為簡單的是將所有的外設都採用獨立(注意是獨立)的訊號線連線至處理器,這樣的好處是容易理解,但問題是:不可行。因為處理器晶片需要引出太多的線了,從晶片的生產和產品的生產角度來看都不實際。加之,處理器(在此我們假設處理器是單核的,而不是多核的)處理事務在微觀上是序列的,也就是說在某一時刻如果要對外設進行讀寫操作,那隻可能是對大量外設中的一個進行,即多個外設不可能在微觀上被處理器同時訪問。需要注意的是,這裡提出了微觀這一概念,這是為了區別於巨集觀。從巨集觀上來講,一個處理器中可以有多個任務同時執行,但這些任務在微觀上卻是一個一個執行的(後面會用序列來描述這裡所說的“一個一個”),多工的序列執行實現是由作業系統扮演著重要的角色來實現的。回到我們的話題,即然將每個外設採用獨立的訊號線連到處理器不可行,且處理器在單一時間內只會對一個外設進行訪問,那我們能不能採用共享的訊號線將所有的晶片連在一起呢?這就是匯流排概念的由來。通俗的說,如果我們周圍有十個家庭,為了讓這十個家庭每兩個之間都能往來,我們並不需要為每兩個家庭修一條單獨(注意是單獨)的路(如果這樣,要修45條路),而是可以修一條大路,然後,每個家都與大路相連。

對於匯流排,我們往往說匯流排是處理器的,而其它的外設是掛在總線上的。那有一個問題,我們每一時間只能訪問掛在總線上的一個外設,那如何區分這些外設呢?和我們的路一樣,我們需要用地址來區分每一個家庭,在總線上,也是採用地址來進行區分的。這樣,匯流排就根據其功能分為兩類了。一類是地址匯流排,這一總線上的資料只會是從處理器向外設“流”,是單向的。另一類則是資料匯流排,用來將資料從處理器傳送到外設(從處理器的角度來說是寫操作)或者是將資料從外設傳送到處理器(從處理器的角度來說是讀操作),顯然,資料匯流排是雙向的。也就是說,在我們的嵌入式系統中同時存在地址匯流排和資料匯流排將所有需要與處理器進行通訊的晶片連在一起的。 匯流排是有寬度的,正如我們的路分為“三車道”或是“四車道”,我們說32位處理器,是指其資料匯流排寬度是32位,也就是“有32輛車能同時跑”,顯然,寬度越是寬我們的處理器速度就越是快,因為我們從外設晶片存取資料的速度會更快,這就是為什麼我們的計算機向64位發展的原因。同樣的,地址匯流排也是有寬度的,對於32位處理器其最大寬度也就是32位。 匯流排的概念有了,那接下來的一個問題是,即使是每一個外設都有一個地址,那這一地址記在哪裡呢?是放在外設晶片上嗎?如果這樣的話,那就有一個問題,每一類外設的地址必須是不能重疊的,而當一個產品中需要兩塊一樣的晶片的話,兩塊晶片的地址就無法區分了,看來這樣操作存在問題。還有,如果這樣的話每一個外設也得與(比如,32根)資料匯流排完全相連,並監聽資料線以瞭解處理器是不是在“叫”自己,這樣很是複雜。此外,地址也有可能因為外設種類的增多而用光。總的來說地址不能存放在外設晶片,那如何讓外設知道,此時它是被處理器招換從而需要進行讀寫訪問的呢?答案就是晶片的片選(CS, chip select)訊號,或者又號使能(ENable)訊號。 片選(CS 或EN)

片選訊號對於外設晶片來講,就是一個(也是一根)通知訊號,告訴晶片“嘿,請開門,我要放些東西進來,或是拿些東西走”,這裡的東西只能是資料,不可能是玉米棒什麼的。那有個問題,這個訊號源從哪裡來呢?顯然,只能從處理器來。那是不是也是像匯流排那樣,每一個晶片都共用一根線連在一起呢?如果這樣,可能處理器“一叫開門”所有的晶片都將“門”打開了。如果是處理器寫資料,那可能所有的晶片都被寫入同樣的資料。而取資料時,每個外設晶片都向外“扔”資料,這一定會造成資料匯流排衝突,因為有的晶片向總線上“扔”1,有的則“扔”0,這種情況下處理器一定會“發瘋”的,因為它不知道應當得到1還是0。 即然這樣,那顯然不能將所有的片選訊號連在一起了,只能是各晶片的片選訊號獨立。前面提到了地址匯流排,我們是採用一根地址線連一個外設晶片呢?還是採用其它的方法。如果採用一根地址線連一個外設晶片,那可能最多隻能掛接32個晶片了,這顯然不行。其實,在現實中,是採用32位的數字來表示一個外設晶片的地址的,比如1可以表示晶片A,而6534可以表示另外一個晶片B,等等。由此看來,理論上我們可以表示2的32次方(4294967296)個裝置,之所以說理論上,是因為有的裝置要佔用大量的地址。即然這樣,那還有一個問題,如果將32位的地址匯流排轉換成晶片的一根片選訊號呢?這需要引入譯碼(器)的概念。 譯碼(器)
譯碼器將一個數據轉換成一根訊號線上的訊號,比如3/8譯碼器,可以將一個位寬是3位的資料轉換成8根(2的3次方)完全獨立的訊號線,當向資料側寫入二進位制的011時,對應的是8根線的第3根,當輸入二進位制的111時,對應的是8根線中的最後一根。有了譯碼器,處理器的地址線就簡化了,只要32根地址線加上外面的譯碼器,就可以訪問大量的外設晶片了。外部裝置的選擇問題,我們已經解決了,現在還得回頭看一看資料匯流排。 在這裡插入圖片描述 圖1 3/8譯碼器

在嵌入式系統中,所有晶片的資料匯流排可以理解成是直接相連的。之所以用了“可以理解”一詞,是因為為了提高匯流排的負載能力,其中會加入匯流排驅動器。為了理解,我們看一看我們生活中的自來水,比如,在北京理論上可能所有的水管是連在一起的,但中間可能為了提高水壓,存在很多小的水站用來增加供水壓力,而不可能全北京所有的自來水自接來自一個水廠。即然所有的資料匯流排是連在一起的,那就可能會有問題。當向外部裝置寫資料時,處理器先向地址匯流排輸送目標外設的地址,地址譯碼器將其轉換成一根訊號的片選訊號送到了目標外設,目標外設收到這一訊號後,將“門”開啟。接下來處理器將要傳送到外設的資料往資料匯流排上一放,由於只有目標外設晶片打開了“門”,所以資料只會進入到目標外設,而其它的外設什麼也不會收到。很好!處理器向外寫資料應當沒有問題,我們接下來看一看讀。讀的話,由於資料是從外設輸送到處理器的,儘管我們採用和寫一樣的方法開啟目標外設的“門”,但此時,其它的外設也在資料匯流排上,它們有可能處於1也可能處於0,是不是會影響處理器讀取目標外設的資料呢?結果當然不會,但我們得引入另一個概念:高阻態。 高阻態 很顯然,當處理器從目標外設讀資料時,我們希望其它沒有被選上的晶片的資料匯流排不會對目標外設所要傳送的資料有影響,那怎麼辦呢?實際上,當晶片沒有被選中時,其資料匯流排都處於高阻態。所謂的高阻態,我們可以理解成這一管腳在外設晶片內部是斷開的,如此一來,顯然不會對處理器從目標外設讀取資料造成任何的影響了。我們說當一個晶片沒有被選中或是沒有被使能時,其資料匯流排一定是處於高阻態的。前面用了“門”的開和關來打比方,那“門”是指什麼呢?是指外設的資料匯流排,片選訊號的作用就是控制將外設的資料匯流排與處理器的資料匯流排相連或是斷開。更多的關於高阻態的講解可參看前面寫的文章《高阻態和三態門》。 驅動 總線上的資料是誰放上去的我們就說誰是那一時刻的驅動者。也就是說,當處理器向外設寫資料時,它是在驅動資料匯流排的,而當處理器從目標外設讀取資料時,目標外設是在驅動資料匯流排的。對於地址匯流排,因為只可能從處理器向目標外設寫,所以地址匯流排永遠是由處理器驅動的。當一個晶片沒有被選中時,我們說它並不驅動資料匯流排。 三態門 前面我們說到外設晶片的資料匯流排在沒有被選中時其處於高阻態,當被選中時,其電平可能是高(1)或是低(0)。如此一來,我們說外設的資料匯流排其晶片管腳是屬於三態門的,即存在高電平、低電平和高阻態,三個狀態。更多的關於三態門的講解可參看前面寫的文章《高阻態和三態門》。 電平的有效性 前面我們瞭解了什麼是片選訊號,也講到了三態門,需要指出的是片選訊號通常不是三態門,其只存在兩個狀態,即高電平或是低電平。前面我們也說了,片選訊號是用來“開門”的,而片選訊號又有高和低電平,那到底是高電平表示“開門”呢?還是低電平?對於這一問題,我們稱如果一個電平對於一個片選訊號表示“開門”那麼它就是這一訊號的有效電平。比如,對於一個片選訊號,如果低電平表示“開門”,那麼我們說這個片選訊號是低電平有效的。雖然,在這裡我們用片選訊號來解釋電平的有效性,但是很多訊號都存在有效性的問題,比如,後面我們將要談的讀訊號和寫訊號都存在有效性問題。 時序 在前面我們說到當處理器要向外設晶片寫資料時,需要先將所需訪問的外設的地址放在地址總線上,然後,由譯碼器將地址總線上的資料轉換成片選訊號,片選訊號則使能目標外設晶片,接下來處理器寫資料到資料匯流排上,從而完成一個寫操作。顯然,在處理器將資料寫到資料匯流排之前地址線上的資料必須一直保留一段時間,否則的話譯碼器不能長時間的使片選訊號有效。當完成了資料的寫操作後,處理器就不需要保證地址總線上的地址有效了。我們可以看出,這一系列的操作都有一定嚴格的時間順序的,這稱之為時序。時序描述了處理器與外部裝置的互動訊號 “規程”,大家只有按照這一“規程”來操作,才能保證處理器與外部裝置之間能正常的通訊。這好比,我們的道路上的紅綠燈,如果我們行人和車輛不按照其指示來通行的話,就會出現事故。通常,採用時序圖來描述晶片之間通訊的訊號“規程”。 在這裡插入圖片描述

圖2 讀時序圖 在這裡插入圖片描述 圖3 讀時序圖 從圖中我們可以看出ADDRESS是表示地址匯流排的,DQ是表示資料匯流排的,CE是片選訊號,且是低電平有效,其寬度要保證在進行讀操作時總是有效的。學會看時序圖對於做嵌入式系統開發非常有幫助,因為我們不可避免的要與晶片打交道。在時序圖中,通常會標識很多的時間需求資訊。在寫啟動程式碼時需要初始化各地址空間的片選地址暫存器和讀寫時序,時序的配置依據就是來自於外設晶片的時間需求,這是晶片手冊很重要的一部分內容。當一個地址空間中存在多個外設晶片時,我們需要考慮到其中最慢的外設晶片的時間需求,否則的話有的晶片就不能正常工作。 讀訊號 當處理器需要從外設晶片讀取訊號時,除了需要產生片選訊號外,還需要告訴外設晶片這是一個讀操作,而不是一個寫操作,這是通過讀訊號來實現的。 寫訊號 前面講了讀訊號,我想對於寫訊號也就不難理解了,這個訊號用於告訴外設晶片,這是一個向外設晶片寫資料的操作。 I/O埠 前面提到了外設(晶片)),現在是對外設進行分類的時候了。大體上外設分為兩類,一類是儲存器外設,而另一類是非儲存器外設,後者常被稱之為I/O裝置,這裡的I/O是Input/Output的簡寫,即輸入、輸出。可見,I/O外設是一個非常寬泛的概念。對於儲存器外設,其特點是,它所佔用的空間是連續的一片。比如,SDRAM記憶體就是屬於儲存器外設,如果其容量是8M位元組,那麼其佔用的地址空間也會是8M的。與儲存器外設所不同的是,I/O外設所點用的地址一般都很少。比如一個I/O外設可能存在多個控制暫存器,這些控制暫存器從處理器來看就是多個I/O埠(地址),向這個地址寫資料就是向外設所對應的暫存器寫資料,反之,也可以是讀。比如,一個串列埠晶片可能存在多個暫存器,一個用來查詢晶片的狀態,一個用來設定晶片的功能,另一個用來讀取晶片從串列埠線所收到的資料,最後,還有一個用來向晶片寫資料以向串列埠線上傳送資料。對於這一串列埠晶片的暫存器,從處理器的角度來看,都是獨立的I/O埠。 I/O埠存在讀、寫性問題,有的埠是隻讀的,有的埠是隻寫的,還有的埠是即可讀也可寫,其讀寫性是由外設晶片的暫存器所決定的,在晶片的資料手冊中能找到。需要指出的是,有些儲存器外設也存在I/O埠,以對其進行一定的控制。從I/O埠這一名字來看,對於處理器來說,就是對從外面讀入資料或是向外面輸出資料的一個介面總稱。 中斷 中斷從硬體的角度來看就是一個能產生高、低電平的一根訊號線,但理解它需要從處理器的角度出發。我們說過了,處理器從微觀上看,所做的工作是按順序進行的,其對程式的處理只能是一條指令一條指令的執行。如果存在需要對外設晶片進行訪問,而有可能從處理器發出讀、寫命令後,由於外設通常比處理器慢很多,所以外設晶片需要一些時間來準備好所需的資料。在這種情況下,如果處理器一直等外設晶片的返回資料再執行後續的指令的話,將耗費寶貴的時間,這些時間完全可以用來做其它的工作。別忘了,從巨集觀上看來處理器常常是多工的,任務是指作業系統所提供的排程單位。當一個任務因為等待外設晶片的資料而阻塞時,我們可以切換到另外的任務,從而提高處理效率。這就有一個問題,當處理器去處理另一個任務時,如果外設晶片的資料好了的話,如果告訴處理器呢?對了!就是通過中斷訊號。中斷訊號的高、低電平可以用來表示是否有中斷需要處理器注意以處理特定的事件(比如,外設資料準備好了的事件)。 由此看來,中斷的引入能大大的提高處理器的運用效率。為了使用處理器上的中斷,一開始我們需要初始化好處理器的中斷控制器,比如安裝好所需的中斷服務程式或稱之為ISR(Interrupt Service Routine),然後,開啟中斷遮蔽位。中斷服務程式中需要做如下的操作: 從外設讀入或向外設寫資料。讀還是寫通常需要讀取外設的中斷狀態暫存器來決定。 清除外設的中斷訊號。我們知道,中斷訊號是由外設晶片驅動的,為了告訴外設晶片,處理器已經處理完了所需做的工作,那麼處理器需要通過一定的方式通知外設晶片。這種方式就是向外設晶片的暫存器中的某一位寫入一個數據,比如,可能是寫入1表示清中斷,也可能是寫入0表示清中斷,這通常在外設的資料手冊中能查到。當外設收到了處理器的清中斷請求後,其就會驅動中斷線使其無效。比如,一個外設的中斷線是當其為低電平表示有中斷,將其從低電平變為高電平就是驅動為無效。 清除處理器的中斷訊號標識。處理器中往往也會儲存外部中斷訊號是否發生過,當我們處理完了外設晶片的中斷時,我們也需要清除處理器上的標識,從而為下一次中斷做準備。需要注意的是,清外設的中斷必須發生在請處理器中斷標識之前! 中斷還存在一個觸發方式問題。有兩種觸發方式 ,一種是電平觸發,另一種是沿觸發。電平觸發是指電平的高低表示外設是否有中斷,而沿觸發則是能過中斷線上的電平的升或降來表示的,顯然,存在兩種沿觸發方式。一種是中斷線從低電平變為高電平,我們稱之為上升沿觸發,另一處是中斷線從高電平轉換為低電平,我們稱之為下降沿觸發。總的來說中斷的觸發方式有電平觸發、上升沿觸發和下降沿觸發。電平觸發方式中處理中中斷設定很重要的一個步驟。 萬用表 萬用表通常是用來檢視電平的高低、電阻的大小等的,是常用且必不可少的工具之一。在嵌入式系統開發中,我們常用的是數字萬用表。 示波器 在嵌入式系統開發中,我們不可避免的要與外設晶片打交道。除錯驅動程式時,除了需要完全看明白晶片的資料手冊,且在軟體高度的過程中,還需要看我們所期望的訊號電平是否發生在晶片上。比如,我們在寫驅動程式時,需要通過寫I/O埠來對外設晶片進行操作,當寫相應的I/O埠時,我們知道所對應晶片的片選訊號應當有效,有時,我們需要驗證是否按預期發生了,這就需要用到示波器。一般的示波器是能同時觀測兩個訊號線的訊號狀態的。示波器都提供一定的功能,比如設定訊號撲捉的方式等等。示波器很重要的一個引數據是其採集頻率,根據Nyquist採集定理,如果我們想用示波器檢視頻率是100M赫茲的訊號,那麼其取樣頻率必須至少是其兩倍,即200M赫茲。有人可能會問:為什麼不用萬用表來看呢?因為萬用表的採集頻率很底,無法採集到很快的訊號變化。 邏輯分析儀 簡單的說邏輯分析器就是具有很多訊號通道的示波器。通過邏輯分析儀,我們可以看到地址匯流排和資料匯流排上的資料。邏輯分析儀都提供一定的程式設計能力,用於程式設計什麼時候開始對總線上的資料進行採集。