एक माइक्रोकंट्रोलर की EEPROM पर लेवलिंग पहनें


15

उदाहरण के लिए: ATtiny2313 के लिए डेटाशीट (जैसा कि अधिकांश Atmel AVR डेटाशीट करते हैं) कहता है:

128 बाइट्स इन-सिस्टम प्रोग्रामेबल EEPROM धीरज: 100,000 लिखें / मिटाएँ चक्र

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

जब आप प्रभावी रूप से उपलब्ध 128 में से केवल एक या दो बाइट्स का उपयोग करते हैं, तो माइक्रोकंट्रोलर के EEPROM पर लेवलिंग करने का एक स्मार्ट तरीका है?


1
यदि 100k लिखने के चक्र एक बाधा थे, तो क्या इसके बजाय कुछ अन्य तकनीक का उपयोग करना समझ में आता है? या तो एक तंत्र जो आंतरिक रूप से समतल करना शामिल है, या परिमाण के आदेश के साथ कुछ या अधिक धीरज?
अंडो घोष

1
@AnindoGhosh मैं सिर्फ अपने कॉन्सेप्ट के प्रमाण के कारण EEPROM बाहर पहनने के कारण माइक्रोकंट्रोलर्स के अपने छोटे स्टॉक को बर्बाद नहीं करना चाहता। मैं चिंता नहीं करना चाहता कि किस बाइट का उपयोग मैं पिछले प्रोजेक्ट पर कर रहा हूं जब नियंत्रक का पुन: उपयोग कर रहा हो। और यह जानना अच्छा लगता है कि मैं हार्डवेयर का इष्टतम उपयोग उपलब्ध करवाता हूं।
जिप्पी

3
यह मदद कर सकता है: AVR101: उच्च धीरज EEPROM भंडारण
m.Alin

1
हो सकता है कि में मेरा उत्तर पर एक नजर है stackoverflow
जिम्मी

TI की MSP430 FRAM श्रृंखला पर एक नजर ... 10 ^ 13 लिखते हैं !!!
जियोमेट्रिकल

जवाबों:


19

आमतौर पर मैं जिस तकनीक का उपयोग करता हूं वह 4-बाइट रोलिंग अनुक्रम संख्या के साथ डेटा को उपसर्ग करना है जहां सबसे बड़ी संख्या सबसे नवीनतम / वर्तमान मूल्य का प्रतिनिधित्व करती है। वास्तविक डेटा के 2 बाइट्स को संग्रहीत करने के मामले में, जो 6 बाइट्स कुल देगा और फिर मैं EEPROM के 128 बाइट्स के लिए एक परिपत्र कतार व्यवस्था बनाता हूं, इसमें 21 प्रविष्टियां होंगी और धीरज को 21 गुना बढ़ाएगा।

फिर जब सबसे बड़ी अनुक्रम संख्या को बूट किया जा सकता है, तो उपयोग की जाने वाली अगली अनुक्रम संख्या और कतार की वर्तमान पूंछ दोनों को निर्धारित करने के लिए। निम्न C छद्म कोड प्रदर्शित करता है, यह मानता है कि प्रारंभिक प्रोग्रामिंग पर EEPROM क्षेत्र 0xFF के मानों को मिटा दिया गया है, इसलिए मैं 0xFFFF के अनुक्रम संख्या की उपेक्षा करता हूं:

struct
{
  uint32_t sequence_no;
  uint16_t my_data;
} QUEUE_ENTRY;

#define EEPROM_SIZE 128
#define QUEUE_ENTRIES (EEPROM_SIZE / sizeof(QUEUE_ENTRY))

uint32_t last_sequence_no;
uint8_t queue_tail;
uint16_t current_value;

// Called at startup
void load_queue()
{
  int i;

  last_sequence_no = 0;
  queue_tail = 0;
  current_value = 0;
  for (i=0; i < QUEUE_ENTRIES; i++)
  {
    // Following assumes you've written a function where the parameters
    // are address, pointer to data, bytes to read
    read_EEPROM(i * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
    if ((QUEUE_ENTRY.sequence_no > last_sequence_no) && (QUEUE_ENTRY.sequence_no != 0xFFFF))
    {
      queue_tail = i;
      last_sequence_no = QUEUE_ENTRY.sequence_no;
      current_value = QUEUE_ENTRY.my_data;
    }
  }
}

void write_value(uint16_t v)
{
  queue_tail++;
  if (queue_tail >= QUEUE_ENTRIES)
    queue_tail = 0;
  last_sequence_no++;
  QUEUE_ENTRY.sequence_no = last_sequence_no;
  QUEUE_ENTRY.my_data = v;
  // Following assumes you've written a function where the parameters
  // are address, pointer to data, bytes to write
  write_EEPROM(queue_tail * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
  current_value = v;
}

एक छोटे EEPROM के लिए एक 3-बाइट अनुक्रम अधिक कुशल होगा, हालांकि मानक डेटा प्रकारों का उपयोग करने के बजाय थोड़ा सा टुकड़ा करने की आवश्यकता होगी।


+1, अच्छा तरीका। क्या कम "टैग" बाइट्स का उपयोग करके भंडारण को थोड़ा अनुकूलित किया जा सकता है, और संभवतः अतिरिक्त वितरण प्रदान करने के लिए हैश बाल्टी तंत्र के कुछ रूप पर निर्भर करता है? कोई समतलन और आपके दृष्टिकोण के बीच एक संकर?
अंडो घोष

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

@ M.Alin द्वारा उल्लिखित Atmel एप्लिकेशन नोट में एक स्मार्ट सरलीकरण है: एक RESET के बाद [[]] बफर के माध्यम से देखने के लिए संभव है, अंतिम [...] बफर तत्व को खोजने के स्थान को खोजने के द्वारा बदल दिया गया जहां एक बफर तत्व और अगले बफर तत्व के बीच अंतर 1 से बड़ा है
जिप्पी

क्या लिखना नहीं चाहिए_वाल्यू () पंक्ति में प्रविष्टि को कतार में रखें * sizeof (QUEUE_ENTRY)? मैं पहली बार सही हो जाऊंगा, लेकिन क्या यह आगे बढ़ना जारी रखना चाहिए अगर एक से अधिक लेखन हो? मुझे load_queue () के बाहर वेतन वृद्धि नहीं दी गई है।
मार्शल इबैंक

2
@ DWORD32: हाँ, यह तकनीकी रूप से सही है, लेकिन व्यवहार में अप्रासंगिक है। उस समय तक, EEPROM पर पहनने की सीमा 2000 के एक कारक से अधिक हो गई होगी!
डेव ट्वीड

5

निम्नलिखित एक विधि है जो बाल्टी का उपयोग करती है और प्रति बाल्टी लगभग एक ओवरहेड बाइट का उपयोग करती है। बाल्टी बाइट्स और ओवरहेड बाइट्स पहनने के बारे में समान मात्रा में मिलते हैं। उदाहरण के लिए, 128 EEPROM बाइट्स दिए जाने पर यह विधि 42 2-बाइट बाल्टियाँ और 44 स्टेटस बाइट्स आवंटित करती है, जो पहनने की क्षमता को 42-गुना बढ़ाती है।

तरीका:

EEPROM पता स्थान को k बाल्टी में विभाजित करें , जहाँ k = / E / ( n +1) data, के साथ n = सेटअप-डेटा-सरणी आकार = बाल्टी आकार, और E = EEPROM आकार (या, आमतौर पर, EEPROM की संख्या) कोशिकाओं को इस डेटा संरचना के लिए समर्पित किया जाएगा)।

एक निर्देशिका आरंभ करें, m बाइट्स की एक सरणी जो कि m = En · k के साथ सभी k पर सेट होती है । अपने डिवाइस को प्रारंभ करते हैं, यह निर्देशिका के माध्यम से पढ़ता है जब तक यह वर्तमान प्रविष्टि है, जो एक बाइट नहीं के बराबर है पाता k । [यदि सभी निर्देशिका प्रविष्टियाँ समान k हैं , तो पहली निर्देशिका प्रविष्टि को 0 से प्रारंभ करें, और वहाँ से जाएँ।]

जब वर्तमान निर्देशिका प्रविष्टि में j होता है , तो बाल्टी j में वर्तमान डेटा होता है। जब आपको एक नया सेटअप-डेटा प्रविष्टि लिखने की आवश्यकता होती है, तो आप वर्तमान निर्देशिका प्रविष्टि में j +1 स्टोर करते हैं; यदि वह इसे k के बराबर बनाता है , तो अगली निर्देशिका प्रविष्टि को 0 से प्रारंभ करें, और वहां से चलें।

नोट बाल्टी के रूप में बाइट्स क्योंकि 2 · कि निर्देशिका बाइट्स पहनने की एक ही राशि के बारे में मिल कश्मीर > मीटरकश्मीर

(मैंने अपने उत्तर से Arduino SE सवाल 34189 , EEPROM के जीवन को कैसे बढ़ाया जाए? ) को अनुकूलित किया ।


2

मैंने इसके लिए एक रोलिंग अनुक्रम संख्या का उपयोग किया है (पीटर के उत्तर के समान)। अनुक्रम संख्या वास्तव में 1 बिट जितनी हो सकती है, क्यू में तत्वों की संख्या विषम है। सिर और पूंछ को फिर 2 लगातार 1 या 0 के द्वारा चिह्नित किया जाता है

उदाहरण के लिए यदि 5 तत्वों के माध्यम से रोल करना चाहते हैं तो क्रम संख्याएँ होंगी:

{01010} (0 पर लिखें) {11010} (1 को लिखें) {10010} (2 को लिखें) {10110} (3 को लिखें) {10100} (4 को लिखें) {10101} (5 को लिखें)


1

आपके पास जिस तरह के EEPROM हैं और आपके डेटा का आकार है, उसके आधार पर कुछ विकल्प हैं।

  1. यदि आपके EEPROM में व्यक्तिगत रूप से मिटने योग्य पृष्ठ हैं और आप 1 पृष्ठ (या अधिक) का उपयोग करते हैं, तो बस उपयोग में आने वाले को छोड़कर सभी पृष्ठों को मिटा दें और पृष्ठों को एक गोलाकार तरीके से पुन: उपयोग करें।

  2. यदि आप केवल उस पृष्ठ के एक अंश का उपयोग करते हैं जिसे एक बार में मिटाना है, तो उस पृष्ठ को डेटा प्रविष्टियों में विभाजित करें। हर बार लिखते समय एक साफ प्रविष्टि का उपयोग करें, और एक बार जब आप स्वच्छ प्रविष्टियों से बाहर निकलते हैं, तो उसे मिटा दें।

यदि आवश्यक हो तो स्वच्छ और गंदी प्रविष्टियों के बीच बताने के लिए "गंदे" बिट का उपयोग करें (आमतौर पर, आपके पास कम से कम एक बाइट है जो 0xFF से अलग होने की गारंटी है, जिसका उपयोग गंदे प्रविष्टियों को ट्रैक करने के लिए किया जा सकता है)।

यदि आपकी EEPROM लाइब्रेरी इरेज़ फ़ंक्शन (जैसे Arduino) को उजागर नहीं करती है, तो यहाँ एल्गोरिथम # 2 के लिए एक साफ चाल है : चूंकि आपकी पहली EEPROM प्रविष्टि हमेशा उपयोग की जाती है, आप इसे पढ़कर "गंदे" बिट का मान निर्धारित कर सकते हैं। एक बार जब आप स्वच्छ प्रविष्टियों से बाहर निकल जाते हैं, तो आप पहले प्रविष्टि से फिर से शुरू करते हैं, "गंदे" बिट को निष्क्रिय करते हैं, और आपकी बाकी प्रविष्टियाँ स्वतः "स्वच्छ" के रूप में चिह्नित हो जाती हैं।

अनुक्रम संख्या और कैटलॉग अंतरिक्ष की बर्बादी है जब तक कि आप खराब पृष्ठों को ट्रैक करने या अपने EEP डेटा के विभिन्न भागों को स्वतंत्र रूप से अपडेट करने में सक्षम नहीं होना चाहते।

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