Diberi mikrokontroler yang menjalankan kode berikut:
volatile bool has_flag = false;
void interrupt(void) //called when an interrupt is received
{
clear_interrupt_flag(); //clear interrupt flag
has_flag = true; //signal that we have an interrupt to process
}
int main()
{
while(1)
{
if(has_flag) //if we had an interrupt
{
has_flag = false; //clear the interrupt flag
process(); //process the interrupt
}
else
sleep(); //place the micro to sleep
}
}
Misalkan if(has_flag)
kondisi bernilai false dan kita akan menjalankan instruksi tidur. Tepat sebelum kami menjalankan instruksi tidur, kami menerima interupsi. Setelah kami meninggalkan interupsi, kami menjalankan instruksi tidur.
Urutan eksekusi ini tidak diinginkan karena:
- Mikrokontroler pergi tidur alih-alih bangun dan memanggil
process()
. - Mikrokontroler mungkin tidak pernah bangun jika tidak ada interupsi setelahnya diterima.
- Panggilan ke
process()
ditunda hingga interupsi berikutnya.
Bagaimana kode dapat ditulis untuk mencegah kondisi lomba ini terjadi?
Edit
Beberapa mikrokontroler, seperti di ATMega, memiliki bit aktifkan Tidur yang mencegah kondisi ini terjadi (terima kasih Kvegaoro karena telah menunjukkan ini). JRoberts menawarkan contoh implementasi yang mencontohkan perilaku ini.
Mikro lainnya, seperti pada PIC18s, tidak memiliki bit ini, dan masalahnya masih terjadi. Namun, micros ini dirancang sedemikian rupa sehingga interupsi masih dapat membangun inti terlepas dari apakah bit global interrupt diaktifkan diatur (terima kasih supercat untuk menunjukkan ini). Untuk arsitektur seperti itu, solusinya adalah menonaktifkan interupsi global tepat sebelum tidur. Jika interupsi menyala tepat sebelum menjalankan instruksi tidur, penangan interupsi tidak akan dieksekusi, inti akan bangun, dan begitu interupsi global diaktifkan kembali, penangan interupsi akan dieksekusi. Dalam pseudo-code, implementasinya akan terlihat seperti ini:
int main()
{
while(1)
{
//clear global interrupt enable bit.
//if the flag tested below is not set, then we enter
//sleep with the global interrupt bit cleared, which is
//the intended behavior.
disable_global_interrupts();
if(has_flag) //if we had an interrupt
{
has_flag = false; //clear the interrupt flag
enable_global_interrupts(); //set global interrupt enable bit.
process(); //process the interrupt
}
else
sleep(); //place the micro to sleep
}
}
interrupt_flag
sebagai int
, dan menambahkannya setiap kali ada interupsi. Kemudian ganti if(has_flag)
ke while (interrupts_count)
dan kemudian tidur. Meskipun demikian, interupsi dapat terjadi setelah Anda keluar dari loop sementara. Jika ini merupakan masalah, maka apakah pemrosesan dalam interrupt itu sendiri?