2012-11-28 53 views
7
static void RadioReleaseSPI(void) { 
    __disable_interrupt(); 
    spiTxRxByteCount &= ~0x0100; 
    __enable_interrupt(); 
} 

मैं समझता हूं कि कई कार्य एसपीआई संसाधन का उपयोग करने का प्रयास कर सकते हैं। spiTxRxByteCount एक वैश्विक चर है जिसका उपयोग यह ट्रैक रखने के लिए किया जाता है कि क्या एसपीआई वर्तमान में किसी अन्य कार्य द्वारा उपयोग में है या नहीं। जब किसी कार्य को एसपीआई की आवश्यकता होती है तो यह देखने के लिए कि क्या एसपीआई का उपयोग किया जा रहा है, यह spiTxRxByteCount की स्थिति की जांच कर सकता है। जब एसपीआई का उपयोग करके कोई कार्य किया जाता है तो यह इस फ़ंक्शन को कॉल करता है और बिट को साफ़ करता है, यह इंगित करने के लिए कि एसपीआई अब मुक्त है। लेकिन पहले इंटरप्ट को अक्षम क्यों करें और फिर उन्हें फिर से सक्षम करें? बस परावर्तक?यहां आवश्यक इंटरप्ट अक्षम क्यों कर रहे हैं?

+0

यदि आपके पास आरटीओएस है, तो mutex का उपयोग क्यों न करें? –

+0

@ [ओएस के तहत इस तरह से लागू सैमफोर ऑपरेशन] (http://www.mpi-sws.org/~druschel/courses/os/lectures/proc4.pdf) –

उत्तर

14

& = एक रीड-संशोधित-लेखन ऑपरेशन करेगा - यह परमाणु नहीं है। आप उस बीच के बीच में बाधाओं को बदलना नहीं चाहते हैं, जिसके परिणामस्वरूप गलत मूल्य के साथ ओवर-लेखन लिखना पड़ता है।

8

परमाणु पहुंच सुनिश्चित करने के लिए आपको इंटरप्ट अक्षम करने की आवश्यकता है। आप किसी अन्य प्रक्रिया को एक्सेस नहीं करना चाहते हैं और जब आप इसे पढ़ रहे हों तो उस चर को संभावित रूप से संशोधित करना चाहते हैं।

Introduction to Embedded Computing से

:

परमाणु पहुँच की आवश्यकता

इस परिदृश्य की कल्पना कीजिए: एक 16-बिट चर जांच करने के लिए अग्रभूमि कार्यक्रम, एक 8 बिट यू सी, जरूरतों पर चल रहा है, इसे कहते एक्स इसलिए यह उच्च बाइट लोड करता है और फिर कम बाइट लोड करता है (या दूसरी तरफ, आदेश कोई फर्क नहीं पड़ता), और उसके बाद 16-बिट मान की जांच करता है। अब एक एक संबंधित आईएसआर के साथ बाधा डालें जो 16-बिट चर को संशोधित करता है। आगे कल्पना करें कि चर के मूल्य 0x1234 पर प्रोग्राम निष्पादन में दिए गए समय के साथ होता है। ,

  • अग्रभूमि भार उच्च बाइट (0x12)
  • ISR होता 0xABCD
  • अग्रभूमि भार कम बाइट (0xCD)
  • अग्रभूमि कार्यक्रम देखता है को संशोधित करता है एक्स: यहाँ वेरी बैड बात कि हो सकता है है 0x12CD का 16-बिट मान।

समस्या यह है कि डेटा की एक माना जाता है कि अविभाज्य टुकड़ा, हमारे चर एक्स, वास्तव में यह, तक पहुँचने क्योंकि चर का उपयोग करने के सीपीयू निर्देश विभाज्य थे करने की प्रक्रिया में संशोधित किया गया था है। और इस प्रकार वेरिएबल एक्स का हमारा भार दूषित हो गया है। आप देख सकते हैं कि परिवर्तनीय पढ़ने के क्रम से कोई फर्क नहीं पड़ता। अगर ऑर्डर हमारे उदाहरण में उलट दिया गया था, तो वैरिएबल को 0x12CD के बजाय 0xAB34 के रूप में गलत तरीके से पढ़ा गया होगा। किसी भी तरह से, मान पढ़ा गया है न तो पुराना मान्य मान (0x1234) और न ही नया मान्य मान (0xABCD)।

लेखन आईएसआर-संदर्भित डेटा बेहतर नहीं है। इस बार मान लें कि अग्रभूमि कार्यक्रम आईएसआर के लाभ के लिए लिखा गया है, पिछले मान 0x1234, और उसके बाद एक नया मान 0xABCD लिखना होगा। में इस मामले में, VBT इस प्रकार है:

  • अग्रभूमि भंडार नए उच्च बाइट (0xAB)
  • ISR होता है, 0xAB34 के रूप में पढ़ता एक्स
  • अग्रभूमि भंडार नए कम बाइट (0xCD)

एक बार फिर कोड (इस बार आईएसआर) न तो 0x1234 का वैध मान, न ही 0xABCD का नया मान्य मान, बल्कि 0xAB34 का अमान्य मान देखता है।

जबकि spiTxRxByteCount &= ~0x0100; सी में एक ही निर्देश की तरह दिख सकता है, यह वास्तव में सीपीयू के लिए कई निर्देश हैं। जीसीसी में संकलित, विधानसभा सूची तो दिखाई देता है: एक अवरोध के बीच उन निर्देशों में से किसी में आता है और डेटा को संशोधित करता

57:atomic.c  ****  spiTxRxByteCount &= ~0x0100; 
    68     .loc 1 57 0 
    69 004d A1000000  movl _spiTxRxByteCount, %eax 
    69  00 
    70 0052 80E4FE  andb $254, %ah 
    71 0055 A3000000  movl %eax, _spiTxRxByteCount 
    71  00 

तो अपना पहला ISR संभावित गलत मान पढ़ सकते हैं। इसलिए आपको उस पर काम करने से पहले इंटरप्ट को अक्षम करने की आवश्यकता है और वेरिएबल volatile घोषित करें।