Cuplikan berikut ini dari kode sumber pustaka TimerOne :
// TimerOne.h:
void (*isrCallback)();
// TimerOne.cpp:
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
Timer1.isrCallback();
}
// TimerOne.cpp:
void TimerOne::attachInterrupt(void (*isr)(), long microseconds)
{
if(microseconds > 0) setPeriod(microseconds);
isrCallback = isr; // register the user's callback with the real ISR
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
resume();
}
Pertanyaannya: jika penghitung waktu sudah berjalan, dan program utama memanggil attachInterrupt()
, dapatkah penghentian waktu terjadi di sana selama penugasan fungsi pointer isrCallback = isr;
? Kemudian, dengan lucky timing, Timer1.isrCallback();
function pointer akan terdiri dari sebagian dari yang lama dan sebagian dari alamat baru, menyebabkan lompatan ISR ke lokasi palsu?
Saya kira ini mungkin terjadi, karena fungsi pointer tentu lebih lebar dari 1 byte, dan mengakses data> 1 byte bukanlah atom. Solusi yang bisa dilakukan adalah:
- Selalu panggil
detachInterrupt()
untuk memastikan timer tidak berjalan, sebelum memanggilattachInterrupt()
, yaitu memperjelas Timer1 docs. - Atau, ubah Timer1, nonaktifkan timer overflow untuk sementara waktu sesaat sebelumnya
isrCallback = isr;
Apakah ini masuk akal, atau ada sesuatu dalam Timer1
penugasan fungsi sumber atau fungsi yang saya lewatkan?
Sepertinya Anda ada benarnya. Hal logis yang harus dilakukan adalah menonaktifkan interupsi sedemikian rupa sehingga Anda tidak mengaktifkannya kembali jika dinonaktifkan terlebih dahulu. Sebagai contoh:
Maksudnya adalah agar Anda menulis kode seperti ini:
Tanpa ketentuan itu, Anda mungkin mendapat gangguan di antara dua baris itu, dan karenanya tidur tanpa batas waktu (karena gangguan yang akan membangunkan Anda telah terjadi sebelum Anda tidur). Ketentuan dalam prosesor bahwa instruksi berikutnya, setelah interupsi menjadi diaktifkan jika mereka tidak diaktifkan sebelumnya, selalu dieksekusi, penjaga terhadap ini.
sumber
TIMSK1=0; TIFR1=_BV(TOV1); isrCallback=isr; TIMSK1=_BV(TOIE1);
? Itu menyimpan satu register CPU dan tidak berkontribusi mengganggu latensi.