哈嘍,大家好围辙。我終于回來了!19號(hào)剛提交完大論文放案,就被抓去出差了姚建,折騰了整整一周,26號(hào)晚上吱殉,才回到學(xué)校掸冤。鴿了好久都沒更新干貨了。今天更新一篇關(guān)于Arm的筆試面試題目友雳,文章內(nèi)容已同步更新在github稿湿。
[toc]
ARM體系與架構(gòu)
硬件基礎(chǔ)
NAND FLASH 和NOR FLASH異同?
不同點(diǎn)
類別 | NOR | NAND |
---|---|---|
讀 | 快 像訪問SRAM一樣押赊,可以隨機(jī)訪問任意地址的數(shù)據(jù)饺藤;如:unsighed short *pwAddr = (unsighed short *)0x02;unisignded short wVal;wVal = *pwAddr | 快,有嚴(yán)格的時(shí)序要求,需要通過一個(gè)函數(shù)才能讀取數(shù)據(jù)流礁,先發(fā)送讀命令->發(fā)送地址->判斷nandflash是否就緒->讀取一頁數(shù)據(jù)讀命令涕俗、發(fā)送地址、判斷狀態(tài)神帅、讀數(shù)據(jù)都是通過操作寄存器實(shí)現(xiàn)的,如數(shù)據(jù)寄存器NFDATA |
寫 | 慢再姑,寫之前需要擦除,因?yàn)閷懼荒苁?->0,擦除可以使0->1 | 快找御,寫之前需要擦除元镀,因?yàn)閷懼荒苁?->0,擦除可以使0->1 |
擦除 | 非常慢(5S) | 快(3ms) |
XIP | 代碼可以直接在NOR FLASH上運(yùn)行 | NO |
可靠性 | 比較高,位反轉(zhuǎn)的比例小于NAND FLASH的10% | 比較低霎桅,位反轉(zhuǎn)比較常見栖疑,必須有校驗(yàn)措施 |
接口 | 與RAM接口相同,地址和數(shù)據(jù)總線分開 | I/O接口 |
可擦除次數(shù) | 10000~100000 | 100000~1000000 |
容量 | 小哆档,1MB~32MB | 大蔽挠,16MB~512MB |
主要用途 | 常用于保存代碼和關(guān)鍵數(shù)據(jù) | 用于保存數(shù)據(jù) |
價(jià)格 | 高 | 低 |
注意:nandflash和norflash的0地址是不沖突的,norflash占用BANK地址,而nandflash不占用BANK地址澳淑,它的0地址是內(nèi)部的比原。
相同點(diǎn)
1 | 寫之前都要先擦除,因?yàn)閷懖僮髦荒苁?->0杠巡,而擦除動(dòng)作是為了把所有位都變1 |
---|---|
2 | 擦除單元都以塊為單位 |
CPU,MPU,MCU,SOC,SOPC聯(lián)系與差別量窘?
1.CPU(Central Processing Unit),是一臺(tái)計(jì)算機(jī)的運(yùn)算核心和控制核心。CPU由運(yùn)算器氢拥、控制器和寄存器及實(shí)現(xiàn)它們之間聯(lián)系的數(shù)據(jù)蚌铜、控制及狀態(tài)的總線構(gòu)成。差不多所有的CPU的運(yùn)作原理可分為四個(gè)階段:提饶酆!(Fetch)冬殃、解碼(Decode)、執(zhí)行(Execute)和寫回(Writeback)叁怪。 CPU從存儲(chǔ)器或高速緩沖存儲(chǔ)器中取出指令审葬,放入指令寄存器,并對(duì)指令譯碼奕谭,并執(zhí)行指令涣觉。所謂的計(jì)算機(jī)的可編程性主要是指對(duì)CPU的編程。
2.MPU (Micro Processor Unit)血柳,叫微處理器(不是微控制器)官册,通常代表一個(gè)功能強(qiáng)大的CPU(暫且理解為增強(qiáng)版的CPU吧),但不是為任何已有的特定計(jì)算目的而設(shè)計(jì)的芯片淫茵。這種芯片往往是個(gè)人計(jì)算機(jī)和高端工作站的核心CPU呼盆。最常見的微處理器是Motorola的68K系列和Intel的X86系列娱颊。
3.MCU(Micro Control Unit)馍忽,叫微控制器谅猾,是指隨著大規(guī)模集成電路的出現(xiàn)及其發(fā)展找都,將計(jì)算機(jī)的CPU序矩、RAM树瞭、ROM婴栽、定時(shí)計(jì)數(shù)器和多種I/O接口集成在一片芯片上满粗,形成芯片級(jí)的芯片,比如51愚争,avr這些芯片映皆,內(nèi)部除了CPU外還有RAM,ROM,可以直接加簡(jiǎn)單的外圍器件(電阻,電容)就可以運(yùn)行代碼了轰枝,而MPU如x86捅彻,arm這些就不能直接放代碼了,它只不過是增強(qiáng)版的CPU鞍陨,所以得添加RAM,ROM步淹。
MCU MPU 最主要的區(qū)別就睡能否直接運(yùn)行代碼从隆。MCU有內(nèi)部的RAM ROM,而MPU是增強(qiáng)版的CPU缭裆,需要添加外部RAM ROM才可以運(yùn)行代碼键闺。
4.SOC(System on Chip),指的是片上系統(tǒng)澈驼,MCU只是芯片級(jí)的芯片辛燥,而SOC是系統(tǒng)級(jí)的芯片,它既MCU(51缝其,avr)那樣有內(nèi)置RAM,ROM同時(shí)又像MPU(arm)那樣強(qiáng)大的挎塌,不單單是放簡(jiǎn)單的代碼,可以放系統(tǒng)級(jí)的代碼内边,也就是說可以運(yùn)行操作系統(tǒng)(將就認(rèn)為是MCU集成化與MPU強(qiáng)處理力各優(yōu)點(diǎn)二合一)榴都。
5.SOPC(System On a Programmable Chip)可編程片上系統(tǒng)(FPGA就是其中一種),上面4點(diǎn)的硬件配置是固化的漠其,就是說51單片機(jī)就是51單片機(jī)缭贡,不能變?yōu)閍vr,而avr就是avr不是51單片機(jī)辉懒,他們的硬件是一次性掩膜成型的,能改的就是軟件配置谍失,說白點(diǎn)就是改代碼眶俩,本來是跑流水燈的,改下代碼快鱼,變成數(shù)碼管颠印,而SOPC則是硬件配置,軟件配置都可以修改抹竹,軟件配置跟上面一樣线罕,沒什么好說的,至于硬件窃判,是可以自己構(gòu)建的也就是說這個(gè)芯片是自己構(gòu)造出來的钞楼,這顆芯片我們叫“白片”,什么芯片都不是袄琳,把硬件配置信息下載進(jìn)去了宛琅,他就是相應(yīng)的芯片了,可以讓他變成51色建,也可以是avr壮虫,甚至arm办素,同時(shí)SOPC是在SOC基礎(chǔ)上來的,所以他也是系統(tǒng)級(jí)的芯片逃顶,所以記得當(dāng)把他變成arm時(shí)還得加外圍ROM殊轴,RAM之類的楷掉,不然就是MPU了。
什么是交叉編譯巷屿?
在一種計(jì)算機(jī)環(huán)境中運(yùn)行的編譯程序遍略,能編譯出在另外一種環(huán)境下運(yùn)行的代碼,我們就稱這種編譯器支持交叉編譯僧著。這個(gè)編譯過程就叫交叉編譯搓逾。簡(jiǎn)單地說,就是在一個(gè)平臺(tái)上生成另一個(gè)平臺(tái)上的可執(zhí)行代碼杯拐。
這里需要注意的是所謂平臺(tái)霞篡,實(shí)際上包含兩個(gè)概念:體系結(jié)構(gòu)(Architecture)、操作系統(tǒng)(OperatingSystem)端逼。同一個(gè)體系結(jié)構(gòu)可以運(yùn)行不同的操作系統(tǒng)朗兵;同樣,同一個(gè)操作系統(tǒng)也可以在不同的體系結(jié)構(gòu)上運(yùn)行顶滩。舉例來說余掖,我們常說的x86 Linux平臺(tái)實(shí)際上是Intel x86體系結(jié)構(gòu)和Linux for x86操作系統(tǒng)的統(tǒng)稱;而x86 WinNT平臺(tái)實(shí)際上是Intel x86體系結(jié)構(gòu)和Windows NT for x86操作系統(tǒng)的簡(jiǎn)稱礁鲁。
為什么需要交叉編譯盐欺?
有時(shí)是因?yàn)槟康钠脚_(tái)上不允許或不能夠安裝我們所需要的編譯器,而我們又需要這個(gè)編譯器的某些特征仅醇;有時(shí)是因?yàn)槟康钠脚_(tái)上的資源貧乏冗美,無法運(yùn)行我們所需要編譯器;有時(shí)又是因?yàn)槟康钠脚_(tái)還沒有建立析二,連操作系統(tǒng)都沒有粉洼,根本談不上運(yùn)行什么編譯器。
描述一下嵌入式基于ROM的運(yùn)行方式和基于RAM的運(yùn)行方式有什么區(qū)別叶摄?
基于RAM
- 需要把硬盤和其他介質(zhì)的代碼先加載到ram中属韧,加載過程中一般有重定位的操作。
- 速度比基于ROM的快蛤吓,可用RAM比基于ROM的少宵喂,因?yàn)樗械拇a,數(shù)據(jù)都必須存放在RAM中会傲。
基于ROM
速度較基于RAM的慢樊破,因?yàn)闀?huì)有一個(gè)把變量愉棱,部分代碼等從存儲(chǔ)器(硬盤,flash)搬移到RAM的過程哲戚。
可用RAM資源比基于RAM的多奔滑;
ARM處理器
什么是哈佛結(jié)構(gòu)和馮諾依曼結(jié)構(gòu)?
定義
馮諾依曼結(jié)構(gòu)釆用指令和數(shù)據(jù)統(tǒng)一編址顺少,使用同條總線傳輸朋其,CPU讀取指令和數(shù)據(jù)的操作無法重疊。
哈佛結(jié)構(gòu)釆用指令和數(shù)據(jù)獨(dú)立編址脆炎,使用兩條獨(dú)立的總線傳輸梅猿,CPU讀取指令和數(shù)據(jù)的操作可以重疊。
利弊
馮諾依曼結(jié)構(gòu)主要用于通用計(jì)算機(jī)領(lǐng)域秒裕,需要對(duì)存儲(chǔ)器中的代碼和數(shù)據(jù)頻繁的進(jìn)行修改袱蚓,統(tǒng)一編址有利于節(jié)約資源。
哈佛結(jié)構(gòu)主要用于嵌入式計(jì)算機(jī)几蜻,程序固化在硬件中喇潘,有較高的可靠性、運(yùn)算速度和較大的吞吐梭稚。
什么是ARM流水線技術(shù)颖低?
流水線技術(shù)通 過多個(gè)功能部件并行工作來縮短程序執(zhí)行時(shí)間,提高處理器核的效率和吞吐率弧烤,從而成為微處理器設(shè)計(jì)中最為重要的技術(shù)之一忱屑。ARM7處理器核使用了典型三級(jí)流水線的馮·諾伊曼結(jié)構(gòu),ARM9系列則采用了基于五級(jí)流水線的哈佛結(jié)構(gòu)暇昂。通過增加流水線級(jí)數(shù)簡(jiǎn)化了流水線各級(jí)的邏輯莺戒,進(jìn)一步提高了處理器的性能。
PC代表程序計(jì)數(shù)器急波,流水線使用三個(gè)階段脏毯,因此指令分為三個(gè)階段執(zhí)行:1.取指(從存儲(chǔ)器裝載一條指令);2.譯碼(識(shí)別將要被執(zhí)行的指令)幔崖;3.執(zhí)行(處理指令并將結(jié)果寫回寄存器)。而R15(PC)總是指向“正在取指”的指令渣淤,而不是指向“正在執(zhí)行”的指令或正在“譯碼”的指令赏寇。一般來說,人們習(xí)慣性約定將“正在執(zhí)行的指令作為參考點(diǎn)”价认,稱之為當(dāng)前第一條指令嗅定,因此PC總是指向第三條指令。當(dāng)ARM狀態(tài)時(shí)用踩,每條指令為4字節(jié)長(zhǎng)渠退,所以PC始終指向該指令地址加8字節(jié)的地址忙迁,即:PC值=當(dāng)前程序執(zhí)行位置+8;
ARM指令是三級(jí)流水線碎乃,取指姊扔,譯指,執(zhí)行梅誓,同時(shí)執(zhí)行的恰梢,現(xiàn)在PC指向的是正在取指的地址(下一條指令),那么cpu正在譯指的指令地址是PC-4(假設(shè)在ARM狀態(tài)下梗掰,一個(gè)指令占4個(gè)字節(jié))嵌言,cpu正在執(zhí)行的指令地址是PC-8,也就是說PC所指向的地址和現(xiàn)在所執(zhí)行的指令地址相差8及穗。
當(dāng)突然發(fā)生中斷的時(shí)候摧茴,保存的是PC的地址(PC-8+4 = PC-4 下一條指令的地址)
這樣你就知道了,如果返回的時(shí)候返回PC埂陆,那么中間就有一個(gè)指令沒有執(zhí)行苛白,所以用SUB pc lr-irq #4
。
ARM有幾種工作模式猜惋?
-
用戶模式(USR)
用戶模式是用戶程序的工作模式丸氛,它運(yùn)行在操作系統(tǒng)的用戶態(tài),它沒有權(quán)限去操作其它硬件資源著摔,只能執(zhí)行處理自己的數(shù)據(jù)缓窜,也不能切換到其它模式下,要想
訪問硬件資源或切換到其它模式只能通過軟中斷或產(chǎn)生異常谍咆。
-
系統(tǒng)模式(SYS)
系統(tǒng)模式是特權(quán)模式禾锤,不受用戶模式的限制。用戶模式和系統(tǒng)模式共用一套寄存器摹察,操作系統(tǒng)在該模式下可以方便的訪問用戶模式的寄存器恩掷,而且操作系統(tǒng)的
一些特權(quán)任務(wù)可以使用這個(gè)模式訪問一些受控的資源。
說明:用戶模式與系統(tǒng)模式兩者使用相同的寄存器供嚎,都沒有SPSR(Saved Program Statement Register黄娘,已保存程序狀態(tài)寄存器),但系統(tǒng)模式比用戶模式有更高的權(quán)限克滴,可以訪問所有系統(tǒng)資源逼争。
-
一般中斷模式(IRQ)
一般中斷模式也叫普通中斷模式,用于處理一般的中斷請(qǐng)求劝赔,通常在硬件產(chǎn)生中斷信號(hào)之后自動(dòng)進(jìn)入該模式誓焦,該模式為特權(quán)模式,可以自由訪問系統(tǒng)硬件資源着帽。
快速中斷模式(FIQ)
快速中斷模式是相對(duì)一般中斷模式而言的杂伟,它是用來處理對(duì)時(shí)間要求比較緊急的中斷請(qǐng)求移层,主要用于高速數(shù)據(jù)傳輸及通道處理中。(快中斷有許多(R8~R14)自己的專用寄存器赫粥,發(fā)生中斷時(shí)观话,使用自己的寄存器就避免了保存和恢復(fù)某些寄存器。如果異常中斷處理程序中使用它自己的物理寄存器之外的其他寄存器傅是,異常中斷處理程序必須保存和恢復(fù)這些寄存器)-
管理模式(SVC)
管理模式是CPU上電后默認(rèn)模式匪燕,因此,在該模式下主要用來做系統(tǒng)的初始化喧笔,軟中斷處理也在該模式下帽驯。當(dāng)用戶模式下的用戶程序請(qǐng)求使用硬件資源時(shí),通過軟件中斷進(jìn)入該模式书闸。說明:系統(tǒng)復(fù)位或開機(jī)尼变、軟中斷時(shí)進(jìn)入到SVC模式下。
終止模式(ABT):
中止模式用于支持虛擬內(nèi)存或存儲(chǔ)器保護(hù)浆劲,當(dāng)用戶程序訪問非法地址嫌术,沒有權(quán)限讀取的內(nèi)存地址時(shí),會(huì)進(jìn)入該模式牌借,linux下編程時(shí)經(jīng)常出現(xiàn)的segment fault通常都是在該模式下拋出返回的度气。未定義模式(UND):
未定義模式用于支持硬件協(xié)處理器的軟件仿真,CPU在指令的譯碼階段不能識(shí)別該指令操作時(shí)膨报,會(huì)進(jìn)入未定義模式狡孔。
- 除了用戶模式外术奖,其它6種模式稱為特權(quán)模式阵翎。所謂特權(quán)模式双絮,即具有如下權(quán)利:
a. MRS(把狀態(tài)寄存器的內(nèi)容放到通用寄存器);
b. MSR(把通用寄存器的內(nèi)容放到狀態(tài)寄存器中)够吩。
由于狀態(tài)寄存器中的內(nèi)容不能夠改變比然,因此,要先把內(nèi)容復(fù)制到通用寄存器中周循,然后修改通用寄存器中的內(nèi)容强法,再把通用寄存器中的內(nèi)容復(fù)制給狀態(tài)寄存器中,即可完成“修改狀態(tài)寄存器”的任務(wù)湾笛。
- 剩下的六種模式中除去系統(tǒng)模式外饮怯,統(tǒng)稱為異常模式。
Arm有多少32位寄存器迄本?
ARM處理器共有37個(gè)寄存器。它包含31個(gè)通用寄存器和6個(gè)狀態(tài)寄存器课竣。
Arm2440和6410有什么區(qū)別嘉赎?
主頻不同置媳。2440是400M的。6410是533/667M的公条;
處理器版本不一樣:2440是arm920T內(nèi)核拇囊,6410是arm1176ZJF內(nèi)核;
6410在視頻處理方面比2440要強(qiáng)很多靶橱。內(nèi)部視頻解碼器寥袭,包括MPEG4等視頻格式;
6410支持WMV9关霸、xvid传黄、mpeg4、h264等格式的硬解碼和編碼队寇;
6410多和很多擴(kuò)展接口比如:tv-out膘掰、CF卡和S-Video輸出等;
spi佳遣、串口识埋、sd接口也比那兩個(gè)要豐富;
6410采用的是DDR內(nèi)存控制器零渐;2440采用的是SDRam內(nèi)存控制器窒舟;
6410為雙總線架構(gòu),一路用于內(nèi)存總線诵盼、一路用于Flash總線惠豺;
6410的啟動(dòng)方式更加靈活:主要包括SD、Nand Flash拦耐、Nor Flash和OneFlash等設(shè)備啟動(dòng)耕腾;
6410的Nand Flash支持SLC和MLC兩種架構(gòu),從而大大擴(kuò)大存儲(chǔ)空間杀糯;
6410為雙總線架構(gòu)扫俺,一路用于內(nèi)存總線、一路用于Flash總線固翰;
6410具備8路DMA通道狼纬,包括LCD、UART骂际、Camera等專用DMA通道疗琉;
6410還支持2D和3D的圖形加速;
ARM指令集分為幾類歉铝?
2類盈简,分別為Thumb指令集,ARM指令集。ARM指令長(zhǎng)度為32位柠贤,Thumb指令長(zhǎng)度為16位香浩。這種特點(diǎn)使得ARM既能執(zhí)行16位指令,又能執(zhí)行32位指令臼勉,從而增強(qiáng)了ARM內(nèi)核的功能邻吭。
通用寄存器包括R0~R15,可以分為具體哪三類宴霸?
通用寄存器包括R0-R15囱晴,可以分為3類:
-
未分組寄存器R0-R7
在所有運(yùn)行模式下,未分組寄存器都指向同一個(gè)物理寄存器瓢谢,他們未被系統(tǒng)用作特殊的用途畸写。因此在中斷或異常處理進(jìn)行異常模式轉(zhuǎn)換時(shí),由于不同的處理器運(yùn)行模式均使用相同的物理寄存器恩闻,所以可能造成寄存器中數(shù)據(jù)的破壞艺糜。
-
分組寄存器R8-R14
對(duì)于分組寄存器,他們每次所訪問的物理寄存器都與當(dāng)前的處理器運(yùn)行模式相關(guān)幢尚。
R13常用作存放堆棧指針破停,用戶也可以使用其他寄存器存放堆棧指針,但在Thumb指令集下尉剩,某些指令強(qiáng)制要求使用R13存放堆棧指針真慢。
R14稱為鏈接寄存器(LR,Link Register)理茎,當(dāng)執(zhí)行子程序時(shí)黑界,R14可得到R15(PC)的備份,執(zhí)行完子程序后皂林,又將R14的值復(fù)制回PC朗鸠,即使用R14保存返回地址。
-
程序計(jì)數(shù)器PC(R15)
寄存器R15用作程序計(jì)數(shù)器(PC)础倍,在ARM狀態(tài)下烛占,位[1:0]為0,位[31:2]用于保存PC沟启;在Thumb狀態(tài)下,位[0]為0忆家,位[31:1]用于保存PC。
Arm處理器有幾種工作狀態(tài)德迹?
從編程的角度來看芽卿,ARM微處理器的工作狀態(tài)一般ARM和Thumb有兩種,并可在兩種狀態(tài)之間切換胳搞。
ARM狀態(tài):此時(shí)處理器執(zhí)行32位的字對(duì)齊ARM指令卸例,絕大部分工作在此狀態(tài)称杨。
Thumb狀態(tài):此時(shí)處理器執(zhí)行16位的半字對(duì)齊的Thumb指令。
ARM系統(tǒng)中筷转,在函數(shù)調(diào)用的時(shí)候列另,參數(shù)是通過哪種方式傳遞的?
當(dāng)參數(shù)小于等于4的時(shí)候是通過r0-r3寄存器來進(jìn)行傳遞的旦装,當(dāng)參數(shù)大于4的時(shí)候是通過壓棧的方式進(jìn)行傳遞。
為什么2440的內(nèi)存起始地址是0x30000000摊滔?
S3C2440處理器有八個(gè)固定的內(nèi)存塊阴绢,只有兩個(gè)是可以作為ROM,SRAM和SDRAM等存儲(chǔ)器bank。具體如下圖所示艰躺。
ARM協(xié)處理器指令包括哪3類呻袭,請(qǐng)描述它們的功能。
ARM協(xié)處理器指令包括以下3類:
用于ARM處理器初始化ARM協(xié)處理器的數(shù)據(jù)處理操作腺兴。
用于ARM處理器的寄存器和ARM協(xié)處理器的寄存器間的數(shù)據(jù)傳送操作左电。
用于在ARM協(xié)處理器的寄存器和內(nèi)存單元之間傳送數(shù)據(jù)。
什么是PLL(鎖相環(huán))页响?
簡(jiǎn)單來說篓足,輸入時(shí)鐘的存在是作為“參考源”。鎖相環(huán)不是為了單純產(chǎn)生同頻同相信號(hào)闰蚕,而是一般集成進(jìn)某種“頻率綜合電路”栈拖,產(chǎn)生一個(gè)不同頻,但鎖相的信號(hào)没陡。
有點(diǎn)繞涩哟,打個(gè)比方:某參考晶振10Mhz,頻率綜合器A使用該參考源產(chǎn)生了900Mhz時(shí)鐘盼玄,而頻率綜合器B產(chǎn)生了1Ghz時(shí)鐘贴彼。雖然兩路頻率不同,但由于使用的通一個(gè)參考源埃儿,他們倆仍然是同源信號(hào)器仗。相反,如果不同源蝌箍,那么即便同頻他們也不可能一致青灼,因?yàn)槭澜缟蠜]有兩個(gè)鐘能做到完全一樣,總有微弱的頻差妓盲,導(dǎo)致相位飄移杂拨。在很多現(xiàn)實(shí)應(yīng)用中有要求同源時(shí)鐘的場(chǎng)合,所以悯衬,鎖相環(huán)被廣泛應(yīng)用弹沽。鎖相環(huán)的另外一項(xiàng)衍生應(yīng)用是相干解調(diào)檀夹,可以自己查查相關(guān)資料。
中斷與異常
中斷與異常有何區(qū)別策橘?
中斷是指外部硬件產(chǎn)生的一個(gè)電信號(hào)從CPU的中斷引腳進(jìn)入炸渡,打斷CPU的運(yùn)行。
異常是指軟件運(yùn)行過程中發(fā)生了一些必須作出處理的事件丽已,CPU自動(dòng)產(chǎn)生一個(gè)陷入來打斷CPU的運(yùn)行蚌堵。異常在處理的時(shí)候必須考慮與處理器的時(shí)鐘同步,實(shí)際上異常也稱為同步中斷沛婴,在處理器執(zhí)行到因編譯錯(cuò)誤而導(dǎo)致的錯(cuò)誤指令時(shí)吼畏,或者在執(zhí)行期間出現(xiàn)特殊錯(cuò)誤,必須靠?jī)?nèi)核處理的時(shí)候嘁灯,處理器就會(huì)產(chǎn)生一個(gè)異常泻蚊。
中斷與DMA有何區(qū)別?
DMA:是一種無須CPU的參與丑婿,就可以讓外設(shè)與系統(tǒng)內(nèi)存之間進(jìn)行雙向數(shù)據(jù)傳輸的硬件機(jī)制性雄,使用DMA可以使系統(tǒng)CPU從實(shí)際的I/O數(shù)據(jù)傳輸過程中擺脫出來,從而大大提高系統(tǒng)的吞吐率羹奉。
中斷:是指CPU在執(zhí)行程序的過程中秒旋,出現(xiàn)了某些突發(fā)事件時(shí),CPU必須暫停執(zhí)行當(dāng)前的程序诀拭,轉(zhuǎn)去處理突發(fā)事件滩褥,處理完畢后CPU又返回源程序被中斷的位置并繼續(xù)執(zhí)行。
所以中斷和DMA的區(qū)別就是:DMA不需CPU參與炫加,而中斷是需要CPU參與的瑰煎。
中斷能不能睡眠,為什么俗孝?下半部能不能睡眠酒甸?
中斷處理的時(shí)候,不應(yīng)該發(fā)生進(jìn)程切換。因?yàn)樵谥袛嗌舷挛闹校?strong>唯一能打斷當(dāng)前中斷handler的只有更高優(yōu)先級(jí)的中斷赋铝,它不會(huì)被進(jìn)程打斷插勤。如果在中斷上下文中休眠,則沒有辦法喚醒它革骨,因?yàn)樗械?strong>wake_up_xxx都是針對(duì)某個(gè)進(jìn)程而言的农尖,而在中斷上下文中,沒有進(jìn)程的概念良哲,沒有一個(gè)task_struct(這點(diǎn)對(duì)于softirq和tasklet一樣)盛卡。因此真的休眠了,比如調(diào)用了會(huì)導(dǎo)致阻塞的例程筑凫,內(nèi)核幾乎肯定會(huì)死滑沧。
-
schedule()在切換進(jìn)程時(shí)并村,保存當(dāng)前的進(jìn)程上下文(CPU寄存器的值、進(jìn)程的狀態(tài)以及堆棧中的內(nèi)容)滓技,以便以后恢復(fù)此進(jìn)程運(yùn)行哩牍。中斷發(fā)生后,內(nèi)核會(huì)先保存當(dāng)前被中斷的進(jìn)程上下文(在調(diào)用中斷處理程序后恢復(fù))令漂。
但在中斷處理程序里膝昆,CPU寄存器的值肯定已經(jīng)變化了(最重要的程序計(jì)數(shù)器PC、堆棧SP等)叠必。如果此時(shí)因?yàn)樗呋蜃枞僮髡{(diào)用了schedule()外潜,則保存的進(jìn)程上下文就不是當(dāng)前的進(jìn)程上下文了。所以挠唆,不可以在中斷處理程序中調(diào)用schedule()。
2.4內(nèi)核中schedule()函數(shù)本身在進(jìn)來的時(shí)候判斷是否處于中斷上下文:
if(unlikely(in_interrupt()))
BUG();
?因此嘱吗,強(qiáng)行調(diào)用schedule()的結(jié)果就是內(nèi)核BUG玄组,但看2.6.18的內(nèi)核schedule()的實(shí)現(xiàn)卻沒有這句,改掉了谒麦。
中斷handler會(huì)使用被中斷的進(jìn)程內(nèi)核堆棧俄讹,但不會(huì)對(duì)它有任何影響,因?yàn)閔andler使用完后會(huì)完全清除它使用的那部分堆棧绕德,恢復(fù)被中斷前的原貌患膛。
處于中斷上下文時(shí)候,內(nèi)核是不可搶占的耻蛇。因此踪蹬,如果休眠,則內(nèi)核一定掛起臣咖。
中斷的響應(yīng)執(zhí)行流程是什么?
中斷的響應(yīng)流程:cpu接受中斷->保存中斷上下文跳轉(zhuǎn)到中斷處理歷程->執(zhí)行中斷上半部->執(zhí)行中斷下半部->恢復(fù)中斷上下文。
當(dāng)一個(gè)異常出現(xiàn)以后艾少,ARM微處理器會(huì)執(zhí)行哪幾步操作副渴?
- 將下一條指令的地址存入相應(yīng)連接寄存器LR,以便程序在處理異常返回時(shí)能從正確的位置重新開始執(zhí)行刁赦。若異常是從ARM狀態(tài)進(jìn)入娶聘,則LR寄存器中保存的是下一條指令的地址(當(dāng)前PC+4或PC+8,與異常的類型有關(guān))甚脉;若異常是從Thumb狀態(tài)進(jìn)入丸升,則在LR寄存器中保存當(dāng)前PC的偏移量,這樣牺氨,異常處理程序就不需要確定異常是從何種狀態(tài)進(jìn)入的发钝。例如:在軟件中斷異常SWI顿涣,指令 MOV PC,R14_svc總是返回到下一條指令酝豪,不管SWI是在ARM狀態(tài)執(zhí)行涛碑,還是在Thumb狀態(tài)執(zhí)行。
- 將CPSR復(fù)制到相應(yīng)的SPSR中孵淘。
- 根據(jù)異常類型蒲障,強(qiáng)制設(shè)置CPSR的運(yùn)行模式位。
- 強(qiáng)制PC從相關(guān)的異常向量地址取下一條指令執(zhí)行瘫证,從而跳轉(zhuǎn)到相應(yīng)的異常處理程序處揉阎。
寫一個(gè)中斷服務(wù)需要注意哪些?如果中斷產(chǎn)生之后要做比較多的事情你是怎么做的背捌?
寫一個(gè)中斷服務(wù)程序要注意快進(jìn)快出毙籽,在中斷服務(wù)程序里面盡量快速采集信息,包括硬件信息毡庆,然后退出中斷坑赡,要做其它事情可以使用工作隊(duì)列或者tasklet方式。也就是中斷上半部和下半部么抗。
中斷服務(wù)程序中不能有阻塞操作毅否。應(yīng)為中斷期間是完全占用CPU的(即不存在內(nèi)核調(diào)度),中斷被阻塞住蝇刀,其他進(jìn)程將無法操作螟加。
中斷服務(wù)程序注意返回值,要用操作系統(tǒng)定義的宏做為返回值吞琐,而不是自己定義的捆探。
如果要做的事情較多,應(yīng)將這些任務(wù)放在后半段(tasklet站粟,等待隊(duì)列等)處理徐许。
為什么FIQ比IRQ要快?
ARM的FIQ模式提供了更多的banked寄存器卒蘸,r8到r14還有SPSR雌隅,而IRQ模式就沒有那么多,R8,R9,R10,R11,R12對(duì)應(yīng)的banked的寄存器就沒有缸沃,這就意味著在ARM的IRQ模式下恰起,中斷處理程序自己要保存R8到R12這幾個(gè)寄存器,然后退出中斷處理時(shí)程序要恢復(fù)這幾個(gè)寄存器蹦渣,而FIQ模式由于這幾個(gè)寄存器都有banked寄存器,模式切換時(shí)CPU自動(dòng)保存這些值到banked寄存器锄奢,退出FIQ模式時(shí)自動(dòng)恢復(fù),所以這個(gè)過程FIQ比IRQ快.不要小看這幾個(gè)寄存器,ARM在編譯的時(shí)候栏账,如果你FIQ中斷處理程序足夠用這幾個(gè)獨(dú)立的寄存器來運(yùn)作,它就不會(huì)進(jìn)行通用寄存器的壓棧,這樣也省了一些時(shí)間制轰。
FIQ比IRQ有更高優(yōu)先級(jí),如果FIQ和IRQ同時(shí)產(chǎn)生调俘,那么FIQ先處理先蒋。
在symbian系統(tǒng)里眯搭,當(dāng)CPU處于FIQ模式處理FIQ中斷的過程中寇蚊,預(yù)取指令異常,未定義指令異常爹梁,軟件中斷全被禁止,所有的中斷被屏蔽。所以FIQ就會(huì)很快執(zhí)行看成,不會(huì)被其他異常或者中斷打斷,所以它又比IRQ快了琴拧。而IRQ不一樣,當(dāng)ARM處理IRQ模式處理IRQ中斷時(shí),如果來了一個(gè)FIQ中斷請(qǐng)求于置,那正在執(zhí)行的IRQ中斷處理程序會(huì)被搶斷,ARM切換到FIQ模式去執(zhí)行這個(gè)FIQ,所以FIQ比IRQ快多了乳讥。
另外FIQ的入口地址是0x1c,IRQ的入口地址是0x18。寫過完整匯編系統(tǒng)的都比較明白這點(diǎn)的差別汹忠,18只能放一條指令,為了不與1C處的FIQ沖突铅乡,這個(gè)地方只能跳轉(zhuǎn)僧界,而FIQ不一樣欢峰,1C以后沒有任何中斷向量表了宠漩,這樣可以直接在1C處放FIQ的中斷處理程序,由于跳轉(zhuǎn)的范圍限制魁索,至少少了一條跳轉(zhuǎn)指令饶火。
中斷和輪詢哪個(gè)效率高?怎樣決定是采用中斷方式還是采用輪詢方式去實(shí)現(xiàn)驅(qū)動(dòng)瀑构?
中斷是CPU處于被動(dòng)狀態(tài)下來接受設(shè)備的信號(hào)澡刹,而輪詢是CPU主動(dòng)去查詢該設(shè)備是否有請(qǐng)求陆赋。
凡事都是兩面性,所以嚷闭,看效率不能簡(jiǎn)單的說那個(gè)效率高攒岛。如果是請(qǐng)求設(shè)備是一個(gè)頻繁請(qǐng)求cpu的設(shè)備,或者有大量數(shù)據(jù)請(qǐng)求的網(wǎng)絡(luò)設(shè)備胞锰,那么輪詢的效率是比中斷高灾锯。如果是一般設(shè)備兼雄,并且該設(shè)備請(qǐng)求cpu的頻率比較低恕稠,則用中斷效率要高一些。主要是看請(qǐng)求頻率。
通信協(xié)議
什么是異步傳輸和同步傳輸技羔?
異步傳輸:是一種典型的基于字節(jié)的輸入輸出张漂,數(shù)據(jù)按每次一個(gè)字節(jié)進(jìn)行傳輸,其傳輸速度低尿这。
同步傳輸:需要外界的時(shí)鐘信號(hào)進(jìn)行通信,是把數(shù)據(jù)字節(jié)組合起來一起發(fā)送仇让,這種組合稱之為幀剪芥,其傳輸速度比異步傳輸快箭券。
RS232和RS485通訊接口有什么區(qū)別你画?
傳輸方式不同。 RS232采取不平衡傳輸方式嗅绸,即所謂單端通訊羹铅。 而RS485則采用平衡傳輸深夯,即差分傳輸方式兑宇。
傳輸距離不同。RS232適合本地設(shè)備之間的通信粱坤,傳輸距離一般不超過20m隶糕。而RS485的傳輸距離為幾十米到上千米。
設(shè)備數(shù)量站玄。RS232 只允許一對(duì)一通信若厚,而RS485 接口在總線上是允許連接多達(dá)128個(gè)收發(fā)器。
連接方式蜒什。RS232测秸,規(guī)定用電平表示數(shù)據(jù),因此線路就是單線路的灾常,用兩根線才能達(dá)到全雙工的目的霎冯;而RS485, 使用差分電平表示數(shù)據(jù)钞瀑,因此,必須用兩根線才能達(dá)到傳輸數(shù)據(jù)的基本要求雕什,要實(shí)現(xiàn)全雙工缠俺,必需用4根線显晶。
?總結(jié):從某種意義上,可以說壹士,線路上存在的僅僅是電流磷雇,RS232/RS485規(guī)定了這些電流在什么樣的線路上流動(dòng)和流動(dòng)的樣式。
SPI協(xié)議
SPI的應(yīng)用
SPI(Serial Peripheral Interface)協(xié)議是由摩托羅拉公司提出的通訊協(xié)議躏救,即串行外圍設(shè)備接口唯笙,是一種高速全雙工的通信總線。SPI總線系統(tǒng)是一種同步串行外設(shè)接口盒使,它可以使MCU與各種外圍設(shè)備以串行方式進(jìn)行通信以交換信息崩掘。SPI總線可直接與各個(gè)廠家生產(chǎn)的多種標(biāo)準(zhǔn)外圍器件相連,包括FLASH少办、RAM苞慢、網(wǎng)絡(luò)控制器、LCD顯示驅(qū)動(dòng)器英妓、A/D轉(zhuǎn)換器和MCU等枉疼。
接口
-
MOSI (Master Output, Slave Input)
主設(shè)備輸出/從設(shè)備輸入引腳鞋拟。主機(jī)的數(shù)據(jù)從這條信號(hào)線輸出骂维,從機(jī)由這條信號(hào)線讀入主機(jī)發(fā)送的數(shù)據(jù),即這條線上數(shù)據(jù)的方向?yàn)橹鳈C(jī)到從機(jī)贺纲。
-
MISO(Master Input,航闺, Slave Output)
主設(shè)備輸入/從設(shè)備輸出引腳。主機(jī)從這條信號(hào)線讀入數(shù)據(jù)猴誊,從機(jī)的數(shù)據(jù)由這條信號(hào)線輸出到主機(jī)潦刃,即在這條線上數(shù)據(jù)的方向?yàn)閺臋C(jī)到主機(jī)。
-
SCLK (Serial Clock)
時(shí)鐘信號(hào)線懈叹,用于通訊數(shù)據(jù)同步乖杠。它由通訊主機(jī)產(chǎn)生,決定了通訊的速率澄成,不同的設(shè)備支持的最高時(shí)鐘頻率不一樣胧洒,如 STM32 的 SPI 時(shí)鐘頻率最大為fpclk/2,兩個(gè)設(shè)備之間通訊時(shí)墨状,通訊速率受限于低速設(shè)備卫漫。
-
SS( Slave Select)
從設(shè)備選擇信號(hào)線,常稱為片選信號(hào)線肾砂,也稱為 NSS列赎、 CS,以下用 NSS 表示镐确。 當(dāng)有多個(gè) SPI 從設(shè)備與 SPI 主機(jī)相連時(shí)包吝,設(shè)備的其它信號(hào)線 SCK饼煞、MOSI 及 MISO 同時(shí)并聯(lián)到相同的 SPI 總線上,即無論有多少個(gè)從設(shè)備诗越,都共同只使用這 3 條總線砖瞧;而每個(gè)從設(shè)備都有獨(dú)立的這一條 NSS 信號(hào)線,本信號(hào)線獨(dú)占主機(jī)的一個(gè)引腳掺喻,即有多少個(gè)從設(shè)備芭届,就有多少條片選信號(hào)線储矩。
I2C 協(xié)議中通過設(shè)備地址來尋址感耙、選中總線上的某個(gè)設(shè)備并與其進(jìn)行通訊;而 SPI 協(xié)議中沒有設(shè)備地址持隧,它使用 NSS 信號(hào)線來尋址即硼,當(dāng)主機(jī)要選擇從設(shè)備時(shí),把該從設(shè)備的 NSS 信號(hào)線設(shè)置為低電平屡拨,該從設(shè)備即被選中只酥,即片選有效,接著主機(jī)開始與被選中的從設(shè)備進(jìn)行 SPI 通訊呀狼。所以SPI 通訊以 NSS 線置低電平為開始信號(hào)裂允,以 NSS 線被拉高作為結(jié)束信號(hào)。
協(xié)議層
SPI 通訊設(shè)備之間的常用連接方式見下圖:
SPI 通訊的通訊時(shí)序哥艇,見下圖:
-
通訊的起始和停止信號(hào)
在圖中的標(biāo)號(hào)1處绝编,NSS 信號(hào)線由高變低,是 SPI 通訊的起始信號(hào)貌踏。 NSS 是每個(gè)從機(jī)各自獨(dú)占的信號(hào)線十饥,當(dāng)從機(jī)檢在自己的 NSS 線檢測(cè)到起始信號(hào)后,就知道自己被主機(jī)選中了祖乳,開始準(zhǔn)備與主機(jī)通訊逗堵。在圖中的標(biāo)號(hào)?處, NSS 信號(hào)由低變高眷昆,是 SPI 通訊的停止信號(hào)蜒秤,表示本次通訊結(jié)束,從機(jī)的選中狀態(tài)被取消亚斋。
-
數(shù)據(jù)有效性
SPI 使用 MOSI 及 MISO 信號(hào)線來傳輸數(shù)據(jù)垦藏,使用 SCK 信號(hào)線進(jìn)行數(shù)據(jù)同步。 MOSI及 MISO 數(shù)據(jù)線在 SCK 的每個(gè)時(shí)鐘周期傳輸一位數(shù)據(jù)伞访,且數(shù)據(jù)輸入輸出是同時(shí)進(jìn)行的掂骏。數(shù)據(jù)傳輸時(shí), MSB 先行(高位先行)或 LSB(低位先行)先行并沒有作硬性規(guī)定厚掷,但要保證兩個(gè) SPI 通訊設(shè)備之間使用同樣的協(xié)定弟灼,一般都會(huì)采用上圖中的 MSB 先行(高位先行)模式级解。
觀察圖中的2345標(biāo)號(hào)處, MOSI 及 MISO 的數(shù)據(jù)在 SCK 的上升沿期間變化輸出田绑,在 SCK 的下降沿時(shí)被采樣勤哗。即在 SCK 的下降沿時(shí)刻, MOSI 及 MISO 的數(shù)據(jù)有效掩驱,高電平時(shí)表示數(shù)據(jù)“1”芒划,為低電平時(shí)表示數(shù)據(jù)“0”。在其它時(shí)刻欧穴,數(shù)據(jù)無效民逼, MOSI 及 MISO為下一次表示數(shù)據(jù)做準(zhǔn)備。
SPI 每次數(shù)據(jù)傳輸可以 8 位或 16 位為單位涮帘,每次傳輸?shù)膯挝粩?shù)不受限制拼苍。
-
CPOL(時(shí)鐘極性)/CPHA(時(shí)鐘相位)及通訊模式
上面講述的圖中的時(shí)序只是 SPI 中的其中一種通訊模式, SPI 一共有四種通訊模式调缨,它們的主要區(qū)別是:總線空閑時(shí) SCK 的時(shí)鐘狀態(tài)以及數(shù)據(jù)采樣時(shí)刻疮鲫。為方便說明,在此引入“時(shí)鐘極性CPOL”和“時(shí)鐘相位 CPHA”的概念弦叶。
時(shí)鐘極性 CPOL 是指 SPI 通訊設(shè)備處于空閑狀態(tài)時(shí)俊犯, SCK 信號(hào)線的電平信號(hào)(即 SPI 通訊開始前、 NSS 線為高電平時(shí) SCK 的狀態(tài))伤哺。 CPOL=0 時(shí)燕侠, SCK 在空閑狀態(tài)時(shí)為低電平,CPOL=1 時(shí)默责,則相反贬循。
時(shí)鐘相位 CPHA 是指數(shù)據(jù)的采樣的時(shí)刻,當(dāng) CPHA=0 時(shí)桃序, MOSI 或 MISO 數(shù)據(jù)線上的信號(hào)將會(huì)在 SCK 時(shí)鐘線的“奇數(shù)邊沿” 被采樣杖虾。當(dāng) CPHA=1 時(shí),數(shù)據(jù)線在 SCK 的“偶數(shù)邊沿” 采樣媒熊。
IIC協(xié)議
簡(jiǎn)介
IIC協(xié)議是由數(shù)據(jù)線SDA和時(shí)鐘SCL構(gòu)成的串行總線奇适,可發(fā)送和接收數(shù)據(jù),是一個(gè)多主機(jī)的半雙工通信方式
每個(gè)掛接在總線上的器件都有個(gè)唯一的地址。位速在標(biāo)準(zhǔn)模式下可達(dá) 100kbit/s,在快速模式下可達(dá)400kbit/s芦鳍,在高速模式下可待3.4Mbit/s嚷往。
I2C總線系統(tǒng)結(jié)構(gòu),如下所示:
I2C時(shí)序介紹
1. 空閑狀態(tài)
當(dāng)總線上的SDA和SCL兩條信號(hào)線同時(shí)處于高電平,便是空閑狀態(tài),如上面的硬件圖所示,當(dāng)我們不傳輸數(shù)據(jù)時(shí), SDA和SCL被上拉電阻拉高,即進(jìn)入空閑狀態(tài)
2. 起始信號(hào)
當(dāng)SCL為高期間,SDA由高到低的跳變柠衅;便是總線的啟動(dòng)信號(hào),只能由主機(jī)發(fā)起,且在空閑狀態(tài)下才能啟動(dòng)該信號(hào),如下圖所示:
3. 停止信號(hào)
當(dāng)SCL為高期間皮仁,SDA由低到高的跳變;便是總線的停止信號(hào),表示數(shù)據(jù)已傳輸完成,如下圖所示:
4. 傳輸數(shù)據(jù)格式
當(dāng)發(fā)了起始信號(hào)后,就開始傳輸數(shù)據(jù),傳輸?shù)臄?shù)據(jù)格式如下圖所示:
當(dāng)SCL為高電平時(shí),便會(huì)獲取SDA數(shù)據(jù)值,其中SDA數(shù)據(jù)必須是穩(wěn)定的(若SDA不穩(wěn)定就會(huì)變成起始/停止信號(hào))。
當(dāng)SCL為低電平時(shí),便是SDA的電平變化狀態(tài)贷祈。
若主從機(jī)在傳輸數(shù)據(jù)期間,需要完成其它功能(例如一個(gè)中斷),可以主動(dòng)拉低SCL,使I2C進(jìn)入等待狀態(tài),直到處理結(jié)束再釋放SCL,數(shù)據(jù)傳輸會(huì)繼續(xù)
5. 應(yīng)答信號(hào)ACK
I2C總線上的數(shù)據(jù)都是以8位數(shù)據(jù)(字節(jié))進(jìn)行的趋急,當(dāng)發(fā)送了8個(gè)數(shù)據(jù)后,發(fā)送方會(huì)在第9個(gè)時(shí)鐘脈沖期間釋放SDA數(shù)據(jù)势誊,當(dāng)接收方接收該字節(jié)成功呜达,便會(huì)輸出一個(gè)ACK應(yīng)答信號(hào),當(dāng)SDA為高電平,表示為非應(yīng)答信號(hào)NACK粟耻,當(dāng)SDA為低電平查近,表示為有效應(yīng)答信號(hào)ACK
PS:當(dāng)主機(jī)為接收方時(shí),收到最后一個(gè)字節(jié)后,主機(jī)可以不發(fā)送ACK,直接發(fā)送停止信號(hào)來結(jié)束傳輸。
當(dāng)從機(jī)為接收方時(shí)挤忙,沒有發(fā)送ACK霜威,則表示從機(jī)可能在忙其它事、或者不匹配地址信號(hào)和不支持多主機(jī)發(fā)送饭玲,主機(jī)可以發(fā)送停止信號(hào)域携,再次發(fā)送起始信號(hào)啟動(dòng)新的傳輸捞蚂。
6. 完整的數(shù)據(jù)傳輸
如下圖所示, 發(fā)送起始信號(hào)后,便發(fā)送一個(gè)8位的設(shè)備地址,其中第8位是對(duì)設(shè)備的讀寫標(biāo)志,后面緊跟著的就是數(shù)據(jù)了,直到發(fā)送停止信號(hào)終止突勇。
PS:當(dāng)我們第一次是讀操作耙考,然后想換成寫操作時(shí)误窖,可以再次發(fā)送一個(gè)起始信號(hào)昂芜,然后發(fā)送讀的設(shè)備地址螺捐,不需要停止信號(hào)便能實(shí)現(xiàn)不同的地址轉(zhuǎn)換睬关。
IIC傳輸數(shù)據(jù)的格式
1.寫操作
剛開始主芯片要發(fā)出一個(gè)start信號(hào)吆录,然后發(fā)出一個(gè)(用來確定是往哪一個(gè)芯片寫數(shù)據(jù))窑滞,方向(讀/寫,0表示寫恢筝,1表示讀)哀卫。回應(yīng)(用來確定這個(gè)設(shè)備是否存在),然后就可以傳輸數(shù)據(jù)撬槽,傳輸數(shù)據(jù)之后此改,要有一個(gè)回應(yīng)信號(hào)(確定數(shù)據(jù)是否接受完成),然后再傳輸下一個(gè)數(shù)據(jù)侄柔。每傳輸一個(gè)數(shù)據(jù)共啃,接受方都會(huì)有一個(gè)回應(yīng)信號(hào),數(shù)據(jù)發(fā)送完之后暂题,主芯片就會(huì)發(fā)送一個(gè)停止信號(hào)移剪。
白色背景:主→從⌒秸撸灰色背景:從→主纵苛。
2.讀操作
剛開始主芯片要發(fā)出一個(gè)start信號(hào),然后發(fā)出一個(gè)設(shè)備地址(用來確定是從哪一個(gè)芯片讀取數(shù)據(jù)),方向(讀/寫攻人,0表示寫幔虏,1表示讀)。回應(yīng)(用來確定這個(gè)設(shè)備是否存在)贝椿,然后就可以傳輸數(shù)據(jù)想括,傳輸數(shù)據(jù)之后,要有一個(gè)回應(yīng)信號(hào)(確定數(shù)據(jù)是否接受完成)烙博,然后在傳輸下一個(gè)數(shù)據(jù)瑟蜈。每傳輸一個(gè)數(shù)據(jù),接受方都會(huì)有一個(gè)回應(yīng)信號(hào)渣窜,數(shù)據(jù)發(fā)送完之后铺根,主芯片就會(huì)發(fā)送一個(gè)停止信號(hào)。
白色背景:主→從乔宿∥挥兀灰色背景:從→主
編程
嵌人式編程中,什么是大端详瑞?什么是小端掂林?
大端模式:低位字節(jié)存在高地址上,高位字節(jié)存在低地址上坝橡。
小端模式:高位字節(jié)存在高地址上泻帮,低位字節(jié)存在低地址上。
STM32屬于小端模式计寇,簡(jiǎn)單的說锣杂,比如u32 temp=0X12345678;假設(shè)temp地址在0X2000 0010番宁。那么在內(nèi)存里面,存放就變成了:
地址 | HEX |
0X2000 0010 | 78 56 43 12 |
因?yàn)槭?6進(jìn)制的元莫,一個(gè)數(shù)為0.5字節(jié),所以 12 代表一個(gè)字節(jié) 34 代表一個(gè)字節(jié)蝶押。
釆用小端模式的CPU對(duì)操作數(shù)的存放方式是從低字節(jié)到高字節(jié)踱蠢,而大端模式對(duì)操作數(shù)的存放方式是從高字節(jié)到低字節(jié)。例如播聪,16位寬的數(shù)0x1234在小端模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開始存放)見表1朽基,而在大端模式CPU內(nèi)存中的存放方式見表2。
??????????????????????表1?0x1234在小端CPU內(nèi)存中的存放方式
內(nèi)存地址 | 存放內(nèi)容 |
---|---|
0x4000 | 0x34 |
0x4001 | 0x12 |
??????????????????????表2?0x1234在大端CPU內(nèi)存中的存放方式
內(nèi)存地址 | 存放內(nèi)容 |
---|---|
0x4000 | 0x12 |
0x4001 | 0x34 |
??32位寬的數(shù)0x12345678在小端模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開始存放)見表3离陶,而在大端模式CPU內(nèi)存中的存放方式見表4稼虎。
??????????????????????表3?0x12345678在小端CPU內(nèi)存中的存放方式
內(nèi)存地址 | 存放內(nèi)容 |
---|---|
0x4000 | 0x78 |
0x4001 | 0x56 |
0x4002 | 0x34 |
0x4003 | 0x12 |
??????????????????????表4?0x12345678在大端CPU內(nèi)存中的存放方式
內(nèi)存地址 | 存放內(nèi)容 |
---|---|
0x4000 | 0x12 |
0x4001 | 0x34 |
0x4002 | 0x56 |
0x4003 | 0x78 |
以下程序?yàn)槔?/p>
#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;
}
程序的輸出結(jié)果為 50。
上例中招刨, sizeof( test)=2霎俩,上例的聲明方式是把一個(gè) short(也就是一塊16位內(nèi)存)分成3部分,各部分的大小分別是4位、5位打却、7位杉适,賦值語句i*( short*)&test)
就是把上面的16位內(nèi)存轉(zhuǎn)換成 short類型進(jìn)行解釋。
變量a的二進(jìn)制表示為0000000000000010柳击,取其低四位是0010.變量b的二進(jìn)制表示為0000000000000011猿推,取其低五位是00011。變量c的二進(jìn)制表示為0000000000000000捌肴,取其低七位是0000000蹬叭。
80x86機(jī)是小端(修改分區(qū)表時(shí)要注意)模式,單片機(jī)一般為大端模式状知。小端一般是低位字節(jié)在高位字節(jié)的前面秽五,也就是低位在內(nèi)存地址低的一端,可以這樣記(小端→低位→在前→與正常邏輯順序相反)饥悴,所以合成后得到0000000000110010坦喘,即十進(jìn)制的50。
下面給出另外一個(gè)例子
#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;//在這里截?cái)辔魃瑁既〉玫氖堑臀? usVal_2 = (unsigned short)uiVal_2;//在這里截?cái)? printf("usVal_1:%x\n",usVal_1);//在這里又轉(zhuǎn)化回來
printf("usVal_2:%x\n",usVal_2);//在這里又轉(zhuǎn)化回來
return 0;
}
??小端模式是低地址存放低字節(jié)瓣铣,高地址存放高字節(jié),結(jié)構(gòu)如下所示
78//低地址
56
34
12//高地址
??在內(nèi)存里面測(cè)試機(jī)是小端济榨,地址由小到大坯沪。
val1:78563412
riVal2:12345678
??結(jié)果如下:
5678
3412
如何判斷計(jì)算機(jī)處理器是大端绿映,還是小端擒滑?
#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處理器,因?yàn)?Intel處理器一般都是小端模式叉弦,所以此時(shí)程序的輸出結(jié)果為:小端
上述代碼中丐一,如果處理器是大端,則返回0淹冰;如果處理器是小端库车,則返回1.聯(lián)合體 union的存放順序是所有成員都從低地址開始存放,如果能夠通過改代碼知道CPU對(duì)內(nèi)存是采用小端模式讀寫樱拴,還是采用大端模式讀寫柠衍,一定會(huì)令面試官刮目相看。
還可以通過指針地址來判斷晶乔,由于在32位計(jì)算機(jī)系統(tǒng)中珍坊, short占兩個(gè)字節(jié),char占1個(gè)字節(jié)正罢,所以可以采用如下做法實(shí)現(xiàn)該判斷阵漏。
#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;
}
程序輸出的結(jié)果為:小端
如何進(jìn)行大小端的轉(zhuǎn)換?
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;
}
如何對(duì)絕對(duì)地址0x100000賦值回还?
(unsigned int*)0x100000 = 1234;
那么要是想讓程序跳轉(zhuǎn)到絕對(duì)地址是0x100000去執(zhí)行,應(yīng)該怎么做叹洲?
*((void (*)( ))0x100000 ) ( );
首先要將0x100000強(qiáng)制轉(zhuǎn)換成函數(shù)指針,即:
(void (*)())0x100000
然后再調(diào)用它:
*((void (*)())0x100000)();·
用typedef可以看得更直觀些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
聯(lián)系作者
關(guān)于作者
作者在準(zhǔn)備秋招的過程中柠硕,憑借這份資料,最后順利拿到了oppo运提,小米仅叫,兆易創(chuàng)新,全志科技糙捺,航朐郏康威視等十余家家公司的offer。現(xiàn)將這部分資料分享出來洪灯,希望能對(duì)大家有幫助坎缭!
如果大家在網(wǎng)上看到了不錯(cuò)的資料,或者在筆試面試中遇到了資料中沒有的知識(shí)點(diǎn)签钩,大家可以關(guān)注我的公眾號(hào)聯(lián)系我掏呼,我替大家整理。
資料如有錯(cuò)誤或者不合適的地方铅檩,可以在github向我提交issues憎夷。由于精力有限,所以只會(huì)用心維護(hù)好github和公眾號(hào)兩個(gè)平臺(tái)昧旨。資料中的勘誤也會(huì)同步更新在github中拾给。
github倉(cāng)庫
這份資料總共有七個(gè)部分,分別為:C/C++兔沃,數(shù)據(jù)結(jié)構(gòu)與算法分析蒋得,Arm體系與架構(gòu),Linux驅(qū)動(dòng)開發(fā)乒疏,操作系統(tǒng)额衙,網(wǎng)絡(luò)編程,名企筆試真題怕吴。所有內(nèi)容均會(huì)同步更新到github倉(cāng)庫中窍侧。點(diǎn)擊跳轉(zhuǎn)