अगर मैं फ्लैश मेमोरी या SRAM से बाहर निकलता हूं तो मैं क्या कर सकता हूं?


28

Arduino प्रलेखन के अनुसार, ATmega328 में बूटलोडर + अपलोड स्केच के लिए 32KB फ्लैश मेमोरी है, और रनटाइम डेटा के लिए केवल 2KB SRAM है। ATmega2560 काफी अधिक है, कुल 256KB और 8KB क्रमशः।

या तो मामले में, वे सीमाएँ छोटी प्रतीत होती हैं, विशेषकर जब स्मार्टफोन जैसे उपभोक्ता उपकरणों के आकार की तुलना में।

अगर आप बाहर भागते हैं तो आप क्या कर सकते हैं? उदाहरण के लिए यदि आपका स्केच बहुत बड़ा है, या आपको रनटाइम पर बहुत अधिक डेटा (जैसे स्ट्रिंग्स) संसाधित करने की आवश्यकता है? क्या फ्लैश या SRAM का विस्तार करने का कोई तरीका है?


कुछ चर अनुकूलन का उपयोग करके देखें। कुछ अलग चर की चर्चा यहाँ की
TheDoctor

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

1
आप वास्तव में एक Teensy 3.2 (Teensyduino Software के साथ) का उपयोग कर सकते हैं, जो एक Arduino के साथ तुलना में होगा। यह देखते हुए कि आप RAM / PROGMEM से बाहर चल रहे हैं, इसका मतलब यह होगा कि आप यह भी संभावना रखते हैं कि आप जो करने की कोशिश कर रहे हैं, वह आपके Arduino को आगे बढ़ा रहा है। एक Teensy 3.2 इतना अधिक महंगा नहीं है। लेकिन है: 32 बिट, 72MHz (wtf !?) 256KB फ्लैश और 64KB रैम और 3x UART। ATmega2560 के रूप में अधिक प्रोग्राम मेमोरी नहीं है, लेकिन रैम और गति में वृद्धि पर्याप्त होनी चाहिए।
पॉल

जवाबों:


30


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

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

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

रनटाइम डेटा (SRAM) ऑप्टिमाइज़ेशन का उपयोग थोड़ा आसान हो जाता है जब आप इसका उपयोग करते हैं। शुरुआती प्रोग्रामर के लिए एक बहुत ही सामान्य नुकसान बहुत अधिक वैश्विक डेटा का उपयोग कर रहा है। वैश्विक दायरे में घोषित कुछ भी स्केच के पूरे जीवनकाल के लिए मौजूद रहेगा, और यह हमेशा आवश्यक नहीं है। यदि एक चर का उपयोग केवल एक फ़ंक्शन के अंदर किया जाता है, और इसे कॉल के बीच बने रहने की आवश्यकता नहीं है, तो इसे एक स्थानीय चर बनाएं। यदि मान को फ़ंक्शन के बीच साझा करने की आवश्यकता है, तो विचार करें कि क्या आप इसे वैश्विक बनाने के बजाय एक पैरामीटर के रूप में पास कर सकते हैं। इस तरह से आप केवल SRAM का उपयोग उन चरों के लिए करेंगे जब आपको वास्तव में इसकी आवश्यकता होगी।

SRAM उपयोग के लिए एक अन्य हत्यारा पाठ प्रसंस्करण है (जैसे Stringकक्षा का उपयोग करके )। आम तौर पर, यदि संभव हो तो आपको स्ट्रिंग संचालन करने से बचना चाहिए। वे बड़े पैमाने पर मेमोरी हॉग हैं। उदाहरण के लिए, यदि आप धारावाहिक के लिए बहुत सारे पाठ का उत्पादन कर रहे हैं, तो Serial.print()स्ट्रिंग संयोजन का उपयोग करने के बजाय कई कॉल का उपयोग करें। यदि संभव हो तो अपने कोड में स्ट्रिंग शाब्दिकों की संख्या को कम करने का प्रयास करें।

यदि संभव हो तो पुनरावृत्ति से बचें। हर बार एक पुनरावर्ती कॉल किया जाता है, यह स्टैक को एक गहरे स्तर पर ले जाता है। इसके बजाय पुनरावर्ती होने के लिए अपने पुनरावर्ती कार्यों को प्रतिबिंबित करें।


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

जाहिर है कि EEPROM आकार और गति में काफी सीमित है, और इसमें सीमित संख्या में लेखन चक्र हैं। यह डेटा सीमाओं का एक बड़ा समाधान नहीं है, लेकिन यह फ़्लैश या SRAM पर बोझ को कम करने के लिए पर्याप्त हो सकता है। एसडी कार्ड जैसे समान बाह्य भंडारण के साथ इंटरफेस करना भी काफी संभव है।

विस्तार
यदि आपने अन्य सभी विकल्पों को समाप्त कर दिया है, तो विस्तार एक संभावना हो सकती है। दुर्भाग्य से, प्रोग्राम स्पेस बढ़ाने के लिए फ्लैश मेमोरी का विस्तार करना संभव नहीं है। हालांकि, यह है SRAM विस्तार करने के लिए संभव। इसका मतलब है कि आप बढ़ते डेटा आकार की कीमत पर कोड के आकार को कम करने के लिए अपने स्केच को फिर से बनाने में सक्षम हो सकते हैं।

अधिक SRAM प्राप्त करना वास्तव में काफी सीधा है। एक विकल्प एक या एक से अधिक 23K256 चिप्स का उपयोग करना है। वे एसपीआई के माध्यम से एक्सेस किए जाते हैं, और आपको उनका उपयोग करने में मदद करने के लिए स्पिरम लाइब्रेरी है। बस सावधान रहना कि वे 3.3V पर नहीं 5V संचालित !

यदि आप मेगा का उपयोग कर रहे हैं, तो आप वैकल्पिक रूप से Lagrangian Point या बीहड़ सर्किट से SRAM विस्तार ढाल प्राप्त कर सकते हैं ।


1
आप प्रोग्राम मेमोरी में लगातार डेटा भी स्टोर कर सकते हैं, बल्कि SRAM, यदि आपके पास SRAM स्पेस इश्यू और फ्री प्रोग्राम मेमोरी है। यहाँ या यहाँ
कॉनर वुल्फ

1
EEPROM का एक और बढ़िया विकल्प एसडी कार्ड है। यह कुछ IO पोर्ट लेता है, लेकिन यदि आपको मैप डेटा या इसी तरह के स्थान के लिए एक बड़े हिस्से की आवश्यकता है, तो पीसी पर कस्टम प्रोग्राम के साथ स्वैप करना और संपादित करना आसान हो सकता है।
बेनामी पेंगुइन

1
लोगों को SPI SRAM या RAM विस्तार का उपयोग करने के लिए प्रोत्साहित नहीं किया जाना चाहिए, अगर वे स्मृति पर कम चल रहे हैं। वह सिर्फ पैसे की बर्बादी है। एक बड़ा MCU चुनना सस्ता होगा। इसके अलावा, प्रदर्शन बहुत खराब हो सकता है। पहले एक बॉलपार्क का अनुमान लगाना चाहिए: यदि अनुमानित रैम का उपयोग सीमा के बहुत करीब है, तो आप गलत बोर्ड / माइक्रोकंट्रोलर / डेवलपमेंट प्लेटफॉर्म चुन रहे हैं। यकीन है, अच्छा उपयोग (फ्लैश में तार संचय) और अनुकूलन (कुछ पुस्तकालयों का उपयोग करने से बचना) सही गेम चेंजर हो सकते हैं। हालाँकि इस बिंदु पर मुझे Arduino सॉफ़्टवेयर प्लेटफ़ॉर्म का उपयोग करने का कोई लाभ नहीं दिखता है।
अगली

24

जब आप अपने कोड को अपने Arduino पर अपलोड करते हैं, तो उदाहरण के लिए एक Uno कहें, यह आपको बताएगा कि उपलब्ध 32K में से कितने बाइट्स का उपयोग करता है। आपके पास कितनी फ़्लैश मेमोरी है (कंप्यूटर हार्ड डिस्क सोचो)। जब आपका प्रोग्राम चल रहा होता है, तो वह SRAM नामक व्हाट्स का उपयोग कर रहा होता है, और वहाँ बहुत कम उपलब्ध होता है।

कभी-कभी आप अपने कार्यक्रम को एक बिंदु पर अजीब तरह से व्यवहार करते हुए देखेंगे, जिसे आपने थोड़ी देर में भी नहीं छुआ है। यह हो सकता है कि आपके सबसे हालिया परिवर्तनों के कारण यह मेमोरी (SRAM) से बाहर चला जाए। यहाँ कुछ सुझाव दिए गए हैं कि कैसे कुछ एसआरएएम को मुक्त किया जाए।

SRAM के बजाय फ्लैश में तार संचय।

सबसे सामान्य चीजों में से एक मैंने देखा है कि चिप मेमोरी से बाहर चल रही है क्योंकि बहुत लंबे तार हैं।

F()तार का उपयोग करते समय फ़ंक्शन का उपयोग करें ताकि वे SRAM के बजाय फ्लैश में संग्रहीत हों, क्योंकि आपके पास बहुत अधिक उपलब्ध है।

Serial.println(F("This string will be stored in flash memory"));

सही डेटा प्रकारों का उपयोग करें

आप int(2 बाइट्स) से byte(1 बाइट) पर स्विच करके एक बाइट बचा सकते हैं । एक अहस्ताक्षरित बाइट आपको 0-255 देगा, यदि आपके पास संख्या है जो 255 से अधिक नहीं है, तो एक बाइट को बचाएं!

मुझे कैसे पता चलेगा कि मैं स्मृति से बाहर चल रहा हूं?

आमतौर पर आप अपने कार्यक्रम को अजीब तरह से व्यवहार करते हुए देखेंगे और आश्चर्य करेंगे कि क्या गलत हुआ ... आपने उस बिंदु के पास कोड में कुछ भी नहीं बदला जहां वह गड़बड़ कर रहा है, तो क्या देता है? यह स्मृति से बाहर चल रहा है।

आपके पास कितनी स्मृति उपलब्ध है, यह बताने के लिए कुछ फ़ंक्शन हैं।

उपलब्ध स्मृति


क्या आप जानते हैं कि F()बात एक Arduino विशिष्ट कार्य है या यह AVR पुस्तकालयों में है? आप उल्लेख करने पर PROGMEM const ...भी विचार कर सकते हैं।
जिप्पी

इसके अलावा, यदि आप बहुत सारे बूलियन से निपटते हैं तो आप अपने चर 5eg द्वारा उपयोग की जाने वाली जगह को कम करने के लिए बिट संरचनाओं का उपयोग कर सकते हैं)।
jfpoilpret

17

दूसरों ने जो कहा है (जिस पर मैं पूरी तरह सहमत हूं) के अलावा, मैं स्मृति के बारे में इस प्रवेश पत्र लेख को पढ़ने की सलाह दूंगा ; यह अच्छी तरह से लिखा गया है, स्मृति के बारे में बहुत सी बातें बताता है और इसे कैसे अनुकूलित किया जाए, इस पर संकेत प्रदान करता है।

पढ़ने के अंत में, मुझे लगता है कि आपको अपने प्रश्न का पूरा जवाब मिलेगा।

इसे योग करने के लिए, आपके पास 2 संभावित अनुकूलन लक्ष्य हैं (यह निर्भर करता है कि आप स्मृति समस्याएं कहां स्थित हैं):

  • फ्लैश (यानी प्रोग्राम मेमोरी); इसके लिए, आप कर सकते हैं:
    • मृत कोड को हटा दें (उदाहरण के लिए कोई भी कोड जो शामिल है लेकिन उपयोग नहीं किया गया है) और अप्रयुक्त चर (वह भी SRAM के साथ मदद करता है)
    • डुप्लिकेट कोड बाहर कारक
    • बूटलोडर को पूरी तरह से हटा दें (आप एक UNO के लिए 0.5K और अन्य Arduino मॉडल के लिए 2 या 4K के बीच प्राप्त कर सकते हैं); हालांकि यह कुछ डाउनसाइड है
  • SRAM (यानी ढेर, ढेर और स्थिर डेटा); इसके लिए आप कर सकते हैं:
    • अप्रयुक्त चर निकालें
    • प्रत्येक चर के आकार का अनुकूलन करें (जैसे कि लंबे -4 बाइट्स का उपयोग न करें- यदि आपको केवल इंट -2 बाइट्स की आवश्यकता है)
    • अपने चरों के लिए सही स्कोप का उपयोग करें (और जब संभव हो स्टैटिक डेटा को स्टैक पसंद करें)
    • सख्त न्यूनतम करने के लिए बफ़र्स का आकार कम करें
    • PROGMEM के लिए निरंतर डेटा ले जाएँ (अर्थात आपका स्टैटिक डेटा फ़्लैश मेमोरी में रहेगा और प्रोग्राम प्रारंभ में SRAM में कॉपी नहीं किया जाएगा); यह भी निरंतर स्ट्रिंग्स पर लागू होता है जिसके लिए आप F()मैक्रो का उपयोग कर सकते हैं )
    • गतिशील आवंटन से बचें अगर यह बिल्कुल आवश्यक नहीं है; आप एक खंडित ढेर से बचेंगे, जो स्मृति मुक्त होने के बाद भी सिकुड़ नहीं सकता है

SRAM उपयोग को कम करने के लिए एक अतिरिक्त दृष्टिकोण का भी वर्णन किया गया है (लेकिन शायद ही कभी इस्तेमाल किया जाता है, क्योंकि यह कोडिंग करते समय बहुत भारी होता है और बहुत कुशल नहीं होता है), इसमें आपके प्रोग्राम द्वारा निर्मित डेटा को संग्रहीत करने के लिए EEPROM का उपयोग होता है, लेकिन बाद में जब तक कुछ शर्तों का उपयोग नहीं किया जाता है तब होता है, जब डेटा को EEPROM से वापस लोड किया जा सकता है।


1
मृत कोड को हटा देना - कंपाइलर आपके लिए इसे संभालने के बारे में वास्तव में अच्छा है- अगर आपके पास बहुत सारे कोड हैं तो इससे कोई फर्क नहीं पड़ेगा। यदि आपको गलती से कोड की आवश्यकता होती है, तो आप निश्चित रूप से अलग हैं।
डेटशीट

9

यदि आप भंडारण से बाहर हैं, तो दो चीजें हैं:

  • किसी तरह अपने कोड को "अनुकूलित" करें ताकि इसे कम भंडारण की आवश्यकता हो; या कम से कम उस विशेष प्रकार के स्टोरेज का कम उपयोग करता है जिसे आप (और अभी भी आपके पास बहुत सारे स्टोरेज का उपयोग करते हैं)। या,
  • अधिक संग्रहण जोड़ें।

ऑनलाइन करने के लिए बहुत सारी युक्तियां हैं (पहले लोगों के लिए और अरुदीनो के साथ लोगों की बहुत सारी चीजों के लिए, निर्माण-भंडारण "अनुकूलन" के बाद पर्याप्त से अधिक है)। तो मैं दूसरे पर ध्यान केंद्रित करूंगा:

3 चीजें हैं जो फ्लैश या एसआरएएम का उपयोग करती हैं; भंडारण को जोड़ने के लिए हर एक को थोड़ा अलग दृष्टिकोण की आवश्यकता होती है:

  • परिवर्तनशील भंडारण: SRAM का विस्तार करना संभव है, क्योंकि सैचलेन पहले ही इंगित कर चुका है। SRAM, FRAM और NVSRAM सभी तेजी से बदलते चर के लिए उपयुक्त हैं। (जबकि सिद्धांत रूप में आप फ्लैश को वेरिएबल स्टोर करने के लिए उपयोग कर सकते हैं, तो आपको फ्लैश वियर-आउट की चिंता करनी होगी)। एसपीआई (एक सीरियल प्रोटोकॉल) Arduino से कनेक्ट करने के लिए सबसे आसान है। SpiRAM पुस्तकालय माइक्रोचिप के साथ काम करता 23K256 धारावाहिक SRAM चिप। Ramtron FM25W256 सीरियल FRAM चिप (अब सरू के स्वामित्व में) भी SPI का उपयोग करता है। सरू CY14B101 NVSRAM भी SPI का उपयोग करता है। आदि।

  • लगातार डेटा जो अभी भी होने की जरूरत है अगली बार बिजली आती है: यह लगभग SRAM के विस्तार के रूप में सरल है। कई बाहरी EEPROM, FRAM, NVSRAM और FLASH स्टोरेज डिवाइस उपलब्ध हैं। वर्तमान में प्रति एमबी सबसे कम लागत एसडी फ्लैश कार्ड है (जो एसपीआई के माध्यम से एक्सेस किया जा सकता है)। रैमट्रॉन FM25W256 (ऊपर देखें), सरू CY14B101 (ऊपर देखें), आदि भी लगातार डेटा स्टोर कर सकते हैं। कई विस्तार शील्ड में एक एसडी कार्ड स्लॉट और कई लाइब्रेरी और ट्यूटोरियल एसडी कार्ड को पढ़ने और लिखने का समर्थन करते हैं। (हम इसके लिए SRAM का उपयोग नहीं कर सकते हैं, क्योंकि SRAM सब कुछ भूल जाता है जब बिजली चली जाती है)।

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

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