總線(Bus)編程
在嵌入式系統中必定會有一塊處理器芯片,此外,還有其它的芯片做爲外部設備(後面簡稱外設),這些芯片與處理器協做實現產品的功能。複雜的產品每每是由大量的芯片組成的。那麼不可避免的是咱們須要將全部的外設與處理器進行相連,最爲簡單的是將全部的外設都採用獨立(注意是獨立)的信號線鏈接至處理器,這樣的好處是容易理解,但問題是:不可行。工具
由於處理器芯片須要引出太多的線了,從芯片的生產和產品的生產角度來看都不實際。加之,處理器(在此咱們假設處理器是單核的,而不是多核的)處理事務在微觀上是串行的,也就是說在某一時刻若是要對外設進行讀寫操做,那隻多是對大量外設中的一個進行,即多個外設不可能在微觀上被處理器同時訪問。ui
須要注意的是,這裏提出了微觀這一律念,這是爲了區別於宏觀。從宏觀上來說,一個處理器中能夠有多個任務同時運行,但這些任務在微觀上倒是一個一個運行的(後面會用串行來描述這裏所說的「一個一個」),多任務的串行運行實現是由操做系統扮演着重要的角色來實現的。操作系統
回到咱們的話題,即然將每一個外設採用獨立的信號線連處處理器不可行,且處理器在單一時間內只會對一個外設進行訪問,那咱們能不能採用共享的信號線將全部的芯片連在一塊兒呢?這就是總線概念的由來。通俗的說,若是咱們周圍有十個家庭,爲了讓這十個家庭每兩個之間都能往來,咱們並不須要爲每兩個家庭修一條單獨(注意是單獨)的路(若是這樣,要修45條路),而是能夠修一條大路,而後,每一個家都與大路相連。調試
對於總線,咱們每每說總線是處理器的,而其它的外設是掛在總線上的。那有一個問題,咱們每一時間只能訪問掛在總線上的一個外設,那如何區分這些外設呢?和咱們的路同樣,咱們須要用地址來區分每個家庭,在總線上,也是採用地址來進行區分的。接口
這樣,總線就根據其功能分爲兩類了。一類是地址總線,這一總線上的數據只會是從處理器向外設「流」,是單向的。另外一類則是數據總線,用來將數據從處理器傳送到外設(從處理器的角度來講是寫操做)或者是將數據從外設傳送處處理器(從處理器的角度來講是讀操做),顯然,數據總線是雙向的。也就是說,在咱們的嵌入式系統中同時存在地址總線和數據總線將全部須要與處理器進行通信的芯片連在一塊兒的。事件
總線是有寬度的,正如咱們的路分爲「三車道」或是「四車道」,咱們說32位處理器,是指其數據總線寬度是32位,也就是「有32輛車能同時跑」,顯然,寬度越是寬咱們的處理器速度就越是快,由於咱們從外設芯片存取數據的速度會更快,這就是爲何咱們的計算機向64位發展的緣由。一樣的,地址總線也是有寬度的,對於32位處理器其最大寬度也就是32位。事務
總線的概念有了,那接下來的一個問題是,即便是每個外設都有一個地址,那這一地址記在哪裏呢?是放在外設芯片上嗎?若是這樣的話,那就有一個問題,每一類外設的地址必須是不能重疊的,而當一個產品中須要兩塊同樣的芯片的話,兩塊芯片的地址就沒法區分了,看來這樣操做存在問題。還有,若是這樣的話每個外設也得與(好比,32根)數據總線徹底相連,並監聽數據線以瞭解處理器是否是在「叫」本身,這樣非常複雜。ip
此外,地址也有可能由於外設種類的增多而用光。總的來講地址不能存放在外設芯片,那如何讓外設知道,此時它是被處理器招換從而須要進行讀寫訪問的呢?答案就是芯片的片選(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也可能處於0,是否是會影響處理器讀取目標外設的數據呢?結果固然不會,但咱們得引入另外一個概念:高阻態。
高阻態
很顯然,當處理器從目標外設讀數據時,咱們但願其它沒有被選上的芯片的數據總線不會對目標外設所要傳送的數據有影響,那怎麼辦呢?實際上,當芯片沒有被選中時,其數據總線都處於高阻態。
所謂的高阻態,咱們能夠理解成這一管腳在外設芯片內部是斷開的,如此一來,顯然不會對處理器從目標外設讀取數據形成任何的影響了。咱們說當一個芯片沒有被選中或是沒有被使能時,其數據總線必定是處於高阻態的。前面用了「門」的開和關來打比方,那「門」是指什麼呢?是指外設的數據總線,片選信號的做用就是控制將外設的數據總線與處理器的數據總線相連或是斷開。
驅動
總線上的數據是誰放上去的咱們就說誰是那一時刻的驅動者。也就是說,當處理器向外設寫數據時,它是在驅動數據總線的,而當處理器從目標外設讀取數據時,目標外設是在驅動數據總線的。對於地址總線,由於只可能從處理器向目標外設寫,因此地址總線永遠是由處理器驅動的。當一個芯片沒有被選中時,咱們說它並不驅動數據總線。
三態門
前面咱們說到外設芯片的數據總線在沒有被選中時其處於高阻態,當被選中時,其電平多是高(1)或是低(0)。如此一來,咱們說外設的數據總線其芯片管腳是屬於三態門的,即存在高電平、低電平和高阻態,三個狀態。
電平的有效性
前面咱們瞭解了什麼是片選信號,也講到了三態門,須要指出的是片選信號一般不是三態門,其只存在兩個狀態,即高電平或是低電平。前面咱們也說了,片選信號是用來「開門」的,而片選信號又有高和低電平,那究竟是高電平表示「開門」呢?仍是低電平?
對於這一問題,咱們稱若是一個電平對於一個片選信號表示「開門」那麼它就是這一信號的有效電平。好比,對於一個片選信號,若是低電平表示「開門」,那麼咱們說這個片選信號是低電平有效的。雖然,在這裏咱們用片選信號來解釋電平的有效性,可是不少信號都存在有效性的問題,好比,後面咱們將要談的讀信號和寫信號都存在有效性問題。
時序
在前面咱們說到當處理器要向外設芯片寫數據時,須要先將所需訪問的外設的地址放在地址總線上,而後,由譯碼器將地址總線上的數據轉換成片選信號,片選信號則使能目標外設芯片,接下來處理器寫數據到數據總線上,從而完成一個寫操做。顯然,在處理器將數據寫到數據總線以前地址線上的數據必須一直保留一段時間,不然的話譯碼器不能長時間的使片選信號有效。
當完成了數據的寫操做後,處理器就不須要保證地址總線上的地址有效了。咱們能夠看出,這一系列的操做都有必定嚴格的時間順序的,這稱之爲時序。時序描述了處理器與外部設備的交互信號 「規程」,你們只有按照這一「規程」來操做,才能保證處理器與外部設備之間能正常的通信。這比如,咱們的道路上的紅綠燈,若是咱們行人和車輛不按照其指示來通行的話,就會出現事故。一般,採用時序圖來描述芯片之間通信的信號「規程」。
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. 從外設讀入或向外設寫數據。讀仍是寫一般須要讀取外設的中斷狀態寄存器來決定。
2. 清除外設的中斷信號。咱們知道,中斷信號是由外設芯片驅動的,爲了告訴外設芯片,處理器已經處理完了所需作的工做,那麼處理器須要經過必定的方式通知外設芯片。這種方式就是向外設芯片的寄存器中的某一位寫入一個數據,好比,多是寫入1表示清中斷,也多是寫入0表示清中斷,這一般在外設的數據手冊中能查到。當外設收到了處理器的清中斷請求後,其就會驅動中斷線使其無效。好比,一個外設的中斷線是當其爲低電平表示有中斷,將其從低電平變爲高電平就是驅動爲無效。
3. 清除處理器的中斷信號標識。處理器中每每也會保存外部中斷信號是否發生過,當咱們處理完了外設芯片的中斷時,咱們也須要清除處理器上的標識,從而爲下一次中斷作準備。須要注意的是,清外設的中斷必須發生在請處理器中斷標識以前。
中斷還存在一個觸發方式問題。有兩種觸發方式 ,一種是電平觸發,另外一種是沿觸發。電平觸發是指電平的高低表示外設是否有中斷,而沿觸發則是能過中斷線上的電平的升或降來表示的,顯然,存在兩種沿觸發方式。一種是中斷線從低電平變爲高電平,咱們稱之爲上升沿觸發,另外一處是中斷線從高電平轉換爲低電平,咱們稱之爲降低沿觸發。總的來講中斷的觸發方式有電平觸發、上升沿觸發和降低沿觸發。電平觸發方式中處理中中斷設置很重要的一個步驟。
萬用表
萬用表一般是用來查看電平的高低、電阻的大小等的,是經常使用且必不可少的工具之一。在嵌入式系統開發中,咱們經常使用的是數字萬用表。
電平(Level)
在數字電路中,分爲高電平和低電平,分別用1和0表示。一個數字電路的管腳,老是存在一個電平的,要麼高要麼低,或者說要麼1要到0(其實,還有另外一種狀態)。
示波器
在嵌入式系統開發中,咱們不可避免的要與外設芯片打交道。調試驅動程序時,除了須要徹底看明白芯片的數據手冊,且在軟件高度的過程當中,還須要看咱們所指望的信號電平是否發生在芯片上。好比,咱們在寫驅動程序時,須要經過寫I/O端口來對外設芯片進行操做,當寫相應的I/O端口時,咱們知道所對應芯片的片選信號應當有效,有時,咱們須要驗證是否按預期發生了,這就須要用到示波器。通常的示波器是能同時觀測兩個信號線的信號狀態的。
示波器都提供必定的功能,好比設置信號撲捉的方式等等。示波器很重要的一個參數據是其採集頻率,根據Nyquist採集定理,若是咱們想用示波器查看頻率是100M赫茲的信號,那麼其採樣頻率必須至少是其兩倍,即200M赫茲。有人可能會問:爲何不用萬用表來看呢?由於萬用表的採集頻率很底,沒法採集到很快的信號變化。
邏輯分析儀
簡單的說邏輯分析器就是具備不少信號通道的示波器。經過邏輯分析儀,咱們能夠看到地址總線和數據總線上的數據。邏輯分析儀都提供必定的編程能力,用於編程何時開始對總線上的數據進行採集。