Saya sedang mengkode Cortex M0 / M4 saat ini dan pendekatan yang kami gunakan dalam C ++ (tidak ada tag C ++, jadi jawaban ini mungkin di luar topik) adalah sebagai berikut:
Kami menggunakan kelas CInterruptVectorTable
yang berisi semua rutinitas layanan interupsi yang disimpan dalam vektor interupsi aktual dari pengontrol:
#pragma location = ".intvec"
extern "C" const intvec_elem __vector_table[] =
{
{ .__ptr = __sfe( "CSTACK" ) }, // 0x00
__iar_program_start, // 0x04
CInterruptVectorTable::IsrNMI, // 0x08
CInterruptVectorTable::IsrHardFault, // 0x0C
//[...]
}
Kelas CInterruptVectorTable
mengimplementasikan abstraksi vektor interupsi, sehingga Anda dapat mengikat berbagai fungsi ke vektor interupsi selama runtime.
Antarmuka kelas itu terlihat seperti ini:
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;
};
Anda perlu membuat fungsi-fungsi yang disimpan dalam tabel vektor static
karena pengontrol tidak dapat memberikan this
-poiner karena tabel vektor bukan objek. Jadi untuk mengatasi masalah itu kita memiliki pThis
pointer- statis di dalam CInterruptVectorTable
. Setelah memasukkan salah satu fungsi interupsi statis, ia dapat mengakses pThis
-pointer untuk mendapatkan akses ke anggota satu objek CInterruptVectorTable
.
Sekarang dalam program, Anda dapat menggunakan SetIsrCallbackfunction
untuk menyediakan pointer fungsi ke static
fungsi yang akan dipanggil ketika interupsi terjadi. Pointer disimpan di InterruptVectorTable_t virtualVectorTable
.
Dan implementasi fungsi interupsi terlihat seperti ini:
void CInterruptVectorTable::IsrNMI(void) {
pThis->virtualVectorTable.IsrNMI();
}
Sehingga akan memanggil static
metode kelas lain (yang bisa private
), yang kemudian dapat berisi static
this
-pointer lain untuk mendapatkan akses ke variabel anggota objek itu (hanya satu).
Saya kira Anda bisa membangun dan antarmuka suka IInterruptHandler
dan menyimpan pointer ke objek, sehingga Anda tidak perlu- static
this
pointer di semua kelas tersebut. (mungkin kita mencobanya di iterasi arsitektur kita selanjutnya)
Pendekatan lain berfungsi dengan baik bagi kami, karena satu-satunya objek yang diizinkan untuk mengimplementasikan pengendali interupsi adalah yang ada di dalam lapisan abstraksi perangkat keras, dan kami biasanya hanya memiliki satu objek untuk setiap blok perangkat keras, sehingga bekerja dengan- static
this
pointer. Dan lapisan abstraksi perangkat keras menyediakan abstraksi lain untuk menyela, yang disebut ICallback
yang kemudian diimplementasikan dalam lapisan perangkat di atas perangkat keras.
Apakah Anda mengakses data global? Tentu Anda melakukannya, tetapi Anda dapat menjadikan sebagian besar data global yang diperlukan bersifat pribadi seperti this
-poiner dan fungsi interupsi.
Ini bukan antipeluru, dan itu menambah overhead. Anda akan kesulitan menerapkan tumpukan IO-Link menggunakan pendekatan ini. Tetapi jika Anda tidak terlalu ketat dengan pengaturan waktu, ini bekerja cukup baik untuk mendapatkan abstraksi fleksibel dari interupsi dan komunikasi dalam modul tanpa menggunakan variabel global yang dapat diakses dari mana saja.