3.ARMv7-M exception model(1)

ARMv7-M exception model

ARMv7-M和ARMv7在异常处理中的不同为:ARMv7-M在异常进入和退出时使用硬件进行关键信息保存和恢复,并且使用Vector中的table代笔异常入口的地址,而不是指令。另外异常分类也有不同。

Overview of the exceptions supported

    ARMv7-M有以下异常:

    Reset

        ARMv7-M支持两种级别Reset:

                1. Power-on reset,Reset处理器,重置所有寄存器(System Control)。

                2. Local Reset, Reset处理器,重置部分寄存器。

        Reset异常的优先级为-3。

    NMI

        Non-Maskable Interrupt是除了Reset之外的最高优先级的异常,优先级为-2。

    HardFault

        HardFault时用于其他异常不能够处理的通用的异常。例如不可恢复的系统错误,但有些HardFault是可恢复的。优先级为-1。Hardfault也可用于Fault升级,有其他Fault升级而来。

    MemManage

        MemManage Fault是又MPU或者固定的内存保护约束产生的,软件可以非使能这种Fault,如果非使能了,那么这种类型的Fault会升级为HardFault。优先级可配置。

    BusFault

        BusFault和访存相关连,比如访存时总线产生的错误会导致这种Fault。软件可以非使能这种Fault,如果非使能了,那么这种类型的Fault会升级为HardFault。优先级可配置。

    UsageFault

        非内存相关的错误,比如:

            Undefined Instruction,未定义指令。

            Invalid state on Instruction Execution,非法的指令运行状态。

            Error on exception return,异常返回出错。

            Attempting to access a disable or unavailable coprocessor,试图访问不存在的协处理器。

            A word or halfword memory accesses to an unaligned address,非对齐访问。

            Division by zero,除0。软件可以非使能这种Fault,如果非使能了,那么这种类型的Fault会升级为HardFault。优先级可配置。

    DebugMonitor

    SVCall

        当软件运行SVC指令时会产生SVCall异常,优先级可配置。

    Interrupts

        PendSV

            使用软件触发的方式产生(写PendSVSET寄存器)。如果应用程序请求底层操作系统服务时,会产生SVCall。那么和SVCall相关的PendSV就会被处理器触发。进而排队等待当前所有中断处理完成再进行        PendSV中断的处理。

        SysTick

            可以由软件写寄存器触发,也可配置Systick功能后由硬件触发。

        external interrupts

            最大可支持496个外部中断,所有中断的优先级都可配置。

Exception number definition

                                                                                         3.ARMv7-M exception model(1)_第1张图片

 

The Vector table

                                                                                             3.ARMv7-M exception model(1)_第2张图片

 

    Vector Table的地址可以由VTOR寄存器更改,也可在Reset时实现一个自定义的地址(stm32 f103系列没有此功能,只有VTOR,但是VTOR在Reset时会被清空)。向量表必须对齐为2的整数次幂,其对齐值大于或等于(支持的异常数x 4),最小的对齐为128byte对齐。所有的异常地址bit[0]都应该被设置为1,因为这个bit在进入异常时会被设置到EPSR.T bit。

Exception priorities and preemption

    在ARMv7-M优先级模型中,数字越低优先级越高。相同优先级的异常优先顺序是固定的且由异常号决定。

    Reset会将软件配置过得优先级清0,业就意味着全部异常(除去Reset,NMI,HardFault)都变为最高优先级。如果在一个异常Pending或者Active时优先级被软件改变了,那么这个改变会同步到指令流里面。

    Maximum supported priority value

        处理器支持的最大优先级数量是可以通过priority bits配置,所支持的最小优先级值是0。priority bits为3-8 bits,即表示为8-256组值,priority bits优先使用高位bits。

    Priority grouping

        优先级组将异常优先级分离为两个部分,组优先(Group Priority)和子优先(Subpriority)。SCS寄存器中的AIRCR.PRIGROUP控制着分离选项,代表了子优先级占用了8-bit优先级中的几bit。

                                                                                              3.ARMv7-M exception model(1)_第3张图片

 

        组优先级定义的时抢占优先(preemption)。如果多个Pending的异常有相同组优先,那么就使用他们的子优先级去决定谁先被处理。

        无论AIRCR.PRIGROUP为何值,Reset,NMI,HardFault的组优先级都为-3,-2,-1。

Execution priority and priority boosting

        当没有Active的异常时,软件会运行在Thread或者Handler模式下,当前的运行优先级值为(所支持的最大异常优先级+1),即最低的优先级。

        运行优先级可以被以下方式定义为最高优先级:

                1. The base level of execution priority

                2. The highest priority of all active exceptions, including any that the current exception preempted

                3. The impact of PRIMASK, FAULTMASK, and BASEPRI values

 

        如果异常处理函数在运行时降低了自己的优先级,那么当前的运行优先级会掉落被抢占的异常的最高抢占优先级上。所以在当前运行的异常处理函数中降低优先级的方式是被禁止的:

                1. 一个被抢占的异常又去抢占当前的异常处理函数。

                2. 和被抢占的异常交换优先级。

        软件能够通过一下机制去提升优先级:

                PRIMASK:设置这个Mask bit为1提升运行优先级值为0。这可以阻止任何可配置优先级的异常变为Active状态,除了fault escalation。

                FAULTMASK:设置这个Mask bit为1去提升运行优先级为-1.软件可以再非NMI和HardFault异常处理函数中取修改这个Mask bit,来将当前运行有限级提升到和HardFault相同,这也意味着会屏蔽掉低于                NMI优先级的异常。如果是在异常中设置此bit,那么当异常返回时会自动将此bit清0(除去NMI异常)。

                BASEPRI:软件可以配置这个寄存器从1-N(最低的可配置优先级)。当这个寄存器清0时,它对运行优先级没有任何影响。当这个寄存器设置非0值时,由AIRCR.GROUP字段的值限定的非零值充当优先级                掩码。当BASEPRI定义的优先级高于当前运行优先级时,这会影响运行优先级。

        优先级提升机制只会影响组优先。不会影响子优先级。子优先只有在排序Pending的异常时有作用,不会影响Active的异常。

    Priority escalation

        四种情形下发生优先级提升:

                1. 当前异常处理函数中触发了同种异常,且此异常为可配置优先级的异常。

                2. 当前异常处理函数中触发了相同优先级或者更低优先级的异常。

                3. 一个可配置优先级没有被使能,但是被触发了。

                4. 当PRIMASK为1时,运行了SVC指令。

    Use of SVCall and PendSV to avoid critical code regions

        上下文切换通常要求处理器在禁用中断的情况下执行关键的代码区域,以避免切换期间关键数据结构的上下文遭到损坏。ARMv7-M可以支持无关键区域的上下文切换,这意味着

        处理器不必禁用中断。

        避免关键区域的ARMv7-M使用模型是:

                1. 使用相同的、最低的异常优先级配置SVCall和PendSV。

                2. 在Thread模式中触发SVCall调用。

                3. 使用PendSV处理从异常处理程序卸载的关键上下文工作,包括可能由SVCall处理程序处理的工作。

Reset behavior

    Reset被触发后会导致处理器终止并丢弃当前运行状态。Reset被释放时,所有寄存器都会恢复为Reset值。

    Reset被触发后,ARM处理器运行的伪代码如下:    

// TakeReset()
// ============
TakeReset()
    CurrentMode = Mode_Thread;
    PRIMASK<0> = '0';
    FAULTMASK<0> = '0';
    /* fault mask cleared at reset */
    BASEPRI<7:0> = Zeros(8);
    /* base priority disabled at reset */
    if HaveFPExt() then
        /* initialize the Floating Point Extn */
        CONTROL<2:0> = '000';
        /* FP inactive, stack is Main, thread is privileged */
        CPACR.cp10 = '00';
        CPACR.cp11 = '00';
        FPDSCR.AHP = '0';
        FPDSCR.DN = '0';
        FPDSCR.FZ = '0';
        FPDSCR.RMode = '00';
        FPCCR.ASPEN = '1';
        FPCCR.LSPEN = '1';
        FPCCR.LSPACT = '0';
        FPCAR = bits(32) UNKNOWN;
        FPFSR = bits(32) UNKNOWN;
        for i = 0 to 31
            S[i] = bits(32) UNKNOWN;
    else
        CONTROL<1:0> = '00';
    /* current stack is Main, thread is privileged */
    for i = 0 to 511
        /* all exceptions Inactive */
        ExceptionActive[i] = '0';
    ResetSCSRegs();
    /* catch-all function for System Control Space reset */
    ClearExclusiveLocal(ProcessorID()); /* Synchronization (LDREX* / STREX*) monitor support */
    ClearEventRegister();
    /* see WFE instruction for more details */
    for i = 0 to 12
        R[i] = bits(32) UNKNOWN;

    bits(32) vectortable = VTOR<31:7>:'0000000';
    SP_main = MemA_with_priv[vectortable, 4, AccType_VECTABLE] AND 0xFFFFFFFC<31:0>;
    SP_process = ((bits(30) UNKNOWN):'00');
    LR = 0xFFFFFFFF<31:0>;
    /* preset to an illegal exception return value */
    tmp = MemA_with_priv[vectortable+4, 4, AccType_VECTABLE];
    tbit = tmp<0>;
    APSR = bits(32) UNKNOWN;
    /* flags UNPREDICTABLE from reset */
    IPSR<8:0> = Zeros(9);
    /* Exception Number cleared */
    EPSR.T = tbit;
    /* T bit set from vector */
    EPSR.IT<7:0> = Zeros(8);
    /* IT/ICI bits cleared */
    BranchTo(tmp AND 0xFFFFFFFE<31:0>); /* address of reset service routine */

Exception entry behavior

    在指令流被抢占时,硬件将上下文状态保存到由一个SP寄存器指向的堆栈上。使用Main Stack还是Process Stack取决于异常时处理器运行的模式。

    被入栈的上下文支持ARM Architecture Procedure Calling Standard(AAPCS)。这意味着异常处理程序可以是符合AAPCS的过程。

    ARMv7-M架构使用了满递减堆栈。

    当将上下文入栈时,硬件会保存8个32-bit的word,包括xPSR,ResturnAddress,LR(R14),R12,R3,R2,R1,R0。

    如果处理器有浮点单元的话,除了这个8字堆栈帧,它还可以将FP state推送到堆栈上,或者在堆栈上为这个状态保留空间。

 

你可能感兴趣的:(ARM,ARMv7-M,Cortex-M,M3,ARM,Exception,ARM,Fault)