รับไมโครคอนโทรลเลอร์ที่ใช้รหัสต่อไปนี้:
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
}
}
สมมติว่าif(has_flag)
สภาพประเมินเป็นเท็จและเรากำลังจะดำเนินการคำสั่งการนอนหลับ ขวาก่อนที่เราจะดำเนินการเรียนการสอนการนอนหลับที่เราได้รับการขัดจังหวะ หลังจากเราออกจากการขัดจังหวะเราดำเนินการสอนการนอนหลับ
ลำดับการดำเนินการนี้ไม่เป็นที่ต้องการเนื่องจาก:
process()
ไมโครคอนโทรลเลอร์ไปนอนแทนการตื่นขึ้นมาและเรียก- ไมโครคอนโทรลเลอร์อาจไม่เคยตื่นขึ้นมาหากไม่ได้รับการขัดจังหวะหลังจากนั้น
- การโทรไปยัง
process()
ถูกเลื่อนออกไปจนกว่าจะมีการขัดจังหวะครั้งต่อไป
รหัสจะถูกเขียนเพื่อป้องกันไม่ให้เกิดสภาพการแข่งขันนี้ได้อย่างไร
แก้ไข
ไมโครคอนโทรลเลอร์บางตัวที่ ATMega มีบิตเปิดใช้งานสลีปซึ่งป้องกันไม่ให้เกิดสภาวะเช่นนี้ (ขอบคุณ Kvegaoro สำหรับการชี้ให้เห็นสิ่งนี้) JRoberts เสนอตัวอย่างการใช้งานที่เป็นตัวอย่างของพฤติกรรมนี้
micros อื่นเช่น PIC18s ไม่มีบิตนี้และปัญหายังคงเกิดขึ้น อย่างไรก็ตามไมโครสโคปเหล่านี้ได้รับการออกแบบมาเพื่อให้อินเตอร์รัปต์ยังคงสามารถปลุกแกนได้โดยไม่คำนึงว่าบิตของอินเตอร์รัปต์จะเปิดใช้งานการตั้งค่าบิตไว้หรือไม่ สำหรับสถาปัตยกรรมดังกล่าวทางออกคือการปิดการใช้งานอินเตอร์รัปต์ชั่วคราวก่อนเข้านอน หากไฟขัดจังหวะก่อนดำเนินการคำสั่ง sleep ตัวจัดการขัดจังหวะจะไม่ถูกประมวลผลแกนกลางจะเริ่มทำงานและเมื่อการขัดจังหวะทั่วโลกถูกเปิดใช้งานอีกครั้งตัวจัดการขัดจังหวะจะถูกดำเนินการ ในโค้ดหลอกการใช้งานจะมีลักษณะเช่นนี้:
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
ตามint
และเพิ่มทุกครั้งที่มีการขัดจังหวะ จากนั้นเปลี่ยนif(has_flag)
ไปเป็นwhile (interrupts_count)
แล้วนอน อย่างไรก็ตามการขัดจังหวะอาจเกิดขึ้นหลังจากที่คุณออกจากวงขณะที่ หากนี่เป็นปัญหาการประมวลผลในอินเทอร์รัปต์จะทำเองหรือไม่?