• SWI软中断


      1 .text
      2 .global _start
      3 
      4 _start:
      5     b reset          /* vector 0 : reset */
      6     ldr pc, und_addr /* vector 4 : und */
      7     ldr pc, swi_addr /* vector 8 : swi */
      8 
      9 und_addr:
     10     .word do_und
     11 
     12 swi_addr:
     13     .word do_swi
     14 
     15 do_und:
     16     /* 执行到这里之前:
     17      * 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址
     18      * 2. SPSR_und保存有被中断模式的CPSR
     19      * 3. CPSR中的M4-M0被设置为11011, 进入到und模式
     20      * 4. 跳到0x4的地方执行程序 
     21      */
     22 
     23     /* sp_und未设置, 先设置它 */
     24     ldr sp, =0x34000000
     25 
     26     /* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */
     27     /* lr是异常处理完后的返回地址, 也要保存 */
     28     stmdb sp!, {r0-r12, lr}  
     29     
     30     /* 保存现场 */
     31     /* 处理und异常 */
     32     mrs r0, cpsr
     33     ldr r1, =und_string
     34     bl printException
     35     
     36     /* 恢复现场 */
     37     ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */
     38     
     39 und_string:
     40     .string "undefined instruction exception"
     41 
     42 .align 4
     43 
     44 do_swi:
     45     /* 执行到这里之前:
     46      * 1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址
     47      * 2. SPSR_svc保存有被中断模式的CPSR
     48      * 3. CPSR中的M4-M0被设置为10011, 进入到svc模式
     49      * 4. 跳到0x08的地方执行程序 
     50      */
     51 
     52     /* sp_svc未设置, 先设置它 */
     53     ldr sp, =0x33e00000
     54 
     55     /* 保存现场 */
     56     /* 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */
     57     /* lr是异常处理完后的返回地址, 也要保存 */
     58     stmdb sp!, {r0-r12, lr}  
     59 
     60     mov r4, lr
     61     
     62     /* 处理swi异常 */
     63     mrs r0, cpsr
     64     ldr r1, =swi_string
     65     bl printException
     66 
     67     sub r0, r4, #4 /* 此时r0中存放的只是地址,地址指向swi 0x123 */
     68     bl printSWIVal
     69     
     70     /* 恢复现场 */
     71     ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */
     72     
     73 swi_string:
     74     .string "swi exception"
     75 
     76 .align 4
     77 
     78 reset:
     79     /* 关闭看门狗 */
     80     ldr r0, =0x53000000
     81     ldr r1, =0
     82     str r1, [r0]
     83 
     84     /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
     85     /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
     86     ldr r0, =0x4C000000
     87     ldr r1, =0xFFFFFFFF
     88     str r1, [r0]
     89 
     90     /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
     91     ldr r0, =0x4C000014
     92     ldr r1, =0x5
     93     str r1, [r0]
     94 
     95     /* 设置CPU工作于异步模式 */
     96     mrc p15,0,r0,c1,c0,0
     97     orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
     98     mcr p15,0,r0,c1,c0,0
     99 
    100     /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 
    101      *  m = MDIV+8 = 92+8=100
    102      *  p = PDIV+2 = 1+2 = 3
    103      *  s = SDIV = 1
    104      *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
    105      */
    106     ldr r0, =0x4C000004
    107     ldr r1, =(92<<12)|(1<<4)|(1<<0)
    108     str r1, [r0]
    109 
    110     /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
    111      * 然后CPU工作于新的频率FCLK
    112      */
    113     
    114     
    115 
    116     /* 设置内存: sp 栈 */
    117     /* 分辨是nor/nand启动
    118      * 写0到0地址, 再读出来
    119      * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
    120      * 否则就是nor启动
    121      */
    122     mov r1, #0
    123     ldr r0, [r1] /* 读出原来的值备份 */
    124     str r1, [r1] /* 0->[0] */ 
    125     ldr r2, [r1] /* r2=[0] */
    126     cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    127     ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    128     moveq sp, #4096  /* nand启动 */
    129     streq r0, [r1]   /* 恢复原来的值 */
    130 
    131     bl sdram_init
    132     //bl sdram_init2     /* 用到有初始值的数组, 不是位置无关码 */
    133 
    134     /* 重定位text, rodata, data段整个程序 */
    135     bl copy2sdram
    136 
    137     /* 清除BSS段 */
    138     bl clean_bss
    139 
    140     /* 复位之后, cpu处于svc模式
    141      * 现在, 切换到usr模式
    142      */
    143     mrs r0, cpsr      /* 读出cpsr */
    144     bic r0, r0, #0xf  /* 修改M4-M0为0b10000, 进入usr模式 */
    145     msr cpsr, r0
    146 
    147     /* 设置 sp_usr */
    148     ldr sp, =0x33f00000
    149 
    150     ldr pc, =sdram
    151 sdram:
    152     bl uart0_init
    153 
    154     bl print1
    155     /* 故意加入一条未定义指令 */
    156 und_code:
    157     .word 0xdeadc0de  /* 未定义指令 */
    158     bl print2
    159 
    160     swi 0x123  /* 执行此命令, 触发SWI异常, 进入0x8执行 */
    161 
    162     //bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
    163     ldr pc, =main  /* 绝对跳转, 跳到SDRAM */
    164 
    165 halt:
    166     b halt

    注意第67行,其中r0中存放的只是地址,地址指向第160,所有r0中存放的不是0x123

    因此,对于下面的两个函数:

     向printHex函数传入的是整型数,实则传入的是r0的地址

     此时打印出来的数值 (printHex)是r0的地址,

    如果,printHex函数传入的参量是 指针的话,输出的就是r0地址中的数值

     观察下面的反汇编代码:

     此时就可以输出正确的结果:

  • 相关阅读:
    调研一类软件的发展演变—聊天软件( 1000-2000 words, in Chinese)
    C++用法的学习心得(要求包含示例,并反映出利用网络获取帮助的过程)
    软件工程学习总结
    南通大学教务管理微信公众号体验
    设计一款给爸爸妈妈用的手机
    第二次作业
    web browser 发展史
    c++用法的学习心得
    电梯调度
    一个数组既有正数也有负数,计算出它的子数组和的最大值。
  • 原文地址:https://www.cnblogs.com/lihanrui/p/13828822.html
Copyright © 2020-2023  润新知