1. 8051與AndesCoreTM 本文將介紹使用8051與AndesCore?差異事項,并對兩種CPU系統相關(guān)事項做說(shuō)明,后面再介紹從 8051移植到AndesCore ?上注意事項,舉中斷向量表及異常處理函數的例子說(shuō)明差異及移植,最后簡(jiǎn)要介紹AndesCore?在MCU應用的三款CPU: N705,N801 和N968A。 2. 8051與AndesCore常見(jiàn)差異事項 2.1. 位寬的差異 位寬是指處理器一次執行指令的數據帶寬。8051 是8 位寬的處理器, 而AndesCore?是32位寬的處理器,支持32位與 16位的混合指令集,位數越寬,在數據的處理方面就更有效率。 2.2. 指令差異 8051 匯編語(yǔ)言共有111 條指令集,AndeStar?的V3m指令集有 157 條,AndeStar?的V3指令集有 200 多條,兩種 CPU的指令集大概可以分為以下幾類(lèi):算術(shù)運算,如加,減,乘,除等操作;數據傳送,如數據在寄存器,內存間的傳送,賦值等;邏輯跳轉,如函數呼叫,無(wú)條件跳轉,條件跳轉,中斷返回等;在A(yíng)ndesCore ?中還有特權模式的指令部分,關(guān)于兩種指令集的具體差別,可以分別參考對應的指令集介紹文檔。 2.3. 地址空間映射差異 AndesCore?使用memory map 方式映射地址空間,主要有兩種,內存的空間映射,如其中的RAM或ROM地址,它們用于存放程序運行時(shí)的代碼和數據,在A(yíng)ndesCore?上代碼在link 后,程序運行的代碼和數據地址會(huì )最終確定,Andes 提供了一個(gè)簡(jiǎn)便的 link script 工具sag ,可以很方便的對系統中可用的內存空間進(jìn)行分配設定。 另一個(gè)是外設所對應的地址空間,可以通過(guò)查看SoC 對應的手冊了解對應的外設映射的空間范圍及相應的使用方法。 2.4. 堆棧設置差異 8051的堆棧的起始位置是固定的(部分衍生 8051可以做程序設定),它通常固定在片內的RAM中,8051 內存空間有限,非常小,程序中所使用的變量存放于特定的數據空間中,并不會(huì )放在堆?臻g,所以在 8051中所需要的堆?臻g很小。而對于 And esCore?來(lái)說(shuō),堆?梢栽O置在任意合適的 RAM上。程序運行時(shí)所有的局部變量都存放在堆棧中,只需要確保在設計系統的時(shí)候有足夠的堆?臻g。在 AndesCore?中有$ sp寄存器表示棧頂位置,這需要在系統上電或者是系統reset 后初始化時(shí)進(jìn)行設置。 2.5. 代碼和數據的存儲差異 在8051 系列單片機中,數據存儲區可以分為內部數據存儲區以及外部數據存儲區。 內部數據存儲區有幾個(gè)區別:data ,bdata,idata。 data : 片內RAM直接尋址區。bdata: 片內RAM位尋址區。idata: 片內 RAM間接尋址區。 外部數據存儲區又有:xdata,pdata。 xdata 和pdata:是外部存儲區,有些芯片會(huì )帶有 XRAM 。 在有些開(kāi)發(fā)工具中,如K eil,可以通過(guò)設置存儲模式來(lái)處理,存儲模式?jīng)Q定了默認的存儲器類(lèi)型, 此存儲器類(lèi)型將應用于函數參數, 局部變量和定義時(shí)未包含存儲器類(lèi)型的變量。 SMALL 所有的變量存放在片內 RAM(data 區間) COMPACT 所有的變量存放在外部存儲區(pdata 區間) LARGE 所有的變量存放在外部存儲區(xdata 區間) AndesCore?以?xún)却嬗成涞姆绞,內存空間不會(huì )有特別的限制,就是說(shuō)不會(huì )像8051那樣需放在某處區間,這樣的設計更方便靈活,允許程序代碼和數據在可用的空間里自由放置。 有時(shí)候需要將某段代碼或者數據存放在指定的位置上,在8051 中,可以在代碼中使用"at" 關(guān)鍵字,但該關(guān)鍵字是 8051 中所特有的,會(huì )造成可移植性和維護的問(wèn)題,在 AndesCore?上,提供了一種簡(jiǎn)便的 link script 工具,如上所提到的sag 工具,在 C 代碼中使用GNU標準的語(yǔ)法格式,在 link 之后相應的代碼和數據將存放于指定的位置,這樣可以避免在代碼中使用"at" 該平臺相關(guān)的屬性設置。 2.6. 數據類(lèi)型及對齊差異 8051和AndesCore ?是不同類(lèi)型的CPU,它們所使用的數據類(lèi)型所對應的寬度也不同,如下表所示: 在鏈接完成后數據通常都會(huì )按照本身的屬性對齊,比如int 類(lèi)型則會(huì )4 bytes對齊,short則會(huì )2 bytes對齊。這樣的存放方式可以提高 CPU對數據讀取時(shí)的效率。雖然AndesCore?是32bit的CPU, 在只需要8bit 和16bit的數據時(shí)能節省存儲空間,但在處理16bit 和32bit的數據上則有更高效。 在8051中有sbit 關(guān)鍵字用于設置對特殊功能寄存器 SFR的直接訪(fǎng)問(wèn),8051的特殊功能寄存器分布在內存地址0x80到0xFF處,如下表: sbit 是8051擴展的變量類(lèi)型,非標準 C 語(yǔ)法,移植的時(shí)候需要將其修改成標準C 操作語(yǔ)法,另外在A(yíng)ndesCore?中,所有的寄存器都是單獨存在的,不會(huì )占用內存的空間。 2.7. 指針使用差異 8051中兩種類(lèi)型的指針,分別是存儲器指針和通用指針,通用指針由3 個(gè)字節組成,第一個(gè)字節用來(lái)指明對應的內存類(lèi)型,所以這種類(lèi)型的指針類(lèi)型占用空間更大也更慢,存儲器指針只能用來(lái)訪(fǎng)問(wèn)指定類(lèi)型的存儲器空間。 而在A(yíng)ndesCore?上指針不會(huì )有這方面的限制,它是一個(gè) 32bit的數據,普通的寄存器就可以存放指針內容,可以訪(fǎng)問(wèn)到系統4G 范圍內的空間(N705,N801地址空間只有 16M,N968A以上的 CPU地址空間可達4G)。 2.8. 函數聲明差異 在8051中由于堆?臻g有限,如果有函數是可重入的,需要在函數聲明的時(shí)候用關(guān)鍵字reentrant 做說(shuō)明。8051 的中斷處理函數則需要使用關(guān)鍵字interrupt 聲明,中斷處理函數有時(shí)也需要用 using 關(guān)鍵字指明哪一寄存器組會(huì )被使用到。 在A(yíng)ndesCore?中,都采用標準的 C 語(yǔ)法,在聲明函數時(shí)并不需要這些附加的聲明。AndesCore?遵行底層的ABI 機制,編譯器處理底層的寄存器及堆棧相關(guān)機制。對于上層用戶(hù)來(lái)說(shuō)是透明的。 3. 系統相關(guān)事項說(shuō)明 3.1. 操作模式 8051只有一種mode,AndesCore?有兩種mode,分別是 superuser mode和user mode ,當系統上電啟動(dòng)時(shí)是在 superuser mode,或者當系統進(jìn)入到中斷或者異常時(shí)也進(jìn)入到superuser mode,當從中斷或者是異常返回后,會(huì )返回到user mode 。由于8051沒(méi)有mode切換的問(wèn)題,所以在移植的時(shí)候只需要理解AndesCore?在mode方面的機制就可以。 3.2. 系統的啟動(dòng) 8051和AndesCore ?的系統啟動(dòng)過(guò)程類(lèi)似,通常在0 地址存放中斷向量表,第一個(gè)向量表是reset,當系統上電或者是reset 后,經(jīng)過(guò)該向量會(huì )跳轉到一個(gè)啟動(dòng)函數中,該啟動(dòng)函數會(huì )完成系統啟動(dòng)所必要的步驟,比如設置CPU,初始化SoC ,清理內存,初始化 C 運行環(huán)境等, 最后完成所有的準備后跳轉到 main函數。 3.3. 中斷處理 8051有5 個(gè)中斷源,通常中斷向量表只是一個(gè)跳轉,會(huì )跳到真正的中斷處理函數,8051只能設置成兩級的中斷優(yōu)先級。 AndesCore?包含了9 個(gè)內部異常,中斷向量號對應于從 0 到8, 9 之后對應于外部中斷,在Internal VIC (IVIC )mode時(shí)可支持32個(gè)外部中斷, 當External VIC(EVIC) mode時(shí)由外部中斷控制器決定, 最多有64個(gè)。 中斷的處理由以下幾部分組成: 1. 實(shí)現中斷處理函數 可以用匯編實(shí)現8051 的中斷處理函數,也可以用C 來(lái)實(shí)現,在8051中C 實(shí)現的中斷處理函數會(huì )有一個(gè)"interrupt" 的關(guān)鍵字,如果有寄存器 bank被使用到,還要加上"using"關(guān)鍵字。如果要將中斷處理函數固定在特定位置還需要使用"at" 關(guān)鍵字,而 AndesCore?使用的是標準的 C 語(yǔ)法,不需要為中斷處理函數做這些設置。 2. 中斷向量表的產(chǎn)生 8051 中斷向量表擺放在 0 開(kāi)始的位置,在A(yíng)ndesCore?中硬件可以設定啟動(dòng)地址,通常設為 0 地址,也可以是非 0 地址,中斷向量表存放在對應系統啟動(dòng)地址處。在程序編寫(xiě)過(guò)程中可以通過(guò)標準的gnu 語(yǔ)法再加上link script 的sag 工具,以使產(chǎn)生的中斷向量表在鏈接的時(shí)候存放于特定的位置。 3. 中斷配置 在8051中,需要做以下設置 1. IE 寄存器中Individual Interrupt Enable 位設1 2. IE 寄存器中EA(Enable All)位設1 3. 當是外部中斷時(shí),配置相關(guān)的pin 為輸入,并設置對應的觸發(fā)屬性為edge或level 觸發(fā)。 而在A(yíng)ndesCore?中需要做以下設置: 1 .設置CPU IVIC 或者 EVIC mode 2 .設置INT_MASK位 3 .設置中斷的優(yōu)先級 4. 關(guān)于異常處理差異 在8051中沒(méi)有異常處理向量,所以在8051中并沒(méi)有這部分的處理函數,在A(yíng)ndesCore?中有一些系統的exception 中斷向量,比如Machine Error,GeneralException, 建議在A(yíng)ndesCore ?上實(shí)現對應的處理函數, 當發(fā)生這類(lèi)異常時(shí)做一些基本的處理。 3.4. 時(shí)序和延遲 在8051中可以采用NOP指令來(lái)延遲,在 AndesCore?中也有NOP指令來(lái)達到類(lèi)似目的。 3.5. 電源管理 8051 單片機中有兩種省電方式,分別是空閑方式和掉電模式, 單片機處于空閑工作方式時(shí),CPU處于睡眠狀態(tài),它的片內其它部件還是會(huì )繼續工作,片內RAM的內容和所有專(zhuān)用寄存器的內容在空閑方式期間都被保存下來(lái)了, 可以通過(guò)中斷或者硬件復位來(lái)終止空閑工作方式。單片機處于掉電工作方式時(shí),片內的振蕩器停止了工作,因此它的一切都被迫停止了。但片內 RAM的內容和專(zhuān)用寄存器的內容一直保持到掉電方式結束為止。掉電方式的喚醒方式只有一種,就是硬件復位。 在A(yíng)ndesCore?上,可以通過(guò)軟件standby 指令使CPU進(jìn)入到低功耗模式,通常標準c 代碼并不能直接控制硬件,Andes 的compiler 提供了intrinsic 函數來(lái)做到這點(diǎn)。分別是:__nds32_standby_no_wake_grant(), __nds32_standby_wake_grant(),__nds32_standby_wait_done().指定系統進(jìn)入低功耗模式時(shí)被喚醒的方式,分別是外部中斷中斷喚醒,電源管理模塊喚醒,和中斷配合電源管理模塊喚醒,可以根據系統需要分別設計。 4. 從8051移植到AndesCore上注意事項 一個(gè)8051工程,當移植到AndesCore?上時(shí)有以下注意事項: 1. 內存映射,代碼和數據擺放位置相關(guān)的設置。 2. 可以不必考慮變量數目,或者是函數的overlay, 因為在32bit 的AndesCore?上開(kāi)發(fā)時(shí)內存空間通常不會(huì )像 8051那樣小。 3. 如果空間允許,在 AndesCore?上盡量使用32bit的數據類(lèi)型,這樣效率會(huì )更高。 4. 在8051上用于表示內存區域屬性的標志如(idata, xdata, bdata, pdata 等)在A(yíng)ndesCore?上可以移除。 5. 在8051上不需要設置內存區塊模式,比如:small, compact, large 等。 6. 在8051 上用于表示對像遠近的屬性"near" 和"far",都可以移除,AndesCore?上的指針的訪(fǎng)問(wèn)可以達到所有地址空間。 7. 在中斷處理函數中不需要像8051那樣指定哪塊寄存器塊會(huì )被用到的關(guān)鍵字"using"。 8. 在8051上中斷處理函數就和普通的函數一樣,中不需要設置其它的關(guān)鍵字,如interrupt 。 9. 如果有8051匯編部分移植到 AndesCore?,需要重新實(shí)現,盡可能的用c 來(lái)實(shí)現,便于維護和調試。 10. 在8051中使用到的#progma 相關(guān)部分需要刪除。 11. 在A(yíng)ndesCore?中函數不需要聲明為"reentrant" 屬性。 12. 如果使用了數學(xué)運算,在8051中默認是使用32bit單精度浮點(diǎn),如果要 保持和8051 中相同的精度,需要將函數名做一些調整,如將 sin() 改成sinf()。 5. 中斷向量及異常處理函數例子 以中斷向量及中斷處理函數的例子說(shuō)明差異及移植。 5.1. 匯編實(shí)現中段向量表 [8051] 該例子顯示怎樣用匯編設置8051的中斷向量和中斷處理函數,在8051匯編中ORG指定了后面匯編代碼的位置,后面的中斷向量通常是一個(gè)跳轉語(yǔ)句。如下例第一個(gè)向量跳到主函數MAIN函數中,另外一個(gè)外部中斷1, 也是一個(gè)跳轉指令:LJMP INT 到后面的用匯編實(shí)現的中斷處理函數 INT 中。 [ AndesCore?] 該例子顯示怎樣用匯編設置AndesCore?的中斷向量表和中斷處理函數, 該例子中exception_vector 是中斷向量表的label, 后面分別表示第0,1,2,3…個(gè)中斷向量,它們只是簡(jiǎn)單的跳轉指令,跳到具體的執行實(shí)體中去,如vector 0 跳到_start, 做系統相關(guān)的初始化操作,_start 是系統啟動(dòng)代碼,用匯編語(yǔ)言來(lái)實(shí)現。vector 9 后面對應的是外部中斷,中斷處理函數如OS_Trap_Interrupt_HW0,OS_Trap_Interrupt_HW1… 它通常用C 來(lái)實(shí)現,可以參考后面5.2 章節的AndesCore?中斷處理函數范例。 在上面用匯編設置AndesCore?的中斷向量表的例子中,我們需要將中斷向量表最終設定在0 地址處,可以通過(guò) section語(yǔ)法配合sag 工具實(shí)現,例子中我們設定該段的 section 名為.vector, 所以在sag 中,我們自定義一個(gè) USER_SECTION 為.vector,并 將.vector放在0 開(kāi)始的地方并作為第一個(gè) section。 通過(guò)上面的sag 語(yǔ)法,并使用andes 提供的sag 轉ld 的工具,可以產(chǎn)生類(lèi)似以下的ld ,在工程進(jìn)行鏈接的時(shí)候選擇該 ld 時(shí)就能確保 .vector鏈接的地址位于0 處。 關(guān)于詳細的SAG使用,可以參考我們的另一篇文章:《Andes 的分散聚合(SAG)機制》 5.2. 中斷處理函數的C 實(shí)現 6. 適用于MCU的Andes CPUs Andes 有三款非常適用于 MCU應用的CPU,分別是:N705,N801,N968A,如下圖所列: N705和N801分別采用了兩級和三級流水線(xiàn),都具有很低的功耗和很好的性能,當應用需要的頻率較低時(shí),使用兩級流水線(xiàn)的N705能發(fā)揮出更好的性能和更低功耗的特性,相比于8051,兩級流水線(xiàn)的 N705 在頻率方面高出許多,比如在TSMC 40nm LP 工藝下能跑到超過(guò)240MHz ,所以完全能勝任8051的應用需求。N968A使用了五級的流水線(xiàn),同樣有低功耗的特性和很好的性能,同時(shí)該款CPU具有很強的可配置性,如支持多種總線(xiàn)接口,還支持了專(zhuān)門(mén)為audio的加速指令,N968A是一個(gè)多面手,性能好,功耗低,又具備強大的可配置特性,適合于多種應用。 |