ARM学习笔记--day11

ARM异常系(中断)
异常是有CPU处理器来控制的,外设是有外设控制器来控制的,然后外设控制器与CPU相连接
七种异常:
    1.复位异常:
        触发原因:①关机-》开机会产生异常
                  ②reset按键会产生异常
    2.未定义指令异常:
        触发原因:指令没有定义的时候触发的异常,包括关键字不对,格式不正确,或者是将代码下载到错误地址上,导致取不出来指令
    3.软中断:
        swi指令触发,是主动触发,一般系统调用就会触发,用户模式触发软中断是用户模式切换到管理模式,然后可以执行系统的函数的调用,用户模式不可以执行
    4.预取址异常:
        4G地址空间,程序在0x20008000,现在MMU被激活,MMU缺页了,还要访问0x20008000,此时由于MMU缺页无法映射到0x20008000处,导致没有权限访问到实际存储空间0x20008000,这个时候还想进入到0x20008000,此时取不出来指令,程序就会卡在这,这个时候处理器会报告异常
    5.数据异常:
        mov r0,r1
        ldr r3,[r0]    //从r0中读取一个数,读到r3,此时从r0的内存地址上取数据出错,就造成数据异常,与内存操作相关的指令会产生异常
        str ldr stm ldm
    6.irq中断
        硬件触发
    7.firq中断
        硬件触发
异常处理函数:异常发生的时候就会触发的函数,这个函数是解决这种异常的函数
七种异常有七种异常处理函数,是需要开发者完成的,那么异常触发的时候怎么知道异常处理函数在哪里?
    1.异常发生的时候,跳转到固定的位置,这个固定地址处放一条跳转指令,再用这条转到我们的异常处理函数,这个固定的位置就是异常向量表
    2.异常处理函数执行前,需要保存现场(工作在异常模式,操作的寄存器都是异常模式下的),用于异常处理函数处理完之后,回复运行正常代码
在异常处理过程中,软件与硬件的责任都有哪些
    硬件的责任:
        1.把pc寄存器更改了,从正常代码执行的pc值改成异常代码执行的pc值,
        2.在pc的值改变之前,将pc的值保存到跳转之前的异常模式下的lr中,pc是取指的地址,根据三级流水线,取指地址是当前执行的地址+8
        3.CPSR寄存器修改了
        4.在异常前,保存CPSR寄存器中的内容到SPSR(根据异常存到相应的SPSR中,SPSR就是用来保存CPSR的值的)中,保证异常结束后,CPSR值跟异常之前是一致的
        异常发生跳转到异常向量表示硬件做的
    软件的责任:
        1.写异常向量表,需要32个字节,每4字节是一条跳转指令,跳转到异常处理函数
        2.明确基地址,不同异常对应的偏移地址
            基地址有两个基地址:
                基地址默认地址是0,关机到开机时从0地址开始,所以就明白复位异常就是从0地址开始,但是0地址是IROM固化的代码,所以需要MMU
                基地址是0xffff0000,需要修改协处理器
            偏移地址:
                复位:偏移是0
                未定义:偏移是4
                软中断:偏移是8
                预取指异常:偏移是12
                数据异常:偏移是16
                irq:偏移是20
                firq:偏移是24
            以上8条指令放到内存0地址,可以先放到代码最前端,通过连接脚本,从0地址开始运行
        3.异常处理函数
            ①压栈,在正常模式下的寄存器与异常模式的有些寄存器是共用的,所以需要先将正常模式下的寄存器压入堆栈保存起来
            ②压栈之前要保证堆栈存在,所以在启动代码里,先分好栈,初始化堆栈
            ③根据具体的需求,写异常处理的代码
            ④弹栈,把之前压入的值弹出来
            ⑤恢复CPSR
            ⑥模式切换回原来的模式
            ⑦保存在lr中的值给回pc寄存器
            sub r14,r14,#4
            stmfd sp!,{r0~r3,r14}压栈
            ....
            ldmfd sp!,{r0~r3,pc}^弹栈,^更新cpsr

一次中断得到流程
start.s
一般ARM,0地址是可映射的,整个程序在0地址处
.global start
start:
    ldr pc,_reset_hdl     @使用ldr对pc赋值来实现跳转,相比于b与bl的好处就是不受跳转范围的限制,这是条伪指令
    ldr pc,_und_hdl
    ldr pc,_swi_hdl
    ldr pc,_pabt_hdl
    ldr pc,_dataerr_hdl
    b .
    ldr pc,_irq_hdl
    ldr pc,_firq_hdl

_reset_hdl:     
    .word reset            @reset就是一个函数
    
reset:
    bl uart_run
_swi_hdl:
    .word swi
swi:
    //确定返回到pc还是pc-4还是pc-8
    stmfd sp!,{r0~r3,r14}
    ……
    ldmfd sp!,{r0~r3,pc}^

trigger_swi:    @trigger_swi是由C语言调用,触发软中断,然后硬件跳转到ldr pc,_swi_hdl,执行swi
    swi 0
    mov pc,lr

MMU原理&激活MMU
    MMU具备通用性
    作用:实现物理地址与虚拟地址的映射
        物理地址:
            CPU的寻址空间0~4G,规定了从哪到哪是nandflash,哪到哪是IROM,哪到哪是DRAM的,就是这4个G是真实存在的,固定不变的
        虚拟地址:
            UC的地址全部是虚拟地址,驱动也是虚拟地址,链接脚本指定的地址就是虚拟地址
            虚拟地址空间是4个G的,但是哪个地址都不映射,或者都映射
            虚拟地址中有个0xe2900000,这个地址指向哪里是不确定的,物理地址不知道现在指向哪,只能等待MMU来告诉物理地址,要操作哪一块内存
            那么怎么通过MMU让虚拟地址找到对应的物理地址?
                MMU会维护一张页表,通过页表去映射,一级查表,操作0xe2900000,MMU通过页表项找到具体与之对应的物理地址,页表项的值改变,下次使用的时候对应的物理地址就会变化
                好处:多进程操作同一地址时,MMU就起作用了,多进程操作的同一地址是虚拟地址,然后MMU在一个进程运行这个地址的时候,会找一个单独的实际物理地址去运行,从而保证多进程运行没有问题
                


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值