精华内容
下载资源
问答
  • 关注+星标公众号,不错过精彩内容转自 | C语言与CPP编程1 前言 最近在公司维护的项目中碰到一个解决了定位很久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数...

    关注+星标公众,不错过精彩内容

    转自 | C语言与CPP编程

    1 前言

    最近在公司维护的项目中碰到一个解决了定位很久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数中调用了 printf 函数,因为中断处理函数的调用了不可重入函数,导致中断丢失和系统位置错误,这里直接导致嵌入式 linux 系统应用进程中的所有线程停掉,进而导致看门狗进程得不到喂狗,设备重启。

    • 那什么是不可重入函数呢?

    • 为什么中断处理函数不能直接调用不可重入函数?

    • 怎样写可重入函数?

    就以上三个问题展开小短文:

    2 什么是不可重入函数?

    可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入 OS 调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。

    满足下列条件的函数多数是不可重入的:

    • 函数体内使用了静态(static)的数据结构;

    • 函数体内调用了 malloc() 或者 free() 函数;

    • 函数体内调用了标准 I/O 函数;

    A. 可重入函数

    void strcpy(char *lpszDest, char *lpszSrc) 
    {
        while(*lpszDest++=*lpszSrc++);///< 使用的局部变量
        *dest=0;
    }
    

    B. 不可重入函数1

    char cTemp;    ///< 全局变量
    void SwapChar1(char *lpcX, char *lpcY) 
    {
        cTemp=*lpcX;
        *lpcX=*lpcY;
        lpcY=cTemp;   ///< 访问了全局变量
    }
    

    C. 不可重入函数2

    void SwapChar2(char *lpcX,char *lpcY)
    {
        static char cTemp;  ///< 静态局部变量
        cTemp=*lpcX;
        *lpcX=*lpcY;
        lpcY=cTemp;   ///< 使用了静态局部变量
    }
    

    3 为什么中断处理函数不能直接调用不可重入函数?

    在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。

    在中断前后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?我们知道中断时确实保存一些上下文,但是仅限于返回地址,cpu 寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量,buffer 等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。

    在中断处理函数中调用有互斥锁保护的全局变量,如果恰好该变量正在被另一个线程调用,会导致中断处理函数不能及时返回,导致中断丢失等严重问题。

    并且在多线程环境中使用,在没有加锁的情况下,对同一段内存块进行并发读写,就会造成 segmentfault/coredump 之类的问题。

    总而言之,中断处理函数做的事情越简单越好。

    4 如何写出可重入的函数?

    • 在函数体内不访问那些全局变量;

    • 如果必须访问全局变量,记住利用互斥信号量来保护全局变量。或者调用该函数前关中断,调用后再开中断;

    • 不使用静态局部变量;

    • 坚持只使用缺省态(auto)局部变量;

    • 在和硬件发生交互的时候,切记关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用 OS_ENTER_KERNAL/OS_EXIT_KERNAL 来描述;

    • 不能调用任何不可重入的函数;

    • 谨慎使用堆栈。最好先在使用前先 OS_ENTER_KERNAL;

    ------------ END ------------

    推荐阅读:

    精选汇总 | 专栏 | 目录 | 搜索

    精选汇总 | ARM、Cortex-M

    精选汇总 | ST工具、下载编程工具

    关关注微信公众号『嵌入式专栏』,底部菜单查看更多内容,回复“加群”按规则加入技术交流群。

    点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

    展开全文
  • 中断函数是硬件或者操作系统自动调用的。。 也就是说只要满足触发条件,就会自动调用中断函数(此时主函数是停止的)。 当中断函数执行完毕,又返回主函数继续执行主函数。 然后这样不断的循环,反正只要是触发中断...

    中断函数是硬件或者操作系统自动调用的。。
    也就是说只要满足触发条件,就会自动调用中断函数(此时主函数是停止的)。
    当中断函数执行完毕,又返回主函数继续执行主函数。
    然后这样不断的循环,反正只要是触发中断的条件一满足。
    就会自动进入中断(前提是你的中断的配置是正确的)

    中断中断

    就是MCU停止当前的执行,做好现场保护。去临时执行中断要求的响应,返回

    通俗点就是:

    你正在图书馆看书,突然尿急了(中断条件满足,置位)。你要记下你在哪个位置,书看到多少页(现场保护),然后你去尿尿(响应中断),尿完了你不再有尿意(清除中断标志)回到你原来的位置,继续看书(中断返回)

    展开全文
  • interrupt()只是改变中断状态而已 interrupt()不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, ...

    . interrupt()只是改变中断状态而已     interrupt()不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。     如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。     线程A在执行sleep,wait,join时,线程B调用A的interrupt方法,的确这一个时候A会有InterruptedException异常抛出来.但这其实是在sleep,wait,join这些方法内部会不断检查中断状态的值,而自己抛出的InterruptedException。     如果线程A正在执行一些指定的操作时如赋值,for,while,if,调用方法等,都不会去检查中断状态,所以线程A不会抛出InterruptedException,而会一直执行着自己的操作.当线程A终于执行到wait(),sleep(),join()时,才马上会抛出InterruptedException.     若没有调用sleep(),wait(),join()这些方法,或是没有在线程里自己检查中断状态自己抛出InterruptedException的话,那InterruptedException是不会被抛出来的.

    展开全文
  • c语言中的中断函数注意事项单片机_C语言函数_中断函数(中断服务程序)在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在...

    c语言中的中断函数注意事项

    单片机_C语言函数_中断函数(中断服务程序)

    在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。

    中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。

    (1)中断源:中断请求信号的来源。(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))

    (2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。期间涉及到CPU响应中断的条件,现场保护,现场恢复。

    (3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。优先级是可以编程的,而优先权是固定的。

    80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。

    80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制

    (1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1

    (2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP

    具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。

    在这里我们讲下注意的事项

    (1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。

    (2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。

    (3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。

    (4)单片机复位后,TCON,SCON给位清零。

    C51语言允许用户自己写中断服务子程序(中断函数)

    首先来了解程序的格式:

    void 函数名() interrupt m [using n]

    {}

    关键字 interrupt m [using n] 表示这是一个中断函数

    m为中断源的编号,有五个中断源,取值为0,1,2,3,4,中断编号会告诉编译器中断程序的入口地址,执行该程序时,这个地址会传个程序计数器PC,于是CPU开始从这里一条一条的执行程序指令。

    n为单片机工作寄存器组(又称通用寄存器组)编号,共四组,取值为0,1,2,3

    中断号中断源

    0 外部中断0

    1 定时器0

    2 外部中断1

    3 定时器1中断

    4 串行口中断

    这5个中断源的中断入口地址为:(在上一篇文章中讲到的ROM前43个存储单元就是他们,这40个地址用来存放中断处理程序的地址单元,每一个类中断的存储单元只有8B,显然不

    展开全文
  • 在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。(1)中断源:...
  • LINUX系统调用原理-既应用层如何调用内核层函数之软件中断SWI:software interrupt 软件中断ARMLinux系统利用SWI指令来从用户空间进入内核空间,还是先让我们了解下这个SWI指令吧。SWI指令用于产生软件中断,从而...
  • 最佳答案 这里的问题不是中断或返回,而是你使用递归而不是在每次递归调用中停止循环.你需要做的是从你的dfs函数返回一个结果,告诉你是否找到了你的节点,然后如果递归调用确实找到它,则打破你的else块中的循环.像...
  • 定时器中断函数的使用

    千次阅读 2021-05-19 18:41:36
    1.定时器与延时的区别大家可能会觉得我们用延时函数照样可以实现上一讲代码的实验现象,但是定时器与延时的概念不同,延时函数需要占用CPU的使用权,正在延时的时候其他任务没有CPU的使用权就会拖慢执行效率。...
  • 不知道从什么时候开始,运行在OS内的程序文件,有了规范,Win系统下是PE,Linux系统下是ELF。符合规范的程序能够被OS调用并...栈的地址从大到小,存放函数调用过程中的指令地址和函数的局部变量。程序员需要关注堆的...
  • 函数调用、系统调用和中断处理都需要上下文切换,请结合 MIPS O32 的ABI 说明上述三种上下文切换时保留现场有什么不同(内容、位置)? 位置 内容 函数调用 ...
  • 函数调用约定常见的函数调用约定[5]:cdecl,stdcall,fastcall,thiscall,naked callMFC调用约定(VS6:Project Settings->C/C++ Calling convention:)1, __cdecl(C调用约定.The C default calling convention)C/C++ ...
  • 从汇编的角度解析函数调用过程看看下面这个简单函数的调用过程:1 int Add(int x,inty)2 {3 int sum = 0;4 sum = x +y;5 returnsum;6 }78 intmain ()9 {10 int a = 10;11 int b = 12;12 int ret = 0;13 ret =Add(a,b...
  • 首先,调用子程序过程发生的时间是已知和固定的,即在主程序中的调用指令(CALL)执行时发生主程序调用子程序,调用指令所在位置是已知和固定的。而中断过程发生的时间一般的随机的,CPU在执行某一主
  • 中断服务函数

    2021-07-30 16:14:19
    4.不要在中断函数中使用printf函数,会带来重入和性能问题 中断并不是程序一开始就判断好会在那里发生,或者会在什么时候发生。中断发生的完全是随机的,中断源连接到硬件,由硬件来产生触发中断,而众所周知,函数...
  •  经过了漫长的检查,发现程序本身的编写没有错误,然后右键单击报错的中断函数void USART1_IRQHandler(void),尝试性的点了下Go to Definition of...... 发现它跳转到了stm32f10x_it.c文件中的USART1_IRQHandler()...
  • 通过生活中一个简单的例子来说明中断。当你正在家中看书时,突然电话铃响了,你停止看书,去接电话,和来电话的人进行交谈,通话结束后回来继续从刚才停止的位置看你的书。这就是生活中的“中断”的现象,就是正常的...
  • 栈帧也叫过程活动记录,是编译器用来实现函数调用过程的一种数据结构。C语言中,每个栈帧对应着一个未运行完的函数。从逻辑上讲,栈帧就是一个函数执行的环境:函数调用框架、函数参数、函数的局部变量、函数执行完...
  • PICC可以实现C语言的中断服务程序。中断服务程序有一个特殊的定义方法:voidinterruptISR(void);...中断函数可以被放置在原程序的任意位置。因为已有关键词“interrupt”声明,PICC在最后进行代码连...
  • 今天做项目发现的问题,程序正常跑没问题,但是偶然发现程序运行时调用一个函数十次了就中断了,记得我焦头烂额搞了一整天,终于搞出来了,原来是我在这个函数里定义了一堆变量,但这些变量都是形如int a = 0;...
  • 1.定义一个空的指针函数 指针函数的参数是uint8_t 类型chtypedef void (* usart_recv_callback)(uint8_t ch);2.声明这个类型usart_recv_callback usart1_recv_cb;3.串口配置时,一个形参为串口中断接收回调void ...
  •  函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数函数为主调函数,被调用函数为被...
  • A: printf函数是不可重入函数,包含了全局变量的使用以及大量循环的使用, 而嵌入式中的触发中断执行的优先级很高, 会随时触发和打断现有代码运行顺序, 那么加载不可重入函数,会导致中断函数异常, Q:如何在stm...
  • 从汇编的角度解析函数调用过程看看下面这个简单函数的调用过程:int Add(int x,int y){int sum = 0;sum = x + y;return sum;}int main (){int a = 10;int b = 12;int ret = 0;ret = Add(a,b);return 0;}今天主要用...
  • 1 函数调用当一个函数调用另一个函数时,并不是去复制被调函数的全部代码到内存,而是采用代码共享的方式。也就是它们都是调用同一个函数的代码,而系统为每一次调用开辟一组存储单元,用来存放本次调用的返回地址...
  • 中断基本知识 中断过程: 芯片设计固化了能产生哪些中断,那么每个中断对应的处理地址(这个可以由用户自己指定,一般放在代码的最前面,意思是该中断一旦产生,程序无条件pc指针直接跳转到该处理地址执行,那么就...
  • 函数调用在用户态下运行,系统调用则通过中断实现,让程序从用户态陷入到内核态,执行相应的操作。 (过程)函数往往由编译系统提供,不同编译系统提供的(过程)函数可以不同;系统调用由操作系统提供。 系统调用...
  • 调用fputc函数输出字符成功,则其返回值是________A)EOF B)1C)0D)输出的字符15 已知函数调用形式:fread(buf,size,count,fp),参数buf的含义是______A)一个整型变量,代表要读入的数据项总数B...
  • 建立一个和这个C文件同名的H文件,把这个C文件中的函数都包含到这个H文件中就ok!例如:有这样一个serial.C文件:/*********************************************************************************程序名称:...
  • 栈与函数调用关系1.什么是栈2.并发的主要场景1.对称多处理器(SMP)的多个CPU2.单CPU内的进程与抢占进程3.中断与进程3.面对竞态的常用方法1.中断屏蔽2.原子操作3.自旋锁4.信号量5.互斥体 1.什么是栈 并发是指多个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 329,631
精华内容 131,852
关键字:

中断函数如何调用