關於ARM loader的一些心得

2021-09-19 10:45:55 字數 3817 閱讀 6572

最近的專案裡需要用ks8695這塊mpu,它是arm922t核心的,有cache,也有mmu,ram和rom需要外擴,最大都支援到64m,足以跑起乙個完整功能的linux核.雖然這mpu主頻最高只有166mhz,相比三星的s3c2410等效能不是很強,但有內建的硬體wan口和lan口,構建網路路由器非常方便.

考慮到各種原因,最主要是實時性響應和速度響應的原因,決定不上linux作業系統,當作普通微控制器以單一任務不斷迴圈的方式實現,這就涉及到了loader的問題.由於專用於網路,普及率不大,這塊mpu的網上資料不多,隨開發板贈送的loader是uboot,uboot是引導linux核心的,功能多,但要在linux環境下編譯和除錯,比較麻煩.我習慣用的工具是ads,因此決定用ads的彙編實現乙個簡單功能的loader(以下提到的**語法全部是針對ads環境的,而且僅是ks8695這塊晶元,對於keil for arm或gcc環境或其他arm晶元需要做別的考慮,但可以參考下面的作法和思路).

玩arm的朋友,少不免要接觸loader,但因為loader涉及到很多跟硬體有關的很抽象的東西,看起來比較複雜和難理解。希望下面說的這些能幫助有興趣的朋友更好理解。

下面由簡單到複雜來說說這個loader。

先想想,這個loader該有哪些功能呢?很明顯,最重要的是,它必須最後能呼叫c語言裡的main函式,因為我不想整個專案都用彙編寫,畢竟我不是自虐狂.而很明顯,如果你要呼叫函式,必須進行入棧,出棧這些保護現場的工作,否則程式就會亂套.

那保護現場工作需要什麼?當然就是需要ram來儲存現場.對於ks8695,它沒有內建可隨意使用的ram(實際上,它有特殊的小容量的ram,但那是給網絡卡這些做硬體資料緩衝,使用者是不能隨意呼叫的,順便提一下,arm晶元很多,不同的廠家有不同的硬體配置,譬如很多低端應用的arm晶元其實有內建的sram,譬如菲利浦的lpc系列),因此,就得使用外擴的ram了.

開發板上用的是sdram,sdram的本身的特性決定,需要定時重新整理的支援,ks8695有內建的sdram控制器,只要往某個專用的暫存器寫入一些與硬體引數有關的數值,該sdram控制器就能自動產生各種讀寫sdram的時序訊號來驅動sdram。然後使用者程式只需用str和ldr指令就能讀寫sdram的內容.

ok,現在有點頭緒了,loader至少要完成這兩個功能:

只要這兩部做完,其實就可以呼叫c裡的main函式,然後由main函式再呼叫各種功能的子函式,以後就愛咋滴就咋滴了.

咋一看,似乎這兩步做完,就天下太平了,真的就這麼簡單嗎?

未必,別忘了,幾乎所有的cpu都帶有中斷觸發機制.乙個稍能完成點實用功能的專案,你想完全避開中斷處理這一部分是完全不可能的,也不現實,你必須按你的需要來編寫各種各樣的中斷服務程式,處理各種各樣的中斷觸發(至於中斷觸發對cpu來說是必需的嗎?中斷有什麼好處?

中斷時cpu的硬體會做什麼動作?...這些就不想羅嗦,有興趣的可以參考51系列的中斷原理作為入門理解).編寫中斷服務程式,可以在c語言裡實現,不要在loader裡實現,loader裡要實現的,是要建立中斷向量表.

中斷向量表是乙個有點專業的名詞,請自行查入門資料.

這裡說說為什麼要建立中斷向量表.在51微控制器裡,是不用自己建立中斷向量表的,這是因為標準51核的中斷,本身就是乙個向量中斷(自行查資料),自身硬體裡就已經有內建的中斷向量表,沒必要自己去建立.就是說,當某個中斷觸發時,51核的硬體會自動把pc置成相應的固定的位址入口來執行相應的中斷處理程式,不同的中斷觸發時,會有不同的位址入口,一一對應,俗稱向量中斷.

但ks8695不是這樣(很多arm晶元沒中斷向量表,但有些arm晶元同時支援向量中斷和非向量中斷兩種模式,可以按需要設定),它沒內建的中斷向量表,當中斷觸發時,無論什麼中斷,入口位址只有乙個,你必須在這個入口程式裡讀取某些中斷暫存器的內容,來判斷究竟是發生了哪個中斷,然後通過查表,查自己建立的中斷向量表,來呼叫相應的中斷處理程式.

現在看來,loader複雜一點點了,歸納一下,現在變成有三個功能需要而且是必須要完成了:

完成了這三步,似乎又天下太平可以一馬平川了,真的是這樣嗎?不是的.下面還有乙個功能必須要實現:變數的初始化.

變數的初始化是個什麼樣的概念呢?舉個簡單的例子,如果你程式裡有個變數這樣定義(這是不可能避免的吧):

uchar i=5;

main()

就是說,i這個變數,初始值是5,具體反映到硬體上面,就是說,i這個變數所對應的記憶體單元,它在相應程式要執行之前,這個記憶體單元裡儲存的數值應該是5.否則,這個記憶體單元儲存的是上電時硬體隨機產生的不確定數值.

自己來做變數初始化的工作,其實不是必要的,而僅僅是當使用的編譯器是ads,才是必要的.如果使用的是其他編譯器,有可能不用做這步.譬如keil的編譯器在鏈結成最終**時,會自動新增一段變數初始化的**,而gcc編譯器記得也是這樣.

現在用的編譯器是ads。

因此,很遺憾,loader又得複雜一點點了,新的列表如下:

這四步做完,確實可以一馬平川了,但如果你想獨步天下,還需要做得更好.作為乙個程式設計人員,通常都是完美主義者,偏執狂,所追求的是無止境的效率和自由,我想很少有人會拒絕耍一些提高程式效率的手段吧?

於是下面可以再多了乙個步驟,但這個功能對ks8695來說其實不是必需的(因為ks8695用的是nor flash,允許單位元組隨機訪問,**可以在nor flash裡執行,但對於別的arm晶元,如果用的是nand flash,由於不支援單位元組讀以及隨機位址訪問,則必須把**拷貝到ram裡,從ram裡執行),只是讓我們的**跑得更快.這個功能是:把**在放在ram裡執行.

對於51核這些微控制器(題外話,廣義嵌入式有兩種,一種是mcu,micro control unit,叫微控制器,特點是運算速度比較慢,偏重於對運算速度要求不高而用於邏輯控制的場合,另外的就是mpu,micro process unit,叫微處理器,特點是處理資料能力非常強,專用於對資料處理要求較高的場合)來說,由於它的應用場合往往對速度要求不高,因此,並沒有設計成**可以在ram執行的結構,也就是說,對標準的51核來說,它的**全部都是存放在rom裡,每個指令要執行時,先從rom裡取指(讀取指令),然後解釋執行.而arm是微處理器,往往用於資料處理場合,對程式效率要求很敏感,因此arm核都設計成可以從rom裡讀取指令執行也可以從ram裡讀取指令執行的結構,它的pc指標如果指向的位址是rom範圍內的位址,那麼讀取的指令就是rom裡的指令,如果指向的是ram範圍,那麼讀取的指令就是存放在ram裡的.眾所周知,ram的讀取速度比flash快很多。

ks8695包括很多arm核的mpu,他們的中斷入口都是放在前端靠近0位址的地方,而中斷處理往往是非常頻繁的,這裡的**被訪問率非常高,因此,如果能把中斷處理甚至整個執行程式的**都拷貝到ram裡並在ram裡執行,無疑會大大提高**的執行效率.在通常的loader設計裡,強烈建議至少把中斷向量表相關拷貝到記憶體裡,然後使用mmu或其他型別的對映功能,把記憶體裡的中斷向量表對映到0位址開頭的位址。

arm裡要完成這項工作通常有兩個步驟:第一,把rom裡的**拷貝到ram裡去,第二,把pc指標指向ram裡的相應位址,讓**從ram裡讀取執行.第一步幾乎所有的arm loader都差不多,但讀取的是nor flash還是nand flash,還是有分別的,如果存放**的是nor flash,可以以位元組為單位拷貝**放到ram裡,如果是nand flash,就要按flash的引數,以block為單位讀取放到ram裡去.

而對於第二步,在上述做完拷貝後,直接把pc置成ram裡存放執行**的所在位址就ok了。

最後步驟歸納如下:

下面是loader的**,已經包括了上面提到的步驟,另外還摻加了一些額外的硬體初始化步驟,注釋已經夠詳細,不想再多說:

寫在末尾的話:如果loader是用來引導linux核心的,要注意的是:初始化堆疊區時,不需要初始化usr模式下的堆疊,這是因為必須要進入usr模式才能初始化usr模式下的堆疊,

而一旦進入了usr模式,就無法回到特權模式,而引導linux核心時,linux核心初始化需要特權模式才能順利執行。也不需要自己建立中斷向量表的查表功能,linux核心初始化時,會建立自己的中斷向量表查表。

送給朋友的一些暖心的話

篇一 送給朋友的經典祝福語 1 有一種問候平常卻很溫暖 有一種信任無言卻最真切 有一種友誼清純卻很長遠 2 我沒有五彩的鮮花,沒有浪漫的詩句,沒有貴重的禮物,沒有特殊的驚喜,只有輕輕的祝福,每天好心情 3 高雅的女人,看背影就知道 奮鬥的女人聽腳步就知道 和善的女人,看笑容就知道 優秀的女人,看你就...

關於會議的一些反思

關於1月29日會議的一些反思 昨天的會議,各部門對測試人員主要提出了當前測試組存在的幾個問題 1 業務知識不熟悉的問題,但又缺乏刨根問題精神的問題 2 自信心缺乏的問題 3 責任心的問題,表現為上班時間無所事事 作為乙個測試人員,站在我個人的立場,我對以上幾點的認識如下。第一點,業務知識不熟悉的問題...

關於公司的一些事

黃總 您好,快畢業那會,面臨尋找工作,我有幾種選擇,因著我的職業規劃和看到公司的企業文化以及公司的前景,我選擇了公司,即使當時說要在車間訓練一年,我也沒有異議,因為覺得這是對自身能力培養是有益處的,真是想好好幹下去,為將來的機械工程師之路做好鋪墊。但是公司有很多事情和你的行為讓我感到失望。去年那麼多...