GZZXB 发表于 2010-3-11 17:48:34

斑竹,把中断的外壳和中断处理程序分家不好移植啊。

深入浅出书中描述:
       把中断外壳留在硬件初始化里,实际的中断处理函数放在硬件驱动函数里面.
       再通过定义"宏"为中介把中断函数插进来,把宏展开的代码就是XXXXX();
       中断函数的调用了,但是很多单片机不允许在中断里面调用函数啊,如合泰/PIC等.
       我在CVAVR里试过也不行.一编译就死机.直接把代码写在中断函数里面就OK.
       这阵子都在研究怎么实现"硬件无关性"感觉好困难,郁闷哪.

Gorgon_Meducer 发表于 2010-3-12 13:21:05

编译死机是编译器的事情……
对于“单片机不允许在中断里面调用函数”的情况,用宏插入实际的代码
就可以了。

不过,深入浅出中描述的这种做法,属于我过去的一种解决思路。
后来,我参考了很多别人的好的做法,意识到一个问题,中断处理程序的
处理方式,在可移植的框架中需要根据实际情况进行分类:

1、实时性要求高的情况下,尽可能使用宏插入代码的方法;如果编译器
   会编译死机,应该考虑换一个编译器(不过我觉得多半换一个版本就
   好了,因为基本的宏处理都有问题,编译器本身就是有BUG的)。

2、在实时性不高的情况下,可以参考下面的处理方式:

假设有一个宏
#if __IS_COMPILER_GCC__
    #include <avr/interrupt.h>

    #define REGISTER_ISR(__VECTOR, __ISR)       \
            extern void __ISR(void);\
            ISR(__VECTOR)\
            {\
                __ISR();\
            }

#elif __IS_COMPILER_IAR__
    #ifndef PRAGMA
      #define PRAGMA(__STRING)   _Pragma(#__STRING)
    #endif
    #ifndef ISR
      #define ISR(num) PRAGMA( vector = num ) __interrupt void isr_##num(void)
    #endif

    #define REGISTER_ISR(__VECTOR, __ISR)       \
            extern __task void __ISR(void);\
            PRAGMA( vector = __VECTOR ) __interrupt void isr_##num(void)\
            {\
                __ISR();\
            }
#endif

则,在最底层程序中,使用如下的代码来处理中断(比如 看门狗定时器中断)

#ifndef SLOW_TIMER_INTERRUPT_SERVICE_ROUTINES
    #warning no defined SLOW_TIMER_INTERRUPT_SERVICE_ROUTINES, \
            all accesses to slow timer will be ignored.

#if __IS_COMPILER_ICC__
#pragma interrupt_handler SLOW_TIMER_INTERRUPT_SERVICE_ROUTINES:iv_WDT
#elif __IS_COMPILER_GCC__ || __IS_COMPILER_IAR__
REGISTER_ISR(WDT_vect, SLOW_TIMER_INTERRUPT_SERVICE_ROUTINES)
#endif

Gorgon_Meducer 发表于 2010-3-12 13:22:36

希望对你有所启发。

另外,中断处理程序属于不易移植的部分,对其考虑通用,通常得不偿失。
用注释把核心代码记录下来,不同平台下根据实际情况来具体实现这些“核心代码”
才是王道。

HAL 层封装以后,外界应该没有中断这个概念了,只剩下service。如果外界还有
中断这样的概念,说明封装不到位,而且代码移植可能会遇到困难。

GZZXB 发表于 2010-3-12 15:19:35

谢谢!!!
页: [1]
查看完整版本: 斑竹,把中断的外壳和中断处理程序分家不好移植啊。