• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 60, 文章 - 0, 評(píng)論 - 197, 引用 - 0
            數(shù)據(jù)加載中……

            s3c2410 MMU 啟用后設(shè)置中斷跳轉(zhuǎn)指令遇到的問(wèn)題

            事情是這樣的, 前些日子在 FS2410 (核心板為三星 s3c2410)開(kāi)發(fā)板上實(shí)現(xiàn)了中斷,包括
            響應(yīng)時(shí)鐘 Timer0, 響應(yīng)按鍵,并實(shí)現(xiàn)了串口通信,能把任何數(shù)據(jù)通過(guò) UART0 發(fā)送到 PC 機(jī)
            上的超級(jí)終端上進(jìn)行顯示,這樣也便于調(diào)試。前兩天又實(shí)現(xiàn)了 MMU 的啟用代碼,歡呼雀躍
            啊..., 可就在這個(gè)時(shí)候問(wèn)題來(lái)了...

            MMU 啟用后中斷不能響應(yīng)了!, start.S 的代碼片段如下(arm-linux-gcc 匯編格式):

               text
               .global _start
               _start:
                b reset
                NOP
                NOP
                NOP
                NOP
                NOP
                ldr pc ,=handle_irq
                NOP
               reset:
                ldr r0, =0x53000000  @ Close Watch-dog Timer
                mov r1, #0x0
                str r1, [r0]
              
                @ init stack
                ldr sp,=4096
                
                @ disable all interrupts
                mov r1, #0x4A000000
                mov r2, #0xffffffff
                str r2, [r1, #0x08]
                ldr r2, =0x7ff
                str r2, [r1, #0x1c]
              
                bl  memory_setup  @ Initialize memory setting
                bl  flash_to_sdram  @ Copy code to sdram
               
                ldr pc, =run_on_sdram
             run_on_sdram:
                ldr sp, =0x33000000
                bl init_mmu_tlb   @ setup page table
                bl init_mmu   @ MMU enabled
              
                msr cpsr_c, #0xd2  @ set the irq mode stack
                ldr sp, =0x31000000
                msr cpsr_c, #0xdf  @ set the system mode stack
                ldr sp, =0x32000000
                bl  init_irq           
                msr cpsr_c, #0x5f  @ set the system mode open the irq
                
                ldr sp, =0x33000000  @ Set stack pointer
                bl  main
               loop:
                b loop
              
            我是通過(guò)在地址 0x00000018 放入一條長(zhǎng)跳轉(zhuǎn)指 ldr pc, =handle_irq 來(lái)響應(yīng)中斷的,在
            沒(méi)有啟用 MMU 之前,代碼工作的很好。通過(guò)如下兩個(gè)函數(shù)啟用了 MMU 實(shí)現(xiàn)虛擬內(nèi)存管理:

                 bl init_mmu_tlb   @ setup page table
                 bl init_mmu   @ MMU enabled

            通過(guò)下面代碼來(lái)映射低端和高端中斷向量表:

              *(tb_base + 0x00000000) = (0x00000000)|(0x03<<10)|(0<<5)|(1<<4)|(1<<3)|0x02;
              *(tb_base + (0xffff0000>>20)) = VECTORS_PHY_BASE|(0x03<<10)|(0<<5)|(1<<4)|(0<<3)|0x02;

            其中 VECTORS_PHY_BASE=0x33f00000, 可以看到:
            通過(guò)設(shè)置頁(yè)表,將 0xffff0000 為首地址的 32 個(gè)字節(jié)的中斷向量表被映射到 0x33ff0000 為首地址的 32 字節(jié)區(qū)域,

            既然設(shè)置了高端中斷向量,我們就要在 0x33ff0000 處設(shè)置中斷跳轉(zhuǎn)指令,通過(guò)調(diào)用下面這個(gè)函數(shù):

               bl  flash_to_sdram

            把程序自身復(fù)制到 SDRAM 的 0x30004000為首地址的區(qū)域,而 0x30004000 前面的 16K 即 0x30000000~0x30003FFF
            用來(lái)放置頁(yè)表,并且把 nand flash 的前 512byte 復(fù)制到 SDRAM 0x33ff0000 處, 因?yàn)閚and flash 的前32byte 是8 個(gè)
            中斷跳轉(zhuǎn)指令,這樣中斷向量表就在 0x33ff0000 處被設(shè)置。

            如何讓 ARM 使用高端的中斷跳轉(zhuǎn)指令呢?通過(guò)設(shè)置 CP15 協(xié)處理器的一些寄存器來(lái)啟用。以下是內(nèi)聯(lián)匯編片段

               /*
                * turn on what we want
                * base location of exception = 0xffff0000
                */
               "orr r0, r0, #0x2000\n"
               "orr r0, r0, #0x0002\n"

               /* MMU enabled*/
               "orr r0, r0, #0x0001\n"

               /* write control register*/
               "mcr p15, 0, r0, c1, c0, 0\n"

            萬(wàn)事俱備,我們可以實(shí)驗(yàn)了,可不幸的中斷不能響應(yīng)了?!...

            ......經(jīng)過(guò)了一天的折騰,發(fā)現(xiàn)將中斷跳轉(zhuǎn)指令由
               b reset
                NOP
                NOP
                NOP
                NOP
                NOP
                ldr pc,=handle_irq
                NOP

            改為

               b reset
                NOP
                NOP
                NOP
                NOP
                NOP
                ldr pc, handle_irq_addr
                NOP
               handle_irq_addr: 
                .long handle_irq


            中斷就能響應(yīng)了,代碼運(yùn)行的很好,可百思不得其解,為什么不能用 ldr pc, =handle_irq
            設(shè)置而非要用下面這種形式呢

                    ldr pc, handle_irq_addr
                    NOP
               handle_irq_addr: 
                    .long handle_irq

            我在 main 函數(shù)里通過(guò)如下代碼將所有的中斷跳轉(zhuǎn)指令(高端的和低端的)都打印出來(lái)了:

            #include "serl.h"
            #include "printf.h"

            #define GPFCON (*(volatile unsigned long *)0x56000050)
            #define GPFDAT (*(volatile unsigned long *)0x56000054)

            int main()
            {
              init_uart();
              GPFDAT = 0x0;
              uart_printf("starting:\n");
              unsigned long *ptr = (unsigned long *)0x30004000;
              unsigned long *ptr2 =(unsigned long *)0x33ff0000;

              unsigned long *ptr3 = (unsigned long *)0x00000000;
              unsigned long *ptr4 = (unsigned long *)0xffff0000;

              int i= 8;
              while (i--) {
                uart_printf("%x  %x  %x  %x\n", *ptr++, *ptr2++, *ptr3++, *ptr4++);
              }
              while (1);
              return 0;
            }

            代碼將數(shù)據(jù)通過(guò)串口在超級(jí)終端上進(jìn)行顯示后,發(fā)現(xiàn)確有微妙不同:

            中斷不能響應(yīng)時(shí)(ldr pc, =handle_irq):
            0x30004000 0x33ff0000 0x00000000 0xffff0000
            -------------------------------------------
            ea000006   ea000006   ea000006   ea000006
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e59ff1fc      e59ff1fc      e59ff1fc      e59ff1fc
            e1a00000   e1a00000   e1a00000   e1a00000


            中斷可以響應(yīng)時(shí)(ldr pc, handle_irq_addr):
            0x30004000 0x33ff0000 0x00000000 0xffff0000
            -------------------------------------------
            ea000007   ea000007   ea000007   ea000007
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e1a00000   e1a00000   e1a00000   e1a00000
            e59ff000     e59ff000     e59ff000     e59ff000
            e1a00000   e1a00000   e1a00000   e1a00000


            難道編譯器對(duì)這兩種跳轉(zhuǎn)產(chǎn)生了不同的影響? 將代碼反匯編來(lái)看個(gè)究竟:

            中斷不能響應(yīng)時(shí)(ldr pc, =handle_irq):
            ---------------------------------------------------------------------
                   0: ea000006  b 0x20
                   4: e1a00000  nop   (mov r0,r0)
                   8: e1a00000  nop   (mov r0,r0)
                   c: e1a00000  nop   (mov r0,r0)
                  10: e1a00000  nop   (mov r0,r0)
                  14: e1a00000  nop   (mov r0,r0)
                  18: e59ff1fc  ldr pc, [pc, #508] ; 0x21c
                  1c: e1a00000  nop   (mov r0,r0)


            發(fā)現(xiàn) ldr pc, =handle_irq 被匯編成

               ldr pc, [pc, #508] ; 0x21c

            我們又發(fā)現(xiàn)編譯器為這條指令生成了一條注釋: ; 0x21c, 它的意思是說(shuō)去地址0x21c 處加載
            數(shù)據(jù),怎么算的呢? 當(dāng)前地址是 0x18, 加上 508 即 0x1fc 得出 0x214,好像不是0x21c,
            慢著... ARM 采用三級(jí)流水結(jié)構(gòu),那么讀 pc 時(shí)得到的得數(shù)值會(huì)是相對(duì)當(dāng)前指令的第二條指
            令的地址, 即當(dāng)前地址值加上 0x8,這么算來(lái):

              0x18 + 0x1fc + 0x8 = 0x21c

            去 0x21c 處看看:

              21c: 30004208  andcc r4, r0, r8, lsl #4

            是 0x30004208 這么個(gè)值,也就是說(shuō) ARM 把 0x30004208 裝進(jìn)了 pc
            ......


            再來(lái)看看將中斷跳轉(zhuǎn)指令改成

                    ldr pc, handle_irq_addr
                    NOP
               handle_irq_addr: 
                     .long handle_irq

            也就是中斷能響應(yīng)時(shí)的反匯編代碼:

                   0: ea000007  b 0x24
                   4: e1a00000  nop   (mov r0,r0)
                   8: e1a00000  nop   (mov r0,r0)
                   c: e1a00000  nop   (mov r0,r0)
                  10: e1a00000  nop   (mov r0,r0)
                  14: e1a00000  nop   (mov r0,r0)
                  18: e59ff000  ldr pc, [pc, #0] ; 0x20
                  1c: e1a00000  nop   (mov r0,r0)

            可以看到 0x18 處為      

                  18: e59ff000  ldr pc, [pc, #0] ; 0x20

            與上面分析同理,去 0x20 處看看:

                  20: 3000420c  andcc r4, r0, ip, lsl #4

            發(fā)現(xiàn) ARM 把 0x3000420c 這個(gè)數(shù)值裝進(jìn)了 pc


            前后對(duì)比一下, 一個(gè)是 0x30004208, 另一個(gè)是 0x3000420c, 兩者相差 4 個(gè)字節(jié)
            而后一種情況多出的4個(gè)字節(jié)是由于 定義
               
               handle_irq_addr: 
                .long handle_irq

            而占用的 4 個(gè)字節(jié)。

            看來(lái)編譯器忠實(shí)的匯編了代碼,那么很可能是 MMU 啟用后對(duì) ldr pc, =handle_irq 這樣
            的中斷跳轉(zhuǎn)指令產(chǎn)生了影響?

            ......現(xiàn)在還沒(méi)有找到合理的解釋,請(qǐng)高手不吝賜教

            posted on 2008-01-28 11:11 Normandy 閱讀(3826) 評(píng)論(3)  編輯 收藏 引用 所屬分類: Embeded Area

            評(píng)論

            # re: s3c2410 MMU 啟用后設(shè)置中斷跳轉(zhuǎn)指令遇到的問(wèn)題  回復(fù)  更多評(píng)論   

            樓主其實(shí)已經(jīng)摸到錯(cuò)誤的門了,雖然沒(méi)能得出結(jié)論…………
            2008-01-28 14:36 | ggyy

            # re: s3c2410 MMU 啟用后設(shè)置中斷跳轉(zhuǎn)指令遇到的問(wèn)題  回復(fù)  更多評(píng)論   

            @ggyy

            呵呵,問(wèn)題已經(jīng)解決,一個(gè)低級(jí)的錯(cuò)誤,原因如下:
            508 + 0x8 即 516, 大于 512, 前面我提到把 Nand flash 的前 512 字節(jié)復(fù)制到 0x33ff0000 處用以設(shè)置高端中斷向量表,這樣當(dāng)發(fā)生 IRQ 中斷時(shí),程序會(huì)去 0x33ff0000 + 508 + 0x8 處把 0x30004208 裝進(jìn) pc 并進(jìn)行跳轉(zhuǎn)來(lái)響應(yīng)中斷,但不幸的是我只復(fù)制了512字節(jié),所以 IRQ 中斷是不能響應(yīng)的。總結(jié)一下,對(duì)比上面提到的兩種設(shè)置中斷跳轉(zhuǎn)指令的方式:

            (1)
            b reset
            NOP
            NOP
            NOP
            NOP
            NOP
            ldr pc,=handle_irq
            NOP

            (2)
            b reset
            NOP
            NOP
            NOP
            NOP
            NOP
            ldr pc, handle_irq_addr
            NOP
            handle_irq_addr:
            .long handle_irq

            第二種方式的好處是顯而易見(jiàn)的,只需要偏移 0x8 就能取到目的地址了;對(duì)第一種方式,ARM 要去通過(guò)一個(gè)偏移來(lái)取到目的地址,具體數(shù)值要看編譯如何設(shè)置了。
            2008-01-29 14:00 | Normandy

            # re: s3c2410 MMU 啟用后設(shè)置中斷跳轉(zhuǎn)指令遇到的問(wèn)題  回復(fù)  更多評(píng)論   

            其實(shí),ARM匯編指令LDR很好的說(shuō)明了這個(gè)問(wèn)題,看看它的說(shuō)明,好好理解下。
            2008-11-14 17:12 | zqs
            久久综合亚洲欧美成人| 99久久精品午夜一区二区| 久久亚洲精品国产亚洲老地址 | 国内精品久久久久久久久电影网| 精品久久人人爽天天玩人人妻| 久久精品蜜芽亚洲国产AV| 久久无码国产| 97久久精品午夜一区二区| 怡红院日本一道日本久久 | 国产精品久久免费| 伊人久久大香线蕉综合热线| A狠狠久久蜜臀婷色中文网| 久久只这里是精品66| 国产成人精品久久亚洲高清不卡 | 少妇被又大又粗又爽毛片久久黑人| 久久99精品久久久久婷婷| 亚洲精品NV久久久久久久久久| 久久亚洲国产精品一区二区| 一本久久a久久精品vr综合| 伊人久久大香线蕉综合5g| 国产亚洲精午夜久久久久久| 国产精品美女久久久久久2018| 久久人人爽人人爽人人片av麻烦 | 久久精品国产国产精品四凭| 99国产欧美久久久精品蜜芽| 亚洲国产另类久久久精品| 久久久亚洲精品蜜桃臀| 国产激情久久久久影院老熟女免费 | 日韩精品久久久久久| 久久er国产精品免费观看2| 久久精品毛片免费观看| 亚洲国产精品无码成人片久久| 少妇无套内谢久久久久| 一本久久免费视频| 久久久久久久久久久| 久久久国产乱子伦精品作者| 亚洲国产另类久久久精品| 丁香狠狠色婷婷久久综合| 66精品综合久久久久久久| 亚洲欧美日韩精品久久| 亚洲午夜无码AV毛片久久|