第10章stm32复位启动中断控制_第1页
第10章stm32复位启动中断控制_第2页
第10章stm32复位启动中断控制_第3页
第10章stm32复位启动中断控制_第4页
第10章stm32复位启动中断控制_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

在ARM编程领域中,凡是打断程序顺序执行的事件,都被称为异常。除了外部中断外,当有指令执行了“非法操作”,或者访问被禁的内存区间,因各种错误产生的fault,以及不可屏蔽中断发生时,都会打断程序的执行,这些情况统称为异常。简单来说:异常包括外部中断和内核fault。外部中断(IRQ):原本处于正常状态,突然有个外部因素干扰,然后马上处理干扰事项,解决好后又回到原来正常状态。在中断产生后一般会去执行中断服务函数,实现特定任务。无特殊说明,后面:异常就是中断,中断就是异常在编译时,每一个函数都有一个入口地址,该地址就是函数名。尽管函数不是变量,但它在内存中仍有其物理地址,该地址能够赋给指针变量。函数名相当于一个指向其函数入口指针常量。函数名后面加圆括号,表示函数调用。若要得到函数的地址,直接用函数名就可以了。函数名就是一个地址,是存放该函数代码在存储器空间上的起始地址。以一个子函数为例,编译器会分配一段内存空间用于存放改子函数代码内

容,这段内存空间的起始地址是一个具体值,在程序里边就是函数名,当

我们在程序其他位置调用该子函数时候,实际上就是让程序跳转到该函数

名地址去运行子函数内容。Cotrex-M4支持大量的中断,包括16-5(保留功能)-1=10个系统异常,和最多240个外部中断。当一个中断发生时候,并由CM4内核接受后,会执行对应的中断服务函数。所以可以想象需要定义非常多的中断服务函数(而实际上并不需要很多,因为一般都只使能我们需要用到的中断)。为方便CM4找到对应的中断函数入口,

CM4

使用了“向量表查表机制”这里使用一张向量表。向量表其实是一个

WORD(32

位整数)数组,每个下标对应一种中断,该下标元素的值则是该中断服务函数的入口地址。支持10

个系统异常和 最多240个外部中断支持3个固定的高优先级和多达256级的可编程优先级,支持128级抢占。#1~15(系统异常)在 CortexM4

中定义,

IRQ#0~239

(外部中

断)中断由各个芯片商定义编号类型优先级描述0N/AN/A不用于异常,实际是栈顶地址1复位-3复位2NMI-2不可屏蔽中断。RCC时钟安全系统(CSS)连接到NMI

向量。3硬fault-1所有被除能的fault,都将“上访”成硬fault4存储器管理可编程MPU访问犯规以及访问非法位置,在“非执行区”取指均可引发5总线fault可编程总线系统收到错误响应6用法fault可编程程序错误导致异常:使用了一条无效指令,或者非法的状态转换。7~10保留N/A11SVCall可编程执行系统服务调用指令(SVC)引发的异常12调试监视器可编程调试监视器(断点,数据观察点,或者是外部调试请求)13保留N/A14PendSV可编程为实时操作系统而设的“可悬挂请求”15SysTick可编程系统滴答时钟16~255IRQ#0~IRQ#239可编程外部中断#0~#239向量表定义了中断的处理例程的入口地址。缺省情况下,CM4认为向量表位于零地址处响应中断时,CM4会根据中断号从表中找出对应的中断处理程序的入口地址每个表项占用4字节位置0x00000000处保存的是MSP的初始值异常类型表项地址偏移量异常向量00x00MSP的初始值10x04复位20x08NMI30x0C硬fault40x10MemManagefault50x14总线fault60x18用法fault7-100x1c-0x28保留110x2cSVC120x30调试监视器130x34保留140x38PendSV150x3cSysTick160x40IRQ

#0170x44IRQ

#118-2550x48-0x3FFIRQ

#2

-

#239中断向量表的跳转支持10个Cortex-M4系统异常和82 个可屏蔽外部中断16个可编程优先级(使用了4位中 断优先级)包括内核异常在内的所有中断均通 过NVIC

进行管理。嵌套向量中断控制器(NVIC)

和处理器内核接口紧密配合,可以实现低延迟的中断处理和晚到中断的高效处理。地址编号说明0x0000_00000MSP(主堆栈指针)初始值0x0000_00041复位向量地址0x0000_00082不可屏蔽中断NMI向量地址0x0000_000C3硬Fault向量地址………………0x0000_003814可挂起的系统服务0x0000_003C15系统嘀嗒定时器0x0000_004016窗口看门狗中断0x0000_004417连到EXTI的电压检测(PVD)中断0x0000_004818连到EXTI线的入侵和时间戳中断………..……0x0000_017895CRYP加密全局中断0x0000_018096哈希和随机数发生器全局中断0x0000_018497FPU全局中断由Cortex-M4定义由STM32定义startup_stm32f407xx.sstm32f4xx_it.cCM4开机复位状态时,首先要做的是读取下面两个值:从地址0x0000

0000

取出MSP(主堆栈指针)的值从地址0x00000004取出复位向量(程序开始执行的地址),复位向量函数就是存放在startup_stm32f407xx.s文件(汇编语言文件中的:Reset_Handler函数。startup_stm32f407xx.s启动文件内容是一个汇编语言文件。阅读汇编程序之前,我们需要对汇编语言中的关键字有一定的了解,我们可以通过IAR软件帮助功能来查询到汇编关键字的含义。MODULE控制指令是用来标记一个块源码的开始,后边的?cstartup

是模块的名字,此文档的最后的END表明模块的结束。模块只有在相同的名字的模块没有被链接进来的时候才会被链接进来。SECTION指令是声明段,一个段不能同时包含public

symbol和pubweak

symbol。SECTION

section:type

[flag]

[(align)]语法格式:section:段的名字type:memory

的类型,取值是CODE(代码段)、CONST(常量数据段,只读)、DATA(数据段:已初始化的,可读可写)语法格式:

SECTION

section:type

[flag]

[(align)]flag:取值NOROOT、ROOT、REORDER、NOREORDER,默认是ROOT。NOROOT表示如果这个段中的符号没有被引用,将会被连接器舍弃,即可被优化。ROOT表示不可被优化。REORDER表示开始一个新的名字是section的段(section),NOREORDER表示开始一个新的名字为section

的片段(fragment),多个片段组成一个段(section)align

:用于指定地址对齐到2^align,他的取值是0到30EXTERN

用导入其他模块的symbol(符号)PUBLIC

导出symbol(符号)DATA表示下边中的标签是32位的标签, THUMB

表示下边的标签是16

位的标签, 所谓的标签是地址的别名,不占用代码 空间,给编译器看的DCD是数据定义或者重定位指令,为的是 定义一个值,或者保留memory,DCD别名是DC32,用于声明一个32位的常量,这部分是中断向量表的内容,需要注意的是,他们的顺序不能改变,此部分会放到flash的最开始部分,当系统启动的时候会加载前两个地址,第一个地址是C程序的栈的栈顶地址,第二个地址是向量表的开始地址,中断发生时会根据向量表的首地址和偏移量来找到程序的入口sfe指令作用是返回栈的结尾,因为栈的增长方向是反方向的THUMB表明下边是thumb指令Reset_Handler在开机或者复位的时候执行LDR

R0,=SystemInit跳转到SystemInit

函数,并将处理器切换到thumb

状态;LDR

R0,=

iar_program_start跳转到

iar_program_start函数,状态也是切换到

thumb

状态;此处的

iar_program_start在程序中找不到是因为它已经被封装到了IAR自带的C库启动代 码中了,当我们编译的时候,在工程配置的linker->library中勾选了Automatic

runtime library

,就告诉了编译器用库中的

iar_program_start,具体实现了什么,我们可以查看

IAR工具为我们提供的源码,具体路径在IAR安装目录下的arm\src\lib\thumb,我们可以看 到有的文件分别的提供了汇编代码和c

代码。其中的cstartup_M.c

文件中有:#pragma

required=

vector_table

void

iar_program_start(

void

){

iar_init_core();

iar_init_vfp();

cmain();}此段的程序中前两个函数是弱函数,在工程共没有定义

cmain

函数作用是初始化段和底层硬件,最后调用main局部变量:在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的。局部变量使用注意事项:1.不同函数中可以使用使用相同名字的变量,它们代表不同的对象,互不干扰。2.形式参数也是局部变量。3.局部变量的作用域在函数内部。全局变量:在函数内部定义的变量是局部变量,而在函数之外定义的变量称为外部变量,也就是全局变量。全局变量注意事项:全局变量可以为本文件中函数所公用。它的有效范围为从定义变量的位置开始到本源文件结束,一般定义在文件前面位置。设置全局变量的作用是增加了函数间数据联系的渠道。如果在同一个源文件中,外部变量和局部变量同名,则在局部变量的作用范围内,外部变量被“屏蔽”,即外部变量将不起作用。使用全局变量缺点全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。函数的通用性降低了,因为函数在执行时要依赖于其所在的外部变量。如果将一个函数移植到另一个文件中,还要将有关的外部变量及其值一起移植过去。使用全局变量过多,会降低程序的清晰性,特别是多个函数都调用同一个变量时。变量的存储类别从变量的作用域来分,可以分为全局变量和局部变量,而从变量值存在的时间来看,可以分为静态存储方式和动态存储方式。静态存储方式:指在程序运行期间由系统分配固定的存储空间方式。动态存储方式:在程序运行期间根据需要进行动态的分配存储空间方式。全局变量存储在静态存储区中动态存储区可以存放以下数据:函数形式参数,在调用函数时给形参分配存储空间。局部变量(未加static声明的局部变量)函数调用时的现场保护和返回地址等。用static声明局部或者全局变量有时候希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即占用的存储单元不被释放,在下一次该函数调用时,该变量已有值,就是上一次函数调用结束时的值。这时可以使用关键字static进行声明。用static声明一个变量的作用有2个:对局部变量用static声明,则使用该变量在整个程序执行期间不释放,为其分配的的空间始终存在。全局变量用static声明,则该变量的作用域只限于本文件堆栈作用栈(stack)空间,用于局部变量,函数调时现场保护和返回地址,函数的形参等。堆(heap)空间,主要用于动态内存分配,也就是说用malloc,calloc,realloc等函数分配的 变量空间是在堆上。堆栈指针SP指向最后一个被压入堆栈的32位数值。在下一次压栈时,SP先自减4,再存入新的数值。POP

操作刚好相反:先从SP

指针处读出上一次被压入的值,再把SP

指针自增4。#include

"string.h"#include

"stdlib.h"intdtemp1=0;//全局初始化区,可以被其他c文件extern用staticint

dtemp2=0;//静态变量,只允许在本文件使用char*ptemp1;//全局未初始化区int

main(void){intdtemp3;//栈charstemp1[]="abc";//栈char*ptemp2;//栈char*ptemp3="defghi";//defghi\0

在常量区,ptemp3在栈空间上//\0为字符串结束符,确实存在的static

int

dtemp4=0;//全局(静态)初始化区ptemp1=(char

*)malloc(8);ptemp2=(char

*)malloc(16);//在堆区申请8个字节空间//在堆区申请20个字节空间strcpy(ptemp1,"defghi");//defghi\0

在常量区while(1){}}MAP文件是编译器编译后生成的内存映像报告文件段(section)

:描述映像文件的代码和数据块。RO:Read-Only的缩写,包括RO-data(只读数据)和RO-code(代码)。RW:Read-Write的缩写,主要是RW-data,RW-data由程序初始化初始值。ZI:Zero-initialized的缩写,主要是ZI-data,由编译器初始化为0。.text:与RO-code同义。.constdata:与RO-data同义。.bss:与ZI-data同义。.data:与RW-data同义stm32f407总共有92个中断源,所以有时难免有两个或者两个以上的中断一起来临,或者正在处理一个中断服务函数时突然又有一个中断来临,以上种种情况微控制器要怎样运行呢?所以微控制器都有一个处理中断的机制。stm32系列芯片用到的机制是:NVIC。NVIC

即嵌套向量中断控制器(Nested

Vectored

Interrupt

Controller)

。STM32的中有一个强大而方便的NVIC,它是属于CM4内核的器件。NVIC控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对CM4内核里面的NVIC进行裁剪,把不需要的部分去掉,所以说STM32的NVIC是CM4的NVIC的一个子集。NVIC寄存器定义在core_cm4.h文件中,CM4内核支持256个中断,其中包含了16个系统异常和240个外部中断,并且具有256级的可编程中断设置。但

STM32

并没有使用CM4

内核的全部东西,而是只用了它的一部分。

STM32F407芯片有92个中断,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,我们常用的就是这82个可屏蔽中断。编号类型优先级描述0N/AN/A不用于异常,实际是栈顶地址1复位-3复位2NMI-2不可屏蔽中断。RCC

时钟安全系统(CSS)连接到NMI

向量。3硬fault-1所有被除能的fault,都将“上访”成硬fault4存储器管理可编程MPU访问犯规以及访问非法位置,在“非执行区”取指均可引发5总线fault可编程总线系统收到错误响应6用法fault可编程程序错误导致异常:使用了一条无效指令,或者非法的状态转换。7~10保留N/A11SVCall可编程执行系统服务调用指令(SVC)引发的异常12调试监视器可编程调试监视器(断点,数据观察点,或者是外部调试请求)13保留N/A14PendSV可编程为实时操作系统而设的“可悬挂请求”15SysTick可编程系统滴答时钟16~255IRQ#0~IRQ#239可编程外部中断#0~#239支持3个固定的高优先级和多达256级的可编程优先级,支持128级抢占。每个中断的优先级由一个8位的寄存器来设定,分为高低两个位段。高位段表示抢占优先级,低位段表示响应(子)优先级。CM4允许最少使用位数为3个位,即至少要支持8级优先级。优先级以MSB对齐,简化程序的跨器件移植STM32中有两个优先级的概念:抢占式优先级和响应优先级,响应优先级也称子优先级,每个中断源都需要被指定这两种优先级。具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套在低抢占式优先级的中断中。当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断向量表中的排位顺序决定先处理哪一个。在应用程序中断及复位控制器AIRCR中设置优先级分组(地址:0xE000_ED0C)NVIC寄存器定义在core_cm4.h文件中,是由Cortex-M4定义,不是STM32定义的一般只用ISER、ICER和IP这三个寄存器ISER[8]:ISER全称是:Interrupt Set-Enable Registers,这是一个中断使能

寄存器组。上面说了CM4内核支持256个中断,这里用8个32位寄存器来控制,每个位控制一个中断。但是STM32F407

的可屏蔽中断只有82个,所以对我们

来说,有用的就是三个(ISER[0]、ISER[1]和ISER[2]),总共可以表示96个中断。而

STM32F407只用了其中的前82位。ISER[0]的bit0~bit31分别对应中断

0~31,ISER[1]的bit0~31

对应中断

32~63

,ISER[2]的bit0~17

对应中断

64~81;这样总共82个中断就分别对应上了。你要使能某个中断,必须设置相应的

ISER位为1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、

IO口映射等设置才算是一个完整的中断设置)。ICER[8]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与ISER的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和ISER一样。这里要专门设置一个ICER来清除中断位,而不是向ISER写0来清除,是因为NVIC的这些寄存器都是写1有效的,写0是无效的,类似我们之前介绍过的GPIO 端口置位/复位寄存器。通过这种方式,使能/除能中断时只需把“当事位”写成1,其它的位可以全部为零。再也不用像以前那样,害怕有些位被写入0而破坏其对应的中断设置(写0没有效

果),从而实现每个中断都可以自顾地设置,而互不侵犯——只需单一的写

指令,不再需要读-改-写。IP[240]:全称是:Interrupt

Priority

Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32的中断分组与这个寄存器组密切相关。IP寄存器组由240个8bit的寄存器组成,每个可屏蔽中断占用8bit,这样总共可以表示240

个可屏蔽中断。而STM32

只用到了其中的前82

个。

IP[0]~IP[81]分别对应中断0~81。而每个可屏蔽中断占用的8bit并没有全部使用,而是只用了高4位,见下表。这4位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据SCB->AIRCR

中的中断分组设置来决定。bit7bit6bit5bit4bit3bit2bit1bit0用于表达优先级未使用形参选择:NVIC_PRIORITYGROUP_0:0位抢占式优先级,4位响应优先级;NVIC_PRIORITYGROUP_1:1位抢占式优先级,3位响应优先级;NVIC_PRIORITYGROUP_2:2位抢占式优先级,2位响应优先级;NVIC_PRIORITYGROUP_3:3位抢占式优先级,1位响应优先级;NVIC_PRIORITYGROUP_4:4位抢占式优先级,0位响应优先级;HAL_NVIC_SetPriority函数用于设置一个中断的优先级,它有三个形参,第一个为IRQn_Type类型参数,指定中断源,它是定义在stm32f407xx.h文件中。第二个和第三个形参分别设定中断的抢占式优先级和响应优先级,这个的设置要与中断组配合使用。HAL_NVIC_SetPriority函数实际是调用定义在core_cm4.h文件的NVIC_SetPriority函数实现功能的,该函数通过设置

SCB_SHP寄存器或者NVIC_IPRx寄存器实现功能。HAL_NVIC_EnableIRQ函数用于在NVIC控制器中使能指定中断,它有一个形参,是

IRQn_Type类型参数。HAL_NVIC_EnableIRQ

函数实际是通过调用定义在core_cm3.h

文件中的NVIC_EnableIRQ函数实现功能,NVIC_EnableIRQ函数设置了NVIC_ISER寄存器内容。HAL_NVIC_DisableIRQ

函数是在NVIC

控制器中禁用指定中断,用法与HAL_NVIC_EnableIRQ函数相同。最终通过设置NVIC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论