天天看點

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

哈喽,大家好。我終于回來了!19号剛送出完大論文,就被抓去出差了,折騰了整整一周,26号晚上,才回到學校。鴿了好久都沒更新幹貨了。今天更新一篇關于Arm的筆試面試題目。

文章目錄

  • ARM體系與架構
    • 硬體基礎
      • NAND FLASH 和NOR FLASH異同?
      • CPU,MPU,MCU,SOC,SOPC聯系與差别?
      • 什麼是交叉編譯?
      • 為什麼需要交叉編譯?
      • 描述一下嵌入式基于ROM的運作方式和基于RAM的運作方式有什麼差別?
    • ARM處理器
      • 什麼是哈佛結構和馮諾依曼結構?
      • 什麼是ARM流水線技術?
      • ARM有幾種工作模式?
      • Arm有多少32位寄存器?
      • Arm2440和6410有什麼差別?
      • ARM指令集分為幾類?
      • 通用寄存器包括R0~R15,可以分為具體哪三類?
      • Arm處理器有幾種工作狀态?
      • ARM系統中,在函數調用的時候,參數是通過哪種方式傳遞的?
      • 為什麼2440的記憶體起始位址是0x30000000?
      • ARM協處理器指令包括哪3類,請描述它們的功能。
      • 什麼是PLL(鎖相環)?
    • 中斷與異常
      • 中斷與異常有何差別?
      • 中斷與DMA有何差別?
      • 中斷能不能睡眠,為什麼?下半部能不能睡眠?
      • 中斷的響應執行流程是什麼?
      • 當一個異常出現以後,ARM微處理器會執行哪幾步操作?
      • 寫一個中斷服務需要注意哪些?如果中斷産生之後要做比較多的事情你是怎麼做的?
      • 為什麼FIQ比IRQ要快?
      • 中斷和輪詢哪個效率高?怎樣決定是采用中斷方式還是采用輪詢方式去實作驅動?
    • 通信協定
      • 什麼是異步傳輸和同步傳輸?
      • RS232和RS485通訊接口有什麼差別?
      • SPI協定
      • IIC協定
    • 程式設計
      • 嵌人式程式設計中,什麼是大端?什麼是小端?
      • 如何判斷計算機處理器是大端,還是小端?
      • 如何進行大小端的轉換?
      • 如何對絕對位址0x100000指派?
  • 聯系作者
    • 關于作者

ARM體系與架構

硬體基礎

NAND FLASH 和NOR FLASH異同?

不同點

類别 NOR NAND
快 像通路SRAM一樣,可以随機通路任意位址的資料;如:unsighed short *pwAddr = (unsighed short *)0x02;unisignded short wVal;wVal = *pwAddr 快,有嚴格的時序要求,需要通過一個函數才能讀取資料,先發送讀指令->發送位址->判斷nandflash是否就緒->讀取一頁資料讀指令、發送位址、判斷狀态、讀資料都是通過操作寄存器實作的,如資料寄存器NFDATA
慢,寫之前需要擦除,因為寫隻能是1->0,擦除可以使0->1 快,寫之前需要擦除,因為寫隻能是1->0,擦除可以使0->1
擦除 非常慢(5S) 快(3ms)
XIP 代碼可以直接在NOR FLASH上運作 NO
可靠性 比較高,位反轉的比例小于NAND FLASH的10% 比較低,位反轉比較常見,必須有校驗措施
接口 與RAM接口相同,位址和資料總線分開 I/O接口
可擦除次數 10000~100000 100000~1000000
容量 小,1MB~32MB 大,16MB~512MB
主要用途 常用于儲存代碼和關鍵資料 用于儲存資料
價格

注意:nandflash和norflash的0位址是不沖突的,norflash占用BANK位址,而nandflash不占用BANK位址,它的0位址是内部的。

相同點

1 寫之前都要先擦除,因為寫操作隻能使1->0,而擦除動作是為了把所有位都變1
2 擦除單元都以塊為機關

CPU,MPU,MCU,SOC,SOPC聯系與差别?

1.CPU(Central Processing Unit),是一台計算機的運算核心和控制核心。CPU由運算器、控制器和寄存器及實作它們之間聯系的資料、控制及狀态的總線構成。差不多所有的CPU的運作原理可分為四個階段:提取(Fetch)、解碼(Decode)、執行(Execute)和寫回(Writeback)。 CPU從存儲器或高速緩沖存儲器中取出指令,放入指令寄存器,并對指令譯碼,并執行指令。所謂的計算機的可程式設計性主要是指對CPU的程式設計。

2.MPU (Micro Processor Unit),叫微處理器(不是微控制器),通常代表一個功能強大的CPU(暫且了解為增強版的CPU吧),但不是為任何已有的特定計算目的而設計的晶片。這種晶片往往是個人計算機和高端工作站的核心CPU。最常見的微處理器是Motorola的68K系列和Intel的X86系列。

3.MCU(Micro Control Unit),叫微控制器,是指随着大規模內建電路的出現及其發展,将計算機的CPU、RAM、ROM、定時計數器和多種I/O接口內建在一片晶片上,形成晶片級的晶片,比如51,avr這些晶片,内部除了CPU外還有RAM,ROM,可以直接加簡單的外圍器件(電阻,電容)就可以運作代碼了,而MPU如x86,arm這些就不能直接放代碼了,它隻不過是增強版的CPU,是以得添加RAM,ROM。

MCU MPU 最主要的差別就睡能否直接運作代碼。MCU有内部的RAM ROM,而MPU是增強版的CPU,需要添加外部RAM ROM才可以運作代碼。

4.SOC(System on Chip),指的是片上系統,MCU隻是晶片級的晶片,而SOC是系統級的晶片,它既MCU(51,avr)那樣有内置RAM,ROM同時又像MPU(arm)那樣強大的,不單單是放簡單的代碼,可以放系統級的代碼,也就是說可以運作作業系統(将就認為是MCU內建化與MPU強處理力各優點二合一)。

5.SOPC(System On a Programmable Chip)可程式設計片上系統(FPGA就是其中一種),上面4點的硬體配置是固化的,就是說51單片機就是51單片機,不能變為avr,而avr就是avr不是51單片機,他們的硬體是一次性掩膜成型的,能改的就是軟體配置,說白點就是改代碼,本來是跑流水燈的,改下代碼,變成數位管,而SOPC則是硬體配置,軟體配置都可以修改,軟體配置跟上面一樣,沒什麼好說的,至于硬體,是可以自己建構的也就是說這個晶片是自己構造出來的,這顆晶片我們叫“白片”,什麼晶片都不是,把硬體配置資訊下載下傳進去了,他就是相應的晶片了,可以讓他變成51,也可以是avr,甚至arm,同時SOPC是在SOC基礎上來的,是以他也是系統級的晶片,是以記得當把他變成arm時還得加外圍ROM,RAM之類的,不然就是MPU了。

什麼是交叉編譯?

在一種計算機環境中運作的編譯程式,能編譯出在另外一種環境下運作的代碼,我們就稱這種編譯器支援交叉編譯。這個編譯過程就叫交叉編譯。簡單地說,就是在一個平台上生成另一個平台上的可執行代碼。

這裡需要注意的是所謂平台,實際上包含兩個概念:體系結構(Architecture)、作業系統(OperatingSystem)。同一個體系結構可以運作不同的作業系統;同樣,同一個作業系統也可以在不同的體系結構上運作。舉例來說,我們常說的x86 Linux平台實際上是Intel x86體系結構和Linux for x86作業系統的統稱;而x86 WinNT平台實際上是Intel x86體系結構和Windows NT for x86作業系統的簡稱。

為什麼需要交叉編譯?

有時是因為目的平台上不允許或不能夠安裝我們所需要的編譯器,而我們又需要這個編譯器的某些特征;有時是因為目的平台上的資源貧乏,無法運作我們所需要編譯器;有時又是因為目的平台還沒有建立,連作業系統都沒有,根本談不上運作什麼編譯器。

描述一下嵌入式基于ROM的運作方式和基于RAM的運作方式有什麼差別?

基于RAM

  1. 需要把硬碟和其他媒體的代碼先加載到ram中,加載過程中一般有重定位的操作。
  2. 速度比基于ROM的快,可用RAM比基于ROM的少,因為所有的代碼,資料都必須存放在RAM中。

基于ROM

  1. 速度較基于RAM的慢,因為會有一個把變量,部分代碼等從存儲器(硬碟,flash)搬移到RAM的過程。
  2. 可用RAM資源比基于RAM的多;

ARM處理器

什麼是哈佛結構和馮諾依曼結構?

定義

馮諾依曼結構釆用指令和資料統一編址,使用同條總線傳輸,CPU讀取指令和資料的操作無法重疊。

哈佛結構釆用指令和資料獨立編址,使用兩條獨立的總線傳輸,CPU讀取指令和資料的操作可以重疊。

利弊

馮諾依曼結構主要用于通用計算機領域,需要對存儲器中的代碼和資料頻繁的進行修改,統一編址有利于節約資源。

哈佛結構主要用于嵌入式計算機,程式固化在硬體中,有較高的可靠性、運算速度和較大的吞吐。

什麼是ARM流水線技術?

流水線技術通 過多個功能部件并行工作來縮短程式執行時間,提高處理器核的效率和吞吐率,進而成為微處理器設計中最為重要的技術之一。ARM7處理器核使用了典型三級流水線的馮·諾伊曼結構,ARM9系列則采用了基于五級流水線的哈佛結構。通過增加流水線級數簡化了流水線各級的邏輯,進一步提高了處理器的性能。

PC代表程式計數器,流水線使用三個階段,是以指令分為三個階段執行:1.取指(從存儲器裝載一條指令);2.譯碼(識别将要被執行的指令);3.執行(處理指令并将結果寫回寄存器)。而R15(PC)總是指向“正在取指”的指令,而不是指向“正在執行”的指令或正在“譯碼”的指令。一般來說,人們習慣性約定将“正在執行的指令作為參考點”,稱之為目前第一條指令,是以PC總是指向第三條指令。當ARM狀态時,每條指令為4位元組長,是以PC始終指向該指令位址加8位元組的位址,即:PC值=目前程式執行位置+8;

ARM指令是三級流水線,取指,譯指,執行,同時執行的,現在PC指向的是正在取指的位址(下一條指令),那麼cpu正在譯指的指令位址是PC-4(假設在ARM狀态下,一個指令占4個位元組),cpu正在執行的指令位址是PC-8,也就是說PC所指向的位址和現在所執行的指令位址相差8。

當突然發生中斷的時候,儲存的是PC的位址(PC-8+4 = PC-4 下一條指令的位址)

這樣你就知道了,如果傳回的時候傳回PC,那麼中間就有一個指令沒有執行,是以用

SUB pc lr-irq #4

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

ARM有幾種工作模式?

  1. 使用者模式(USR)

    使用者模式是使用者程式的工作模式,它運作在作業系統的使用者态,它沒有權限去操作其它硬體資源,隻能執行處理自己的資料,也不能切換到其它模式下,要想

    通路硬體資源或切換到其它模式隻能通過軟中斷或産生異常。

  2. 系統模式(SYS)

    系統模式是特權模式,不受使用者模式的限制。使用者模式和系統模式共用一套寄存器,作業系統在該模式下可以友善的通路使用者模式的寄存器,而且作業系統的

    一些特權任務可以使用這個模式通路一些受控的資源。

    說明:使用者模式與系統模式兩者使用相同的寄存器,都沒有SPSR(Saved Program Statement Register,已儲存程式狀态寄存器),但系統模式比使用者模式有更高的權限,可以通路所有系統資源。
  3. 一般中斷模式(IRQ)

    一般中斷模式也叫普通中斷模式,用于處理一般的中斷請求,通常在硬體産生中斷信号之後自動進入該模式,該模式為特權模式,可以自由通路系統硬體資源。

  4. 快速中斷模式(FIQ)

    快速中斷模式是相對一般中斷模式而言的,它是用來處理對時間要求比較緊急的中斷請求,主要用于高速資料傳輸及通道進行中。(快中斷有許多(R8~R14)自己的專用寄存器,發生中斷時,使用自己的寄存器就避免了儲存和恢複某些寄存器。如果異常中斷處理程式中使用它自己的實體寄存器之外的其他寄存器,異常中斷處理程式必須儲存和恢複這些寄存器)

  5. 管理模式(SVC)

    管理模式是CPU上電後預設模式,是以,在該模式下主要用來做系統的初始化,軟中斷處理也在該模式下。當使用者模式下的使用者程式請求使用硬體資源時,通過軟體中斷進入該模式。

    說明:系統複位或開機、軟中斷時進入到SVC模式下。
  6. 終止模式(ABT):

    中止模式用于支援虛拟記憶體或存儲器保護,當使用者程式通路非法位址,沒有權限讀取的記憶體位址時,會進入該模式,linux下程式設計時經常出現的segment fault通常都是在該模式下抛出傳回的。

  7. 未定義模式(UND):

    未定義模式用于支援硬體協處理器的軟體仿真,CPU在指令的譯碼階段不能識别該指令操作時,會進入未定義模式。

  1. 除了使用者模式外,其它6種模式稱為特權模式。所謂特權模式,即具有如下權利:

a. MRS(把狀态寄存器的内容放到通用寄存器);

b. MSR(把通用寄存器的内容放到狀态寄存器中)。

由于狀态寄存器中的内容不能夠改變,是以,要先把内容複制到通用寄存器中,然後修改通用寄存器中的内容,再把通用寄存器中的内容複制給狀态寄存器中,即可完成“修改狀态寄存器”的任務。

  1. 剩下的六種模式中除去系統模式外,統稱為異常模式。

Arm有多少32位寄存器?

ARM處理器共有37個寄存器。它包含31個通用寄存器和6個狀态寄存器。

Arm2440和6410有什麼差別?

  1. 主頻不同。2440是400M的。6410是533/667M的;
  2. 處理器版本不一樣:2440是arm920T核心,6410是arm1176ZJF核心;
  3. 6410在視訊處理方面比2440要強很多。内部視訊解碼器,包括MPEG4等視訊格式;
  4. 6410支援WMV9、xvid、mpeg4、h264等格式的硬解碼和編碼;
  5. 6410多和很多擴充接口比如:tv-out、CF卡和S-Video輸出等;
  6. spi、序列槽、sd接口也比那兩個要豐富;
  7. 6410采用的是DDR記憶體控制器;2440采用的是SDRam記憶體控制器;
  8. 6410為雙總線架構,一路用于記憶體總線、一路用于Flash總線;
  9. 6410的啟動方式更加靈活:主要包括SD、Nand Flash、Nor Flash和OneFlash等裝置啟動;
  10. 6410的Nand Flash支援SLC和MLC兩種架構,進而大大擴大存儲空間;
  11. 6410為雙總線架構,一路用于記憶體總線、一路用于Flash總線;
  12. 6410具備8路DMA通道,包括LCD、UART、Camera等專用DMA通道;
  13. 6410還支援2D和3D的圖形加速;

ARM指令集分為幾類?

2類,分别為Thumb指令集,ARM指令集。ARM指令長度為32位,Thumb指令長度為16位。這種特點使得ARM既能執行16位指令,又能執行32位指令,進而增強了ARM核心的功能。

通用寄存器包括R0~R15,可以分為具體哪三類?

通用寄存器包括R0-R15,可以分為3類:

  1. 未分組寄存器R0-R7

    在所有運作模式下,未分組寄存器都指向同一個實體寄存器,他們未被系統用作特殊的用途。是以在中斷或異常處理進行異常模式轉換時,由于不同的處理器運作模式均使用相同的實體寄存器,是以可能造成寄存器中資料的破壞。

  2. 分組寄存器R8-R14

    對于分組寄存器,他們每次所通路的實體寄存器都與目前的處理器運作模式相關。

    R13常用作存放堆棧指針,使用者也可以使用其他寄存器存放堆棧指針,但在Thumb指令集下,某些指令強制要求使用R13存放堆棧指針。

    R14稱為連結寄存器(LR,Link Register),當執行子程式時,R14可得到R15(PC)的備份,執行完子程式後,又将R14的值複制回PC,即使用R14儲存傳回位址。

  3. 程式計數器PC(R15)

    寄存器R15用作程式計數器(PC),在ARM狀态下,位[1:0]為0,位[31:2]用于儲存PC;在Thumb狀态下,位[0]為0,位[31:1]用于儲存PC。

Arm處理器有幾種工作狀态?

從程式設計的角度來看,ARM微處理器的工作狀态一般ARM和Thumb有兩種,并可在兩種狀态之間切換。

  1. ARM狀态:此時處理器執行32位的字對齊ARM指令,絕大部分工作在此狀态。
  2. Thumb狀态:此時處理器執行16位的半字對齊的Thumb指令。

ARM系統中,在函數調用的時候,參數是通過哪種方式傳遞的?

當參數小于等于4的時候是通過r0-r3寄存器來進行傳遞的,當參數大于4的時候是通過壓棧的方式進行傳遞。

為什麼2440的記憶體起始位址是0x30000000?

S3C2440處理器有八個固定的記憶體塊,隻有兩個是可以作為ROM,SRAM和SDRAM等存儲器bank。具體如下圖所示。

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

ARM協處理器指令包括哪3類,請描述它們的功能。

ARM協處理器指令包括以下3類:

  1. 用于ARM處理器初始化ARM協處理器的資料處理操作。
  2. 用于ARM處理器的寄存器和ARM協處理器的寄存器間的資料傳送操作。
  3. 用于在ARM協處理器的寄存器和記憶體單元之間傳送資料。

什麼是PLL(鎖相環)?

簡單來說,輸入時鐘的存在是作為“參考源”。鎖相環不是為了單純産生同頻同相信号,而是一般內建進某種“頻率綜合電路”,産生一個不同頻,但鎖相的信号。

有點繞,打個比方:某參考晶振10Mhz,頻率綜合器A使用該參考源産生了900Mhz時鐘,而頻率綜合器B産生了1Ghz時鐘。雖然兩路頻率不同,但由于使用的通一個參考源,他們倆仍然是同源信号。相反,如果不同源,那麼即便同頻他們也不可能一緻,因為世界上沒有兩個鐘能做到完全一樣,總有微弱的頻差,導緻相位飄移。在很多現實應用中有要求同源時鐘的場合,是以,鎖相環被廣泛應用。鎖相環的另外一項衍生應用是相幹解調,可以自己查查相關資料。

中斷與異常

中斷與異常有何差別?

中斷是指外部硬體産生的一個電信号從CPU的中斷引腳進入,打斷CPU的運作。

異常是指軟體運作過程中發生了一些必須作出處理的事件,CPU自動産生一個陷入來打斷CPU的運作。異常在處理的時候必須考慮與處理器的時鐘同步,實際上異常也稱為同步中斷,在處理器執行到因編譯錯誤而導緻的錯誤指令時,或者在執行期間出現特殊錯誤,必須靠核心處理的時候,處理器就會産生一個異常。

中斷與DMA有何差別?

DMA:是一種無須CPU的參與,就可以讓外設與系統記憶體之間進行雙向資料傳輸的硬體機制,使用DMA可以使系統CPU從實際的I/O資料傳輸過程中擺脫出來,進而大大提高系統的吞吐率。

中斷:是指CPU在執行程式的過程中,出現了某些突發事件時,CPU必須暫停執行目前的程式,轉去處理突發事件,處理完畢後CPU又傳回源程式被中斷的位置并繼續執行。

是以中斷和DMA的差別就是:DMA不需CPU參與,而中斷是需要CPU參與的。

中斷能不能睡眠,為什麼?下半部能不能睡眠?

  1. 中斷處理的時候,不應該發生程序切換。因為在中斷上下文中,唯一能打斷目前中斷handler的隻有更高優先級的中斷,它不會被程序打斷。如果在中斷上下文中休眠,則沒有辦法喚醒它,因為所有的wake_up_xxx都是針對某個程序而言的,而在中斷上下文中,沒有程序的概念,沒有一個task_struct(這點對于softirq和tasklet一樣)。是以真的休眠了,比如調用了會導緻阻塞的例程,核心幾乎肯定會死。
  2. schedule()在切換程序時,儲存目前的程序上下文(CPU寄存器的值、程序的狀态以及堆棧中的内容),以便以後恢複此程序運作。中斷發生後,核心會先儲存目前被中斷的程序上下文(在調用中斷處理程式後恢複)。

    但在中斷處理程式裡,CPU寄存器的值肯定已經變化了(最重要的程式計數器PC、堆棧SP等)。如果此時因為睡眠或阻塞操作調用了schedule(),則儲存的程序上下文就不是目前的程序上下文了。是以,不可以在中斷處理程式中調用schedule()。

  3. 2.4核心中schedule()函數本身在進來的時候判斷是否處于中斷上下文:
if(unlikely(in_interrupt()))
BUG();
           

 是以,強行調用schedule()的結果就是核心BUG,但看2.6.18的核心schedule()的實作卻沒有這句,改掉了。

  1. 中斷handler會使用被中斷的程序核心堆棧,但不會對它有任何影響,因為handler使用完後會完全清除它使用的那部分堆棧,恢複被中斷前的原貌。
  2. 處于中斷上下文時候,核心是不可搶占的。是以,如果休眠,則核心一定挂起。

中斷的響應執行流程是什麼?

中斷的響應流程:cpu接受中斷->儲存中斷上下文跳轉到中斷處理曆程->執行中斷上半部->執行中斷下半部->恢複中斷上下文。

當一個異常出現以後,ARM微處理器會執行哪幾步操作?

  1. 将下一條指令的位址存入相應連接配接寄存器LR,以便程式在處理異常傳回時能從正确的位置重新開始執行。若異常是從ARM狀态進入,則LR寄存器中儲存的是下一條指令的位址(目前PC+4或PC+8,與異常的類型有關);若異常是從Thumb狀态進入,則在LR寄存器中儲存目前PC的偏移量,這樣,異常處理程式就不需要确定異常是從何種狀态進入的。例如:在軟體中斷異常SWI,指令 MOV PC,R14_svc總是傳回到下一條指令,不管SWI是在ARM狀态執行,還是在Thumb狀态執行。
  2. 将CPSR複制到相應的SPSR中。
  3. 根據異常類型,強制設定CPSR的運作模式位。
  4. 強制PC從相關的異常向量位址取下一條指令執行,進而跳轉到相應的異常處理程式處。

寫一個中斷服務需要注意哪些?如果中斷産生之後要做比較多的事情你是怎麼做的?

  1. 寫一個中斷服務程式要注意快進快出,在中斷服務程式裡面盡量快速采集資訊,包括硬體資訊,然後退出中斷,要做其它事情可以使用工作隊列或者tasklet方式。也就是中斷上半部和下半部。
  2. 中斷服務程式中不能有阻塞操作。應為中斷期間是完全占用CPU的(即不存在核心排程),中斷被阻塞住,其他程序将無法操作。
  3. 中斷服務程式注意傳回值,要用作業系統定義的宏做為傳回值,而不是自己定義的。
  4. 如果要做的事情較多,應将這些任務放在後半段(tasklet,等待隊列等)處理。

為什麼FIQ比IRQ要快?

  1. ARM的FIQ模式提供了更多的banked寄存器,r8到r14還有SPSR,而IRQ模式就沒有那麼多,R8,R9,R10,R11,R12對應的banked的寄存器就沒有,這就意味着在ARM的IRQ模式下,中斷處理程式自己要儲存R8到R12這幾個寄存器,然後退出中斷處理時程式要恢複這幾個寄存器,而FIQ模式由于這幾個寄存器都有banked寄存器,模式切換時CPU自動儲存這些值到banked寄存器,退出FIQ模式時自動恢複,是以這個過程FIQ比IRQ快.不要小看這幾個寄存器,ARM在編譯的時候,如果你FIQ中斷處理程式足夠用這幾個獨立的寄存器來運作,它就不會進行通用寄存器的壓棧,這樣也省了一些時間。
  2. FIQ比IRQ有更高優先級,如果FIQ和IRQ同時産生,那麼FIQ先處理。
  3. 在symbian系統裡,當CPU處于FIQ模式處理FIQ中斷的過程中,預取指令異常,未定義指令異常,軟體中斷全被禁止,所有的中斷被屏蔽。是以FIQ就會很快執行,不會被其他異常或者中斷打斷,是以它又比IRQ快了。而IRQ不一樣,當ARM處理IRQ模式處理IRQ中斷時,如果來了一個FIQ中斷請求,那正在執行的IRQ中斷處理程式會被搶斷,ARM切換到FIQ模式去執行這個FIQ,是以FIQ比IRQ快多了。
  4. 另外FIQ的入口位址是0x1c,IRQ的入口位址是0x18。寫過完整彙編系統的都比較明白這點的差别,18隻能放一條指令,為了不與1C處的FIQ沖突,這個地方隻能跳轉,而FIQ不一樣,1C以後沒有任何中斷向量表了,這樣可以直接在1C處放FIQ的中斷處理程式,由于跳轉的範圍限制,至少少了一條跳轉指令。

中斷和輪詢哪個效率高?怎樣決定是采用中斷方式還是采用輪詢方式去實作驅動?

中斷是CPU處于被動狀态下來接受裝置的信号,而輪詢是CPU主動去查詢該裝置是否有請求。

凡事都是兩面性,是以,看效率不能簡單的說那個效率高。如果是請求裝置是一個頻繁請求cpu的裝置,或者有大量資料請求的網絡裝置,那麼輪詢的效率是比中斷高。如果是一般裝置,并且該裝置請求cpu的頻率比較低,則用中斷效率要高一些。主要是看請求頻率。

通信協定

什麼是異步傳輸和同步傳輸?

異步傳輸:是一種典型的基于位元組的輸入輸出,資料按每次一個位元組進行傳輸,其傳輸速度低。

同步傳輸:需要外界的時鐘信号進行通信,是把資料位元組組合起來一起發送,這種組合稱之為幀,其傳輸速度比異步傳輸快。

RS232和RS485通訊接口有什麼差別?

  1. 傳輸方式不同。 RS232采取不平衡傳輸方式,即所謂單端通訊。 而RS485則采用平衡傳輸,即差分傳輸方式。
  2. 傳輸距離不同。RS232适合本地裝置之間的通信,傳輸距離一般不超過20m。而RS485的傳輸距離為幾十米到上千米。
  3. 裝置數量。RS232 隻允許一對一通信,而RS485 接口在總線上是允許連接配接多達128個收發器。
  4. 連接配接方式。RS232,規定用電平表示資料,是以線路就是單線路的,用兩根線才能達到全雙工的目的;而RS485, 使用差分電平表示資料,是以,必須用兩根線才能達到傳輸資料的基本要求,要實作全雙工,必需用4根線。

 總結:從某種意義上,可以說,線路上存在的僅僅是電流,RS232/RS485規定了這些電流在什麼樣的線路上流動和流動的樣式。

SPI協定

SPI的應用

SPI(Serial Peripheral Interface)協定是由摩托羅拉公司提出的通訊協定,即串行外圍裝置接口,是一種高速全雙工的通信總線。SPI總線系統是一種同步串行外設接口,它可以使MCU與各種外圍裝置以串行方式進行通信以交換資訊。SPI總線可直接與各個廠家生産的多種标準外圍器件相連,包括FLASH、RAM、網絡控制器、LCD顯示驅動器、A/D轉換器和MCU等。

接口

  1. MOSI (Master Output, Slave Input)

    主裝置輸出/從裝置輸入引腳。主機的資料從這條信号線輸出,從機由這條信号線讀入主機發送的資料,即這條線上資料的方向為主機到從機。

  2. MISO(Master Input,, Slave Output)

    主裝置輸入/從裝置輸出引腳。主機從這條信号線讀入資料,從機的資料由這條信号線輸出到主機,即在這條線上資料的方向為從機到主機。

  3. SCLK (Serial Clock)

    時鐘信号線,用于通訊資料同步。它由通訊主機産生,決定了通訊的速率,不同的裝置支援的最高時鐘頻率不一樣,如 STM32 的 SPI 時鐘頻率最大為fpclk/2,兩個裝置之間通訊時,通訊速率受限于低速裝置。

  4. SS( Slave Select)

    從裝置選擇信号線,常稱為片選信号線,也稱為 NSS、 CS,以下用 NSS 表示。 當有多個 SPI 從裝置與 SPI 主機相連時,裝置的其它信号線 SCK、MOSI 及 MISO 同時并聯到相同的 SPI 總線上,即無論有多少個從裝置,都共同隻使用這 3 條總線;而每個從裝置都有獨立的這一條 NSS 信号線,本信号線獨占主機的一個引腳,即有多少個從裝置,就有多少條片選信号線。

    I2C 協定中通過裝置位址來尋址、選中總線上的某個裝置并與其進行通訊;而 SPI 協定中沒有裝置位址,它使用 NSS 信号線來尋址,當主機要選擇從裝置時,把該從裝置的 NSS 信号線設定為低電平,該從裝置即被選中,即片選有效,接着主機開始與被選中的從裝置進行 SPI 通訊。是以SPI 通訊以 NSS 線置低電平為開始信号,以 NSS 線被拉高作為結束信号。

協定層

SPI 通訊裝置之間的常用連接配接方式見下圖:

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

SPI 通訊的通訊時序,見下圖:

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者
  1. 通訊的起始和停止信号

    在圖中的标号1處,NSS 信号線由高變低,是 SPI 通訊的起始信号。 NSS 是每個從機各自獨占的信号線,當從機檢在自己的 NSS 線檢測到起始信号後,就知道自己被主機選中了,開始準備與主機通訊。在圖中的标号處, NSS 信号由低變高,是 SPI 通訊的停止信号,表示本次通訊結束,從機的選中狀态被取消。

  2. 資料有效性

    SPI 使用 MOSI 及 MISO 信号線來傳輸資料,使用 SCK 信号線進行資料同步。 MOSI及 MISO 資料線在 SCK 的每個時鐘周期傳輸一位資料,且資料輸入輸出是同時進行的。資料傳輸時, MSB 先行(高位先行)或 LSB(低位先行)先行并沒有作硬性規定,但要保證兩個 SPI 通訊裝置之間使用同樣的協定,一般都會采用上圖中的 MSB 先行(高位先行)模式。

    觀察圖中的2345标号處, MOSI 及 MISO 的資料在 SCK 的上升沿期間變化輸出,在 SCK 的下降沿時被采樣。即在 SCK 的下降沿時刻, MOSI 及 MISO 的資料有效,高電平時表示資料“1”,為低電平時表示資料“0”。在其它時刻,資料無效, MOSI 及 MISO為下一次表示資料做準備。

    SPI 每次資料傳輸可以 8 位或 16 位為機關,每次傳輸的機關數不受限制。

  3. CPOL(時鐘極性)/CPHA(時鐘相位)及通訊模式

    上面講述的圖中的時序隻是 SPI 中的其中一種通訊模式, SPI 一共有四種通訊模式,它們的主要差別是:總線空閑時 SCK 的時鐘狀态以及資料采樣時刻。為友善說明,在此引入“時鐘極性CPOL”和“時鐘相位 CPHA”的概念。

    時鐘極性 CPOL 是指 SPI 通訊裝置處于空閑狀态時, SCK 信号線的電平信号(即 SPI 通訊開始前、 NSS 線為高電平時 SCK 的狀态)。 CPOL=0 時, SCK 在空閑狀态時為低電平,CPOL=1 時,則相反。

    時鐘相位 CPHA 是指資料的采樣的時刻,當 CPHA=0 時, MOSI 或 MISO 資料線上的信号将會在 SCK 時鐘線的“奇數邊沿” 被采樣。當 CPHA=1 時,資料線在 SCK 的“偶數邊沿” 采樣。

IIC協定

簡介

IIC協定是由資料線SDA和時鐘SCL構成的串行總線,可發送和接收資料,是一個多主機的半雙工通信方式

每個挂接在總線上的器件都有個唯一的位址。位速在标準模式下可達 100kbit/s,在快速模式下可達400kbit/s,在高速模式下可待3.4Mbit/s。

I2C總線系統結構,如下所示:

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

I2C時序介紹

1. 空閑狀态

當總線上的SDA和SCL兩條信号線同時處于高電平,便是空閑狀态,如上面的硬體圖所示,當我們不傳輸資料時, SDA和SCL被上拉電阻拉高,即進入空閑狀态

2. 起始信号

當SCL為高期間,SDA由高到低的跳變;便是總線的啟動信号,隻能由主機發起,且在空閑狀态下才能啟動該信号,如下圖所示:

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

3. 停止信号

當SCL為高期間,SDA由低到高的跳變;便是總線的**停止信号,**表示資料已傳輸完成,如下圖所示:

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

4. 傳輸資料格式

當發了起始信号後,就開始傳輸資料,傳輸的資料格式如下圖所示:

當SCL為高電平時,便會擷取SDA資料值,其中SDA資料必須是穩定的(若SDA不穩定就會變成起始/停止信号)。

當SCL為低電平時,便是SDA的電平變化狀态。

若主從機在傳輸資料期間,需要完成其它功能(例如一個中斷),可以主動拉低SCL,使I2C進入等待狀态,直到處理結束再釋放SCL,資料傳輸會繼續

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

5. 應答信号ACK

I2C總線上的資料都是以8位資料(位元組)進行的,當發送了8個資料後,發送方會在第9個時鐘脈沖期間釋放SDA資料,當接收方接收該位元組成功,便會輸出一個ACK應答信号,當SDA為高電平,表示為非應答信号NACK,當SDA為低電平,表示為有效應答信号ACK

PS:當主機為接收方時,收到最後一個位元組後,主機可以不發送ACK,直接發送停止信号來結束傳輸。

當從機為接收方時,沒有發送ACK,則表示從機可能在忙其它事、或者不比對位址信号和不支援多主機發送,主機可以發送停止信号,再次發送起始信号啟動新的傳輸。

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

6. 完整的資料傳輸

如下圖所示, 發送起始信号後,便發送一個8位的裝置位址,其中第8位是對裝置的讀寫标志,後面緊跟着的就是資料了,直到發送停止信号終止。

PS:當我們第一次是讀操作,然後想換成寫操作時,可以再次發送一個起始信号,然後發送讀的裝置位址,不需要停止信号便能實作不同的位址轉換。

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

IIC傳輸資料的格式

1.寫操作

剛開始主晶片要發出一個start信号,然後發出一個(用來确定是往哪一個晶片寫資料),方向(讀/寫,0表示寫,1表示讀)。回應(用來确定這個裝置是否存在),然後就可以傳輸資料,傳輸資料之後,要有一個回應信号(确定資料是否接受完成),然後再傳輸下一個資料。每傳輸一個資料,接受方都會有一個回應信号,資料發送完之後,主晶片就會發送一個停止信号。

白色背景:主→從。灰色背景:從→主。

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

2.讀操作

剛開始主晶片要發出一個start信号,然後發出一個裝置位址(用來确定是從哪一個晶片讀取資料),方向(讀/寫,0表示寫,1表示讀)。回應(用來确定這個裝置是否存在),然後就可以傳輸資料,傳輸資料之後,要有一個回應信号(确定資料是否接受完成),然後在傳輸下一個資料。每傳輸一個資料,接受方都會有一個回應信号,資料發送完之後,主晶片就會發送一個停止信号。

白色背景:主→從。灰色背景:從→主

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協定,轉載請附上原文出處連結和本聲明。

本文連結:https://blog.csdn.net/qq_16933601/article/details/116234673

程式設計

嵌人式程式設計中,什麼是大端?什麼是小端?

大端模式:低位位元組存在高位址上,高位位元組存在低位址上。

小端模式:高位位元組存在高位址上,低位位元組存在低位址上。

嵌入式軟體工程師筆試面試指南-ARM體系與架構ARM體系與架構聯系作者

STM32屬于小端模式,簡單的說,比如u32 temp=0X12345678;假設temp位址在0X2000 0010。那麼在記憶體裡面,存放就變成了:

位址         |            HEX     |
0X2000 0010  |  78   56   43  12  |
           

因為是16進制的,一個數為0.5位元組,是以 12 代表一個位元組 34 代表一個位元組。

釆用小端模式的CPU對操作數的存放方式是從低位元組到高位元組,而大端模式對操作數的存放方式是從高位元組到低位元組。例如,16位寬的數0x1234在小端模式CPU記憶體中的存放方式(假設從位址0x4000開始存放)見表1,而在大端模式CPU記憶體中的存放方式見表2。

                      表1 0x1234在小端CPU記憶體中的存放方式

記憶體位址 存放内容
0x4000 0x34
0x4001 0x12

                      表2 0x1234在大端CPU記憶體中的存放方式

記憶體位址 存放内容
0x4000 0x12
0x4001 0x34

  32位寬的數0x12345678在小端模式CPU記憶體中的存放方式(假設從位址0x4000開始存放)見表3,而在大端模式CPU記憶體中的存放方式見表4。

                      表3 0x12345678在小端CPU記憶體中的存放方式

記憶體位址 存放内容
0x4000 0x78
0x4001 0x56
0x4002 0x34
0x4003 0x12

                      表4 0x12345678在大端CPU記憶體中的存放方式

記憶體位址 存放内容
0x4000 0x12
0x4001 0x34
0x4002 0x56
0x4003 0x78

以下程式為例:

#include <stdio.h>
struct mybitfields
{
	unsigned short a:4;
	unsigned short b:5;
	unsigned short c:7;
}test;
int main()
{
	int i;
	test.a = 2;
	test.b = 3;
	test.c = 0;
	i =*((short*)&test);
	printf("%d\n",i);
	return 0;
}
           

程式的輸出結果為 50。

上例中, sizeof( test)=2,上例的聲明方式是把一個 short(也就是一塊16位記憶體)分成3部分,各部分的大小分别是4位、5位、7位,指派語句

i*( short*)&test)

就是把上面的16位記憶體轉換成 short類型進行解釋。

變量a的二進制表示為0000000000000010,取其低四位是0010.變量b的二進制表示為0000000000000011,取其低五位是00011。變量c的二進制表示為0000000000000000,取其低七位是0000000。

80x86機是小端(修改分區表時要注意)模式,單片機一般為大端模式。小端一般是低位位元組在高位位元組的前面,也就是低位在記憶體位址低的一端,可以這樣記(小端→低位→在前→與正常邏輯順序相反),是以合成後得到0000000000110010,即十進制的50。

下面給出另外一個例子

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
	unsigned int uiVal_1 = 0x12345678;
	unsigned int uiVal_2 = 0;
	unsigned char aucVal[4] = {0x12,0x34,0x56,0x78};
	unsigned short usVal_1 = 0;
	unsigned short usVal_2 = 0;
	memcpy(&uiVal_2,aucVal,sizeof(uiVal_2));
	usVal_1 = (unsigned short)uiVal_1;//在這裡截斷,都取得的是低位
	usVal_2 = (unsigned short)uiVal_2;//在這裡截斷
	printf("usVal_1:%x\n",usVal_1);//在這裡又轉化回來
	printf("usVal_2:%x\n",usVal_2);//在這裡又轉化回來
	return 0;

}
           

  小端模式是低位址存放低位元組,高位址存放高位元組,結構如下所示

78//低位址
56
34
12//高位址
           

  在記憶體裡面測試機是小端,位址由小到大。

val1:78563412
riVal2:12345678
           

  結果如下:

5678
3412
           

如何判斷計算機處理器是大端,還是小端?

#include <stdio.h>
int checkCPU()
{
	{
		union w
		{
			int a;
			char b;
		}c;
		c.a =1;
		return(c.b == 1);
	}
}
int main()
{
	if(checkCPU())
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}
           

編者的處理器為ntel處理器,因為 Intel處理器一般都是小端模式,是以此時程式的輸出結果為:小端

上述代碼中,如果處理器是大端,則傳回0;如果處理器是小端,則傳回1.聯合體 union的存放順序是所有成員都從低位址開始存放,如果能夠通過改代碼知道CPU對記憶體是采用小端模式讀寫,還是采用大端模式讀寫,一定會令面試官刮目相看。

還可以通過指針位址來判斷,由于在32位計算機系統中, short占兩個位元組,char占1個位元組,是以可以采用如下做法實作該判斷。

#include <stdio.h>
int checkCPU()
{
	unsigned short usData = 0x1122;
	unsigned char*pucData = (unsigned char*)&usData;
	return (*pucData == 0x22);
}
int main()
{
	if(checkCPU())
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}
           

程式輸出的結果為:小端

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協定,轉載請附上原文出處連結和本聲明。

本文連結:https://blog.csdn.net/qq_16933601/article/details/116234673

如何進行大小端的轉換?

int swapInt32(int intValue){

    int temp = 0;

    temp = ((intValue & 0x000000FF) <<24)|

           ((intValue & 0x0000FF00) <<8) |

           ((intValue & 0x00FF0000) >>8) |

           ((intValue & 0xFF000000) >>24);
    return temp;
}
/*short型:*/
unsigned short swapShort16(unsigned short shortValue){

 

return ((shortValue & 0x00FF ) <<8) | ((shortValue & 0xFF00)>>8);

}
/*float型:*/
float swapFloat32(float floatValue){

         typedef union SWAP_UNION{

         float unionFloat;

         int   unionInt;

         }SWAP_UNION;
         
         SWAP_UNION swapUnion;
         swapUnion.unionFloat = floatValue;
         swapUnion.unionInt = swapInt32(  swapUnion.unionInt);

		return     swapUnion.unionFloat;
}
/*double型換一種寫法,用一下指針,不然移位移死了……*/
void swapDouble64(unsigned char *pIn, unsigned char *pOut){

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

pOut[7-i] = pIn[i];

}

int main()
{
    int x = 0x12345678;
    int y = swapInt32(x);
    printf("%x\r\n",y);
    return 0;
}
           

如何對絕對位址0x100000指派?

那麼要是想讓程式跳轉到絕對位址是0x100000去執行,應該怎麼做?

首先要将0x100000強制轉換成函數指針,即:

然後再調用它:

*((void (*)())0x100000)();·
           

用typedef可以看得更直覺些:

typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
           

聯系作者

關于作者

作者在準備秋招的過程中,憑借這份資料,最後順利拿到了oppo,小米,兆易創新,全志科技,海康威視等十餘家家公司的offer。現将這部分資料分享出來,希望能對大家有幫助!

如果大家在網上看到了不錯的資料,或者在筆試面試中遇到了資料中沒有的知識點,大家可以關注我的公衆号聯系我,我替大家整理。

繼續閱讀