স্কেচগুলি কেন এত জায়গা এবং স্মৃতি গ্রহণ করে?


12

আমি যখন এই স্কেচটি ইউনের জন্য সংকলন করব:

int led = 7;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);
}

আমি পাই:

স্কেচ প্রোগ্রাম স্টোরেজ স্পেসের 5,098 বাইট (17%) ব্যবহার করে।

সর্বোচ্চ 28,672 বাইট। গ্লোবাল ভেরিয়েবলগুলি 153 বাইট (5%) গতিশীল মেমরি ব্যবহার করে, স্থানীয় ভেরিয়েবলের জন্য 2,407 বাইট রেখে। সর্বোচ্চ 2,560 বাইট।

এমনকি আমি যখন বেয়ারিমিনিমাম স্কেচটি সংকলন করি:

void setup() {                
  // setup    
}

void loop() {
  // loop
}

আমি পাই:

স্কেচ প্রোগ্রাম স্টোরেজ স্পেসের 4,548 বাইট (15%) ব্যবহার করে।

সর্বোচ্চ 28,672 বাইট। গ্লোবাল ভেরিয়েবলগুলি ডায়ামিক মেমোরির 151 বাইট (5%) ব্যবহার করে, স্থানীয় ভেরিয়েবলের জন্য 2,409 বাইট রেখে। সর্বোচ্চ 2,560 বাইট।

একটি খালি ন্যূনতম স্কেচ কেন বরাদ্দ হওয়া প্রোগ্রামের স্টোরেজ স্পেসের 15% নেয়? এবং কেন খুব সাধারণ স্কেচ প্রোগ্রামের স্টোরেজ স্পেসের 17% নেয়? আরডুইনো ওয়েবসাইট অনুসারে :

আপনার প্রোগ্রামে প্রচুর স্ট্রিং থাকার মাধ্যমে এগুলি ব্যবহার করা সহজ। উদাহরণস্বরূপ, একটি ঘোষণার মতো: char message[] = "I support the Cape Wind project.";এসআরএমে 33 বাইট রাখে (প্রতিটি অক্ষর একটি বাইট নেয়, আরও '\ 0' টার্মিনেটর)।

যাইহোক, এই স্কেচগুলির কোনওটিতে কোনও স্ট্রিং ঘোষিত হয়নি।

দেখে মনে হচ্ছে তারা আমদানি করতে পারে বা আমি উল্লেখ না করে এমন অন্যান্য গ্রন্থাগার / শ্রেণি ব্যবহার করতে পারে। সম্ভবত এটি একটি সিস্টেম ডিফল্ট লাইব্রেরি আমদানি করে? নাকি এটা অন্য কিছু?

উত্তর:


6

ইউইউএন একটি কম্বো। পার্ট আরডুইনো এবং পার্ট ওপেনডাব্লুআরটি (লিনাক্স)। আপনার প্রশ্নটি আরডিনো সম্পর্কিত reference যেখানে এটি আসলে লিওনার্দোর মতো একটি এটিমেগ 32u4 এবং কোনও ইউএনও নয় (এটিমেগ 328 পি)। 32u4 (লিও) ভার্চুয়াল সিরিয়াল পোর্টগুলির মাধ্যমে ইউএসবি মাধ্যমে যোগাযোগ করে (সংক্ষিপ্ত উত্তর: এটি সমর্থন করা প্রয়োজন) , যেখানে ইউএনওর একটি সত্যিকারের সিরিয়াল পোর্ট (ওরফে ইউআরটি) রয়েছে। নীচে এভিআর প্রসেসরগুলির জন্য বিভিন্ন বোর্ডের ধরণের পরিসংখ্যান তৈরি করা হয়।

ইউএনও-তে লক্ষ্য করুন একটি বাহ্যিক চিপ রয়েছে যা ইউএসবিটিকে সিরিয়াল পোর্টের ডিটিআর পিনে রূপান্তর করে যা এটি বুটলোডারের সাথে রিবুটের কারণে সংযুক্ত হওয়ার সময় এটিমেগ 328 এর রিসেট পিনটি টগল করে। বিপরীতে লিও / ইউনের ইউএসবি থেকে সিরিয়াল 32u4 এর ফার্মওয়্যারটিতে প্রয়োগ করা হয়েছে। অতএব দূরবর্তীভাবে রিও বুট করার জন্য লিও বা ইউইন এর 32u4 চিপটি লোড করা ফার্মওয়্যারটি সর্বদা ইউএসবি ক্লায়েন্টের সাইড ড্রাইভারকে সমর্থন করে। যা প্রায় 4K খরচ করে।

ইউএনওতে যদি ইউআরএস-এর প্রয়োজন ছিল না এবং বেয়ারমিনিয়াম.ইনোর ক্ষেত্রে অন্য কোনও গ্রন্থাগার সংস্থান না বলা হয়েছিল, মূল আরডুইনো লাইব্রেরির জন্য প্রায় 466 বাইট প্রয়োজন।

একটি ইউএনওতে বেয়ারিমিনিমিম.ইনো এর পরিসংখ্যান সংকলন করুন (এটিমেগ 328 পি)

Sketch uses 466 bytes (1%) of program storage space. Maximum is 32,256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2,039 bytes for local variables. Maximum is 2,048 bytes.

একটি লিওনার্দোতে বেটিমিনিমিম.ইনো এর পরিসংখ্যান সংকলন করুন (এটিমেগা 32u4)

Sketch uses 4,554 bytes (15%) of program storage space. Maximum is 28,672 bytes.
Global variables use 151 bytes (5%) of dynamic memory, leaving 2,409 bytes for local variables. Maximum is 2,560 bytes.

ইউন (এটিমেগা 32 ইউ 4) এর BareMinimum.ino এর পরিসংখ্যান সংকলন করুন

Sketch uses 4,548 bytes (15%) of program storage space. Maximum is 28,672 bytes.
Global variables use 151 bytes (5%) of dynamic memory, leaving 2,409 bytes for local variables. Maximum is 2,560 bytes.

7

আরডুইনো প্রচুর স্ট্যান্ডার্ড লাইব্রেরি, বিঘ্ন ইত্যাদিতে সংকলন করে ... উদাহরণস্বরূপ, পিনমোড এবং ডিজিটাল রাইটিং ফাংশনগুলি রান টাইমে জিপিআইওতে ডেটা লেখার জন্য নিবন্ধভুক্ত করার জন্য একটি অনুসন্ধান সারণী ব্যবহার করে। আর একটি উদাহরণ হ'ল আরডুইনো সময়ের ট্র্যাক রাখে, এটি ডিফল্টরূপে কিছু বিঘ্ন সংজ্ঞা দেয় এবং এই সমস্ত কার্যকারিতাটিতে কিছু জায়গা প্রয়োজন। আপনি লক্ষ্য করবেন যে আপনি যদি প্রোগ্রামটি প্রসারিত করেন তবে পাদদেশের মুদ্রণটি কিছুটা পরিবর্তিত হবে।

আমি ব্যক্তিগতভাবে "ব্লাট" ছাড়াই ন্যূনতম ন্যূনতম প্রোগ্রামগুলি নিয়ন্ত্রণ করতে পছন্দ করি তবে আপনি খুব দ্রুত EE.SE এবং SO বিশ্বে প্রবেশ করবেন কারণ বেশ কয়েকটি সহজ ফাংশন ব্যবহার করা বাক্সটির বাইরে চলে না। পিনমোড এবং ডিজিটাল রাইটের জন্য কিছু বিকল্প লাইব্রেরি রয়েছে যা একটি ছোট পায়ের ছাপে সংকলন করে, তবে অন্যান্য অসুবিধাগুলি নিয়ে আসে যেমন উদাহরণস্বরূপ স্ট্যাটিক সংকলিত পিনগুলি (যেখানে ledকোনও চলক হতে পারে না তবে ধ্রুবক হয়)।


সুতরাং মূলত এটি আপনি জিজ্ঞাসা না করে স্ট্যান্ডার্ড লাইব্রেরি সব ধরণের মধ্যে সংকলন? ঝরঝরে।
hichris123

হ্যাঁ, আমি সাধারণত এটিকে "ফোলা" বলে থাকি তবে এটি সত্যই একটি ব্যবহারযোগ্য জিনিস। আরডুইনো হ'ল নিম্ন প্রবেশ স্তর পরিবেশ যা কেবলমাত্র খুব বেশি চিন্তাভাবনা না করেই কাজ করে। আপনার যদি আরও প্রয়োজন হয়, আরডুইনো আপনাকে বিকল্প লাইব্রেরি ব্যবহার করতে দেয় বা আপনি খালি ধাতব বিরুদ্ধে সংকলন করতে পারেন। শেষটি সম্ভবত আরডিনো.এসইর বাইরে নেই
জিপ্পি

আমার @ এমপিফ্লাগ উত্তরটি দেখুন। তেমন ফুসকুড়ি নেই। বা কমপক্ষে মূল ন্যূনতম কার্যকারিতার জন্য লাইব্রেরিতে। স্কেচ না বলা পর্যন্ত কোনও স্ট্যান্ডার্ড লাইব্রেরি অন্তর্ভুক্ত নেই। বরং 15% হ'ল 32u4 এর ইউএসবি সাপোর্টের কারণে।
এমপিফ্লাগা

4

আপনার ইতিমধ্যে কিছু পুরোপুরি ভাল উত্তর রয়েছে। আমি কেবল কিছু পরিসংখ্যান শেয়ার করার জন্য এটি পোস্ট করছি আমি একদিন নিজেকে একই ধরণের প্রশ্ন জিজ্ঞাসা করেছি: একটি ন্যূনতম স্কেচে এত স্থান কী নিচ্ছে? একই কার্যকারিতা অর্জনের জন্য ন্যূনতম কী প্রয়োজন?

নীচে একটি ন্যূনতম ব্লিঙ্কি প্রোগ্রামের তিনটি সংস্করণ রয়েছে যা প্রতি সেকেন্ডে 13 টি পিনে এলইডি টগল করে। সমস্ত তিনটি সংস্করণ একটি ইউনোর জন্য সংযুক্ত করা হয়েছে (কোনও ইউএসবি জড়িত নেই) avr-gcc 4.8.2, avr-libc 1.8.0 এবং arduino-core 1.0.5 (আমি আরডুইনো আইডিই ব্যবহার করি না) ব্যবহার করে।

প্রথমত, স্ট্যান্ডার্ড আরডুইনো উপায়:

const uint8_t ledPin = 13;

void setup() {
    pinMode(ledPin, OUTPUT);
}

void loop() {
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
    delay(1000);
}

এটি 1018 বাইটে সংকলন করে। উভয় avr-nmএবং অপ্রয়োজনীয় ব্যবহার করে , আমি সেই আকারটি পৃথক ফাংশনে বিভক্ত করেছিলাম। বৃহত্তম থেকে ক্ষুদ্রতম পর্যন্ত:

 148 A ISR(TIMER0_OVF_vect)
 118 A init
 114 A pinMode
 108 A digitalWrite
 104 C vector table
  82 A turnOffPWM
  76 A delay
  70 A micros
  40 U loop
  26 A main
  20 A digital_pin_to_timer_PGM
  20 A digital_pin_to_port_PGM
  20 A digital_pin_to_bit_mask_PGM
  16 C __do_clear_bss
  12 C __init
  10 A port_to_output_PGM
  10 A port_to_mode_PGM
   8 U setup
   8 C .init9 (call main, jmp exit)
   4 C __bad_interrupt
   4 C _exit
-----------------------------------
1018   TOTAL

উপরের তালিকায়, প্রথম কলামটি বাইটের আকার এবং দ্বিতীয় কলামটি জানিয়েছে যে কোডটি আড়ডিনো কোর লাইব্রেরি (এ, 822 বাইট মোট), সি রানটাইম (সি, 148 বাইট) বা ব্যবহারকারী (ইউ) থেকে এসেছে কিনা , 48 বাইট)।

এই তালিকায় দেখা যাবে, বৃহত্তম ফাংশনটি হল টাইমার 0 ওভারফ্লো বিঘ্নিতভাবে পরিবেশন করা রুটিন। এই রুটিন ট্র্যাকিং সময় দায়ী, এবং প্রয়োজন হয় millis(), micros()এবং delay()। দ্বিতীয় বৃহত্তম ফাংশনটি হ'ল init(), যা পিডব্লিউএম এর জন্য হার্ডওয়্যার টাইমার নির্ধারণ করে, TIMER0_OVF বিঘ্নকে সক্ষম করে এবং ইউএসআর্টকে সংযোগ বিচ্ছিন্ন করে (এটি বুটলোডার দ্বারা ব্যবহৃত হয়েছিল)। এটি এবং পূর্ববর্তী উভয় ফাংশনই সংজ্ঞায়িত করা হয়েছে <Arduino directory>/hardware/arduino/cores/arduino/wiring.c

এরপরে সি + অ্যাভার-লিবিসি সংস্করণটি রয়েছে:

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= _BV(PB5);     /* set pin PB5 as output */
    for (;;) {
        PINB = _BV(PB5);  /* toggle PB5 */
        _delay_ms(1000);
    }
}

পৃথক আকারের ব্রেক-ডাউন:

104 C vector table
 26 U main
 12 C __init
  8 C .init9 (call main, jmp exit)
  4 C __bad_interrupt
  4 C _exit
----------------------------------
158   TOTAL

এটি অন্তর্নিহিত ফাংশন সহ সি রানটাইমের জন্য 132 বাইট এবং ব্যবহারকারী কোডের 26 বাইট _delay_ms()

এটি লক্ষ করা যেতে পারে যেহেতু এই প্রোগ্রামটি বিঘ্ন ব্যবহার করে না, তাই বাধা ভেক্টর টেবিলের প্রয়োজন নেই এবং নিয়মিত ব্যবহারকারী কোডটি তার জায়গায় স্থাপন করা যেতে পারে। নিম্নলিখিত সমাবেশ সংস্করণ ঠিক যে কাজ করে:

#include <avr/io.h>
#define io(reg) _SFR_IO_ADDR(reg)

    sbi io(DDRB), 5  ; set PB5 as output
loop:
    sbi io(PINB), 5  ; toggle PB5
    ldi r26, 49      ; delay for 49 * 2^16 * 5 cycles
delay:
    sbiw r24, 1
    sbci r26, 0
    brne delay
    rjmp loop

এটি avr-gcc -nostdlibকেবল 14 বাইটে একত্রিত হয় (এর সাথে ) বেশিরভাগটি টগলগুলি বিলম্ব করতে ব্যবহৃত হয় যাতে পলক দৃশ্যমান হয়। আপনি যদি এই বিলম্বের লুপটি সরিয়ে ফেলেন তবে আপনি একটি 6-বাইট প্রোগ্রাম শেষ করবেন যা দেখতে খুব দ্রুত জ্বলজ্বল করে (2 মেগাহার্টজ এ):

    sbi io(DDRB), 5  ; set PB5 as output
loop:
    sbi io(PINB), 5  ; toggle PB5
    rjmp loop

3

আমি একটি পোস্ট লিখেছিলাম কেন একটি এলইডি জ্বলতে 1000 বাইট লাগে?

সংক্ষিপ্ত উত্তরটি হল: " দুটি এলইডি জ্বলতে 2000 বাইট লাগে না !"

দীর্ঘ উত্তরটি হ'ল স্ট্যান্ডার্ড আরডিনো লাইব্রেরিগুলিতে (যা আপনি চান না তবে আপনাকে ব্যবহার করতে হবে না) আপনার জীবনকে সহজ করার জন্য কিছু সুন্দর কার্যকারিতা রয়েছে। উদাহরণস্বরূপ, আপনি রানটাইমের সময় পিনগুলি সংখ্যার মাধ্যমে সম্বোধন করতে পারেন, যেখানে গ্রন্থাগারটি পিন 8 টি সঠিক পোর্ট এবং সঠিক বিট সংখ্যায় রূপান্তর করে। আপনি যদি হার্ড-কোড পোর্ট অ্যাক্সেস করেন তবে আপনি সেই ওভারহেড সংরক্ষণ করতে পারেন।

এমনকি যদি আপনি সেগুলি ব্যবহার না করেন তবে স্ট্যান্ডার্ড লাইব্রেরিতে "টিক্স" গণনা করার কোড অন্তর্ভুক্ত থাকে যাতে আপনি বর্তমান "সময়" (কল করে millis()) জানতে পারেন। এটি করার জন্য এটি কিছু বিঘ্নিত পরিষেবার রুটিনগুলির ওভারহেড যুক্ত করতে হবে।

আপনি যদি এই স্কেচটিতে (আরডুইনো ইউনোতে) সরল করেন তবে আপনি প্রোগ্রামের মেমোরির ব্যবহার 178 বাইটে (আইডিই 1.0.0 এ) পেয়ে যাবেন:

int main ()
  {
  DDRB = bit (5);
  while (true)
    PINB = bit (5);
  }

ঠিক আছে, 178 বাইটটি তেমন কিছু নয় এবং এর মধ্যে প্রথম 104 বাইট হ'ল হার্ডওয়্যার বিঘ্নিত ভেক্টর (26 টি ভেক্টরের জন্য 4 বাইট প্রতিটি)।

সুতরাং যুক্তিযুক্তভাবে, একটি এলইডি জ্বলতে কেবল মাত্র 74 বাইট দরকার। এবং 74৪ বাইটের মধ্যে বেশিরভাগই বিশ্বব্যাপী স্মৃতিশক্তি আরম্ভ করার জন্য সংকলকটির দ্বারা উত্পন্ন কোড। আপনি যদি দুটি এলইডি জ্বলতে যথেষ্ট কোড যুক্ত করেন:

int main ()
  {
  DDRB = bit (5);  // pin 13
  DDRB |= bit (4);  // pin 12

  while (true)
    {
    PINB = bit (5); // pin 13
    PINB = bit (4); // pin 12
    }
  }

তারপরে কোডের আকার 186 বাইটে বেড়ে যায়। সুতরাং আপনি যুক্তি দিতে পারেন যে এটি 186 - 178 = 8একটি এলইডি পলক করতে কেবল বাইটস লাগে ।

সুতরাং, একটি এলইডি জ্বলতে 8 বাইট। আমার কাছে বেশ দক্ষ মনে হচ্ছে।


আপনি যদি ঘরে বসে এটি চেষ্টা করার জন্য প্রলুব্ধ হন তবে আমার এটি উল্লেখ করা উচিত যে উপরের পোস্ট কোডটি দুটি এলইডি জ্বলজ্বল করে, এটি সত্যিই খুব দ্রুত করে। প্রকৃতপক্ষে, তারা 2 মেগাহার্টজ এ ঝলক দেয় - স্ক্রিনশট দেখুন। চ্যানেল 1 (হলুদ) পিন 12, চ্যানেল 2 (সায়ান) পিন 13 হয়।

পিনের দ্রুত ঝলকানো 12 এবং 13

আপনি দেখতে পাচ্ছেন, আউটপুট পিনগুলিতে 2 মেগাহার্টজ এর ফ্রিকোয়েন্সি সহ বর্গাকার তরঙ্গ রয়েছে। কোডে পিন টগলিংয়ের ক্রমের কারণে পিন 13 পিন 12 এর আগে 62.5 এনএস (এক ঘড়ির চক্র) পরিবর্তন করে।

সুতরাং আপনি যদি আমার চেয়ে আরও ভাল চোখ না পান তবে আপনি আসলে কোনও ঝলকানো প্রভাব দেখতে পাবেন না।


একটি মজাদার অতিরিক্ত হিসাবে, আপনি আসলে একই পিনের টোগল করে একটি পিনের মতো প্রোগ্রামের জায়গাতে দুটি পিন টগল করতে পারেন ।

int main ()
  {
  DDRB = bit (4) | bit (5);  // set pins 12 and 13 to output

  while (true)
    PINB =  bit (4) | bit (5); // toggle pins 12 and 13
  } // end of main

এটি 178 বাইট মধ্যে সংকলন।

এটি আপনাকে উচ্চতর ফ্রিকোয়েন্সি দেয়:

পিনগুলি খুব দ্রুত জ্বলজ্বলে 12 এবং 13

এখন আমরা 2.66 মেগাহার্টজ পর্যন্ত আছি।


এটি অর্থে একটি টন করে তোলে। তাহলে স্ট্যান্ডার্ড লাইব্রেরিগুলি কি কেবল শিরোনামগুলি বিল্ড টাইমে স্বয়ংক্রিয়ভাবে অন্তর্ভুক্ত থাকে? এবং কিভাবে আপনি করতে সক্ষম হয়েছি না তাদের অন্তর্ভুক্ত?
hichris123

2
লিঙ্কার আক্রমণাত্মকভাবে কোডটি সরিয়ে দেয় যা ব্যবহৃত হয় না। কল না করে init()(যেমনটি সাধারণভাবে করা main()হয়) তারপরে ফাইলের তারিং.সি. (যা এতে রয়েছে init) লিঙ্ক করা হয়নি As ফলস্বরূপ, বাধা হ্যান্ডলারের (যেমন millis(), micros()ইত্যাদি) জন্য প্রক্রিয়া বাদ দেওয়া হয়েছিল। এটি বাদ দেওয়ার জন্য সম্ভবত এটি সম্ভবত ব্যবহারিক নয়, যদি না আপনার কখনই জিনিসগুলির সময় প্রয়োজন হয় না তবে সত্য যে স্কেচটি আপনি এটিতে রেখেছিলেন তার উপর নির্ভর করে আকার আকারে বৃদ্ধি পায়। উদাহরণস্বরূপ, আপনি যদি সিরিয়াল ব্যবহার করেন তবে প্রোগ্রাম মেমরি এবং র‌্যাম উভয়ই হিট নেয়।
নিক গ্যামন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.