Ich schreibe ein kleines Framework für meine eingebettete Robotik-Projekt. Wir laufen auf einem Xilinx Zynq FPGA (FPGA und ARM Cortex A9 eingebettet auf einem einzigen Chip)Anfügen einer Methode an eine Interrupt-Routine in C++ 11
Die Idee ist relativ einfach. In meinem main()
möchte ich den Interrupt initialisieren und dann die Routine (eine run()
Methode) von der Haupt auch aufrufen. Irgendwie muss die run()
Methode an den Interrupt angehängt werden, während sie sich an verschiedenen Stellen im Code befinden.
Der Interrupt wird in einer statischen Timer
Klasse initialisiert. Innerhalb initInterrupt()
ist die interruptRoutine()
angebracht, die auch in der Timer
Klasse ist. Letztendlich zwingt uns das, dass unser gesamter Code innerhalbinterruptRoutine()
laufen muss.
Irgendwie wollen wir eine run()
Methode innerhalb der main.cc
Datei haben (über der Timer
Klasse), die alle Logik und alle anderen Funktionsaufrufe speichert.
Wie können wir das erreichen?
Die main.cc:
int main() {
Timer::initInterrupt();
Timer::run([] {
// All logic goes here?
// Very hopeful thinking that this is possible...
});
}
Die Timer-Klasse:
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()
}
Ich denke, es ist ein bisschen komplexer als ich erklärte. Ich möchte nicht, dass meine 'Timer'-Klasse irgendetwas über irgendeine Logik weiß. Es folgt SRP. Der Hauptverantwortliche delegiert alles, aber ich muss irgendwie den ganzen Code bei einem Interrupt ausführen. Das Problem ist, dass der einzige Ort, wo ich es für jetzt tun kann, innerhalb der 'Timer' Klasse in der' interruptRoutine() ' – Ortix92
@ Ortix92 - was ist mit der virtuellen Methode in einer abgeleiteten Klasse und ich erwähnte? Würde das für dich funktionieren? Ansonsten verwende einfach eine reguläre Callback-Funktion. – Roddy