一个关于STM8中断应用异常的话题

发布者:bobojrt最新更新时间:2017-11-19 来源: eefocus关键字:STM8  中断应用 手机看文章 扫描二维码
随时随地手机看文章

某日一工程师跟我反映,他在使用STM8S芯片开发产品,用到某ADC通道,使用连续采集模式,开启ADC转换结束中断。整个中断程序执行时间大概200多us,因为连续采集转换,在这个ISR处理过程中可能会有新的EOC标志产生。

他发现一个奇怪的现象,ADC中断服务程序能够不停的自己嵌套自己,仿佛进入了递归嵌套,最后导致堆栈溢出跑飞而令系统复位。在调试过程中也的确能发现ADC中断服务程序有连续多次入栈的情况。


后来他发现这个异常跟在ADC ISR中首尾分别加了一句关中断和开中断语句有关。即在ISR的开头加了disableInterrupt(); ISR结尾部分加了 enableInterrupt();

 

如果拿掉首尾那2句开关中断的代码就一切正常。现在最大的疑问就是为什么加了这两句开关中断代码会导致ADC中断服务程序能自己嵌套自己?按道理说应该没有影响才对啊?

关于中断函数不少人可能会这样写,在ISR的首尾分别加上关中断和开中断指令,尤其51系列过来的人,经常会在进中断后来一句CLR EA,中断退出之前补一句 SETB EA之类的指令。51系列芯片那样写是没有问题的。

那对于STM8芯片来讲,这样写很可能就会出问题。有时或许有跟上面一样的写法而没有出问题,那是因为你程序简单没有复杂的多中断响应事件,或者说即使某时段只有单一中断源,但在中断响应过程中并无新的中断请求发生。

说实在的,要解释上面工程师的疑问,有点说来话长。不妨先直接说出原因,有兴趣的话就细看技术资料或下面的分析。

显然,问题就出在他在ISR里面做了关中断、开中断的操作,随意了改变正在执行的中断服务程序的中断优先级而导致的问题。

那个disableInterrupt();函数所对应的汇编指令就是SIM,该指令就是关闭所有可屏蔽的中断请求,此时执行程序所处中断优先级为L3,即软件中断禁用级。正因为如此,此时不会发生RESET/TRAP/TLI以外的中断。

下面截图是STM8技术手册关于SIM指令的描述。在复位后的程序开始使用该指令是没用的。【为什么没用呢,因为程序复位后所处中断优先级就是L3。等会下面还会提到。】

红色方框内那句明确说明,在中断执行程序的开头不需使用该指令【SIM】,因为当前中断程序的优先级已经被自动的在CC寄存器中L1,L0位设定。【到底怎么设定自动的呢,下面文字在讲ITC_SPR寄存器时有描述。】


再来看看 enableInterrupt(); 其实它所对应的汇编指令就是 RIM.该指令就是解除所有中断屏蔽,允许各路中断请求。执行该指令后,此时执行程序所处中断优先级为L0,即主程序运行级别,属于最低优先级别。换句话说,此时任何新的或待处理的中断请求都可以中断或打断当前的执行程序。

下面是STM8相关技术手册对RIM指令的描述。它说该指令一般放在复位之后的主程序代码里,并提示在WFI/HALT指令前无须使用该指令。【此处并未对该提示作细节展开。它意思是说WFI/HALT指令还具备跟RIM指令同样的解除中断屏蔽、允许中断请求的功效。】


好,那我们结合上面案例具体分析下。

先假设上面那位工程师对ADC中断的软件优先级设置为2.【当然也可设置为3或1】

当ADC产生EOC中断请求进入中断服务程序【ISR】后,他首先来个SIM指令【即disableInterrupt();】,此时ISR程序不管刚才响应时刻的中断优先级是多少,现在被强行更改变为L3。从这点看,这个指令用得就显得随意或任性,在有多个中断源的情况下,有可能无意中改变了设计者关于各个中断响应轻重缓急的先后秩序的初衷。

继续回到这个话题。当ADC ISR执行一定时间后,在IRET返回前他又来个RIM指令。前面我们介绍了RIM指令的作用,此时ISR的中断优先级又由刚才的L3跳到L0,即最低软件优先级。可此时外边侯着的新的ADC EOC中断请求,它的软件中断优先级一定高于L0,机会来了,不用等本次ISR执行完,立即嵌套进入下一轮ADC ISR 程序。每进一次还要压一次栈,这样多次循环下去,直至堆栈穿底,PC乱飞,系统崩溃复位。

原因大致就这样,不要想当然、随意地在ISR里面添加些影响执行程序优先级的指令,换句话说你在使用类似SIM/RIM指令时一定要心里清楚在做什么,有什么目的,会对当前中断程序优先级产生什么影响。

如果希望在执行某中断程序时不要被其它可屏蔽的中断请求打断,怎么办呢?很简单,将相关中断的ITC_SPR寄存器中相应软件优先级位配置为L3即可。当中断程序执行完毕退出后再回到之前的软件中断优先级。

关于STM8中断原理,个人觉得技术资料讲得不是很细致。这里根据个人的理解做了个简单的总结,一起分享下。并在后面用个实例验证上面的分析结论。


STM8中断可分为不可屏蔽中断和可屏蔽中断。不可屏蔽中断是指RESET,TRAP,TLI.可屏蔽中断是指那些基于GPIO的外部中断和其它外设中断。


中断优先级分硬件优先级和软件优先级。硬件优先级是固定的,参照各芯片数据手册里的中断矢量表的序号来定,序号越小硬件优先级越高。各中断源或事件的软件中断优先级可以通过寄存器编程配置,其中RESET,TRAP非屏蔽中断事件无软件中断优先级。


中断的管理主要基于两个寄存器,一个是CCR,一个是ITC_SPRx. 其中CCR寄存器中的L1和L0位表示当前程序执行代码所处中断优先级。ITC_SPRx.各寄存器分别对应各个中断服务程序的软件中断优先级,用户可自行配置各中断服务程序所处的中断优先级。软件中断优先级分为4级,从低往高依次是LEVEL0,LEVEL1,LEVEL2,LEVEL3,分别对应CCR寄存器中的L1、L0位的10,01,00,11。

L0级即用户主程序级,就是程序处在按部就班的用户主程序代码执行状态,为最低软件优先级。此时CCR寄存器中的L1、L0为10。

L3级又称软件中断禁用级。这个地方的表述和理解可能有点费劲。在L3软件中断优先级状态下,不会发生软件中断,即所谓的中断关闭状态。此时CCR寄存器中的L1、L0为11。其中,RESET\TRAP\TLI三个中断源是特例,可以打断L3优先级状态下的执行程序而产生中断。

总之,STM8芯片任何时刻的程序执行总处于某一软件中断优先级状态,其软件中断优先级由当前CCR寄存器中的L1、L0位决定。理解这个概念很重要。

下面截图是对CCR寄存器描述,系统复位后的默认值为0x28,对应到L1\L0就是11。即系统复位后中断软件优先级为L3,软件中断禁用级,也就是中断关闭状态。这也正好印证了上面讲SIM指令时,芯片复位后使用SIM没啥意义。因为芯片复位后程序执行就处于软件中断禁用级。



上面提到,各个可屏蔽中断源的软件中断优先级可以通过ITC_SPRx 寄存器进行配置。一共8个ITC_SPR寄存器,每个寄存器最多可以配置4个中断源的软件中断优先级。当某中断请求得到响应时,该寄存器里相应中断源的VECTnSPR[1:0] 两位数据会自动载入到CCR寄存器中的L1、L0位进而决定该中断服务程序所处软件中断优先级。所以,在各中断服务程序里除非有需要,不要在中断服务程序里随意使用类似SIM/RIM这些导致改变执行程序中断优先级的指令。否则,程序优先级改变了而自己可能还不知晓。


我们说中断,提优先级,无非就是为了拟定妥善处理多个中断事件发生竞争时的处理规则。对于STM8芯片,在同一时刻多个中断请求发生时,响应规则如下:

中断请求中相对最高软件优先级的中断先响应;

如果软件优先级一样,硬件优先级相对最高的先响应;


当某中断程序正在执行时外部又产生了新的中断请求的处理规则:

如果新的中断请求的软件中断优先级高于正在执行的中断程服务序的中断优先级时,当前中断程序将被打断,保护好当前现场后转而去执行新的高优先级中断程序。即发生中断程序嵌套。因为软件中断优先级最高为3,不难理解当正在执行的中断程序的优先级为L3时是不可能再被RESET,TRAP,TLI以外的中断事件打断的,即呈现软件中断关闭状态。

另外,如果在中断服务程序里使用HALT,POPCC,RIM,SIM和WFI都可能会改变当前中断服务程序的中断优先级。

当在某ISR执行过程中调整L1、L0的值修改软件中断优先级,同时该中断请求标志没来及清除或新的中断请求已经产生,如果修改L1\L0后的新中断请求之软件中断优先级高于当前中断服务程序的优先级,这时就会发生中断重入,即该中断会被重新响应,重新运行该中断服务程序。上面工程师遇到的异常现象就是这种情形。

最后,以TIM1溢出更新中断服务程序为例,结合具体的测试代码一起验证下。此处把TIM1的溢出周期设置为2MS,TIM1中断执行时间大概16ms【当然是指不被中断的情况】,这样设计的目的是为了保证在中断服务程序执行过程中有新的TIM1溢出中断请求发生。中断程序要做的事情很简单,就是将某个IO口的电平先高后底各近8MS然后退出。【除了TIM1外,测试程序也没有别的其它中断使能。】

不妨看看下面两种不同情形,TIM1溢出中断服务程序的运行结果。

一、ISR里面不添加SIM/RIM指令时的情形。

__interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler( void )

{

TIM1_ClearFlag(TIM1_FLAG_UPDATE);//清除TIM1更新标志

GPIO_WriteHigh(GPIOC,GPIO_PIN_6 ); // PC6 HIGH

// disableInterrupts();

Delay(21000); //延时约 7.8ms

GPIO_WriteLow(GPIOC,PGPIO_PIN_6 _); // PC6 LOW

// enableInterrupts();

Delay(21000); //延时约 7.8ms

}

这种情况下,整个中断服务程序运行过程中程序优先级没有变化。运行过程中不存在被中断的情况。Pc6输出波形如下图一。

输出波形图一【PC6 输出信号】

二、ISR里面添加SIM和RIM或者只放RIM指令时的情形。

__interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler( void )

{

TIM1_ClearFlag(TIM1_FLAG_UPDATE);//清除TIM1更新标志

GPIO_WriteHigh(GPIOC,GPIO_PIN_6 ); // PC6 HIGH

// disableInterrupts();

Delay(21000); //延时约 7.8ms

GPIO_WriteLow(GPIOC,GPIO_PIN_6 ); // PC6 LOW

enableInterrupts();

Delay(21000); //延时约 7.8ms

}

此时pc6波形输出混乱无章,如下图2。TIM1中断程序不停的嵌套重入,导致堆栈溢出,PC跑飞。显然跟上面的图1相差悬殊。另外,通过示波器观察芯片复位脚也可看到绵延不断的复位脉冲如下图3。


输出波形图二【PC6 输出信号】

从上面图二不难看出是因为中断不断自我重入,而进中断是先将PC6置高,所以大量的高电平呈现。



输出波形图三【复位脚信号】

最后的最后,估计很多工程师在编写STM8中断程序时,像上面的工程师那样写代码。有时因此而出现些莫名其妙的异常会让人很难找到错误的原因。


关键字:STM8  中断应用 引用地址:一个关于STM8中断应用异常的话题

上一篇:关于STC单片机的几点建议
下一篇:单片机串口通信中的异步通信和同步通信

推荐阅读最新更新时间:2024-03-16 15:45

出现“Unable to create configuration 'Debug' using tool chain ‘STM8
用IAR打开STM8时,出现“Unable to create configuration 'Debug' using tool chain ‘STM8’, 出现这个问题的原因是按装的IAR不正确,要装ST for STM8 版本的,而不能用ST for ARM版本的 ST for ARM图标 ST for STM8 图标
[单片机]
出现“Unable to create configuration 'Debug' using tool chain ‘<font color='red'>STM8</font>’
更快、更灵活的探针问市——STM8 和STM32微控制器
意法半导体推出了 STLINK-V3 下一代 STM8 和 STM32微控制器 代码烧写及调试探针,进一步改进代码烧写及调试灵活性,提高效率。STLINK-V3支持大容量存储,具有虚拟COM端口和多路桥接功能,烧写性能是上一代探针的三倍,产品价格具市场竞争力,节省应用开发时间,简化设备现场重新编程流程。 除提供典型的JTAG /串行线调试(SWD)和单线接口模块(SWIM)连接外,STLINK-V3的虚拟COM端口(VCP)和多路桥接器还可以通过UART、I2C、SPI或CAN接口或GPIO引脚与微控制器通信,方便开发人员使用自定义控制命令自动执行测试,并在PC主机上观察运行时数据,或者使用STLINK-V3配合引导加载
[测试测量]
更快、更灵活的探针问市——<font color='red'>STM8</font> 和STM32微控制器
基于STM8的电容触摸式按键软件库介绍
STM8S系列触摸按键软件库基本结构如下图所示,分成下面几个部分: 基于上述软件库架构 1) 用户软件通过API接口调用相应的函数启动按键信号采集,通过访问相应的变量来获得按键 的状态,以及通过对一些控制变量的配置来修改触摸式按键的工作参数。 2) 后处理部分是STM8S系列软件库的核心部分,包含了一些列的校准,滤波算法。通过ECS (环境处理系统)的处理,达到环境自适应的功能。 3) 采集部分主要通过对IO口以及定时器的控制来获得按键的充放电时间。
[单片机]
基于<font color='red'>STM8</font>的电容触摸式按键软件库介绍
STM8->RCC
尝试通过RTC中断唤醒halt()低功耗模式,需要一个功耗低的时钟源作为RTC运行时钟,选择LSI的16分频作为时钟源: void RCC_LSI(void) { CLK_LSICmd (ENABLE); CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSI); while(CLK_GetFlagStatus(CLK_FLAG_LSIRDY)==RESET); CLK_SYSCLKSourceSwitchCmd (ENABLE); if(CLK_GetSYSCLKSource()==CLK_SYSCLKSource_LSI) { CLK_SYSCLK
[单片机]
STM8->RCC
STM8 IAR相关笔记
如果.h文件不在程序根目录下,需要说明位置,如下图: 这样编译器就能找到.h文件的位置,不会出错。至于.c文件直接位置添加即可,如下图
[单片机]
三、STM8的学习笔记-----GPIO操作
3.1.前言 STM8系列是意法半导体公司生产的8位的单片机。该型号单片机分为STM8A、STM8S、STM8L三个系列。本次学习我采用的STM8S103这块板; 在我的学习过程中,学习单片机,首先得知道如何控制它的GPIO口。关于GPIO共有12种工作模式,如果理解了这12种工作模式,那么在GPIO的学习过程中也会事半功倍。 3.2.对STM8的GPIO介绍 GPIO(英文:General-purpose input/output),通用型之输入输出的简称。其引角可以供使用者由程序控制并自由使用,通过对PIN脚的初始化可以实现通用输入(GPI)或者输出(GPO)或通用输入输出(GPIO)。 3.3.简单操作单个I/O
[单片机]
三、<font color='red'>STM8</font>的学习笔记-----GPIO操作
STM8 控制电脑风扇转速 4PIN PWM
程序代码: #include stm8s.h #include stm8s_gpio.h #define PWM_F 640 uint8_t HexTable ={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; uint16_t CCR1_Val = 100; void DelayApi
[单片机]
<font color='red'>STM8</font> 控制电脑风扇转速 4PIN PWM
意法半导体发布STM8微控制器开发工具
意法半导体(纽约证券交易所代码:STM),日前宣布国际开发工具供应商IAR Systems推出开发工具“STM8系列嵌入式设计工作台”(EWSTM8),支持8位微控制器市场主流的STM8系列产品。 这一行动将简化采用STM8微控制器的应用设计,为开发人员获取最佳的微控制器性能、功能和成本提供更高的灵活性。IAR的EWSTM8开发工具套件结合该公司现有的支持STM32系列32位微控制器的EWARM开发工具,让意法半导体两大微控制器系列产品共用相同的工具和工具厂商,这种兼容性为开发人员带来很多好处,例如,开发人员熟悉的用户界面和相同的C语言文件扩展名命名方法,这些好处有助于加快开发项目的进度。 IAR EW
[单片机]
意法半导体发布<font color='red'>STM8</font>微控制器开发工具
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved