日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

AR/QCA SPI 启动原理和 ART 地址定位原理

發(fā)布時(shí)間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AR/QCA SPI 启动原理和 ART 地址定位原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自:http://www.right.com.cn

本貼主要講解 Bootloader 是如何在使用 SPI Flash 的 AR/QCA 的芯片上啟動(dòng)的,以及 OpenWrt 代碼 ar71xx 的 mach 文件中類(lèi)似于 u8 *art = KSEG1ADDR(0x1fff0000) 中 0x1fff0000 是如何得來(lái)的。

樓主之前在 U-Boot 編譯教程中進(jìn)行過(guò)簡(jiǎn)單的描述,但是因?yàn)閷?shí)在是太簡(jiǎn)略了,所以打算寫(xiě)一個(gè)詳細(xì)版的。

下面樓主將按照必要的順序依次講解。


1. CPU 地址、總線地址、映射

對(duì)于 MIPS CPU 來(lái)說(shuō),只有一種地址,即 CPU 地址。32 位 CPU 的尋址范圍稱(chēng)為它的地址空間,也就是 4GB,從 0x00000000 到 0xffffffff。
而總線,則是用來(lái)連接外設(shè)的,外設(shè)的寄存器、RAM、ROM等,都要通過(guò)總線來(lái)訪問(wèn)。總線也有自己的地址空間。

CPU 地址跟總線地址是相互獨(dú)立的。因此,要讓 CPU 能夠訪問(wèn)到外設(shè),就必須要讓 CPU 地址跟總線地址產(chǎn)生某種關(guān)聯(lián),這就是映射。
這就好比數(shù)學(xué)里面的映射。MIPS CPU 上的映射是從 CPU 上一段地址空間到總線上一段地址空間的一一映射。

有了這樣的關(guān)聯(lián)后,就很容易通過(guò)對(duì) CPU 地址的操作來(lái)變成對(duì)總線上外設(shè)的操作了。


2. AR/QCA 的總線地址布局

以 AR9344 為例,如圖:
?

可以看到 AR/QCA 的 CPU 使用了總線地址的 0x00000000 ~ 0x1fffffff 共 512MB 的地址空間。
注意到內(nèi)存也是通過(guò)總線來(lái)訪問(wèn)的。由圖可知 AR/QCA 只有最大 256MB 的內(nèi)存尋址能力。


3. MIPS 的內(nèi)存布局

MIPS32 (即 32 位) 的內(nèi)存模型都是一致的,如圖:
?

(圖片來(lái)自 MIPS32 74K Processor Core Family Software User’s Manual)


由于 Bootloader 跟 Linux 內(nèi)核都運(yùn)行在 Kernel Mode 下,所以這里也只就 Kernel Mode 進(jìn)行討論。

由圖可以看到,Kernel Mode 下,CPU 的地址空間被分為了5段: kuseg kseg0 kseg1 kseg2 kseg3。
kuseg 空間為 2GB,是用于用戶態(tài)程序訪問(wèn)用的,kseg2 kseg3 是用作內(nèi)核的內(nèi)存分頁(yè)用的。
這里只重點(diǎn)討論 kseg0 和 kseg1。kseg0 和 kseg1 都占用 512MB 的地址空間。

由 MIPS 手冊(cè)可知,kseg0 和 kseg1 都映射到了總線地址上的相同區(qū)域,也就是總線地址的 0x00000000 ~ 0x1fffffff 共 512MB 的空間。
這個(gè)映射是固定映射,也就是不會(huì)經(jīng)過(guò) MMU 的轉(zhuǎn)換,訪問(wèn) kseg0 跟 kseg1 都會(huì)直接被映射到總線上 0x00000000 ~ 0x1fffffff 的對(duì)應(yīng)位置。

由于 AR/QCA 使用的總線地址空間也是這個(gè)范圍,因此通過(guò) kseg0 或 kseg1 就都能訪問(wèn)到整個(gè)總線地址空間。
如圖:
?

從這里可以看到,kseg0 的范圍是 0x80000000 ~0x9fffffff,kseg1 的范圍是 0xa0000000 ~ 0xbfffffff。
又,總線地址空間范圍是 0x00000000 ~ 0x1fffffff,那么:

1. 從總線地址映射到 kseg0 的方法是:在保證總線地址有效 (即總線地址在 0x00000000 ~ 0x1fffffff 內(nèi)) 的情況下,將總線地址加上 kseg0 的起始地址,即:
  kseg0(addr) = 0x80000000 + addr
2. 從總線地址映射到 kseg1 的方法與從總線地址映射到 kseg0 的方法類(lèi)似,即:
  kseg1(addr) = 0xa0000000 + addr
3. 從 kseg0 和 kseg1 映射到總線的方法是:將 CPU 地址除以 kseg0 或 kseg1 段長(zhǎng)度,取余,得到的就是總線地址,即:
  bus(addr) = addr % 0x20000000

實(shí)際上,在 Linux 內(nèi)核中,arch/mips/include/asm/addrspace.h 提供了相應(yīng)的宏來(lái)進(jìn)行上述的地址轉(zhuǎn)換,簡(jiǎn)化后如下:

#define virt_to_bus(_virt) ((_virt) & 0x1fffffff)
#define KSEG0ADDR(_addr) ((_addr & 0x1fffffff) | 0x80000000)
#define KSEG1ADDR(_addr) ((_addr & 0x1fffffff) | 0xa0000000)
virt_to_bus 即為總 CPU 地址轉(zhuǎn)換到總線地址, 與 0x1fffffff (即低 512MB 的掩碼) 進(jìn)行按位與操作,相當(dāng)于除以 0x20000000 取余,即舍棄掉 512MB 之上的部分,只剩下低 512MB 的部分;
KSEG0ADDR 與 KSEG1ADDR 都先保證輸入地址是有效的,再進(jìn)行轉(zhuǎn)換,這里的按位或運(yùn)算,在結(jié)果上等同于加法運(yùn)算

雖然 kseg0 跟 kseg1 都映射在總線相同的地址空間上,但是,它們的作用卻并不相同:

kseg0 經(jīng)過(guò)了緩存,kseg1 沒(méi)有經(jīng)過(guò)緩存。

kseg0 經(jīng)過(guò)了緩存,也就是說(shuō)從這個(gè)段讀取出來(lái)的數(shù)據(jù),可能是緩存過(guò)的,跟總線上實(shí)際的數(shù)據(jù)可能不同;向其寫(xiě)入的數(shù)據(jù),可能會(huì)被延遲寫(xiě)入總線。
kseg1 則沒(méi)有經(jīng)過(guò)緩存,對(duì)這個(gè)段的任何讀寫(xiě)操作都將立即反映在總線上。

所以:
kseg0 主要用于需要加速的內(nèi)存訪問(wèn)和 ROM 訪問(wèn)
kseg1 主要用于設(shè)備寄存器的訪問(wèn)


4. MIPS 上的啟動(dòng)地址

MIPS 的 CPU 在復(fù)位后,會(huì)從 CPU 地址的 0xbfc00000 開(kāi)始執(zhí)行,也就是總線地址的 0x1fc00000。
可以看出 CPU 是在 kseg1 段上開(kāi)始執(zhí)行的,這是因?yàn)樵?CPU 復(fù)位后,緩存還沒(méi)用初始化,可能并不能使用。在不能保證 kseg0 段一定能使用的情況下,那么肯定只有從 kseg1 段開(kāi)始執(zhí)行了。


5. SPI Flash 和映射

這里的 SPI Flash 特指 SPI 接口的 NOR Flash (當(dāng)然也有 SPI NAND Flash)。

NOR Flash 有個(gè)特點(diǎn),即給出一個(gè)確切的地址,那么它就能連續(xù)輸出從這個(gè)地址開(kāi)始的數(shù)據(jù)。這個(gè)特點(diǎn)跟 DRAM 類(lèi)似,因此它可以被用作啟動(dòng)設(shè)備。
這個(gè)特性被稱(chēng)為 XIP (eXecute-In-Place)。

為了實(shí)現(xiàn)這個(gè)特性,就需要 CPU 能夠通過(guò) CPU 地址空間訪問(wèn)到 Flash 上的數(shù)據(jù)。
由于 Flash 是一個(gè)外設(shè),因此對(duì)它的訪問(wèn)是通過(guò)總線來(lái)進(jìn)行的。

這里,又用到了映射:
Flash 有自己的地址空間,即存儲(chǔ)數(shù)據(jù)的地址。
由于 Flash 是外設(shè),因此它的地址空間會(huì)被映射在總線上面。這又是一個(gè)映射,只不過(guò)是從總線到 Flash 的映射。

那么,通過(guò) CPU 訪問(wèn) Flash,實(shí)際上經(jīng)過(guò)了兩次映射:第一次是 CPU 地址到總線地址的映射,第二次是總線地址到 Flash 地址的映射。
這樣,CPU 就能夠直接讀取 Flash 的數(shù)據(jù)了。


6. AR/QCA 的 CPU 在 SPI Flash 上的啟動(dòng)

以 AR9344 為例,其它的型號(hào)也都基本相同

AR9344 遵循 MIPS 的要求,CPU 復(fù)位后,從 0xbfc00000 開(kāi)始執(zhí)行。

那么,總線地址 0x1fc00000 對(duì)應(yīng)了什么外設(shè)呢?
從第 2 節(jié)可以看出, 0x1f000000 ~ 0x1fffffff 對(duì)應(yīng)的正是 SPI Flash。

但是,Flash 是從 0x1f000000 開(kāi)始映射的,那么 0x1fc00000 處映射的又是什么呢?

實(shí)際上,Flash 確實(shí)是從 0x1f000000 開(kāi)始映射的,總共可以映射 16MB 的 Flash 空間。
為了兼容 MIPS 要求的 0xbfc00000 的復(fù)位地址,AR9344 在 0x1fc00000 處又重新對(duì) Flash 進(jìn)行了一次映射,映射了 Flash 開(kāi)頭的 4MB

但是,如果 0x1fc00000 處映射了 Flash, 那么從 0x1f000000 處就只能訪問(wèn) 12MB 的 Flash 空間了。
因此 AR9344 專(zhuān)門(mén)設(shè)置了一個(gè)寄存器,用來(lái)控制是否從 0x1fc00000 處重新映射 Flash。
這樣的話,當(dāng) Bootloader 完成了啟動(dòng)過(guò)程,就可以關(guān)閉在 0x1fc00000 的重新映射,這樣就能從 0x1f000000 處訪問(wèn)到完整的 16MB 的 Flash 空間了。


7. 如果 Flash 容量小于 16MB,那么會(huì)怎樣

上一節(jié)已經(jīng)說(shuō)了,從 0x1f000000 可以映射 16MB 的 Flash 空間,那么如果 Flash 容量小于 16M,會(huì)怎么樣?

實(shí)際上,Flash 對(duì)于地址有個(gè)回繞功能,也就是說(shuō),如果給定的地址超過(guò)了 Flash 的地址范圍,那么 Flash 會(huì)自動(dòng)讓地址變成 0,即又從頭開(kāi)始。
Flash 的內(nèi)部處理方式是將地址中超出容量的那些位 置零(或者說(shuō)溢出),效果上相當(dāng)于用給出的地址除以 Flash 的容量取余數(shù)。
這樣對(duì) Flash 來(lái)說(shuō),地址總是有效的,對(duì)外界來(lái)說(shuō),就像是 Flash 的數(shù)據(jù)在循環(huán)。

例如:某個(gè) Flash 的容量是 4MB,那么它的地址范圍就是 0x000000 ~ 0x3fffff。
如果訪問(wèn) 0x400000,就變成了訪問(wèn) 0x000000;如果訪問(wèn) 0x7f0000,就變成了訪問(wèn) 0x3f0000;如果訪問(wèn) 0xff0000,也是變成了訪問(wèn) 0x3f0000。

回到 AR9344 的 16MB 映射,如果 Flash 容量小于 16MB,那么在這 16MB 上的體現(xiàn)就是 Flash 數(shù)據(jù)重復(fù)映射了多次
例如:Flash 是 8MB 的,那么它就在 0x1f000000 和 0x1f800000 上各映射了一次;
如果 Flash 是 4MB 的,那么它就在 0x1f000000、0x1f400000、0x1f800000、0x1fc00000 上各映射了一次;


8. OpenWrt 的 mach 文件中,ART 數(shù)據(jù)地址的來(lái)歷

在上面幾節(jié)說(shuō)來(lái)這么多之后,對(duì)于類(lèi)似于 u8 *art = KSEG1ADDR(0x1fff0000) 這樣的地址就應(yīng)該很好理解了:

假設(shè) ART 位于 Flash 的最后 64KB,那么它在 Flash 中的地址就是 Flash 容量 - 64KB。

例如:
Flash 是 4MB 的,那么 ART 在 Flash 中的起始地址就是 0x400000 - 0x10000 = 0x3f0000;
Flash 是 8MB 的,那么 ART 在 Flash 中的起始地址就是 0x800000 - 0x10000 = 0x7f0000;
Flash 是 16MB 的,那么 ART 在 Flash 中的起始地址就是 0x1000000 - 0x10000 = 0xff0000;

那么,這個(gè)地址在總上的映射就是 0x1f000000 + ART 地址,即:
Flash 是 4MB 的,那么 ART 在總線中的起始地址就是 0x1f000000 + 0x3f0000 = 0x1f3f0000;
Flash 是 8MB 的,那么 ART 在總線中的起始地址就是 0x1f000000 + 0x7f0000 = 0x1f7f0000;
Flash 是 16MB 的,那么 ART 在總線中的起始地址就是 0x1f000000 + 0xff0000 = 0x1fff0000;

現(xiàn)在,假設(shè) OpenWrt 并不知道 Flash 的容量:
如果在 mach 中使用 8MB Flash 的 ART 地址 0x1f7f0000,如果 Flash 是 16MB 的,那么通過(guò) 0x1f7f0000 就無(wú)法獲取正確的 ART 數(shù)據(jù)。

那么解決方法是什么呢:
那就是假設(shè) Flash 都是 16MB 的,這樣的話就會(huì)使用 0x1fff0000 這個(gè)地址。
當(dāng) Flash 容量小于 16MB 時(shí),根據(jù)上一節(jié)所說(shuō)的地址回繞功能,通過(guò) 0xff0000 訪問(wèn)到的就是 Flash 實(shí)際最后 64KB 的內(nèi)容。

這就是 mach 文件中這個(gè)地址的來(lái)歷。


9. (補(bǔ)充) 為什么從 AR7240 開(kāi)始 U-Boot 的基址是 0x9f000000

如果編譯過(guò) U-Boot,那么可能會(huì)發(fā)現(xiàn) AR7161/AR913X 之類(lèi)的 CPU,其啟動(dòng)地址,即 U-Boot 的基址 (TEXT_BASE) 是 0xbf000000;而之后的 CPU (從 AR7240 開(kāi)始),其 U-Boot 的基址是 0x9f000000。
但是如第6節(jié)所說(shuō),CPU 復(fù)位后的執(zhí)行地址是 0xbfc00000,那么為什么 U-Boot 能從這兩個(gè)地址啟動(dòng)呢?

就 AR7161/AR913X 來(lái)說(shuō),這很容易根據(jù)解釋:
首先必須明確,無(wú)論 U-Boot 在編譯時(shí)指定的基址是什么,CPU 總是從 0xbfc00000 開(kāi)始執(zhí)行的。
根據(jù)第6節(jié)所述,0xbf000000 跟 0xbfc00000 映射了相同的 Flash 地址,也就是說(shuō)這兩個(gè)地址最多能映射4MB相同的數(shù)據(jù)。
那么 U-Boot 在執(zhí)行時(shí),就可以根據(jù) (當(dāng)前執(zhí)行地址 - 0xbfc00000 + 0xbf000000) 的方式跳轉(zhuǎn)到與 0xbf000000 相對(duì)應(yīng)的地址來(lái)繼續(xù)執(zhí)行。
在執(zhí)行跳轉(zhuǎn)后,U-Boot 會(huì)立即關(guān)閉 0x1fc00000 處 Flash 的重映射,因此 U-Boot 必須在進(jìn)入 C 環(huán)境 (即使用棧幀) 之前完成跳轉(zhuǎn),否則棧中會(huì)保留 0xbfc00000 相關(guān)的地址,在禁用 Flash 重映射后會(huì)失效。

就 AR7240 開(kāi)始的 CPU 來(lái)說(shuō),就要考慮到緩存了:
從 AR7240 開(kāi)始,CPU 支持 Flash 映射的讀緩存和指令緩存。但是根據(jù)第4節(jié)的描述,CPU 初始化時(shí),kseg0 段的緩存并未初始化,不能訪問(wèn)。
因此 U-Boot 會(huì)先將緩存初始化,然后使用和 AR7161/AR913X 相同的方式 (當(dāng)前執(zhí)行地址 - 0xbfc00000 + 0x9f000000) 來(lái)跳轉(zhuǎn)到與 0x9f000000 相對(duì)應(yīng)的地址 ,即 kseg0 段來(lái)執(zhí)行。

AR7161/AR913X 不支持 Flash 映射的指令緩存,雖然可以從 0x9f000000 讀取 Flash 數(shù)據(jù),但是從 0x9f000000 執(zhí)行則會(huì)導(dǎo)致 CPU 異常。

從 kseg0 執(zhí)行 U-Boot 的好處顯而易見(jiàn):有緩存,能加快 U-Boot 的執(zhí)行速度。


10. 后記

嵌入式設(shè)備開(kāi)發(fā)需要掌握很多的知識(shí),并不是只會(huì)編程就行了。例如還需要學(xué)習(xí)計(jì)算機(jī)組成原理、操作系統(tǒng)原理等等。
很多開(kāi)發(fā)者對(duì)這些并不了解,因此對(duì)于這些文件都會(huì)有相當(dāng)多的疑問(wèn)。
樓主盡量將文章內(nèi)容簡(jiǎn)化,以使其變得能夠容易理解,并希望能夠起到拋磚引玉的作用。

希望通過(guò)此文讓開(kāi)發(fā)者能過(guò)對(duì)嵌入式設(shè)備開(kāi)發(fā)有更深入的了解,消除疑惑。


總結(jié)

以上是生活随笔為你收集整理的AR/QCA SPI 启动原理和 ART 地址定位原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产欧美日韩专区发布 | 熟女国产精品一区二区三 | 涩涩一区 | 朋友的姐姐2在线观看 | 国产乱性 | 亚洲最新av | 美女扒开下面让男人捅 | 一区二区乱子伦在线播放 | 天天曰夜夜曰 | 国产伦精品一区二区三区高清 | 2022av在线| 日韩一区二区三区视频在线观看 | 四虎中文字幕 | 免费色站| 都市豪门艳霸淫美妇 | 91学生片黄 | 久久精品美女 | 亚洲成人精品在线 | 欧美一级片 | 孕妇毛片 | 成人福利视频 | 午夜影院在线免费观看 | 天堂成人在线观看 | 日韩中文在线播放 | 成年人免费看的视频 | 国产欧美日韩精品一区二区三区 | 污污视频在线看 | 波多野结衣高清视频 | 无码黑人精品一区二区 | 狠狠地日 | 狂躁美女大bbbbbb黑人 | 四虎最新域名 | chien国产乱露脸对白 | 国产午夜视频在线播放 | 自拍偷拍2019 | 国内av网 | 婷婷在线观看视频 | 久久久久久久麻豆 | 91女神在线| a在线观看视频 | 中文字幕免费高清在线观看 | 制服诱惑一区二区三区 | 色av一区 | 欧美三级韩国三级日本三斤在线观看 | 黑人极品ⅴideos精品欧美棵 | 色多多污 | 美女又爽又黄视频毛茸茸 | 午夜免费片 | 色www亚洲国产张柏芝 | 污污污www精品国产网站 | 久久精品2 | 日本三级中文字幕在线观看 | 性爱视频免费 | 亚洲高清免费视频 | 日韩一级影院 | 福利视频在线导航 | 国产三级直播 | 青青草手机在线观看 | av网址有哪些 | 色88久久久久高潮综合影院 | 天堂资源 | 国产精品果冻传媒 | 我们的生活第五季在线观看免费 | 91看片就是不一样 | 僵尸艳谈| 国产在线观看av | 97理伦| 日韩人妻无码一区二区三区 | 成人精品网址 | xxx麻豆| 国产男女无遮挡猛进猛出 | 老司机深夜福利视频 | 亚洲精品高清视频在线观看 | 亚洲自拍偷拍欧美 | 成人无码久久久久毛片 | 国产99对白在线播放 | 91精品免费在线观看 | 91亚色视频| 黄色国产一区 | 国产一级特黄a高潮片 | 色黄大色黄女片免费中国 | free性护士vidos猛交 | 1级性生活片 | 6080av| 午夜免费片 | 99这里有精品视频 | 日日做夜夜爽毛片麻豆 | 亚洲成人精品一区 | 欧美一级高清片 | 国产良妇出轨视频在线观看 | 男人添女人荫蒂国产 | 精品久久人人 | 99在线观看免费 | 日韩成人精品一区二区 | 日本黄色大片视频 | 四虎影库在线播放 | 日韩色资源 | 狠狠久久久 | 国产乱色|