एक माइक्रोकंट्रोलर के विभिन्न मेमोरी प्रकारों में क्या रहता है?


25

विभिन्न मेमोरी सेगमेंट हैं जिनमें संकलन के बाद विभिन्न प्रकार के डेटा सी कोड से डाले जाते हैं। अर्थात्: .text, .data, .bss, ढेर और ढेर। मैं बस यह जानना चाहता हूं कि इनमें से प्रत्येक सेगमेंट एक माइक्रोकंट्रोलर मेमोरी में कहां रहेगा। अर्थात, कौन सा डेटा किस प्रकार की मेमोरी में जाता है, जिसे देखते हुए मेमोरी प्रकार RAM, NVRAM, ROM, EEPROM, FLOS आदि हैं।

मुझे यहां ऐसे ही सवालों के जवाब मिले हैं, लेकिन वे यह समझाने में नाकाम रहे कि अलग-अलग मेमोरी प्रकारों में से प्रत्येक की सामग्री क्या होगी।

किसी भी तरह की मदद की बहुत सराहना की जाती है। अग्रिम में धन्यवाद!


1
NVRAM, ROM, EEPROM और Flash एक ही चीज़ के लिए बहुत अलग नाम हैं: गैर-वाष्पशील मेमोरी।
लुंडिन

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

@ सीनहॉलिहेन ओपी माइक्रोकंट्रोलर्स के बारे में पूछ रहा है, जो लगभग हमेशा फ्लैश से बाहर निकलते हैं (आपने असाधारण के साथ अपनी टिप्पणी को योग्य किया था)। उदाहरण के लिए, एमबी के बाहरी रैम के साथ माइक्रो प्रोसेसर चलने वाले लिनक्स, उनके कार्यक्रमों को कॉपी करने के लिए रैम में कॉपी करेंगे, जो संभवत: एक माउंटेबल वॉल्यूम के रूप में कार्य करने वाले एसडी कार्ड से दूर होंगे।
tcrosley

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

1
एक चीज को दूसरे से जोड़ने के लिए कोई नियम नहीं हैं, यकीन है कि केवल पाठ और रॉडटा जैसे सामान केवल आदर्श रूप से फ्लैश में जाना चाहते हैं, लेकिन .data और ऑफसेट .bss का आकार वहां भी जाता है (और फिर नकल करके मिलता है। बूटस्ट्रैप कोड)। इन शर्तों (.text, आदि) का माइक्रोकंट्रोलर्स के साथ कोई लेना-देना नहीं है यह एक कंपाइलर / टूलचिन चीज है जो कंपाइलर / टूलचिन्स के सभी लक्ष्यों पर लागू होती है। दिन के अंत में प्रोग्रामर तय करता है कि चीजें कहां जाती हैं और आमतौर पर लिंकर स्क्रिप्ट के माध्यम से टूलकिन को सूचित करती हैं।
Old_timer

जवाबों:


38

.text

.Text खंड में वास्तविक कोड होता है, और इसे माइक्रोकंट्रोलर्स के लिए फ्लैश मेमोरी में प्रोग्राम किया जाता है। फ्लैश मेमोरी के कई, गैर-सन्निहित ब्लॉक होने पर एक से अधिक टेक्स्ट सेगमेंट हो सकते हैं; उदाहरण के लिए मेमोरी के शीर्ष पर स्थित एक वेक्टर और इंटरप्ट वैक्टर, और 0 से शुरू होने वाला कोड; या बूटस्ट्रैप और मुख्य कार्यक्रम के लिए अलग-अलग अनुभाग।

.बीएस और डाटाटा

तीन प्रकार के डेटा हैं जिन्हें किसी फ़ंक्शन या प्रक्रिया के लिए बाहरी आवंटित किया जा सकता है; पहला अनइंस्टाल्यूटेड डेटा है (ऐतिहासिक रूप से कहा जाता है। एलबीएस, जिसमें 0 इनिशियलाइज़्ड डेटा भी शामिल है), और दूसरा इनिशियलाइज़्ड (नॉन-बीएसएस), या .डाटा है। "बीएसएस" नाम ऐतिहासिक रूप से "ब्लॉक स्टार्टेड बाई सिंबल" से आता है, जिसका उपयोग लगभग 60 साल पहले एक असेंबलर में किया गया था। ये दोनों क्षेत्र राम में स्थित हैं।

जैसा कि एक कार्यक्रम संकलित किया गया है, चर इन दो सामान्य क्षेत्रों में से एक को आवंटित किया जाएगा। लिंकिंग चरण के दौरान, सभी डेटा आइटम एक साथ एकत्र किए जाएंगे। सभी चर जिन्हें आरंभ करने की आवश्यकता होती है, प्रारंभिक मानों को रखने के लिए प्रोग्राम मेमोरी के एक हिस्से को अलग रखा जाएगा, और मुख्य () कहा जाता है, आमतौर पर चर को प्रारंभ किया जाएगा, आमतौर पर crt0 नामक एक मॉड्यूल द्वारा। Bss सेक्शन को एक ही स्टार्टअप कोड द्वारा सभी शून्य में आरंभ किया जाता है।

कुछ माइक्रोकंट्रोलर के साथ, छोटे निर्देश हैं जो रैम के पहले पृष्ठ (पहले 256 स्थानों, जिसे कभी-कभी पृष्ठ 0 कहा जाता है) तक पहुंच की अनुमति देता है। इन प्रोसेसरों के लिए कंपाइलर एक कीवर्ड को आरक्षित कर सकता है जैसे कि nearचर को वहां रखा जाए। इसी तरह, ऐसे माइक्रोकंट्रोलर भी हैं जो केवल एक पॉइंटर रजिस्टर (अतिरिक्त निर्देशों की आवश्यकता) के माध्यम से कुछ क्षेत्रों को संदर्भित कर सकते हैं, और ऐसे चर नामित हैं far। अंत में, कुछ प्रोसेसर बिट द्वारा मेमोरी के एक सेक्शन को संबोधित कर सकते हैं और कंपाइलर के पास इसे निर्दिष्ट करने का एक तरीका होगा (जैसे कि कीवर्ड bit)।

इसलिए अतिरिक्त खंड जैसे .nearbs और .neardata, आदि हो सकते हैं, जहाँ ये चर एकत्र किए जाते हैं।

.rodata

किसी फ़ंक्शन या प्रक्रिया के लिए बाहरी बाहरी प्रकार का तीसरा प्रकार आरंभिक चर की तरह है, सिवाय इसके कि यह केवल पढ़ने के लिए है और इसे प्रोग्राम द्वारा संशोधित नहीं किया जा सकता है। C भाषा में, इन चर को constकीवर्ड का उपयोग करके दर्शाया जाता है । वे आमतौर पर प्रोग्राम फ्लैश मेमोरी के भाग के रूप में संग्रहीत होते हैं। कभी-कभी उन्हें एक .rodata (केवल पढ़ने के लिए डेटा) खंड के हिस्से के रूप में पहचाना जाता है। हार्वर्ड आर्किटेक्चर का उपयोग करने वाले माइक्रोकंट्रोलर्स पर , कंपाइलर को इन चर तक पहुंचने के लिए विशेष निर्देशों का उपयोग करना चाहिए।

ढेर और ढेर

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

स्टैक पर रखे गए वैरिएबल कीवर्ड के बिना किसी फ़ंक्शन या प्रक्रिया के भीतर परिभाषित कोई भी चर हैं static। उन्हें एक बार स्वचालित चर ( autoकीवर्ड) कहा जाता था , लेकिन उस कीवर्ड की आवश्यकता नहीं है। ऐतिहासिक रूप से, autoमौजूद है क्योंकि यह B भाषा का हिस्सा था जो C से पहले था, और वहां इसकी आवश्यकता थी। स्टैक पर फ़ंक्शन पैरामीटर भी रखे जाते हैं।

यहाँ RAM के लिए एक विशिष्ट लेआउट दिया गया है (कोई विशेष पेज 0 अनुभाग नहीं मानते हुए):

यहाँ छवि विवरण दर्ज करें

EEPROM, ROM और NVRAM

फ़्लैश मेमोरी के साथ आने से पहले, EEPROM (विद्युत रूप से मिटाए जाने योग्य प्रोग्राम-रीड-ओनली मेमोरी) का उपयोग प्रोग्राम और कास्ट डेटा (.text और .rodata सेगमेंट) को संग्रहीत करने के लिए किया गया था। अब EEPROM की बस एक छोटी राशि (जैसे 2KB से 8KB बाइट्स) उपलब्ध है, यदि कोई हो, और इसका उपयोग आमतौर पर कॉन्फ़िगरेशन डेटा या डेटा की अन्य छोटी मात्रा को संग्रहीत करने के लिए किया जाता है, जिसे पावर-डाउन पावर अप पर बनाए रखने की आवश्यकता होती है चक्र। इन्हें प्रोग्राम में वैरिएबल के रूप में घोषित नहीं किया जाता है, बल्कि इसके बजाय माइक्रोकंट्रोलर में विशेष रजिस्टरों का उपयोग करने के लिए लिखा जाता है। EEPROM को एक अलग चिप में भी लागू किया जा सकता है और एक SPI या I busC बस के माध्यम से पहुँचा जा सकता है।

ROM अनिवार्य रूप से Flash के समान है, सिवाय इसके कि इसे कारखाने में क्रमादेशित किया जाता है (उपयोगकर्ता द्वारा प्रोग्राम करने योग्य नहीं)। इसका उपयोग केवल बहुत अधिक मात्रा वाले उपकरणों के लिए किया जाता है।

NVRAM (गैर-वाष्पशील रैम) EEPROM का एक विकल्प है, और इसे आमतौर पर बाहरी आईसी के रूप में लागू किया जाता है। बैटरी के बैकअप होने पर नियमित रैम को गैर-वाष्पशील माना जा सकता है; उस स्थिति में कोई विशेष पहुँच विधियों की आवश्यकता नहीं है।

हालाँकि डेटा को फ़्लैश में सहेजा जा सकता है, लेकिन फ्लैश मेमोरी में सीमित संख्या में इरेज़ / प्रोग्राम साइकल (1000 से 10,000) हैं, इसलिए यह वास्तव में इसके लिए डिज़ाइन नहीं किया गया है। इसके लिए एक बार में मेमोरी को ब्लॉक करना पड़ता है, इसलिए बस कुछ बाइट्स को अपडेट करना असुविधाजनक है। यह कोड और केवल-पढ़ने योग्य चर के लिए अभिप्रेत है।

EEPROM को मिटा / कार्यक्रम चक्र (100,000 से 1,000,000) पर बहुत अधिक सीमाएं हैं, इसलिए यह इस उद्देश्य के लिए बहुत बेहतर है। यदि माइक्रोकंट्रोलर पर EEPROM उपलब्ध है और यह काफी बड़ा है, तो यह वह जगह है जहाँ आप गैर-वाष्पशील डेटा को सहेजना चाहते हैं। हालाँकि लिखने से पहले आपको पहले ब्लॉक (आमतौर पर 4KB) को भी मिटाना होगा।

यदि कोई EEPROM नहीं है या यह बहुत छोटा है, तो एक बाहरी चिप की आवश्यकता है। एक 32KB EEPROM केवल 66 EP है और इसे 1,000,000 बार तक मिटाया / लिखा जा सकता है। समान संख्या में मिटा / कार्यक्रम संचालन के साथ एक एनवीआरएएम बहुत अधिक महंगा है (एक्स 10) एनवीआरएएम आमतौर पर ईईपीआरओएम की तुलना में पढ़ने के लिए तेज होते हैं, लेकिन लिखने के लिए धीमा। वे एक बार में या ब्‍लॉक में लिखे जा सकते हैं।

इन दोनों का एक बेहतर विकल्प एफआरएएम (फेरोइलेक्ट्रिक रैम) है, जिसमें अनिवार्य रूप से अनंत चक्र (100 ट्रिलियन) और कोई लेखन देरी नहीं है। यह एनवीआरएएम के समान मूल्य के बारे में है, 32KB के लिए $ 5 के आसपास।


यह कुछ वास्तविक उपयोगी जानकारी थी। क्या आप कृपया अपने स्पष्टीकरण का संदर्भ प्रदान कर सकते हैं? पाठ्य पुस्तकों या पत्रिकाओं की तरह, अगर मैं इस बारे में अधिक पढ़ना चाहता हूं ..?
सोजू टी वर्गीज

एक और सवाल, क्या आप कृपया एक मेमोरी के फायदे या नुकसान का अंदाजा दूसरे (EEPROM, NVRAM और FLOS) को दे सकते हैं?
सूजू टी वर्गीज

अच्छा जवाब। मैंने एक पूरक पोस्ट किया जिसमें सी भाषा विशेष रूप से कहाँ जाती है, इस पर अधिक ध्यान केंद्रित किया।
लंडिन

1
@SojuTVarghese मैंने अपना उत्तर अपडेट किया और FRAM के बारे में कुछ जानकारी भी शामिल की।
tcrosley

@ लुंडिन हमने एक ही खंड के नाम (जैसे .रोडाटा) का उपयोग किया है, इसलिए उत्तर एक दूसरे के पूरक हैं।
tcrosley

21

सामान्य एम्बेडेड सिस्टम:

Segment     Memory   Contents

.data       RAM      Explicitly initialized variables with static storage duration
.bss        RAM      Zero-initialized variables with static storage duration
.stack      RAM      Local variables and function call parameters
.heap       RAM      Dynamically allocated variables (usually not used in embedded systems)
.rodata     ROM      const variables with static storage duration. String literals.
.text       ROM      The program. Integer constants. Initializer lists.

इसके अलावा, स्टार्ट-अप कोड और इंटरप्ट वैक्टर के लिए आमतौर पर अलग-अलग फ्लैश सेगमेंट होते हैं।


स्पष्टीकरण:

एक चर में स्थिर भंडारण अवधि होती है यदि इसे घोषित किया जाता है staticया यदि यह फ़ाइल दायरे (कभी-कभी "वैश्विक" कहा जाता है) में रहता है। सी में एक नियम है जो कहता है कि सभी स्थिर भंडारण अवधि चर जो प्रोग्रामर ने प्रारंभिक रूप से प्रारंभ नहीं की थी उन्हें शून्य से आरंभ किया जाना चाहिए।

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

उदाहरण:

static int a;                // .bss
static int b = 0;            // .bss      
int c;                       // .bss
static int d = 1;            // .data
int e = 1;                   // .data

void func (void)
{
  static int x;              // .bss
  static int y = 0;          // .bss
  static int z = 1;          // .data
  static int* ptr = NULL;    // .bss
}

कृपया ध्यान रखें कि एम्बेडेड सिस्टम के लिए एक बहुत ही सामान्य गैर-मानक सेटअप एक "न्यूनतम स्टार्ट-अप" है, जिसका अर्थ है कि कार्यक्रम स्थिर भंडारण अवधि के साथ वस्तुओं के सभी आरंभीकरण को छोड़ देगा । इसलिए यह समझदारी हो सकती है कि ऐसे चर के आरंभिक मूल्यों पर निर्भर रहने वाले कार्यक्रमों को कभी न लिखें, बल्कि उन्हें पहली बार उपयोग करने से पहले "रन-टाइम" में सेट करें।

अन्य खंडों के उदाहरण:

const int a = 0;           // .rodata
const int b;               // .rodata (nonsense code but C allows it, unlike C++)
static const int c = 0;    // .rodata
static const int d = 1;    // .rodata

void func (int param)      // .stack
{
  int e;                   // .stack
  int f=0;                 // .stack
  int g=1;                 // .stack
  const int h=param;       // .stack
  static const int i=1;    // .rodata, static storage duration

  char* ptr;               // ptr goes to .stack
  ptr = malloc(1);         // pointed-at memory goes to .heap
}

वेरीएबल्स जो स्टैक पर जा सकते हैं वे अक्सर अनुकूलन के दौरान सीपीयू रजिस्टरों में समाप्त हो सकते हैं। अंगूठे के एक नियम के रूप में, किसी भी चर का जो इसका पता नहीं है, उसे सीपीयू रजिस्टर में रखा जा सकता है।

ध्यान दें कि पॉइंटर्स अन्य चर की तुलना में थोड़ा अधिक जटिल हैं, क्योंकि वे दो अलग-अलग प्रकार की अनुमति देते हैं const, इस पर निर्भर करता है कि पॉइंट-एट डेटा केवल पढ़ा जाना चाहिए, या यदि पॉइंटर स्वयं होना चाहिए। यह अंतर जानना बहुत महत्वपूर्ण है ताकि आपके संकेत दुर्घटना में राम द्वारा समाप्त न हों, जब आप चाहते थे कि वे फ्लैश में हों।

int* j=0;                  // .bss
const int* k=0;            // .bss, non-const pointer to const data
int* const l=0;            // .rodata, const pointer to non-const data
const int* const m=0;      // .rodata, const pointer to const data

void (*fptr1)(void);       // .bss
void (*const fptr2)(void); // .rodata
void (const* fptr3)(void); // invalid, doesn't make sense since functions can't be modified

पूर्णांक स्थिरांक, इनिशियलाइज़र सूची, स्ट्रिंग शाब्दिक आदि के मामले में, वे संकलक के आधार पर या तो .text या .rodata में समाप्त हो सकते हैं। इस प्रकार, वे समाप्त होते हैं:

#define n 0                // .text
int o = 5;                 // 5 goes to .text (part of the instruction)
int p[] = {1,2,3};         // {1,2,3} goes to .text
char q[] = "hello";        // "hello" goes to .rodata

मुझे समझ में नहीं आ रहा है, आपके पहले उदाहरण कोड में, 'स्थिर int b = 0;' .bs में जाता है और क्यों 'स्थिर int d = 1;' चला जाता है .डाटा ..? मेरी समझ में, दोनों स्टैटिक वैरिएबल हैं जिन्हें प्रोग्रामर द्वारा इनिशियलाइज़ किया गया है .. तो क्या फर्क पड़ता है? @ लुंडिन
सोजू टी वर्गीज

2
@SojuTVarghese .bss डेटा को ब्लॉक के रूप में 0 से प्रारंभ किया जाता है; विशिष्ट मूल्य जैसे d = 1 को फ़्लैश में संग्रहीत किया जाना है।
tcrosley

@SojuTVarghese ने कुछ स्पष्टीकरण जोड़ा।
लंडिन

@ लुंडिन इसके अलावा, आपके पिछले उदाहरण कोड से, क्या इसका मतलब है कि सभी आरंभिक मूल्य .text या .rodata और उनके संबंधित चर अकेले .bs या .data में जाते हैं? यदि हां, तो चर और उनके संबंधित मूल्य एक दूसरे के लिए मैप कैसे किए जाते हैं (यानी, .bs / .data और .text / .rodata सेगमेंट के बीच)?
सूजू टी वर्गीज

@SojuTVarghese नहीं, .dataआम तौर पर फ्लैश में एक तथाकथित लोड पता होता है, जहां प्रारंभिक मान संग्रहीत किए जाते हैं, और रैम में एक तथाकथित आभासी पता (एक माइक्रोकंट्रोलर में वास्तव में आभासी नहीं) होता है, जहां निष्पादन के दौरान चर संग्रहित होता है। mainप्रारंभ करने से पहले प्रारंभिक मान लोड पते से वर्चुअल पते पर कॉपी किए जाते हैं। आपको शून्य स्टोर करने की आवश्यकता नहीं है, इसलिए .bssइसके प्रारंभिक मूल्यों को संग्रहीत करने की आवश्यकता नहीं है। sourceware.org/binutils/docs/ld/…
starblue

1

जबकि कोई भी डेटा प्रोग्रामर चुनता है किसी भी मेमोरी में जा सकता है, आम तौर पर सिस्टम सबसे अच्छा काम करता है (और इसका उपयोग करने का इरादा है) जहां डेटा का उपयोग प्रोफ़ाइल मेमोरी के रीड / राइट प्रोफाइल से मेल खाता है।

उदाहरण के लिए प्रोग्राम कोड WFRM (कुछ पढ़े लिखे कई) हैं, और इसमें बहुत कुछ है। यह फ्लेश अच्छी तरह से फिट बैठता है। ROM OTOH एक बार डब्ल्यू आरएम है।

ढेर और ढेर छोटे हैं, जिनमें बहुत सारे पढ़े और लिखे गए हैं। यह रैम सबसे अच्छा होगा।

EEPROM उन दोनों में से किसी का भी उपयोग नहीं करता है, लेकिन यह पावर-अप के पार लगातार डेटा की छोटी मात्रा के प्रोफाइल के अनुरूप है, इसलिए उपयोगकर्ता विशिष्ट आरंभिक डेटा, और शायद लॉगिंग परिणाम।

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