将方法附加到 c++11 中的中断例程
Attaching a method to an interrupt routine in c++11
我正在为我的嵌入式机器人项目编写一个小框架。我们运行在赛灵思Zynq FPGA(FPGA和ARM Cortex A9嵌入在单个芯片上(
这个想法相对简单。在我的main()
中,我想初始化中断,然后从main调用例程(run()
方法(。不知何故,当该方法位于代码中的不同位置时,run()
方法必须附加到中断。
中断在静态Timer
类中初始化。 在initInterrupt()
内部附加了interruptRoutine()
,它也在Timer
类中。 最终,这迫使我们所有代码都必须在 interruptRoutine()
.
不知何故,我们希望在main.cc
文件(在Timer
类上方(中有一个run()
方法,该方法存储所有逻辑和所有其他函数调用。
我们如何才能做到这一点?
main.cc:
int main() {
Timer::initInterrupt();
Timer::run([] {
// All logic goes here?
// Very hopeful thinking that this is possible...
});
}
计时器类:
class Timer {
public:
static void initInterrupt(void);
static void interruptRoutine(void*);
static void run();
};
/**
* Initialize main interrupt routine
*/
void initInterrupt(void) {
// Declare pointers
XScuTimer_Config* ConfigPtr;
XScuGic_Config* IntcConfig;
// Initialize timers by looking up config and initializing with that config
ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
XScuTimer_CfgInitialize(&TimerInstance, ConfigPtr, ConfigPtr->BaseAddr);
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(&IntcInstance, IntcConfig,
IntcConfig->CpuBaseAddress);
// Initialize exception handling
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler, &IntcInstance);
// Connect interrupt routine to exception handler
XScuGic_Connect(&IntcInstance, TIMER_IRPT_INTR,
(Xil_ExceptionHandler) interruptRoutine, (void *) (&TimerInstance));
// Enable interrupts
XScuGic_Enable(&IntcInstance, TIMER_IRPT_INTR);
XScuTimer_EnableInterrupt(&TimerInstance);
// Enable exception handler
Xil_ExceptionEnable();
// Set auto reload so timer reloads when interrupt is cleared
XScuTimer_EnableAutoReload(&TimerInstance);
// Set timer value
XScuTimer_LoadTimer(&TimerInstance, TIMER_LOAD_VALUE);
// Start interrupt
XScuTimer_Start (&TimerInstance);
}
/**
* main interrupt routine
*/
inline void Timer::interruptRoutine(void *CallBackRef) {
// Define pointer to timer
XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
// If timer is expired, clear interrupt status
if (XScuTimer_IsExpired(TimerInstancePtr)) {
XScuTimer_ClearInterruptStatus(TimerInstancePtr);
// Currently all the application logic is handled in here
}
}
inline void Timer::run(Callback){
// We want all our application logic to be handled in here but it has to be called from the main()
}
在计时器类中,添加一个布尔标志"计时器已过"。此标志是从计时器回调设置的。
然后,主程序通过计时器类中的 getter 函数检查此标志。
如果设置了该标志,则main
通过计时器类中的 setter 函数清除该标志,然后执行需要执行的代码。
请记住,对标志的访问必须是原子的!假设它不会被中断,这不是 ISR 内部的问题,但它可能是上述 setter/getter 函数内部的问题。
请注意,以上可能是设计中断的最常见方法。您将希望避免从 ISR 内部执行实际代码,除非您的实时要求非常严格。
这是可能的,但您需要一些基元来向Timer::run()
方法发出信号。 第一个问题是当前代码没有为计时器中断提供this
指针。 您似乎正在使用 xscutimer.h 代码。 你有这个代码,
// Connect interrupt routine to exception handler
XScuGic_Connect(&IntcInstance, TIMER_IRPT_INTR,
(Xil_ExceptionHandler) interruptRoutine, (void *) (&TimerInstance));
代码片段中不清楚TimerInstance
值。 但是,它应该是静态Timer
类实例。 此外,Timer::interruptRoutine
应该是一种static
方法,而不是inline
.然后,您的Timer
类应该有一个XScuTimer
成员。 此外,您需要向 run 方法发出某种信号,理想情况下还需要一个 yield()
类型的函数。 然后运行看起来像,
Timer::run() {
while(1) {
while(no_work)
wfi(); //ARM typically has a wfi or wait for interrupt.
// do work
}
}
理想情况下,yield
的核心是等待中断指令,以最大限度地降低功耗。如果您不关心功耗,您可以旋转no_work
。当然,no_work
必须设置为false
由Timer::interruptRoutine
.
no_work
变量应该是无锁的或安全的中断。 sig_atomic_t
或其他方式(取决于您的工作(是合适的。 要么工具包有这些东西,要么你必须自己实现它们。 请提供您正在使用的 xilinx 库的参考。
这个问题关于全局变量和 ISR 可能很有用。 对于Cortex-A CPU,您可以使用ldrex
和strex
及其所有注意事项(不像人们想象的那么容易使用(,以实现非常灵活的ISR/主线信令。 根据您的编译器/库,它可能由C++无锁/原子功能或适合 Xilinx 库的功能提供;这些可以在基础实现中使用ldrex
和strex
,您不必知道使用它们的复杂性。 必须使用MMU才能工作。
这要么比你想象的简单,要么比你解释的更复杂!
Timer::run()
做事:-
inline void Timer::run()
{
... complex stuff...
}
中断例程调用run()
inline void Timer::interruptRoutine(void *CallBackRef) {
// Define pointer to timer
XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
// If timer is expired, clear interrupt status
if (XScuTimer_IsExpired(TimerInstancePtr)) {
XScuTimer_ClearInterruptStatus(TimerInstancePtr);
run();
}
你想run()
从主...
int main() {
Timer::initInterrupt();
Timer::run();
}
不清楚是否要避免将run
逻辑放在Timer
类中?如果是这样,请run()
成为Timer
实例的抽象虚拟方法,然后从Timer
派生MyTimer
,并将您的代码添加到其run()
方法中。
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- c++类声明时,相同的例程,不同的成员变量类型
- C++为线程工作动态地分割例程
- 子例程,不使用 pow,并带有参数和返回
- 直接在RcppArmadillo中调用LAPACK例程
- 如何将C++子例程链接到 x86 程序集程序?
- PX 转换例程编译问题
- 成功完成TLS握手后,服务器关闭时出现错误的SSL例程:SSL3_GET_RECORD:错误的版本号
- 只允许授权代码调用库中的例程
- 可中断线程类 C++11 - 遇到错误?
- 指向成员对象的指针 - 中断线程
- JNI 不满意链接错误: 动态链接库 (DLL) 初始化例程失败
- 调用子例程时类型不匹配
- 如果在例程中,Gdb 会在错误时中断
- 将方法附加到 c++11 中的中断例程
- 在中断例程中使用C++对象(和volatile)的正确方法是什么
- 中断 arduino 例程以运行基于延迟的慢速进程
- 我的中断例程无法正确访问数组
- 作为中断服务例程的静态模板成员函数
- C++中的中断服务例程