मैमोरी-मैप्ड I / O एड्रेसिंग कैसे काम करता है?


29

मैमोरी-मैप्ड I / O एड्रेसिंग कैसे काम करता है?

मैं I2S आपूर्ति किए गए नमूने को समझने की कोशिश कर रहा हूं : किसी को भी यह चल रहा है?

घड़ियों को कॉन्फ़िगर करना:

#define BCM2708_PERI_BASE        0x20000000
#define CLOCK_BASE               (BCM2708_PERI_BASE + 0x101000) /* Clocks */

यह पहली बार कोड को मैप करता है ...

clk_map = (unsigned char *)mmap(
      (caddr_t)clk_mem,
      MAP_BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      CLOCK_BASE
   );

फिर यह कुछ करता है ...

 // Always use volatile pointer!
   clk = (volatile unsigned *)clk_map;

और जब इसे संदर्भित किया जाता है तो 0x26 और 0x27 के ये अजीब जोड़ हैं, इसके बारे में क्या है?

 printf("Disabling I2S clock\n");
 *(clk+0x26) = 0x5A000000;
 *(clk+0x27) = 0x5A000000;

 usleep(10);

 printf("Confiure I2S clock\n");
 *(clk+0x26) = 0x5A000001;
 *(clk+0x27) = 0x5A000000 | 3<<12 | 1<<9; // divider: 3.125==0b11.001

 usleep(10);
 printf("Enabling I2S clock\n");
 *(clk+0x26) = 0x5A000011;

डेटाशीट को देखते हुए, मैं देख सकता हूं कि उन्हें आधार मान की तरह इनमें से कुछ मूल्य कहां मिले हैं, लेकिन मैं दूसरों को समझने के लिए संघर्ष कर रहा हूं। वह कहाँ CLOCK_BASEनिर्धारित है और क्या चल रहा है?


1
यह शायद StackOverflow के लिए सबसे उपयुक्त है। हालांकि यह आरपीआई से संबंधित है। आपको प्रोग्रामिंग सवालों के जवाब मिलने की अधिक संभावना होगी।
Jivings

4
हो सकता है, लेकिन मुझे लगता है कि यह डेटाशीट और पाई हार्डवेयर की व्याख्या को मिलाकर एक अधिक सामान्य पाई प्रोग्रामिंग से संबंधित प्रश्न है। देखते हैं कि यह कुछ अच्छी जानकारी मिलती है या नहीं।
डॉग एर्स

ठीक है। आइए देखें कि यह कैसे होता है :)
जीव 8

1
मुझे नहीं लगता कि स्टैक ओवरफ्लो पर यह बहुत अच्छा होगा - यह बहुत विशेषज्ञ है और संभवतः यहां अधिक विशेषज्ञ का ध्यान जाएगा।
फ्लेक्सो

जवाबों:


18

एक कंप्यूटर पर आप एक निर्दिष्ट 'मेमोरी एड्रेस' पर लिखते हैं। यह पता सिस्टम द्वारा हार्डवेयर पते के रूप में पहचाना जाता है, और उपयुक्त हार्डवेयर उचित मूल्य प्राप्त या भेजता है।

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

रास्पबेरी पाई 0x20000000 पते पर हार्डवेयर रजिस्टरों की एक विशाल रेंज को पहचानती है। रजिस्टरों की एक श्रेणी जो घड़ी सिस्टम को नियंत्रित करती है, BCM2708_PERI_BASE + 0x101000 से एक्सेस की जाती है। I2S घड़ी को नियंत्रित करने वाले रजिस्टर उस ब्लॉक में 38 वें और 39 वें रजिस्टर हैं, जो BCM2708_PERI_BASE + 0x101000 + 0x26 और 0x27 का उपयोग करते हुए लिखे गए हैं

आप केवल घड़ी के मूल्यों को नहीं बदल सकते, हालांकि, आपको घड़ी को अक्षम करना होगा, मूल्यों को बदलना होगा और इसे पुनः आरंभ करना होगा।

अगर यह जवाब बहुत बुनियादी है, तो मेरी माफी। किस मामले में आपका प्रश्न वास्तव में कट्टर है, सौभाग्य। आपको यह लिंक मददगार लग सकता है

अपडेट: एमएमएपी का उपयोग क्यों करें और सीधे मेमोरी में न लिखें?

जब कोई प्रोग्राम मेमोरी एड्रेस चला रहा होता है तो उसे लगता है कि यह असली एड्रेस नहीं हैं, मेमोरी मैनेजर द्वारा उन्हें असली एड्रेस पर मैप किया जाता है। यह एक प्रोग्राम को दूसरे को प्रभावित करने में सक्षम होने से रोकता है। दो प्रक्रियाएं अपने स्वयं के पते पर 1234 को पूरी तरह से खुशी से पढ़ और लिख सकती हैं, और मेमोरी मैनेजर दोनों स्थानों को पूरी तरह से अलग रखेगा।

हालाँकि, हार्डवेयर पोर्ट पूर्ण भौतिक पते पर हैं। लेकिन आप उन्हें सीधे नहीं लिख सकते क्योंकि स्मृति प्रबंधक आपका पता लेगा और इसे आपके व्यक्तिगत मेमोरी क्षेत्र में मैप कर देगा।

लिनक्स / देव / मेम पर एक ' चरित्र डिवाइस फ़ाइल है जो कंप्यूटर की मुख्य मेमोरी की एक छवि है '

यदि आप इसे एक फ़ाइल की तरह खोलते हैं तो आप इसे एक फ़ाइल की तरह पढ़ और लिख सकते हैं। आपूर्ति किए गए नमूने में मेम_ एफडी एक फ़ाइल हैंडल है जो ओपनिंग / देव / मेम से हुई है

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

इसलिए इस नमूने में कोड भौतिक मेमोरी के लिए एक हैंडल बना रहा है, जैसे कि यह डिस्क पर एक फ़ाइल थी, और फिर सिस्टम से इसका इलाज करने के लिए कह रहा था जैसे कि यह मेमोरी थी। आभासी मेमोरी मैनेजर को गोल करने और वास्तविक भौतिक पते पर लिखने के लिए थोड़ा जटिल, लेकिन आवश्यक है। मान 0x20000000, ऐसा लगता है, एक लाल हेरिंग का एक सा है। कोड इस पते को संकेत के रूप में प्रस्तावित कर रहा है, सिस्टम को यहां मैप / देव / मेम करने की आवश्यकता नहीं है, हालांकि यह संभवतः करता है। आम तौर पर मूल्य शून्य को पारित किया जाएगा, और सिस्टम उस फ़ाइल हैंडल को मैप करेगा जो उसने सबसे अच्छा सोचा था।

अब भौतिक मेमोरी को वर्चुअल मेमोरी में प्रोसेस किया जाता है, और जहां आप उम्मीद करते हैं वहां जाकर पढ़ते और लिखते हैं।

संदर्भ:

http://www.kernel.org/doc/man-pages/online/pages/man2/mmap.2.html

http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=8496&p=104359

https://superuser.com/questions/71389/what-is-dev-mem


मेरे पास अभी भी कुछ सवाल हैं: वे एमएमएपी क्यों करते हैं? सिर्फ मेमोरी को सीधे एक्सेस क्यों न करें?
एलेक्स चेम्बरलेन

@AlexChamberlain क्योंकि कोड लिनक्स पर चलता है, इसलिए आप मेमोरी को सीधे एक्सेस नहीं कर सकते क्योंकि प्रत्येक प्रक्रिया को अपना वर्चुअल मेमोरी स्पेस मिलता है। हालाँकि कोई भी खुल सकता है और भौतिक स्मृति तक सीधी पहुँच प्राप्त करने के लिए mmap / dev / mem
nos

1

@AlexChamberlain यह OS संरचना के कारण है। आप बिना जा सकते हैं mmapलेकिन पेजिंग घोषित है, इसलिए कोई सीधी पहुँच नहीं है। कर्नेल मोड में आप बिना mmapकिसी आवश्यकता के कर्नेल मॉड्यूल के रूप में अपने ड्राइवर को सम्मिलित कर सकते हैं mmap। इसके अलावा, सरलतम OS मामले में, जहाँ कोई भी पृष्ठ तालिका मेमोरी का उपयोग नहीं किया जाता है, आप mmapया तो, इसके बिना भी पहुँच सकते हैं । प्रत्यक्ष भौतिक पता पहुंच।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.