निम्नलिखित कोड को चलाने वाले एक माइक्रोकंट्रोलर को देखते हुए:
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 एक उदाहरण कार्यान्वयन प्रदान करता है जो इस व्यवहार को उदाहरण देता है।
PIC18s में अन्य माइक्रो, इस बिट नहीं है, और समस्या अभी भी होती है। हालाँकि, इन माइक्रो को इस तरह से डिज़ाइन किया गया है कि व्यवधान अभी भी मूल जागृति को जागृत कर सकता है कि क्या वैश्विक व्यवधान सक्षम बिट सेट किया गया है (यह इंगित करने के लिए सुपरकैट धन्यवाद)। ऐसे आर्किटेक्चर के लिए, समाधान सोने जाने से ठीक पहले वैश्विक रुकावटों को अक्षम करना है। यदि नींद निर्देश को निष्पादित करने से ठीक पहले एक बाधा आग लग जाती है, तो बाधा हैंडलर को निष्पादित नहीं किया जाएगा, कोर जाग जाएगा, और एक बार वैश्विक रुकावटों को फिर से सक्षम करने के बाद, बाधित हैंडलर निष्पादित किया जाएगा। छद्म कोड में, कार्यान्वयन इस तरह दिखेगा:
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)
और फिर नींद। फिर भी, आप लूप से बाहर निकलने के बाद रुकावट हो सकते हैं। यदि यह एक समस्या है, तो क्या प्रसंस्करण खुद को बाधित कर रहा है?