當例外發生時,處理器會負責如下的動作
1. 拷貝CPSR到對應例外處理模式的SPSR
2. 改變CPSR到對應的例外處理模式,以及對應處理模式的暫存器群,
任何例外處理都會disable IRQ位元,在FIQ和RESET的例外發生時,才會disable FIQ位元
3. 拷貝PC(r15)到對應處理模式的LR(r14)
4. 設定PC(r15)到對應中斷向量的位址
SWI和Undefined instruction的例外事件:
這兩種例外,都是執行指令所引起的,且都是在PC(r15)沒有更新前,去處理例外事件,所以回到原來的執行程序時,需要執行下一個的指令,因為前一個指令,就是呼叫例外處理程式處理
(for undefined instruction:這個例外事件程式可以當作發展自有命令的模擬開發方式)
the return instruction is:
MOVS pc, lr
The handler entry and exit code to stack the return address and pop it on return is:
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
prefetch abort的例外事件:
若fetch的指令為無效的位址,在fetch的階段就會標記這個指令,不過要等到Execute階段才會去處理例外事件,這時這個例外事件可能透過MMU對應vitrual memory locations到正確的physical memory,也許還有physical memory和儲存設備之間的swap動作...
PS:在Execute階段處理例外事件時,pc(r15)還未更新
然後回到原來程序時,應該跳回到原來的指令,這時就可以正確fetch這個位址的指令,所以
the return instruction is:
SUBS pc,lr, #4
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#4
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
FIQ和IRQ的例外事件:
在執行完指令完且更新PC(r15)後,會檢查IRQ及FIQ的腳位是否為Low,若成立則處理例外事件,所以回到原來的執行程序時,需要執行下一個的指令,因為前一個指令,已經執行過了
the return instruction is:
SUBS pc, lr, #4
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#4
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
data abort的例外事件:
在執行load或store的相關指令時,執行完且更新PC(r15)後,才會發生data abort的例外事件,這時這個例外事件可能透過MMU對應vitrual memory locations到正確的physical memory,也許還有physical memory和儲存設備之間的swap動作...
所以回到原來程序時,應該跳回到原來的指令,然後就可以正確load或stroe這個位址的資料,所以
the return instruction is:
SUBS pc, lr, #8
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#8
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
似乎這些例外處理的返回位址計算,應該是CPU的責任,不過當年ARM CPU的其中一個主要訴求,就是很小的晶片面積,所以就不浪費邏輯閘,讓軟體來處理這些動作,或者說讓軟體開發者有更大的彈性...
目前有接觸過ARM 7,擁有三階的管線(Fetch. Decode. Execute),之後更強大的ARM系列的CPU,有提供5階或更多的管線,不知道例外處理返回位址的計算,是不是不同???(有機會碰到在看看)
雖然這兩張圖用來代表管線處理指令流的示意,也許有不恰當的地方,不過我喜歡這樣的描述方式來記憶返回位址的計算,重點是例外發生時,PC(r15)是否有更新,以及各種例外對於返回後,處理的需求,就可以推論返回位址的計算
相關連結:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0040d/index.html 第九章相關內容
http://infocenter.arm.com/help/topic/com.arm.doc.dui0040d/DUI0040D.pdf ,pdf文件下載
2009年2月26日 星期四
2008年12月19日 星期五
內存屏障(memory barrier)
memory barrier 長這樣 __asm__ __volatile__("": : :"memory")
首先gcc對於匯編語言(組合語言),是使用AT&T的語法,不同於INTEL的組合語言語法
格式 : __asm__(組合語言:輸出:輸入:修飾詞")
__volatile__ 代表這行指令(這些組合語言),不和前面的指令一起最佳化
"memory" 告訴GCC這些組合語言會改變所有的RAM的資料
因為沒組合語言,又告訴gcc所有RAM的內容都改變,
所以這個memory barrier的效用,
會讓這行之前被gcc所cache到暫存器的資料通通寫回RAM裡面
也告訴gcc會讓之後讀取RAM的資料,必須再從RAM裡讀取出來,
參考資料:
http://blog.chinaunix.net/u1/55599/showart_1099203.html
http://hi.baidu.com/hilyjiang/blog/item/2254e62afd6db42cd42af180.html
http://lyowu.yourblog.org/logs/135030.html
http://blog.openrays.org/blog.php?do=showone&tid=329
http://fanqiang.chinaunix.net/a4/b8/20010704/130401784_b.html
首先gcc對於匯編語言(組合語言),是使用AT&T的語法,不同於INTEL的組合語言語法
格式 : __asm__(組合語言:輸出:輸入:修飾詞")
__volatile__ 代表這行指令(這些組合語言),不和前面的指令一起最佳化
"memory" 告訴GCC這些組合語言會改變所有的RAM的資料
因為沒組合語言,又告訴gcc所有RAM的內容都改變,
所以這個memory barrier的效用,
會讓這行之前被gcc所cache到暫存器的資料通通寫回RAM裡面
也告訴gcc會讓之後讀取RAM的資料,必須再從RAM裡讀取出來,
參考資料:
http://blog.chinaunix.net/u1/55599/showart_1099203.html
http://hi.baidu.com/hilyjiang/blog/item/2254e62afd6db42cd42af180.html
http://lyowu.yourblog.org/logs/135030.html
http://blog.openrays.org/blog.php?do=showone&tid=329
http://fanqiang.chinaunix.net/a4/b8/20010704/130401784_b.html
2008年7月24日 星期四
udhcp and route 設定 for linux
在busybox-1.00-pre7,已經包含了udhcp 的client 和 server,
linux-2.4.20 核心設定
Code maturity level options --->
[*] Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL)
這個選項開放一些新的的功能或著實驗的選項,讓使用者可以選擇
General setup --->
[*] Networking support (CONFIG_NET)
這樣才有Networking Options ---> 和 Network device support ---> 這兩大選項
[*] Sysctl support (CONFIG_SYSCTL)
可以讓/proc下出現sys的子目錄,當然proc這個檔案系統要先開啟
Networking options --->
[*] Packet Socket (CONFIG_PACKET)
udhcpc 需要這個選項
[*]Unix domain sockets (CONFIG_UNIX)
使用netstat可以看到 Active UNIX domain sockets (w/o servers) 的列表,udhcpd 需要這個選項
[*] TCP/IP networking (CONFIG_INET)
可以在/proc/sys/下出現net/ipv4的子目錄,例如 echo "1" > /proc/sys/net/ivp4/net_ipforward ,linux才有路由的功能, 還有會擁有 lo 這個 loopback 網路裝置, 可以ping 自己!!!
Network device support --->
[*] Network device support (CONFIG_NETDEVICES)
基本上這個大選項,是在選擇網卡的dirver,不過在一些SOC的embedded system中,雖然廠商已經porting好了相關網路驅動,且放置在和晶片相關的選項中(廠商所分出的一個大選項),不過上面的 (CONFIG_NETDEVICES)還是要選,不然掛udhcpd會失敗,
udhcp 介紹:
udhcpc: 需要一個 script file, 注意是一個可執行的檔,不是設定檔,udhcpc利用shell 變數和 script file 做互動
udhcpd: 需要一個設定檔,這個設定檔可以指定相關的資訊的儲存檔案路徑
關於這些設定檔的參考,udhcpd可以參考 udhcpd.conf , udhcpc 可以參考這網站內的S50default
相關連結:
參考一
在udhcpc的script裡需要ifconfig和route指令(需要在busybox裡設定),還有一些相關的核心設定參數,在這裡紀錄一下
由於我的 embedded linux 有兩個網路介面(再加一個lo),所以也實驗了Router的設定linux-2.4.20 核心設定
Code maturity level options --->
[*] Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL)
這個選項開放一些新的的功能或著實驗的選項,讓使用者可以選擇
General setup --->
[*] Networking support (CONFIG_NET)
這樣才有Networking Options ---> 和 Network device support ---> 這兩大選項
[*] Sysctl support (CONFIG_SYSCTL)
可以讓/proc下出現sys的子目錄,當然proc這個檔案系統要先開啟
Networking options --->
[*] Packet Socket (CONFIG_PACKET)
udhcpc 需要這個選項
[*]Unix domain sockets (CONFIG_UNIX)
使用netstat可以看到 Active UNIX domain sockets (w/o servers) 的列表,udhcpd 需要這個選項
[*] TCP/IP networking (CONFIG_INET)
可以在/proc/sys/下出現net/ipv4的子目錄,例如 echo "1" > /proc/sys/net/ivp4/net_ipforward ,linux才有路由的功能, 還有會擁有 lo 這個 loopback 網路裝置, 可以ping 自己!!!
Network device support --->
[*] Network device support (CONFIG_NETDEVICES)
基本上這個大選項,是在選擇網卡的dirver,不過在一些SOC的embedded system中,雖然廠商已經porting好了相關網路驅動,且放置在和晶片相關的選項中(廠商所分出的一個大選項),不過上面的 (CONFIG_NETDEVICES)還是要選,不然掛udhcpd會失敗,
udhcp 介紹:
udhcpc: 需要一個 script file, 注意是一個可執行的檔,不是設定檔,udhcpc利用shell 變數和 script file 做互動
udhcpd: 需要一個設定檔,這個設定檔可以指定相關的資訊的儲存檔案路徑
關於這些設定檔的參考,udhcpd可以參考 udhcpd.conf , udhcpc 可以參考這網站內的S50default
相關連結:
參考一
2008年7月11日 星期五
MTD 測試
MTD 裝置通常是用來當作是Flash的裝置,若是系統沒有Flash可以測試,也可以用記憶體來模擬MTD裝置,以下紀錄核心, /dev, mtd-utils 的選擇和設定
linux 2.4.20 Kernel 設定
進入Memory Technology Devices (MTD) --->
[*] Memory Technology Devices (MTD) support (CONFIG_MTD)
[*] Direct char device access to MTD devices (CONFIG_MTD_CHAR)
[*] Caching block device access to MTD devices (CONFIG_MTD_BLOCK)
進入Self-contained MTD device drivers --->
[*]Test driver using RAM (CONFIG_MTD_MTDRAM)
(1024) MTDRAM device size in kiB (CONFIG_MTDRAM_TOTAL_SIZE)
(128) MTDRAM erase block size in kiB (CONFIG_MTDRAM_ERASE_SIZE)
/dev/mtdblock0 b 31 0
/dev/mtdblock1 b 31 1
/dev/mtdblock2 b 31 2
依序類推...
/dev/mtd0 c 90 0
/dev/mtd1 c 90 2
/dev/mtd2 c 90 4
依序類推...
mtd-utils-1.0.0 下載
發現一個問題:
mkfs.jffs2 -d test -o test.bin
dd if=test.bin of=/dev/mtdblock0
mount -t jffs2 /dve/mtdblock0 /mnt/flash
在最後一個步驟後會有錯誤訊息,研究一下,終於了解.....
既然是模擬Flash memory,有一個參數很重要,那就是 CONFIG_MTDRAM_ERASE_SIZE,所以使用mkfs.jffs2指令來產生image檔案時,必須 "mkfs.jffs2 -e0x20000 -d ./root -o test.bin",如此才能吻合RAM所模擬的FLASH memory
註: mkfs.jffs2 的參數 -e "size" 代表erase block的大小
一般實際有Flash的系統上,會利用CFI去偵測FLASH得到這些資訊
mtd-utils-1.0.0 裡,試過mkfs.jffs2. flash_erase. flash_eraseall 這三個命令
flash_eraseall 作用在 /dev/mtd0 會有問題.看一下flash_eraseall.c, grep bbtest=1,改成bbtest=0就可以了,這個修改是讓程式跳過bad block的檢查,我想應該是核心的MTD子系統沒有建置bad block check的機制,了解不多,不過至少可以用了.... :-)
linux 2.4.20 Kernel 設定
進入Memory Technology Devices (MTD) --->
[*] Memory Technology Devices (MTD) support (CONFIG_MTD)
[*] Direct char device access to MTD devices (CONFIG_MTD_CHAR)
[*] Caching block device access to MTD devices (CONFIG_MTD_BLOCK)
進入Self-contained MTD device drivers --->
[*]Test driver using RAM (CONFIG_MTD_MTDRAM)
(1024) MTDRAM device size in kiB (CONFIG_MTDRAM_TOTAL_SIZE)
(128) MTDRAM erase block size in kiB (CONFIG_MTDRAM_ERASE_SIZE)
/dev/mtdblock0 b 31 0
/dev/mtdblock1 b 31 1
/dev/mtdblock2 b 31 2
依序類推...
/dev/mtd0 c 90 0
/dev/mtd1 c 90 2
/dev/mtd2 c 90 4
依序類推...
mtd-utils-1.0.0 下載
發現一個問題:
mkfs.jffs2 -d test -o test.bin
dd if=test.bin of=/dev/mtdblock0
mount -t jffs2 /dve/mtdblock0 /mnt/flash
在最後一個步驟後會有錯誤訊息,研究一下,終於了解.....
既然是模擬Flash memory,有一個參數很重要,那就是 CONFIG_MTDRAM_ERASE_SIZE,所以使用mkfs.jffs2指令來產生image檔案時,必須 "mkfs.jffs2 -e0x20000 -d ./root -o test.bin",如此才能吻合RAM所模擬的FLASH memory
註: mkfs.jffs2 的參數 -e "size" 代表erase block的大小
一般實際有Flash的系統上,會利用CFI去偵測FLASH得到這些資訊
mtd-utils-1.0.0 裡,試過mkfs.jffs2. flash_erase. flash_eraseall 這三個命令
flash_eraseall 作用在 /dev/mtd0 會有問題.看一下flash_eraseall.c, grep bbtest=1,改成bbtest=0就可以了,這個修改是讓程式跳過bad block的檢查,我想應該是核心的MTD子系統沒有建置bad block check的機制,了解不多,不過至少可以用了.... :-)
訂閱:
文章 (Atom)

