关于STM32中断向量表的位置 、重定向问题
STM32常见问题解析(论文资料)
STM32常见问题解析1、时钟安全系统(CSS)时钟安全系统被激活后,时钟监控器将实时监控外部高速振荡器;如果HSE时钟发生故障,外部振荡器自动被关闭,产生时钟安全中断,该中断被连接到Cortex‐M3的NMI的中断;同时CSS将内部RC振荡器切换为STM32的系统时钟源(对于STM32F103,时钟失效事件还将被送到高级定时器TIM1的刹车输入端,用以实现电机保护控制)。
操作流程:1)、启动时钟安全系统CSS: RCC_ClockSecuritySystemCmd(ENABLE); (NMI中断是不可屏蔽的!)2)外部振荡器失效时,产生NMI中断,对应的中断程序:void NMIException(void){if (RCC_GetITStatus(RCC_IT_CSS) != RESET){ // HSE、PLL已被禁止(但是PLL设置未变)…… // 客户添加相应的系统保护代码处// 下面为HSE恢复后的预设置代码RCC_HSEConfig(RCC_HSE_ON); // 使能HSERCC_ITConfig(RCC_IT_HSERDY, ENABLE); // 使能HSE就绪中断RCC_ITConfig(RCC_IT_PLLRDY, ENABLE); // 使能PLL就绪中断RCC_ClearITPendingBit(RCC_IT_CSS); // 清除时钟安全系统中断的挂起位// 至此,一旦HSE时钟恢复,将发生HSERDY中断,在RCC中断处理程序里, 系统时钟可以设置到以前的状态}}3)、在RCC的中断处理程序中,再对HSE和PLL进行相应的处理。
注意:一旦CSS被激活,当HSE时钟出现故障时将产生CSS中断,同时自动产生 NMI。
NMI 将被不断执行,直到CSS中断挂起位被清除。
因此,在NMI的处理程序中 必须通过设置时钟中断寄存器(RCC_CIR)里的CSSC位来清除CSS中断。
STM32引脚列表中主功能,默认复用功能和重定义功能的区别STM32F103RCT6引脚功能及使用
STM32引脚列表中主功能,默认复用功能和重定义功能的区别STM32F103RCT6引脚功能及使用1 主功能就是STM32基本IO口,与外设没有连接的,我们可以直接输出或读入高低电平使用时采用要初始化GPIO结构体参数,并打开端口的时钟2 默认复用功能是与外设连接的IO口,单片机通过控制IO口控制外设。
使用时采用要初始化GPIO结构体参数,IO口的工作模式要更具STM32中文参考手册中,IO口复用功能的设置工作模式,设置时,与主功能的唯一区别就是IO口的工作模式的不同。
3 当我想把外设不连接到默认引脚上,那就根据“重定义功能”这一列来重新定义外设连接的IO口。
一般情况我们不会用到。
注意:一旦需要对AFIO寄存器配置时,一定要打开AFIO的时钟(一般在使用外部中断EXTI或外设引脚重定义时)--------------------- 转载----------------------------STM32F103RCT6引脚功能及使用说明:1) VBAT:VBAT给RTC和备份区域供电,目的是在VDD断电时保证相关区域的数据内容有效,一般连接到外部电池。
若不用此功能,可直接连接到VDD。
2) 供电方案:Ø每个VDD各接一个0.1uF陶瓷电容,VDD3需要再接一个4.7~10uF的钽电容;Ø VDDA:10nF陶瓷电容+1nF钽电容;ØVREF+:可接VDDA,也可接外部参考源,此时,需要接10nF陶瓷电容+1nF钽电容;3) PC13/PC14/PC15:内部连接了模拟开关,只能通过少量的电流,驱动能力不够(不能用于点亮LED),且不能同时使用,尽量不用。
4) 进入待机模式之后,PA0-WKUP引脚上的上升沿,作为待机模式唤醒条件。
5) USART:CTS/RTS/CK/TX/RX,一般只使用TX/RX引脚实现异步通信,加上CK可以实现同步通信,CTS/RTS是硬件流控引脚,一般不用。
解析STM32启动过程
解析STM32启动过程
STM32启动过程是指当电源被接通时,STM32芯片进行自检并加载固
件的过程。
这个过程可以分为四个主要阶段:复位阶段、时钟初始化阶段、中断向量表重定位阶段和主函数执行阶段。
时钟初始化阶段是STM32启动的第二个阶段。
在复位阶段,系统时钟
会被配置为默认的内部RC振荡器,通常为8MHz。
在时钟初始化阶段,可
以通过程序代码来配置系统时钟,包括选择和配置时钟源、设置时钟分频等。
时钟的初始化是系统正常运行的前提条件,因为大多数外设的工作频
率都与系统时钟相关。
主函数执行阶段是STM32启动的最后一个阶段。
在中断向量表重定位
完成后,主函数会被调用执行。
主函数中通常会初始化系统的各种外设,
配置时钟、GPIO、中断等,并进入一个无限循环等待外设事件的发生。
一
旦外设事件发生,会触发中断,处理对应的中断服务程序。
总结来说,STM32启动过程包括复位阶段、时钟初始化阶段、中断向
量表重定位阶段和主函数执行阶段。
复位阶段进行系统自检和硬件初始化,时钟初始化阶段配置系统时钟,中断向量表重定位阶段将中断向量表重定
位到实际的起始地址,主函数执行阶段初始化外设并进入循环等待外设事
件的发生。
这个过程是STM32系统启动的基本过程,对于系统的正常运行
起着关键作用。
STM32 NVIC中断向量表设置以及EXTI中断寄存器设置
两位控制,分级 0-3. 第 2 行意思是打开中断编号为 6 的中断,即允许外部中断 0 第 3 行意思即设定中断编号为 6 的中断优先级具体分配情况,0XA0—1010 0000,即 抢占优先级和响应优先级都设置为 2. 这里需要注意,我并没有设置中断偏移,采用了默认设置,如果有需要时,则要对 SCB->VOTR 进行相关设置 4、 中断函数的书写 A. 中断函数名的书写有要求,否则会找不到中断入口。在 3.5 库函数之前,在 stm32f10x_it.c 中就预先写好了个外部中断的函数名称,我们只要将对应的执行过程 填充进去就可以;但 3.5 库函数里没有给出,因此我们参考之前的。比如例程中我 写的中断函数名称就为 void EXTI0_IRQHandler(void)。 B. 在进入中断后我们需要做的动作有 2 部,一次执行中断过程,2 是清除中断挂起标 识,因为执行完毕了。如果不清除中断挂起标识,则无法再次进入中断。 看例程
图2 从图中,我们可以看到和中断相关的寄存器总共有 6 个,他们分别是 1.EXTI_IMR(Interrupt mask register )中断屏蔽寄存器。
图3 该寄存器复位值为 0,往对应寄存器内写 1 则打开中断 2. EXTI_EMR( Event mask register )中断事件屏蔽寄存器
#ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in
Internal SRAM. */ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in
stm32 外部中断详细讲解 (转)
4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组
}
设置相应的时钟所需要的RCC函数在stm32f10x_rcc.c中,所以要在工程中添加此文件。
2. 设置好相应的中断
设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:
第0组:所有4bit用于指定响应优先级;
第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级;
第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级;
第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级;
第4组:所有4位用于指定抢占式优先级。
所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel; //选择中断通道3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占式中断优先级设置为1
STM32中断优先级彻底讲解
STM32中断优先级彻底讲解stm32目前支持的中断共为84个(16个内核+68个外部),16级可编程中断优先级的设置(仅使用中断优先级设置8bit中的高4位)和16个抢占优先级(因为抢占优先级最多可以有四位数)。
二:优先级推论stm32(cortex-m3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。
具备低抢占市场式优先级的中断可以在具备高抢占市场式优先级的中断处理过程中被积极响应,即为中断嵌套,或者说低抢占市场式优先级的中断可以嵌套高抢占市场式优先级的中断。
当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。
如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序同意先处置哪一个。
三:优先级分组既然每个中断源都须要被选定这两种优先级,就须要存有适当的寄存器位记录每个中断的优先级;在cortex-m3中定义了8个比特位用作设置中断源的优先级,这8个比特位在nvic应用领域中断与登位掌控递丛器(aircr)的中断优先级分组域中,可以存有8种分配方式,如下:所有8位用于指定响应优先级最低1十一位用作选定抢占市场式优先级,最高7十一位用作选定积极响应优先级最低2十一位用作选定抢占市场式优先级,最高6十一位用作选定积极响应优先级最低3十一位用作选定抢占市场式优先级,最高5十一位用作选定积极响应优先级最低4十一位用作选定抢占市场式优先级,最高4十一位用作选定积极响应优先级最低5十一位用作选定抢占市场式优先级,最高3十一位用作选定积极响应优先级最低6十一位用作选定抢占市场式优先级,最高2十一位用作选定积极响应优先级最低7十一位用作选定抢占市场式优先级,最高1十一位用作选定积极响应优先级这就是优先级分组的概念。
STM32F0系列MCU中断向量表的重映射
STM32F0系列MCU中断向量表的重映射最近使⽤了⼀款Cortex-M0内核的芯⽚STM32F030CC,发现它中断向量表的重映射⽅法与STM32F10x系列的有所区别,在这⾥记录与分享⼀下。
由于需要通过IAP进⾏固件升级,所以芯⽚的FLASH⾥⾯要烧录两份代码:⼀个Boot loader, ⼀个⽤户应⽤程序。
理所当然的,在⽤户应⽤程序中,必须得重新映射中断向量表。
可是在ST提供的固件库⾥,我却没有发现类似于stm32f10x固件库中的void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)接⼝。
浏览了⼀下,原来M0并没有SCB->VTOR这个寄存器,难怪ST的库⾥没有提供NVIC_SetVectorTable这个接⼝。
这下要怎么办?在⽹络上搜索了⼀下,受到⽹友的启发,我在中找到以下说明:Physical remap Once the boot mode is selected, the application software can modify the memory accessible in the code area.This modification is performed by programming the MEM_MODE bits in the SYSCFG configuration register 1 (SYSCFG_CFGR1). Unlike Cortex® M3 and M4, the M0 CPU does not support the vector table relocation. For application code which is located in a different address than 0x0800 0000, some additional code must be added in order to be able to serve the application interrupts. A solution will be to relocate by software the vector table to the internal SRAM: • Copy the vector table from the Flash (mapped at the base of the application load address) to the base address of the SRAM at0x2000 0000. • Remap SRAM at address 0x0000 0000, using SYSCFG configuration register 1. • Then once an interrupt occurs, the Cortex®-M0 processor will fetch the interrupt handler start address from the relocated vector table in SRAM, then it will jump to execute the interrupt handler located in the Flash. This operation should be done at the initialization phase of the application. Please refer to and attached IAP code from for more details. OK,解决⽅法找到了! 在⽤户应⽤程序中,按照以上⽅法,添加以下两⾏代码:memcpy((void*)0x20000000, (void*)0x08004000, VECTOR_SIZE);SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM); 其中,0x2000 0000是SRAM的起始地址,这个不需要改动。
stm32解决中断冲突的方法
stm32解决中断冲突的方法如何解决STM32中的中断冲突第一步:了解STM32中断机制STM32微控制器系列是STMicroelectronics开发的一系列32位ARM Cortex-M内核的微控制器。
STM32使用向量中断控制器(NVIC)来管理中断。
每个可中断源都有一个特定的中断优先级,并且可以通过调整优先级来控制中断的触发和处理顺序。
中断是STM32系统中非常重要的一部分,它允许微控制器在处理其他任务时根据需要对外部事件作出响应。
但是,在STM32中使用多个中断时可能会出现冲突的问题。
这可能导致一些中断无法触发或中断优先级错误。
为了解决这个问题,可以采取以下方法。
第二步:了解中断冲突的原因中断冲突可能是由于中断优先级设置错误、中断嵌套问题或中断间共享资源引起的。
中断优先级设置错误是指中断的优先级设置不正确,导致某些中断会被覆盖或延迟触发。
中断嵌套问题是指当一个中断正在处理时,另一个中断发生,导致中断无法正确触发。
中断间共享资源引起的冲突是指多个中断同时访问共享资源,导致数据错误或冲突。
第三步:调整中断优先级首先,调整中断的优先级是解决中断冲突的关键。
在STM32中,每个中断源都有一个特定的优先级,范围从0到15。
较低的数值表示更高的优先级,而较高的数值表示较低的优先级。
为了更好地控制中断触发和处理顺序,可以根据系统需求适当调整中断的优先级。
调整中断优先级可通过在NVIC中设置相关的中断控制器寄存器来实现。
有两个关键的寄存器需要设置:中断优先级寄存器(IPR)和中断使能寄存器(IER)。
中断优先级寄存器用于设置中断的优先级,而中断使能寄存器用于使能或禁用中断。
为了防止冲突,可以将高优先级的中断设置为较低的值(例如0或1),而将低优先级的中断设置为较高的值(例如14或15)。
这样可以确保高优先级的中断首先得到处理,从而避免了中断冲突。
第四步:正确处理中断嵌套另一个常见的中断冲突问题是中断嵌套。
STM32 中断向量表的位置 、重定向
STM32 中断向量表的位置、重定向我们也知道怎么跳到main 函数了,那么,中断发生后,又是怎么跑到中断入口地址的呢?从stm32f10x.s 可以看到,已经定义好了一大堆的中断响应函数,这就是中断向量表,标号__Vectors,表示中断向量表入口地址,例如:AREA RESET, DATA, READONLY ;定义只读数据段,实际上是在CODE区(假设STM32 从FLASH 启动,则此中断向量表起始地址即为0x8000000)EXPORT __VectorsIMPORT OS_CPU_SysTickHandler IMPORTOS_CPU_PendSVHandler__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler这个向量表的编写是有讲究的,跟硬件一一对应不能乱写的,CPU 找入口地址就靠它了,bin 文件开头就是他们的地址,参考手册RM0008 的10.1.2 节可以看到排列。
我们再结合CORTEX-M3 的特性,他上电后根据boot 引脚来决定PC 位置,比如boot 设置为flash 启动,则启动后PC 跳到0x08000000。
此时CPU 会先取2 个地址,第一个是栈顶地址,第二个是复位异常地址,故有了上面的写法,这样就跳到reset_handler。
那么这个reset_handler 的实际地址是多少.?下面的一堆例如Nmi_handler 地址又是多少呢?发生中断是怎么跑到这个地址的呢?下面挨个讲解。
STM32学习记录12 中断向量表
STM32 学习记录12 中断向量表从stm32f10x.s 可以看到,已经定义好了一大堆的中断响应函数,这就是中断向量表,标号__Vectors,表示中断向量表入口地址,例如:AREA RESET, DATA, READONLY ;定义只读数据段,实际上是在CODE 区(假设STM32 从FLASH 启动,则此中断向量表起始地址即为0x8000000)EXPORT__VectorsIMPORT OS_CPU_SysTickHandler IMPORTOS_CPU_PendSVHandler__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler这个向量表的编写是有讲究的,跟硬件一一对应不能乱写的,CPU 找入口地址就靠它了,bin 文件开头就是他们的地址,参考手册RM0008 的10.1.2 节可以看到排列。
我们再结合CORTEX-M3 的特性,他上电后根据boot 引脚来决定PC 位置,比如boot 设置为flash 启动,则启动后PC 跳到0x08000000。
此时CPU 会先取2 个地址,第一个是栈顶地址,第二个是复位异常地址,故有了上面的写法,这样就跳到reset_handler。
那么这个reset_handler 的实际地址是多少.?下面的一堆例如Nmi_handler 地址又是多少呢?发生中断是怎么跑到这个地址的呢?下面挨个讲解。
stm32 freertos 中断写法
在STM32微控制器上使用FreeRTOS实时操作系统时,中断服务例程(ISR)的写法需要遵循一定的规范,以确保中断处理能够在不同的任务之间正确地进行。
以下是一些基本步骤和注意事项,用于在FreeRTOS中实现中断服务例程:1. **中断向量表初始化**:在系统启动时,需要初始化中断向量表,将中断处理函数的地址映射到相应的中断号上。
2. **中断优先级设置**:在FreeRTOS中,可以通过NVIC(嵌套向量中断控制器)设置中断的优先级。
在中断服务例程中,可以使用`HAL_NVIC_SetPriority`函数设置优先级。
3. **中断使能**:在中断服务例程编写完成后,需要使用`HAL_NVIC_EnableIRQ`或`HAL_NVIC_Enable`函数使能中断。
4. **中断服务例程的原型**:中断服务例程应该有一个原型,其中包含了中断号和中断服务例程的函数指针。
5. **在中断服务例程中保护现场**:在进入中断服务例程之前,应该保存CPU的状态,包括程序计数器和其他必要的寄存器,以防止中断服务例程被其他中断打断。
6. **中断服务例程的退出**:在中断服务例程结束时,应该恢复之前保存的状态,并使用`HAL_NVIC_DisableIRQ`或`HAL_NVIC_Disable`函数禁用中断。
7. **使用FreeRTOS的API**:如果需要在中断服务例程中使用FreeRTOS的API,比如创建任务、等待消息等,应该确保这些操作不会导致中断被禁止的时间过长,以免影响系统的响应性。
以下是一个简单的STM32中断服务例程的示例代码:```cvoid EXTI0_IRQHandler(void) {// 保存状态HAL_NVIC_DisableIRQ(EXTI0_IRQn); // 禁用中断// 中断处理逻辑// ...// 恢复状态HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 使能中断} ```。
stm32 中断向量表 NVIC_SetVectorTable() 应用
stm32 中断向量表NVIC_SetVectorTable()应用
STM32 的中断向量表的设置主要是用在IAP程序中,如果是普通的flash 中只有一个程序,一般不需要设置这个。
顾名思义,这个表存放的是中
断服务函数的入口地址,当发生中断时,CPU 来这个表中查询,以此获取中断
函数的入口地址。
在stm32 的启动文件中,设置完成堆栈,就来设置中断向
量表,AREA RESET, DATA, READONLY ;定义只读数据段,实际上是在CODE 区(假设STM32 从FLASH 启动,则此中断向量表起始地址即为
0x8000000)如果改变了程序的起始地址,这种就是IAP 的情况了,像这个样
子那么这个时候就需要重新设置中断向量表
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00010000);//重新配置中断向量表配合地址的改变,这样程序运行的时候才能找到中断服务函数的入口地址,
正常执行。
附件:对中断向量表更深入的解释显然,200039c0 就是栈顶地址,
而08006F21 就是reset_handler 地址!stm32 小端模式,高字节在高位,低字节在低位,所以这个要反过来看。
tips:感谢大家的阅读,本文由我司收集整编。
仅供参阅!。
stm32定时器中断配置
stm32 定时器中断配置
stm32 中断
stm32 的Cortex 内核具有强大的异常响应系统,它把能够打断当前代码执行流程的事件分为异常(excepTIon)和中断(terryp),并把它们用二个表管理起来,编号为0~15 的称为内核异常,而16 以上的则称为外部中断(外,相对内核而言),这个表就称为中断向量表。
而STM32 对这个表重新进行了编排,把编号从-3 至6 的中断向量定义为系统异常,编号为负的内核异常不能被设置优先级,如复位(Reset)、不可屏蔽中断(NMI)、硬错误(Hardfault)。
从编号7 开始的为外部中断,这些中断的优先级都是可以自行设置的。
STM32 的中断如此之多,配置起来并不容易,因此,我们需要一个
强大而方便的中断控制器NVIC,NVIC 是属于Cortex 内核的器件。
stm32 中断配置
配置STM32 的中断只需要理解2 个内容,配置4 个变量即可。
STM32外部中断原理与配置
STM32外部中断原理与配置STM32-外部中断原理与配置IO⼝外部中断原理概述STM32控制器⽀持的外部中断/事件请求中断线M3M4M7EXTI线0~15:对应外部IO⼝的输⼊中断。
√√√EXTI线16:连接到PVD输出。
√√√EXTI线17:连接到RTC闹钟事件。
√√√EXTI线18:连接到USB OTG FS唤醒事件。
√√√EXTI线19:连接到以太⽹唤醒事件。
√√EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件√√EXTI线21:连接到RTC⼊侵和时间戳事件。
√√EXTI线22:连接到RTC唤醒事件。
√√EXSTI线23:连接到LPTIM1异步事件√IO⼝外部中断STM32的每个IO都可以作为外部中断输⼊。
每个外部中断线可以独⽴的配置触发⽅式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专⽤的状态位。
STM32供IO使⽤的中断线只有16个,但是STM32F系列的IO⼝多达上百个,STM32F103ZGT6(112),那么中断线怎么跟io⼝对应呢?GPIO和中断线映射关系GPIOx.0映射到EXTI0GPIOx.1映射到EXTI1……GPIOx.14映射到EXTI14GPIOx.15映射到EXTI15对于M4/M7,配置寄存器为SYSCFG_EXTIRx对于M3,配置寄存器为AFIO_EXTICRx如下图所⽰,EXTI0[3:0]有4个位,可以配置16个,所以可以从PA0选择到PI0。
也就是说16个中断线,最多可以处理16*16个外部引脚的中断。
可以在⼿册中找到SYSCFG 外部中断配置寄存器:16个中断线就分配16个中断服务函数?IO⼝外部中断在中断向量表中只分配了7个中断向量,也就是只能使⽤7个中断服务函数。
从表中可以看出,外部中断线5~ 9分配⼀个中断向量,共⽤⼀个服务函数外部中断线10~15分配⼀个中断向量,共⽤⼀个中断服务函数。
中断服务函数列表:EXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI9_5_IRQHandlerEXTI15_10_IRQHandlerIO⼝外部中断HAL库配置⽅法外部中断操作使⽤到的函数分布⽂件stm32fxxx_hal_gpio.hstm32fxxx_hal_gpio.c外部中断配置:外部中断的中断线映射配置和触发⽅式都是在GPIO初始化函数中完成:GPIO_InitTypeDef GPIO_Initure;GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA,&GPIO_Initure);void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init){uint32_t position;uint32_t ioposition = 0x00;uint32_t iocurrent = 0x00;uint32_t temp = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Init->Pin));assert_param(IS_GPIO_MODE(GPIO_Init->Mode));assert_param(IS_GPIO_PULL(GPIO_Init->Pull));/* Configure the port pins */for(position = 0; position < GPIO_NUMBER; position++){/* Get the IO position */ioposition = ((uint32_t)0x01) << position;/* Get the current IO position */iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;if(iocurrent == ioposition){/*--------------------- GPIO Mode Configuration ------------------------*//* In case of Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)){/* Check the Alternate function parameter */assert_param(IS_GPIO_AF(GPIO_Init->Alternate));/* Configure Alternate function mapped with the current IO */temp = GPIOx->AFR[position >> 3];temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));GPIOx->AFR[position >> 3] = temp;}/* Configure IO Direction mode (Input, Output, Alternate or Analog) */temp = GPIOx->MODER;temp &= ~(GPIO_MODER_MODER0 << (position * 2));temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));GPIOx->MODER = temp;/* In case of Output or Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {/* Check the Speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));/* Configure the IO Speed */temp = GPIOx->OSPEEDR;temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));temp |= (GPIO_Init->Speed << (position * 2));GPIOx->OSPEEDR = temp;/* Configure the IO Output Type */temp = GPIOx->OTYPER;temp &= ~(GPIO_OTYPER_OT_0 << position) ;temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);GPIOx->OTYPER = temp;}/* Activate the Pull-up or Pull down resistor for the current IO */temp = GPIOx->PUPDR;temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));temp |= ((GPIO_Init->Pull) << (position * 2));GPIOx->PUPDR = temp;/*--------------------- EXTI Mode Configuration ------------------------*//* Configure the External Interrupt or event for the current IO */if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE){/* Enable SYSCFG Clock */__HAL_RCC_SYSCFG_CLK_ENABLE();temp = SYSCFG->EXTICR[position >> 2];temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03)));SYSCFG->EXTICR[position >> 2] = temp;/* Clear EXTI line configuration */temp = EXTI->IMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT){temp |= iocurrent;}EXTI->IMR = temp;temp = EXTI->EMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT){temp |= iocurrent;}EXTI->EMR = temp;/* Clear Rising Falling edge configuration */temp = EXTI->RTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE){temp |= iocurrent;}EXTI->RTSR = temp;temp = EXTI->FTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE){temp |= iocurrent;}EXTI->FTSR = temp;}}}}和串⼝中断⼀样,HAL库同样提供了外部中断通⽤处理函数HAL_GPIO_EXTI_IRQHandler,我们在外部中断服务函数中会调⽤该函数处理中断。
中断向量表重映射与复制
中断向量表重映射与复制2009年09月09日星期三下午 01:51/******************************************************************** *********** 文档名:中断向量表重映射与复制* 创建:/netee/* 日期:2009-9-9********************************************************************* *********/关键字:中断向量表重映射,中断向量表复制,建立多个KEIL工程,多个MAIN 函数一、为什么要做中断向量表的重映射?对于LPC2XXX系列芯片:当程序中用到中断的功能时,在产生中断后,处理器会将会跳到处理中断的地址处去执行。
而在产生中断后处理器首先会跳到指定的地址处。
这个指定的地址只有三个地方:Boot ROM区,内部FLASH区的0x00000000地址处,或者内部SRAM区的0x40000000地址处。
(若是LPC2378,则还有一个用户外部存储器区域)那么产生中断后它到底会跳到哪个地址,就要看存储器映射控制寄存器(MEMMAP-0XE01FC040)的位1:0(MAP)的值,默认值为00,这时中断向量被重新映射到Boot ROM区,当为01时,则中断向量位于FLASH中也就是地址0x00000000处,当为10时,则中断向量被重新映射到SRAM中,地址为0x40000000,当为11时,为用户外部存储器模式。
二、什么时候需要做向量表重映射?1、当工程中编写的中断向量表在内部FLASH中0x00000000处时,则需要重新映射,映射方法:只需要将MEMMAP的1:0位的值设为01即可;2、当中断向量表在SRAM中时,则需要重新映射,映射方法:只需要将MEMMAP的1:0位的值设为10可;三、什么时候需要做中断向量表的复制?当中断向量表放在内部FLASH中,而且起始地址不是0x00000000时,此时如果程序运行后产生中断,则中断向量找不到处理中断的地址,这时候就会出错。
(2)STM32使用HAL库操作外部中断——理论讲解
(2)STM32使⽤HAL库操作外部中断——理论讲解1.中断触发过程对主程序压栈——把中断服务函数的地址写⼊到程序计数器(PC)——执⾏中断服务函数2.中断向量表中断服务函数的地址在STM32的⼿册上的中断向量表中(如下是⼀部分):如上表所⽰,EXTI0中断服务函数的地址是0x00000058。
意思就是如果触发了外部中断那么就从0x00000058地址开始执⾏,这个地址的函数可以在HAL库的启动⽂件中找到。
很明显,EXTI0的中断服务函数的函数名是:EXTI0_IRQHandlerEXTI0~EXTI4是独⽴的,9~5共⽤中断源,15~10共⽤中断源,9~5和15~10的中断需要在中断函数中判断是哪个中断引脚。
3.HAL库中的中断服务函数。
这⾥我们要⽤PD10引脚触发外部中断,根据向量表,EXTI10的中断服务函数是:EXTI15_10_IRQHandler。
HAL库中代码是这样执⾏的:(1)⾸先是中断服务函数PD10外部中断触发之后程序计数器被写⼊0x000000E0(EXTI15_10_IRQHandler函数的地址)然后程序开始执⾏EXTI15_10_IRQHandler函数:EXTI15_10_IRQHandler函数只是调⽤了另⼀个函数HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);在这个函数中清楚中断标志位然后⼜调⽤了⼀个HAL_GPIO_EXTI_Callback(GPIO_Pin)函数。
根据函数名Callback也能看出来这⾥才是真正执⾏具体功能的函数,该函数需要⽤户在mian.c⽂件中重写:4.NVIC中断控制器步骤1-3说明了⼀个最基本的中断过程。
然⽽还有⼀个重要的概念没有讲到,NVIC中断控制器。
STM32⽀持中断嵌套,为了更好的更强⼤的实现中断嵌套,ST给出了⼀个NVIC中断控制器来专门管理中断。
我们都知道⾼优先级的中断能打断低优先级的中断优先执⾏,等⾼优先级中断执⾏完之后在返回去执⾏被打断的中断,这就是中断嵌套。
STM32F0重映射中断向量表测试
while(1);
}
从0x0800 0000、0x2000 0000开始;
(2)APP中
正常编程,只修改:(即IROM从APP的起始地址开始,但IRAM跳过__Vectors)
从0x0800 0C00、0x2000 00C0开始;
方法2:
和方法1相同,唯一不同的就是在APP中,进入main()后也增加了memcpy((void*)0x20000000, (void*)FLASH_BASE_RUN, 0xC0);
(4)、从0x8000 0C00,0x2000 0000开始,在IAP+APP中复制FLASH到RAM
(5)、从0x8000 0C00,0x2000 00C0开始,在IAP+APP中复制FLASH到RAM--正常
(6)、其他IAP中不复制RAM、APP中复制且是/否初始化0x2000 0000……之类的,试了多种情况结果都不可行。
…………
if(……)//0xABCDEFAB
{………把APP2复制到APP1………
}ቤተ መጻሕፍቲ ባይዱ
else//0x12345678或其他值,从RunData运行区中正常运行
{
memcpy((void*)0x20000000, (void*)FLASH_BASE_RUN, 0xC0);
SYSCFG->CFGR1 |= 0x03;
#define FLASH_BASE_RUN 0x08000C00//FLASH运行区的起始地址
#define FLASH_BASE_UPDATA 0x08008000//FLASH下载区的起始地址
…………
static void IAP_Load_App(void)
stm32中断优先级的处理原则
STM32中断优先级的处理原则1. 引言在嵌入式系统中,中断是一种常用的机制,用于在特定事件发生时打断CPU的正常执行流程,转而执行特定的中断处理程序。
STM32系列微控制器提供了丰富的中断控制功能,并支持多个优先级的中断。
正确设置中断优先级是确保系统稳定性和可靠性的重要步骤。
本文将介绍STM32中断优先级处理原则,包括如何设置优先级、不同类型中断之间的关系以及注意事项等内容。
2. 中断优先级概述STM32微控制器支持多个优先级的中断,其中数字越小表示优先级越高。
当多个中断同时发生时,只有具有最高优先级的中断会被响应。
其他低优先级的中断将被挂起,等待当前正在处理的高优先级中断完成后再进行处理。
每个STM32微控制器都有一个向量表(Vector Table),其中存储了各个中断向量及其对应的ISR(Interrupt Service Routine)。
在初始化过程中,需要将需要使用到的ISR函数指针写入向量表相应位置。
3. 中断优先级设置原则在STM32微控制器上配置和设置各个外设的中断优先级时,需要遵循以下原则:3.1 高优先级中断的响应时间高优先级中断的响应时间应尽量短,以确保系统对紧急事件的及时响应。
通常情况下,系统启动和初始化过程中会配置一些必要的高优先级中断,如系统滴答定时器(SysTick)等。
3.2 低优先级中断的执行时间低优先级中断可能会被高优先级中断打断,在高优先级中断执行期间无法得到处理。
因此,低优先级中断的执行时间应尽量短,以减少对系统性能和实时性的影响。
STM32微控制器支持不同外设之间和相同外设内部的中断嵌套。
在设置嵌套中断时,需要注意以下原则: - 外设之间:不同外设之间的中断嵌套顺序应根据具体需求和业务逻辑进行设置。
- 外设内部:在具有多个可触发相同类型中断源的外设上,需要根据业务需求设置不同源之间的触发次序。
3.4 中断抢占与屏蔽STM32微控制器支持中断的抢占和屏蔽功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于STM32 中断向量表的位置、重定向问题
首先我们需要跳到main 函数,这个就不多说了。
那么,中断发生后,又
是怎么跑到中断入口地址的呢?从stm32f10x.s 可以看到,已经定义好了一大堆
的中断响应函数,这就是中断向量表,标号__Vectors,表示中断向量表入口地
址,例如:AREA RESET, DATA, READONLY ; 定义只读数据段,实际上是在CODE 区(假设STM32 从FLASH 启动,则此中断向量表起始地址即为
0x8000000)EXPORT __Vectors IMPORT OS_CPU_SysTickHandler IMPORT OS_CPU_PendSVHandler__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler 这个向量表的编写是有讲究的,跟硬件一一对应不能乱写的,CPU 找入口地址就靠它了,bin 文件开头就是他们的
地址,参考手册RM0008 的10.1.2 节可以看到排列。
我们再结合CORTEX-M3
的特性,他上电后根据boot 引脚来决定PC 位置,比如boot 设置为flash 启动,
则启动后PC 跳到0x08000000。
此时CPU 会先取2 个地址,第一个是栈顶地址,第二个是复位异常地址,故有了上面的写法,这样就跳到reset_handler。
那么
这个reset_handler 的实际地址是多少.?下面的一堆例如Nmi_handler 地址又是
多少呢?发生中断是怎么跑到这个地址的呢?下面挨个讲解。
1、我们可以通
过反向来得知这些入口地址,查看工程下的map 文件就可以看到了,这个地址
跟keil 里面设置的target->flash 起始地址息息相关,实际上我们不太需要关心,
让编译器分配,中断向量表放的就是他们的地址。
2、对比ARM7/ARM9 内核,Cortex-M3 内核则是固定了中断向量表的位置而起始地址是可变化的。
3、进到。