कोर्टेक्स (एआरएम) माइक्रोकंट्रोलर्स पर डब्ल्यूएफआई (वेट-फॉर-इंटरप्ट) के लिए सर्वश्रेष्ठ पैटर्न


18

मैं EFM Gekko नियंत्रकों (http://energymicro.com/) का उपयोग करके बैटरी-संचालित सॉफ़्टवेयर विकसित करने में लगा रहा हूं और जब भी ऐसा करने के लिए उपयोगी कुछ नहीं हो तो सोते समय नियंत्रक चाहेंगे। इस उद्देश्य के लिए WFI (इंट्रस्ट के लिए प्रतीक्षा करें) निर्देश का उपयोग किया जाता है; यह प्रोसेसर को तब तक सोने के लिए रखेगा जब तक कोई व्यवधान नहीं होता।

अगर नींद किसी जगह पर जमा हो रही है, तो कुछ ऐसा करने के लिए लोड-एक्सक्लूसिव / स्टोर-एक्सक्लूसिव ऑपरेशन का उपयोग कर सकते हैं:

  // NOT_sleep 2 के साथ लोड हो जाता है किसी भी समय ऐसा होता है
  // मुख्य लूप को कम से कम एक बार चक्र करने के लिए मजबूर करना चाहिए। यदि कोई व्यवधान
  // होता है जो निम्न कथन के दौरान इसे 2 पर रीसेट करने का कारण बनता है,
  // व्यवहार ऐसा होगा जैसे इसके बाद व्यवधान हुआ।

  store_exclusive (load_exclusive (NOT_sleep) >> 1);

  जबकि (! dont_sleep)
  {
    // यदि अगले कथन और store_exclusive के बीच में व्यवधान होता है, तो सोएं नहीं
    load_exclusive (SLEEP_TRIGGER);
    अगर (!__leleep)             
      store_exclusive (SLEEP_TRIGGER);
  }

अगर load_exclusive और store_exclusive कार्रवाइयों के बीच कोई बाधा उत्पन्न होती है, तो प्रभाव store_exclusive को छोड़ना होगा, इस प्रकार सिस्टम लूप के माध्यम से एक और बार चल सकता है (यह देखने के लिए कि क्या अंतर ने NOT_leepep सेट किया है)। दुर्भाग्य से, स्लीप मोड को ट्रिगर करने के लिए गीकको एक डब्ल्यूएफआई निर्देश के बजाय एक लिखित पते का उपयोग करता है; कोड लिखना पसंद है

  अगर (!__leleep)
    डब्ल्यूएफआई ();

जोखिम उठाएँगे कि 'if' और 'wfi' के बीच एक व्यवधान उत्पन्न हो सकता है और NOT_sleep सेट कर सकते हैं, लेकिन wfi आगे बढ़ेगा और वैसे भी निष्पादित होगा। इसे रोकने के लिए सबसे अच्छा पैटर्न क्या है? WFI निष्पादित करने से ठीक पहले प्रोसेसर को बाधित करने से रोकने के लिए PRIMASK को 1 पर सेट करें, और इसके तुरंत बाद साफ़ करें? या कुछ बेहतर ट्रिक है?

संपादित करें

मैं इवेंट बिट के बारे में सोच रहा हूँ। सामान्य विवरण के अनुसार, यह बहु-प्रोसेसर समर्थन के लिए अभिप्रेत है, लेकिन यह सोचता है कि क्या निम्नलिखित की तरह कुछ काम कर सकता है:

  अगर (नॉट_सलीप)
    SEV (); / * निम्नलिखित WFE स्पष्ट घटना ध्वज बना देगा लेकिन नींद नहीं / *
  WFE ();

हर बाधा जो सेट नहीं करती है, वह भी एक SEV निर्देश को निष्पादित करना चाहिए, इसलिए यदि "अगर" परीक्षण के बाद रुकावट होती है, तो WFE ईवेंट ध्वज को साफ़ कर देगा, लेकिन सो नहीं जाएगा। क्या यह एक अच्छे प्रतिमान की तरह लगता है?


1
WFI इंस्ट्रक्शन कोर को सोने के लिए नहीं रखता है यदि निर्देश के निष्पादित होने पर इसकी जागृत स्थिति सही है। उदाहरण के लिए यदि कोई अस्पष्ट IRQ है जब WFI निष्पादित होता है तो यह NOP के रूप में कार्य करता है।
मार्क

@ मर्क: मुद्दा यह होगा कि यदि "अगर (!__leleep)") और "डब्ल्यूएफआई" के बीच में कोई रुकावट आती है, तो डब्ल्यूएफआई के क्रियान्वयन के समय व्यवधान की स्थिति लंबित नहीं होगी, लेकिन हो सकता है कि व्यवधान न हो, क्योंकि यह नहीं है। कुछ ऐसा किया जो मुख्य पाश को एक और पुनरावृत्ति चलाने के लिए उचित ठहराएगा। मेरा एक सरू पीएसओसी आवेदन पर, कोई भी व्यवधान जो एक विस्तारित वेकअप का कारण बन सकता है, यदि मुख्य-पंक्ति कोड सोने के बारे में था, तो स्टैक को बंद कर देगा, लेकिन यह बहुत अच्छा लगता है और मुझे लगता है कि एआरएम ऐसे स्टैक जोड़तोड़ को हतोत्साहित करता है।
सुपरकैट

@supercat WFI निष्पादित होने पर रुकावट साफ हो सकती है या नहीं भी हो सकती है। इसका आप पर और कब / कहाँ आप रुकावट को साफ़ करना चुनते हैं। जब आप जागते या सोते रहना चाहते हैं, तो सूचित करने के लिए NOT_sleep वेरिएबल से छुटकारा पाएं और केवल एक नकाबपोश व्यवधान का उपयोग करें। आप बस एक साथ सभी बयान से छुटकारा पा सकते हैं और मुख्य लूप के अंत में डब्ल्यूएफआई छोड़ सकते हैं। यदि आपने सभी अनुरोधों को सेवित कर लिया है, तो IRQ को साफ़ करें ताकि आप सो सकें। यदि आपको जागृत रहने की आवश्यकता है, तो आईआरक्यू को ट्रिगर करें, इसका मुखौटा कुछ भी नहीं होता है, लेकिन जब डब्ल्यूएफआई इसे निष्पादित करने की कोशिश करता है तो यह एनओपी होगा।
मार्क

2
@supercat एक अधिक मौलिक स्तर पर, ऐसा लगता है कि आपके 'बिग मेन लूप' डिज़ाइन के साथ एक बाधित-संचालित डिज़ाइन को मिलाने की कोशिश की जा रही है, जो आमतौर पर नॉन टाइम क्रिटिकल होता है, अक्सर मतदान आधारित होता है और इसमें न्यूनतम व्यवधान होता है। इनको मिलाने से बदसूरत बल्कि तेज़ हो सकते हैं। यदि संभव हो तो एक डिजाइन प्रतिमान या दूसरे का उपयोग करने के लिए चुनें। याद रखें कि आधुनिक रुकावट नियंत्रकों के साथ आप मूल रूप से इंटरप्ट्स के बीच प्रीमेप्टिव मल्टीटास्किंग प्राप्त करते हैं और किन राशियों को कार्य कतार (सेवा एक बाधा, फिर अगली उच्च प्राथमिकता, आदि) मिलती है। इसे अपने फायदे के लिए इस्तेमाल करो।
मार्क

@ मर्क: मैंने एक प्रणाली विकसित की है जो बैटरी चालित एप्लिकेशन में PIC 18x का बहुत अच्छा इस्तेमाल करती है; स्टैक सीमाओं के कारण, यह एक बाधा के भीतर बहुत अधिक संभाल नहीं सकता है, इसलिए सामान का विशाल बहुमत मुख्य लूप में एक सुविधाजनक आधार पर संभाला जाता है। यह ज्यादातर बहुत अच्छी तरह से काम करता है, हालांकि कुछ स्थानों पर लंबे समय से चल रहे संचालन के कारण चीजें एक-दूसरे के लिए अवरुद्ध हो जाती हैं। यदि मैं एक एआरएम के लिए पलायन करता हूं, तो मैं लंबे समय से चल रहे कार्यों को विभाजित करने के लिए एक सरल आरटीओएस का उपयोग कर सकता हूं, लेकिन मुझे यकीन नहीं है कि प्रीमेप्टिव या सहकारी मल्टीटास्किंग का उपयोग करना है या नहीं।
22

जवाबों:


3

मुझे पूरी तरह से dont_sleepबात समझ में नहीं आई, लेकिन एक चीज जो आप आजमा सकते हैं, वह है PendSV हैंडलर में "मुख्य काम", सबसे कम प्राथमिकता पर सेट करना। फिर बस हर बार जब आप की जरूरत है कुछ अन्य हैंडलर से एक PendSV अनुसूची। यहां देखें कि यह कैसे करना है (यह एम 1 के लिए है लेकिन एम 3 बहुत अलग नहीं है)।

एक और चीज जिसका आप उपयोग कर सकते हैं (शायद पिछले दृष्टिकोण के साथ) स्लीप-ऑन-एग्जिट सुविधा है। यदि आप इसे सक्षम करते हैं, तो प्रोसेसर अंतिम ISR हैंडलर से बाहर निकलने के बाद सो जाएगा, बिना आपको डब्ल्यूएफआई कॉल करने के लिए। कुछ उदाहरण यहाँ देखें ।


5
डब्ल्यूएफआई निर्देश को प्रोसेसर को जगाने के लिए इंटरप्ट करने की आवश्यकता नहीं होती है, सीपीएसआर में एफ और आई बिट्स को अनदेखा किया जाता है।
मार्क

1
@ मैं डॉक्स में उस बिट को याद किया होगा, क्या आपके पास इसके बारे में कुछ लिंक / संकेत हैं? कोर को जगाने वाले रुकावट सिग्नल का क्या होता है? क्या यह तब तक रुका हुआ है जब तक कि बाधा फिर से सक्षम न हो जाए?
इगोर स्कोचिन्स्की

एएसएम संदर्भ मैनुअल यहां है: infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/ ... प्रांतस्था-एम 3 के लिए अधिक विशिष्ट जानकारी यहां है: infocenter .arm.com / help/ index.jsp? विषय = / com.arm.doc.dui0552a /… संक्षेप में जब एक नकाबपोश व्यवधान कोर जाग उठता है और WFI निर्देश के बाद संचालन जारी रखता है। यदि आपने एक और डब्ल्यूएफआई जारी करने का प्रयास किए बिना यह स्पष्ट कर दिया कि डब्ल्यूएफआई में लंबित रुकावट एनओपी के रूप में कार्य करेगा (डब्ल्यूएफआई के लिए जगा हालत सच है तो कोर सो नहीं जाएगा)।
मार्क

@ मर्क: एक बात जिस पर मैं विचार कर रहा था, वह है कि कोई भी बाधा हैंडलर हो जो सेट न करें_सेप भी एक एसईवी ("सेट इवेंट") निर्देश को निष्पादित करता है, और फिर डब्ल्यूएफआई के बजाय डब्ल्यूएफई ("इवेंट के लिए प्रतीक्षा करें") का उपयोग करें। Gekko उदाहरण WFI का उपयोग करते प्रतीत होते हैं, लेकिन मुझे लगता है कि WFE भी काम कर सकता है। कोई विचार?
सुपरकैट

10

इसे एक महत्वपूर्ण अनुभाग के अंदर रखें। ISRs नहीं चलेंगे, इसलिए आप WFI से पहले न तो बदलने का खतरा न उठाएं, लेकिन वे अभी भी प्रोसेसर को जगाएंगे और महत्वपूर्ण खंड समाप्त होते ही ISR निष्पादित करेंगे।

uint8 interruptStatus;
interruptStatus = EnterCriticalSection();
if (!dont_sleep)
  WFI();
ExitCriticalSection(interruptStatus);

आपके विकास के वातावरण में संभवतः महत्वपूर्ण कार्य हैं, लेकिन यह इस तरह है:

EnterCriticalSection है:

MRS r0, PRIMASK /* Save interrupt state. */
CPSID i /* Turn off interrupts. */
BX lr /* Return. */

ExitCriticalSection है:

MSR PRIMASK, r0 /* Restore interrupt states. */
BX lr /* Return. */

2
उत्सुकता से, कई एआरएम पुस्तकालय एक महत्वपूर्ण-अनुभाग कार्यान्वयन का उपयोग करते हैं जो स्थानीय रूप से स्थिति को संरक्षित करने के बजाय एक वैश्विक काउंटर का उपयोग करता है। मुझे लगता है कि काउंटर अप्रोच अधिक जटिल है, क्योंकि सभी कोड सिस्टम-वाइड एक ही काउंटर का उपयोग करता है, तो यह दिमाग चकरा देने वाला है।
सुपरकैट

1
जब तक हम महत्वपूर्ण खंड से बाहर नहीं निकलते, तब तक बाधित नहीं होगा? यदि ऐसा है, तो WFI CPU को अनिश्चित काल तक प्रतीक्षा करने का कारण नहीं बनेगा?
कॉर्नेलियु ज़ुजु

1
@Kenzi Shrimp का जवाब एक लिनक्स चर्चा धागे की ओर इशारा करता है जो मेरे पिछले प्रश्न का उत्तर देता है। मैंने उसका उत्तर और तुम्हारा स्पष्ट करने के लिए संपादन किया।
कोर्नेलियू ज़ुजु

@CorneliuZuzu अपनी खुद की चर्चा के लिए किसी और के उत्तर का संपादन करना एक महान विचार नहीं है। 'केवल लिंक' उत्तर को बेहतर बनाने के लिए उद्धरण जोड़ना एक अलग मामला है। यदि आपके पास अपने जीते जाने का वास्तविक प्रश्न है, तो शायद इसे एक प्रश्न के रूप में पूछें, और इस एक से लिंक करें।
सीन हुलिएन

1
@ सीनयोहिलाने को मैंने अमान्य नहीं किया और न ही उसके उत्तर से कुछ हटाया। यह काम क्यों करता है, इस पर एक छोटा स्पष्टीकरण अलग चर्चा नहीं है। ईमानदारी से, मुझे नहीं लगता कि यह उत्तर WFI स्पष्टीकरण के बिना अप-वोट के योग्य है, लेकिन यह इसके साथ सबसे योग्य है।
कोर्नेलियु ज़ुजु

7

आपका विचार ठीक है, यह वही है जो लिनक्स लागू करता है। देखें यहाँ

उपर्युक्त चर्चा सूत्र से उपयोगी उद्धरण स्पष्ट करने के लिए कि डब्ल्यूएफआई विकलांगों के साथ भी काम क्यों करता है:

यदि आप अगले व्यवधान के बाद निष्क्रिय होना चाहते हैं, तो आपको कुछ तैयारी करनी होगी। उस तैयारी के दौरान, एक व्यवधान सक्रिय हो सकता है। इस तरह की रुकावट एक जागृत घटना हो सकती है जिसे आप खोज रहे हैं।

कोई फर्क नहीं पड़ता कि आपका कोड कितना अच्छा है, यदि आप व्यवधान को अक्षम नहीं करते हैं, तो आपके पास हमेशा सोने जाने की तैयारी करने और वास्तव में सोने जाने की दौड़ के बीच एक दौड़ होगी, जिसके परिणामस्वरूप जागने की घटनाएं घटती हैं।

यही कारण है कि सभी एआरएम सीपीयू से मैं अवगत हूं, भले ही वे कोर सीपीयू (सीपीएसआर आई बिट) पर नकाब लगाए हुए हैं।

कुछ भी और आप निष्क्रिय मोड का उपयोग करना भूल जाना चाहिए।


1
आप WFI या WFE निर्देश के समय में व्यवधान को अक्षम करने की बात कर रहे हैं? क्या आप इस उद्देश्य के लिए WFI या WFE का उपयोग करने के बीच कोई सार्थक अंतर देखते हैं?
सुपरकैट

1
@ सुपरकैट: मैं निश्चित रूप से डब्ल्यूएफआई का उपयोग करूंगा। डब्ल्यूईएफ आईएमओ मुख्य रूप से मल्टीकोर सिस्टम में कोर के बीच सिंक्रनाइज़ेशन संकेत के लिए है (उदाहरण के लिए एफएलई पर डब्ल्यूएफई असफल हो रहा है और स्पिनॉक से बाहर जाने के बाद एसईवी जारी करना)। इसके अलावा, WFE इंटरप्ट मास्किंग फ्लैग को ध्यान में रखता है इसलिए यह WFI के समान उपयोगी नहीं है। यह पैटर्न वास्तव में लिनक्स में अच्छा काम करता है।
झींझक

2

ऐसा मानते हुए:

  1. मुख्य धागा पृष्ठभूमि कार्यों को चलाता है
  2. व्यवधान केवल उच्च प्राथमिकता वाले कार्य और कोई पृष्ठभूमि कार्य नहीं चलाते हैं
  3. मुख्य धागे को किसी भी समय बाधित किया जा सकता है (यह आम तौर पर मुखौटे को बाधित नहीं करता है)

फिर समाधान ध्वज सत्यापन और WFI के बीच व्यवधान को रोकने के लिए PRIMASK का उपयोग करना है:

mask_interrupts();
if (!dont_sleep)
    wfi();
unmask_interrupts();

0

एग्जिट मोड पर नींद के बारे में क्या? यह स्वचालित रूप से किसी भी समय आईआरक्यू हैंडलर से बाहर निकल जाता है, इसलिए सो जाता है कि कॉन्फ़िगर होने के बाद वास्तव में कोई "सामान्य मोड" नहीं चल रहा है। एक IRQ होता है, यह उठता है और हैंडलर चलाता है, और वापस सो जाता है। कोई डब्ल्यूएफआई की जरूरत है।


2
इस तथ्य के साथ एक सबसे अच्छा सौदा कैसे होना चाहिए कि किस प्रकार की नींद में प्रोसेसर गिरना चाहिए जो एक बाधा के दौरान होने वाली किसी चीज के आधार पर भिन्न हो सकता है? उदाहरण के लिए, एक पिन-चेंज ईवेंट संकेत दे सकता है कि सीरियल डेटा आगामी हो सकता है, और इसलिए प्रोसेसर को डेटा की प्रतीक्षा करते समय प्राथमिक घड़ी थरथरानवाला चालू रखना चाहिए। यदि मुख्य लूप ईवेंट फ़्लैग को साफ़ करता है, जांच करता है कि क्या चल रहा है, और प्रोसेसर को WFI के साथ एक उपयुक्त स्लीप मोड में डाल देता है, तो किसी भी रुकावट से यह प्रभावित हो सकता है कि कौन सा मोड उपयुक्त होगा जो ईवेंट फ़्लैग को सेट करेगा ...
supercat

... और नींद को खत्म करो। एक मुख्य-लूप हैंडलर का नियंत्रण होने से स्लीप मोड साफ-सुथरा लगता है, जबकि हर बाधा में इसकी चिंता होती है। हर रुकावट पर मुख्य लूप के उस भाग को "स्पिन" करने से वह संभवतः कुशल नहीं हो सकता है, लेकिन यह बहुत बुरा भी नहीं होना चाहिए, खासकर यदि सभी व्यवधान जो नींद के व्यवहार को प्रभावित कर सकते हैं, वह किसी न किसी झंडे को प्रभावित कर सकता है।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.