您的位置:首页 > 其它

Cortex-M0【中断向量表】【中断控制和系统控制

2017-07-14 09:25 302 查看
SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM
Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.syd-tek.com/

Cortex-M0中断向量表

__Vectors 
     DCD     __initial_sp              ; Top of Stack

                DCD     Reset_Handler             ; Reset Handler

                DCD     NMI_Handler               ; NMI Handler

                DCD     HardFault_Handler         ; Hard Fault Handler

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     SVC_Handler        ; SVCall Handler

                DCD     0                         ; Reserved

                DCD     0                         ; Reserved

                DCD     PendSV_Handler   ; PendSV Handler

                DCD     SysTick_Handler   ; SysTick Handler

下文摘录于:http://blog.csdn.net/fervor_heart/article/details/8288914

这里向前辈敬礼!

NMI (Non Maskable Interrupt)——不可屏蔽中断(即CPU不能屏蔽)

无论状态寄存器中 IF 位的状态如何,CPU收到有效的NMI必须进行响应;NMI是上升沿有效;中断类型号固定为2;它在被响应时无中断响应周期.不可屏蔽中断通常用于故障处理(如:协处理器运算出错,存储器校验出错,I/O通道校验出错等).

  IF = Interrupt Flag(中断状态)

  在DSP等学习中NMI解释同样为“不可屏蔽中断”,其英文解释为“External Non-Maskable Interrupt”

下文摘录于:http://blog.csdn.net/guozhongwei1/article/details/49544671

这里向前辈敬礼!


SVC和PendSV

SVC(系统服务调用,亦简称系统调用)和PendSV(可悬起系统调用),它们多用于在操作系统之上的软件开发中。SVC 用于产生系统函数的调用请求。例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个SVC 异常,然后操作系统提供的SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。 

这种“提出要求——得到满足”的方式,很好、很强大、很方便、很灵活、很能可持续发展。首先,它使用户程序从控制硬件的繁文缛节中解脱出来,而是由OS 负责控制具体的硬件。第二,OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠。第三,它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险。第四,通过SVC 的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。开发应用程序唯一需要知道的就是操作系统提供的应用编程接口(API),并且了解各个请求代号和参数表,然后就可以使用SVC
来提出要求了(事实上,为使用方便,操作系统往往会提供 

一层封皮,以使系统调用的形式看起来和普通的函数调用一致。各封皮函数会正确使用SVC指令来执行系统调用——译者注)。其实,严格地讲,操作硬件的工作是由设备驱动程序完成的,只是对应用程序来说,它们也是操作系统的一部分。如图7.14 所示 


 

SVC 异常通过执行”SVC”指令来产生。该指令需要一个立即数,充当系统调用代号。SVC异常服务例程稍后会提取出此代号,从而解释本次调用的具体要求,再调用相应的服务函数。例如,
SVC 0x3 ; 调用3 号系统服务
1

在SVC 服务例程执行后,上次执行的SVC 指令地址可以根据自动入栈的返回地址计算出。找到了SVC 指令后,就可以读取该SVC 指令的机器码,从机器码中萃取出立即数,就获知了请求执行的功能代号。如果用户程序使用的是PSP,服务例程还需要先执行
MRS Rn,PSP
1

指令来获取应用程序的堆栈指针。通过分析LR 的值,可以获知在SVC 指令执行时,正在使用哪个堆栈。 

由CM3 的中断优先级模型可知,你不能在SVC 服务例程中嵌套使用SVC 指令(事实上这样做也没意义),因为同优先级的异常不能抢占自身。这种作法会产生一个用法fault。同理,在NMI 服务例程中也不得使用SVC,否则将触发硬fault。

PendSV: 

另一个相关的异常是PendSV(可悬起的系统调用),它和SVC 协同使用。一方面,SVC异常是必须立即得到响应的(若因优先级不比当前正处理的高,或是其它原因使之无法立即响应,将上访成硬fault——译者注),应用程序执行SVC 时都是希望所需的请求立即得到响应。另一方面,PendSV 则不同,它是可以像普通的中断一样被悬起的(不像SVC 那样会上访)。OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动作。悬起PendSV 的方法是:手工往NVIC 的PendSV 悬起寄存器中写1。悬起后,如果优先级不够高,则将缓期等待执行。 
PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是:
执行一个系统调用
系统滴答定时器(SYSTICK)中断,(轮转调度中需要) 

举个简单的例子来辅助理解。假设有这么一个系统,里面有两个就绪的任务,并且通过SysTick 异常启动上下文切换。如图7.15 所示。 



上图是两个任务轮转调度的示意图。但若在产生SysTick 异常时正在响应一个中断,则SysTick 异常会抢占其ISR。在这种情况下,OS 不得执行上下文切换,否则将使中断请求被延迟,而且在真实系统中延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这种事。因此,在CM3 中也是严禁没商量——如果OS 在某中断活跃时尝试切入线程模式,将触犯用法fault 异常。 



为解决此问题,早期的OS 大多会检测当前是否有中断在活跃中,只有没有任何中断需要响应时,才执行上下文切换(切换期间无法响应中断)。然而,这种方法的弊端在于,它可以把任务切换动作拖延很久(因为如果抢占了IRQ,则本次SysTick 在执行后不得作上下文切换,只能等待下一次SysTick 异常),尤其是当某中断源的频率和SysTick 异常的频率比较接近时,会发生“共振”。 

现在好了,PendSV 来完美解决这个问题了。PendSV 异常会自动延迟上下文切换的请求,直到其它的ISR 都完成了处理后才放行。为实现这个机制,需要把PendSV 编程为最低优先级的异常。如果OS 检测到某IRQ 正在活动并且被SysTick 抢占,它将悬起一个PendSV 异常,以便缓期执行上下文切换。如图7.17 所示 



个中事件的流水账记录如下: 
任务 A 呼叫SVC 来请求任务切换(例如,等待某些工作完成)
OS 接收到请求,做好上下文切换的准备,并且pend 一个PendSV 异常。
当 CPU 退出SVC 后,它立即进入PendSV,从而执行上下文切换。
当 PendSV 执行完毕后,将返回到任务B,同时进入线程模式。
发生了一个中断,并且中断服务程序开始执行
在 ISR 执行过程中,发生SysTick 异常,并且抢占了该ISR。
OS 执行必要的操作,然后pend 起PendSV 异常以作好上下文切换的准备。
当 SysTick 退出后,回到先前被抢占的ISR 中,ISR 继续执行
ISR 执行完毕并退出后,PendSV 服务例程开始执行,并且在里面执行上下文切换
当 PendSV 执行完毕后,回到任务A,同时系统再次进入线程模式。

Cortex-M0中断控制和系统控制 

本文摘录于:http://blog.csdn.net/jasenmaodj/article/details/46941605

版权归原作者所有,这里向前辈致敬!

一. NVIC和系统控制块特性

1. 灵活的中断管理:使能/禁止中断,优先级配置
2. 硬件嵌套中断支持
3. 向量化的异常入口
4. 中断屏蔽
5. NVIC寄存器的起始地址:0xE000E100, 对其访问必须是每次32bit
6. SCB的起始地址: 0xE000E010,也是每次32bit访问。

二. 中断使能和清除使能

1. 中断寄存器是可编程的,用于控制中断请求(异常编号16以上)的使能(SETENA)和禁止(CLRENA), 如下所示:




     这里说一下:

    对于ARM M0而言,SysTick_Handler是第15号中断,从16号开始是NVIC所控制的外部中断,最多只能有32个外部中断

2. 使能/禁止 中断的代码:
1). C代码:

*(volatile unsigned long) (0xE000E100) = 0x4 ; //使能#2中断
*(volatile unsigned long) (0xE000E180) = 0x4 ; //禁止#2中断

2). 汇编代码:

LDR R0, =0xE000E100  ;  //SETEAN寄存器的地址
MOVS R1, #04         ;  //设置#2中断
STR R1, [R0]         ;  //使能中断#2

3). CMSIS标准设备驱动函数:

void NVIC_EnableIRQ(IRQn_Type_IRQn);  //使能中断#IRQn;
void NVIC_DisableIRQ(IRQn_Type_IRQn); //禁止中断#IRQn;

三. 中断挂起和清除挂起:

1. 可以通过操作中断挂起(SETPEND)和清除挂起(CLRPEND),这两个寄存器来访问和修改中断挂起状态。

      如果软件配置挂起中断就是软中断的实现!


2.挂起/清除挂起的代码:
1). C代码:

*(volatile unsigned long)(0xE000E100) = 0x4 ; //使能中断#2
*(volatile unsigned long)(0xE000E200) = 0x4 ; // 挂起中断#2
*(volatile unsigned long)(0xE000E280) = 0x4 ; // 清除中断#2的挂起状态

2). 汇编代码:

LDR R0, =0xE000E100   ;  //设置使能中断寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //使能#2中断
LDR R0, =0xE000E200   ;  //设置挂起中断寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //挂起#2中断
LDR R0, =0xE000E280   ;  //设置清除中断挂起寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //清除#2的挂起状态

 3). CMSIS标准设备驱动函数:

void NVIC_SetPendingIRQ(IRQn_Type_IRQn)  ; //设置一个中断挂起
void NVIC_ClearPendingIRQ(IRQn_Type_IRQn); //清除中断挂起
void NVIC_GetPendingIRQ(IRQn_Type_IRQn)  ; //读取中断挂起状态

四. 中断优先级:(0xE000E400~0xE000E41C)

1. 每个外部中断都有一个对应的中断有先级寄存器,每个优先级都是只有一个字节且只有最高2Bit有效;
2. NVIC支持字传输,所以每次访问都会涉及4个中断优先级寄存器。

    也就是说ARM MO只是支持四级优先级,并且高优先级中断能够打断低优先级中断。



3. 设置中断优先级代码:(先读一个字,再修改对应字节,最后整个字写回)

1). C代码:

unsigned long temp;                           //定义一个临时变量
temp = *(volatile unsigned long)(0xE000E400); //读取IRP0值
temp &= (0xFF00FFFF |(0xC0 << 16));           //修改中断#2优先级为0xC0
*(volatile unsigned long)(0xE000E400) = temp; //设置IPR0

2). 汇编代码:

LDR R0, =0xE000E100   ;  //设置使能中断寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //使能#2中断
LDR R0, =0xE000E200   ;  //设置挂起中断寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //挂起#2中断
LDR R0, =0xE000E280   ;  //设置清除中断挂起寄存器地址
MOVS R1, #0x4         ;  //中断#2
STR R1, [R0]          ;  //清除#2的挂起状态

 3). CMSIS标准设备驱动函数:

void NVIC_SetPriority(IRQn_Type_IRQn, uint32_t priority)  ; //设置中断优先级
uint32_t NVIC_GetPriority(IRQn_Type_IRQn);                  //读取中断优先级

这里的priority是0,1,2,3.函数内部会自动移位到对应的优先级最高2位:
void NVIC_SetPriority(2, 3) ; //设置#2中断的优先级为0xC0

    SYD8801设置中断优先级的方法如下:

    NVIC_SetPriority(GPIO_IRQn, 3);

    NVIC_SetPriority(UART0_IRQn, 0);

五. 异常屏蔽寄存器(PRIMASK)

1.对时间敏感的应用,需要用PRIMASK来屏蔽掉除NMI和硬件错误异常以外的其他所有中断和异常。
2.PRIMASK只有1Bit有效,默认为0,为1时起屏蔽作用。
3.操作PRIMASK的代码:
1). 汇编代码:

MOVS R0, #1      ;
MSR  PRIMASK, R0 ; //使用MSR指令设置PRIMASK值

2). CPS指令:

CPSIE  i ;        //清除PRIMASK值
CPSID  i ;        //设置PRIMASK值

3). CMSIS标准设备驱动函数:

void _enable_irq(void)  ;  //清除PRIMASK值
void _disable_irq(void) ;  //设置PRIMASK值

六. 中断输入和挂起行为

1. Cortex-M0允许电平触发和脉冲触发两种方式;
2. 每个外部中断请求都会对应一个挂起状态寄存器,且只有1bit,当开始处理这个异常时,硬件会自动清除挂起状态;
3. 大多数外设都是使用电平触发,当执行中断服务程序并且清除外设中断信号之前,该信号一直为高:




4. 使用脉冲触发中断时,至少持续1个时钟周期:




七. 中断等待 (中断确认 –> 中断服务处理开始执行)

1. Cortex-M0中断默认等待的时间为16个时钟周期;
2. 中断等待的条件:
1). 改中断使能并且没有被PRIMASK屏蔽掉;
2). 存储器系统没有任何等待。

3. IRQLATENCY的8位信号可以控制中断等待:设置为0,则以最快速度响应中断。

八. 系统异常的控制寄存器(SHPR2,SHPR3)

1. Cortex-M0处理器只有SVC、PendSV和SysTick 3个与OS相关的系统异常才具有可编程的 优先级




2. 符合CMSIS的设备驱动,可使用如下方式访问:




3. 中断控制状态寄存器(ICSR, 0xE000ED04):
P139, 表9.6
4. 符合CMSIS的设备驱动,可使用 "SCB -> ICRS" 来访问。

九. 系统控制寄存器(0xE000E000~0xE000EFFF)

1. SCS包括NVIC、调试控制、SysTick定时器;
2. CPU ID基址寄存器(0xE000ED00),只读,包含处理器ID信息,"SCB -> CPUID" 访问;
3. 应用中断和复位控制寄存器(AIRCR, 0xE000ED0C):
1). 用于应用程序请求系统复位,识别系统的大小端,以及清除所有的异常活动状态:




2). CMSIS 设备驱动,可以使用 "SCB -> AIRCR" 来访问;
3). CMSIS 设备驱动, 请求系统复位的函数:

Void NVIC_SystemReset(void);

十. 配置和控制寄存器(CCR, 0xE000ED14)

1. CCR 只读, 决定了栈的双字节对齐设置和非对称访问的处理;
2. CMSIS 设备驱动,可以使用 "SCB -> CCR" 来访问;


       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息