大家好,欢迎阅读《跟涛哥一起学嵌入式》第05集,我们今天讨论一下中断的基本概念。

中断,是嵌入式开发中经常使用的一个功能,也是嵌入式工程师必须要掌握的一个概念:CPU和外设通信时,一般都采用中断的形式异步通信,可以大大提高CPU资源的利用率。而你对中断的理解,到底有多少呢?不要急,一道程序改错题,就可以测出你的嵌入式系统功底。

比如,我们在嵌入式ARM裸机平台上,要实现一个MP3播放器,要求实现如下功能:当按键按下时,可以播放、暂停、播放下一首、上一首。为此,我们设计一个按键中断服务程序,当有按键发生时,我们去读取按键的值,然后再根据按键值去执行不同的操作,设计的按键中断函数如下:

int keyboard_isr(int irq_num)
{
    char *buf =(char *)malloc(512);
    int key_value = 0,

    key_value = keyboard_scan();
    if(key_value == 1)
    {
        mp3_decode(buf,"xx.mp3");
        sleep(10);
        mp3_play(buf);//play    
    }
    else if(key_value == 2)
        mp3_pause(buf);//pause
    else if(key_value == 3)
        mp3_next(buf);//next song
    else if(key_value == 4)
        mp3_prev(buf);//prev song
    else
    {
        printf("UND key !");
        return -1;
    }
    return 0;   
} 

这个中断函数差不多有8处错误或设计不合理的地方,先不用急着往下翻,你可以自己先思考下,看自己能找出来几处。

(此处应有掌声,暂停2分钟)...

好,我们接下来继续分析,看看这个中断函数到底有哪些错误。

错误1:中断关键字irq

中断函数没有使用关键字标记。C标准中没有定义中断函数,对于普通的函数调用,编译器会帮我们自动实现函数的调用栈及出栈入栈管理,而对于中断函数,我们知道,中断是可以随时发生的,编译器无法确定你中断函数在哪里发生,所以就无法帮你实现调用栈。那怎么办?难道我们程序员自己实现?没关系,各大编译器厂商一般会通过增加一些关键字,来帮助程序员实现中断的现场保护代码。因此,我们可以使用interrupt或irq关键字声明即可

__irq int keyboard_isr(int irq_num);

错误2:malloc/free

对于MP3解码的数据,我们使用malloc函数申请了一个动态堆内存来存放,但是函数退出后没有及时释放,造成了内存泄露。关于函数的调用栈、调用传参过程、程序的内存分配,如果不是很明白,可以参考《C语言嵌入式Linux高级编程》第4期:堆栈管理。

错误3:C标准库

嵌入式裸机开发中,一般很少使用C标准库的。很多嵌入式编译厂商、IDE开发商并没有完全实现C标准库,或者只是实现了一部分。所以在一般在嵌入式系统中,我们可以使用一个全局数组来代替malloc申请的动态内存。

错误4:中断返回值

中断函数由于没有独立的函数栈,是不能有返回值的。想一想:中断函数在哪里被调用、何时被调用,我们全都不知道,中断函数的返回值应该传给谁?它会破坏当前被中断函数的函数栈。

错误5:中断传参

同上,中断函数也是不能传参的,传给谁?谁调用了它?都是未知的。如果你给中断函数传参,也会破坏当前被中断函数的函数栈。所以中断函数正确的声明形式应该为:

__irq void keyboard_isr(void);

错误6:延时

避免耗时、延时、可重入函数,比如sleep、printf等。

错误7:短小精悍、快速反应

中断函数要求快速响应,短小精悍。要速战速决,快速撤离中断现场,然后等待下一次中断。如果你在中断程序中,要做大量工作:播放、解码、延时,十分不合理。这些耗时的工作应该放到中断外去做。如Linux中的中断处理,就放到了中断下半部去做。

好了,以上都是我们在编写中断函数时必须要掌握的一些基础知识和技能,接下来就卖个关子:想一想,上面这个函数的设计,还有什么不合理之处?思考的越多,你就得到的越多。老司机要下车了,先带你到这里,剩下的就靠你了~

本文根据《C语言嵌入式Linux高级编程》视频教程改编。《跟涛哥一起学嵌入式》,会持续跟大家分享嵌入式相关技术、学习方法、学习路线、求职面试等,有兴趣可加入嵌入式技术交流群:475504428,或微信公众号:宅学部落(armlinuxfun)。如果想系统学习嵌入式C语言进阶,可关注51CTO学院,我的个人主页:http://edu.51cto.com/lecturer/10824150.html