目前,我正在为Cortex M0 / M4进行编码,而我们在C ++中使用的方法(没有C ++标签,因此此答案可能是题外话)如下:
我们使用一个CInterruptVectorTable
包含所有中断服务例程的类,这些例程存储在控制器的实际中断向量中:
#pragma location = ".intvec"
extern "C" const intvec_elem __vector_table[] =
{
{ .__ptr = __sfe( "CSTACK" ) }, // 0x00
__iar_program_start, // 0x04
CInterruptVectorTable::IsrNMI, // 0x08
CInterruptVectorTable::IsrHardFault, // 0x0C
//[...]
}
该类CInterruptVectorTable
实现了中断向量的抽象,因此您可以在运行时将不同的函数绑定到中断向量。
该类的接口如下所示:
class CInterruptVectorTable {
public :
typedef void (*IsrCallbackfunction_t)(void);
enum InterruptId_t {
INTERRUPT_ID_NMI,
INTERRUPT_ID_HARDFAULT,
//[...]
};
typedef struct InterruptVectorTable_t {
IsrCallbackfunction_t IsrNMI;
IsrCallbackfunction_t IsrHardFault;
//[...]
} InterruptVectorTable_t;
typedef InterruptVectorTable_t* PinterruptVectorTable_t;
public :
CInterruptVectorTable(void);
void SetIsrCallbackfunction(const InterruptId_t& interruptID, const IsrCallbackfunction_t& isrCallbackFunction);
private :
static void IsrStandard(void);
public :
static void IsrNMI(void);
static void IsrHardFault(void);
//[...]
private :
volatile InterruptVectorTable_t virtualVectorTable;
static volatile CInterruptVectorTable* pThis;
};
您需要制作存储在向量表中的函数,static
因为控制器不能提供this
-pointer,因为向量表不是对象。因此,要解决该问题,我们在中有一个静态pThis
指针CInterruptVectorTable
。进入静态中断函数之一后,它可以访问pThis
-pointer以访问的一个对象的成员CInterruptVectorTable
。
现在在程序中,您可以使用SetIsrCallbackfunction
来提供指向static
发生中断时要调用的函数的函数指针。指针存储在中InterruptVectorTable_t virtualVectorTable
。
中断功能的实现如下所示:
void CInterruptVectorTable::IsrNMI(void) {
pThis->virtualVectorTable.IsrNMI();
}
因此,它将调用static
另一个类的方法(可以是private
),然后该方法可以包含另一个static
this
-pointer来访问该对象的成员变量(仅一个)。
我猜您可以构建并连接IInterruptHandler
和存储对象的指针,因此static
this
在所有这些类中都不需要-pointer。(也许我们会在我们的架构的下一个迭代中尝试)
另一种方法对我们来说很好用,因为唯一允许实现中断处理程序的对象是硬件抽象层内部的对象,并且每个硬件块通常只有一个对象,因此使用static
this
-pointer 可以很好地工作。硬件抽象层为中断提供了另一种抽象,称为中断,ICallback
然后在硬件上方的设备层中实现该抽象。
您是否访问全局数据?当然可以,但是您可以使所需的大多数全局数据私有化,例如this
-pointers和中断函数。
它不是防弹的,它增加了开销。您将很难使用这种方法来实现IO-Link堆栈。但是,如果您对时序的要求不是很严格,那么在不使用可从任何地方访问的全局变量的情况下,在模块中灵活地获取中断和通信的抽象效果很好。