在中断函数和MAIN函数中同时调用同一个函数的有趣现象

发布者:masphia最新更新时间:2018-12-19 来源: eefocus关键字:中断函数  MAIN函数 手机看文章 扫描二维码
随时随地手机看文章

此处的信息适用于:


C51所有版本


症状


我添加了一个中断处理程序(ISR)到我的项目中,然而我却得到了如下的警告:


***WARNING L15:  MULTIPLE CALL TO SEGMENT

SEGMENT:   ?PR?_WRITE_GMVLX1_REG?D_GMVLX1

CALLER1:   ?PR?VSYNC_INTERRUPT?MAIN

CALLER2:   ?C_C51STARTUP


***WARNING L15:  MULTIPLE CALL TO SEGMENT

SEGMENT:   ?PR?_SPI_SEND_WORD?D_SPI

CALLER1:   ?PR?VSYNC_INTERRUPT?MAIN

CALLER2:   ?C_C51STARTUP


***WARNING L15:  MULTIPLE CALL TO SEGMENT

SEGMENT:   ?PR?SPI_RECEIVE_WORD?D_SPI

CALLER1:   ?PR?VSYNC_INTERRUPT?MAIN

CALLER2:   ?C_C51STARTUP


上面这些都是什么?我该如何解决这个问题呢?


原因


Warning 15向我们表明了linker发现了一个函数,这个函数不仅在main code里被调用了,而且在ISR(或者被ISR调用的函数中)被调用了。或者是被同时被多个ISR同时调用了。


这样会产生一个问题,就是在此函数不是一个可重入函数,而当此函数已经在执行时它可能被另一个ISR所调用。这样就会导致结果是可变的而且很可能会导致一些参数的错误。


另一个问题就是本地变量和参数所使用的内存可能被其他函数的内存覆盖。如果函数是由中断所调用的,则此函数的内存就会被使用。这会引起其它函数的内存错误。


举例来说,对于你的第一个警告,WRITE_GMVLX1_REG是会被多个root所调用。其被定义在D_GMVLX1.C或者D_GMVLX1.A51中。他不仅会被ISR(或者被ISR调用的函数)而且也会被MAIN.C中的VSYNC_INTERRUPT函数所调用。


解决方法


有几种方法去解决这个问题


如果你100%确认这个函数的两个副本都不会同时执行(如果此函数是被main调用并且中断是未被使能的)并且此函数没有使用内存(只使用的寄存器),那么你就可以忽略此警告。


如果此函数使用了内存,你就要使用OVERLAY directive来将此函数从覆盖分析(overlay anaysis)中移除。举例如下:


OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)


如上语句能阻止被此函数使用的内存遭到覆盖。如果这个函数调用了你程序中其他的在别处的函数,那么你可能需要将这些函数也排除在覆盖分析之外。


如果当此函数在执行时可以被调用,那么事情就会变得比较的复杂。你可能需要:


无论何时当从main中调用此函数时,需要关闭中断。你可能需要对被调用的函数使用#pragma disable。你也必须使用OVERLAY directive将此函数从overlay analysis中移除。


为此函数创建两个副本。一个给main,一个给ISR。


使此函数可重入。举例如下:

void myfunc(void) reentrant {

 ...

}


上面的定义会产生一个用来存储参数和本地变量的可重入的栈。如果使用了这种方法那么这个可重入的栈必须在STARTUP.A51中配置。这样会花费更多的RAM并且会减缓可冲入函数的执行。


关键字:中断函数  MAIN函数 引用地址:在中断函数和MAIN函数中同时调用同一个函数的有趣现象

上一篇:89c51中断系统及中断控制
下一篇:STM8S类型单片机UART一直进入接收中断问题解决方案

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

MDK开发环境STM32启动文件_main函数分析
======================================================================== ** Section #1 'ER_IROM1' (SHT_PROGBITS) Size : 1008 bytes (alignment 4) Address: 0x08000000 $d.realdata RESET __Vectors ;向量表起始地址 0x08000000: 20000460 `.. DCD 536872032
[单片机]
C语言程序执行的第一条指令,并不在 main 函数
C语言程序执行的第一条指令,并不在 main 函数中。当我们生成一个C程序的可执行文件时,编译器总是在我们的代码前加一段固定的代码 crt0.o,它是编译器自带的一个文件。此段代码设置 C 程序的堆栈等,然后调用 main 函数。很可惜,在我们的裸板上,这段代码无法执行,所以我们得自己写一个。这段代码很简单,只有 3条指令。crt0.s 代码: 1 .text 2 .global _start 3 _start: 4 ldr sp, =1024*4 @设置堆栈,注意:不能大于 4k(栈区是向下增长的) @nand flash 中的代码在复位后会自动
[单片机]
STM32串口中断实验总结函数的初始化必须在变量的初始化之后
在进行串口的实验的时候,自己没有看教程,写了一段代码,但是进行编译之后发现一直有错误,就算我把代码更改之后还是一直有错误。对比了官方给的教程之后发现唯一的不同之处就是我的有一个函数的初始化是在变量的初始化之前,进行的初始化,在进行相应的知识查询之后,还有请教了师兄之后,发现了自己以前一直没有注意到的问题就是,函数的初始化必须放到变量的初始化之后,否则在使用keil也就是MDK进行建立工程的时候就会报错。 注意细节
[单片机]
STM32串口<font color='red'>中断</font>实验总结<font color='red'>函数</font>的初始化必须在变量的初始化之后
重构外部中断回调函数来区分外部中断具体引脚做具体对应的任务
1.STM32CubeMX配置如下: 这里GPIO mode一共有六种分别是: (1)上升沿触发外部中断 (2)下降沿触发外部中断 (3)边沿触发外部中断 (4)上升沿触发外部事件 (5)下降沿触发外部事件 (6)边沿触发外部事件 2.CubeMX生成的代码: /** Configure pins as * EXTI */ void MX_GPIO_Init(void) { __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIO时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DATA_4
[单片机]
重构外部<font color='red'>中断</font>回调<font color='red'>函数</font>来区分外部<font color='red'>中断</font>具体引脚做具体对应的任务
中断服务函数能不能带形参和返回值
从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通过总线把电信号发送给中断控制器。如果中断的线是激活的,中断控制器就把电信号发送给处理器的某个特定引脚。处理器于是立即停止自己正在做的事,跳到中断处理程序的入口点,进行中断处理。 (1) 硬中断 由与系统相连的外设(比如网卡、硬盘)自动产生的。主要是用来通知操作系统系统外设状态的变化。比如当网卡收到数据包的时候,就会发出一个中断。我们通常所说的中断指的是硬中断(hardirq)。 (2) 软中断 为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间就可以完成的工作,而将那些处理事件比
[单片机]
C51中断函数格式
C51 Keil 编译器中断函数语法定义: void 函数名() interrupt n using m C51编译器允许0~31个中断,C51控制器所提供的中断及中断地址如下: 中断号 中断源 中断地址 0 EXTERNAL 0 0003H 1 TIMER/COUNTER 0 000BH 2 EXTERNAL 1 0013H 3 TIMER/COUNTER 1 001BH 4 SERIAL PORT 0023H 中断函数编写规则: 不能进行参数传递 无返回值 在任何情况,不能直接调用中断函数 可以在中断函数定义中用using指定当前使用的寄存器组 void 函数名 () i
[单片机]
51单片机中断处理函数能否影响全局变量
在用keil4.60写51的定时器中断处理函数的时候,遇到了这么一个纠结的问题,就是我定义了一个全局变量temp,一旦触发定时器中断进入处理函数时将temp=123,在开中断前temp=888,我本用keil调试看看里边的变量变化情况的,无意中发现keil竟然显示不了全局变量,只能显示当前调用函数的局部变量,这样一来靠调试我是完全不知道全局变量的值变成了什么。上网查了一下,竟然有人说中断处理函数不能改变全局变量的值,决定不相信,做个测试就知道了。昨天实验室没有51开发板来做测试,就只好先画了个proteus的仿真电路图,把程序下载进去看看运行的结果。 如果处理函数可以改变全局变量,led2亮,否则led1亮 #includ
[单片机]
51单片机<font color='red'>中断</font>处理<font color='red'>函数</font>能否影响全局变量
51单片机的中断函数
中断使用interrupt 关键字和终端编号0-4来实现: 返回值 函数名 interrupt n n对应中断源的编号,中断编号告诉中断器中断程序的入口地址,它对应着IE寄存器中的使能位,即IE寄存器中的0位对应着外部中断0。 8051单片机的中断源以及终端编号如下: 中断编号 中断源 入口地址 0 外部中断0 0003H 1 定时器/计数器0 溢出 000BH 2 外部中断1 0013H 3 定时器/计数器1 溢出 001BH 4 串行口中断 0023H 在51系列单片机中,有的
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

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

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

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