Kysymys:
Miksi luonnokset vievät niin paljon tilaa ja muistia?
hichris123
2014-02-22 03:29:25 UTC
view on stackexchange narkive permalink

Kun käännän tämän luonnoksen Yúnille:

  int led = 7; void setup () {pinMode (led, OUTPUT); } void loop () {digitalWrite (led, HIGH);}  

Saan:

Sketch käyttää 5098 tavua (17%) ohjelman tallennustilaa .

Enimmäismäärä on 28 672 tavua. Globaalit muuttujat käyttävät 153 tavua (5%) dynaamista muistia, jolloin paikallisille muuttujille jää 2407 tavua. Enimmäismäärä on 2560 tavua.

Silloinkin kun käännän BareMinimum-luonnoksen:

  void setup () {// setup} void loop () {// loop}  

Saan:

Sketch käyttää 4548 tavua (15%) ohjelman tallennustilaa.

Enimmäismäärä on 28672 tavua . Globaalit muuttujat käyttävät 151 tavua (5%) dynaamista muistia, jolloin paikallisille muuttujille jää 2409 tavua. Enimmäismäärä on 2 560 tavua.

Miksi pelkkä minimiluonnos vie 15% osoitetusta tallennustilasta? Ja miksi hyvin yksinkertainen luonnos vie 17% ohjelman tallennustilasta? Arduino-verkkosivuston mukaan:

Kaikkea on helppo käyttää, jos ohjelmassa on paljon merkkijonoja. Esimerkiksi seuraava ilmoitus: char message [] = "Tuen Cape Wind -projektia."; lisää 33 tavua SRAM-muistiin (jokainen merkki vie tavun sekä terminaalin '\ 0').

Kummassakaan luonnoksessa ei kuitenkaan ole ilmoitettu merkkijonoja.

Näyttää siltä, ​​että he saattavat tuoda tai käyttää muita kirjastoja / luokkia, joita en pidä määritä. Ehkä se tuo järjestelmän oletuskirjaston? Vai onko se jotain muuta?

Neljä vastused:
#1
+7
jippie
2014-02-22 03:36:27 UTC
view on stackexchange narkive permalink

Arduino kääntää useita standardikirjastoja, keskeytyksiä jne. Esimerkiksi. PinMode- ja digitalWrite-toiminnot käyttävät hakutaulukkoa selvittääkseen ajon aikana, mihin GPIO-rekisteröinteihin kirjoitetaan tietoja. Toinen esimerkki on, että Arduino seuraa aikaa, se määrittää oletusarvoisesti keskeytykset ja kaikki tämä toiminto vaatii tilaa. Huomaat, että jos laajennat ohjelmaa, jalanjälki muuttuu vain vähän.

Henkilökohtaisesti haluan ohjelmoida ohjaimet vähimmäismäärällä, ilman "paisumista", mutta pääset nopeasti EE.SE ja SO, koska useat helppokäyttöiset toiminnot eivät enää toimi alusta alkaen. On olemassa joitain vaihtoehtoisia kirjastoja pinMode- ja digitalWrite-tiedostoille, jotka kootaan pienemmäksi, mutta joilla on muita haittoja, kuten esimerkiksi staattiset käännetyt nastat (joissa led ei voi olla muuttuja, mutta on vakio).

Joten pohjimmiltaan se kokoaa kaikenlaisissa vakiokirjastoissa kyselemättä? Siisti.
Kyllä, kutsun sitä yleensä "paisutukseksi", mutta se on todella käyttökelpoisuus. Arduino on matalan lähtötason ympäristö, joka toimii vain liikaa miettimättä. Jos tarvitset enemmän, Arduino antaa sinun käyttää vaihtoehtoisia kirjastoja tai voit kääntää paljasta metallia vastaan. Viimeinen on luultavasti Arduino.SE: n ulkopuolella
Katso @mpflaga-vastaukseni. Ei ole niin paljon turvotusta. Tai ainakin ydinkirjastossa vähimmäistoimintojen saamiseksi. Mukana ei ole oikeastaan ​​paljon standardikirjastoja, ellei niitä kutsuta luonnokseksi. Pikemminkin 15% johtuu 32u4: n USB-tuesta.
#2
+6
mpflaga
2014-02-22 11:58:43 UTC
view on stackexchange narkive permalink

YUN on yhdistelmä. Osa Arduino ja Osa OpenWRT (Linux). Kysymyksesi koskee Arduinoa. Missä tämä on tosiasiallisesti ATmega32u4, joka on samanlainen kuin Leonardo eikä UNO (ATmega328p). 32u4 (Leo) kommunikoi virtuaalisten sarjaporttien kautta USB: n kautta (lyhyt vastaus: tätä on tuettava) , jossa UNO: lla on todellinen sarjaportti (alias UART). Alla on rakennettu tilastotietoja AVR-suorittimien eri levytyypeistä.

Huomautus UNO: ssa on ulkoinen siru, joka muuntaa USB: n Serial-portin DTR-nastaksi, joka vaihtaa ATmega328: n palautustapin, kun se on kytketty aiheuttaen uudelleenkäynnistyksen käynnistyslataimeen. Sitä vastoin Leo / Yunin USB-sarja -sarja on toteutettu 32u4: n laiteohjelmistossa. Siksi Leo tai YUN: n 32u4-sirun uudelleenkäynnistämiseksi ladatun laiteohjelmiston on aina tuettava USB-asiakaspuolen ohjainta. Mikä kuluttaa noin 4K.

Jos USB: tä EI tarvinnut eikä muita kirjastoresursseja kutsuttu, kuten BareMinimum.ino: n tapauksessa UNO: lla, Arduino-ydinkirjastoon tarvitaan vain noin 466 tavua.

koota BareMinimum.inon tilastot UNO: lla (ATmega328p)

  Sketch käyttää 466 tavua (1%) ohjelman tallennustilaa. Enimmäismäärä on 32256 tavua. Globaalit muuttujat käyttävät 9 tavua (0%) dynaamista muistia, jättäen 2039 tavua paikallisille muuttujille. Enimmäismäärä on 2048 tavua.  

koota BareMinimum.inon tilastot Leonardon (ATmega32u4)

  Sketch -ohjelmassa käytetään 4554 tavua (15%) ohjelman tallennustilaa . Enimmäismäärä on 28 672 tavua. Globaalit muuttujat käyttävät 151 tavua (5%) dynaamista muistia, jolloin paikallisiin muuttujiin jää 2409 tavua. Enimmäismäärä on 2560 tavua.  

koota BareMinimum.inon tilastot Yunissa (ATmega32u4)

  Sketch käyttää 4548 tavua (15%) ohjelman tallennustilaa . Enimmäismäärä on 28 672 tavua. Globaalit muuttujat käyttävät 151 tavua (5%) dynaamista muistia, jolloin paikallisiin muuttujiin jää 2409 tavua. Enimmäismäärä on 2560 tavua.  
#3
+4
Edgar Bonet
2015-07-07 13:12:17 UTC
view on stackexchange narkive permalink

Sinulla on jo joitakin erinomaisia ​​vastauksia. Lähetän tämän vain jakamaan joitain tilastoja, jotka tein eräänä päivänä, kysyin itseltäni samanlaisia ​​kysymyksiä: Mikä vie niin paljon tilaa vähäisessä luonnoksessa? Mitä niitä tarvitaan vähintään saman toiminnallisuuden saavuttamiseksi?

Alla on kolme versiota vähäisemmästä vilkkuvasta ohjelmasta, joka vaihtaa ledin nastalle 13 joka sekunti. Kaikki kolme versiota on koottu anUnolle (ei USB-liitäntää) käyttäen avr-gcc 4.8.2, avr-libc 1.8.0 jaarduino-core 1.0.5 (en käytä Arduino IDE: tä).

Ensinnäkin, tavallinen Arduino-tapa:

  const uint8_t ledPin = 13; void setup () {pinMode (ledPin, OUTPUT);} void loop () {digitalWrite (ledPin, HIGH); viive (1000); digitalWrite (ledPin, LOW); delay (1000);}  

Tämä kokoaa 1018 tavua. Käyttämällä sekä avr-nm että purkamista jaoin tämän koon yksittäisiin toimintoihin. Suurimmasta pienimpään:

  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 .init_ad ------------------------ 1018 YHTEENSÄ  

Yllä olevassa luettelossa ensimmäinen sarake on koko tavuina , ja toisessa sarakkeessa kerrotaan, tuleeko koodi Arduino-ydinkirjastosta (A, 822 tavua yhteensä), C-ajonaikaisesta (C, 148 tavua) vai käyttäjästä (U, 48 tavua).

Kuten voidaan tässä luettelossa nähdään, että suurin toiminto on ajastimen 0 ylivuoto-keskeytyksen hoito. Tämä rutiini on vastuussa ajan jäljittämisestä, ja sitä tarvitaan millis () , micros () ja delay () . Toiseksi suurin toiminto on init () , joka asettaa laitteiston ajastimet PWM: lle sallii TIMER0_OVF-keskeytyksen ja katkaisee USART-yhteyden (jota käynnistyslatain käytti). Sekä tämä että edellinen toiminto määritettiin <Arduino-hakemistossa> / hardware / arduino / cores / arduino / wiring.c .

Seuraava on C + avr-libc -versio:

  #include <avr / io.h> # include <util / delay.h>int main (void) {DDRB | = _BV (PB5); / * aseta nasta PB5 lähdöksi * / ((;;) {PINB = _BV (PB5); / * Vaihda PB5 * / _viive_ms (1000); }}  

Yksittäisten kokojen erittely:

  104 C-vektoritaulukko 26 U main 12 C __init 8 C .init9 (call main, jmp exit) 4 C __bad_interrupt 4 C _exit ---------------------------------- 158 YHTEENSÄ  

Tämä on 132 tavua C-ajon ajaksi ja 26 tavua käyttäjäkoodia, mukaan lukien sisäinen toiminto _delay_ms().

Voidaan huomata, että koska tämä Ohjelma ei käytä keskeytyksiä, keskeytysvektoritaulukkoa ei tarvita, ja tavallisen käyttäjän koodekki voitaisiin laittaa sen tilalle. Seuraava kokoonpanoversio tekee tarkalleen näin:

  #insulje <avr / io.h> # define io (reg) _SFR_IO_ADDR (reg) sbi io (DDRB), 5; aseta PB5 lähtöaukoksi: sbi io (PINB), 5; kytkin PB5 ldi r26, 49; viive 49 * 2 ^ 16 * 5 jaksolle viive: sbiw r24, 1 sbci r26, 0 brne delay rjmp -silmukka  

Tämä on koottu ( avr-gcc -nostdlib ) vain 14 tavuun, joista suurinta osaa käytetään viivästyttämään vaihtoja niin, että vilkkuminen ei ole näkyvissä. Jos poistat kyseisen viiveen, saat 6 tavun ohjelmaa, joka vilkkuu liian nopeasti, jotta sitä ei voida nähdä (taajuudella 2 MHz):

  sbi io (DDRB), 5; aseta PB5 lähtöaukoksi: sbi io (PINB), 5; vaihda PB5 rjmp -silmukka  
#4
+3
Nick Gammon
2015-07-07 07:17:10 UTC
view on stackexchange narkive permalink

Kirjoitin viestin aiheesta Miksi yhden LEDin vilkkuminen vaatii 1000 tavua?.

Lyhyt vastaus on: "Vilkkuminen ei vaadi 2000 tavua kaksi LEDiä! "

Pidempi vastaus on, että tavallisissa Arduino-kirjastoissa (joita sinun ei tarvitse käyttää, jos et halua) on mukavia toimintoja yksinkertaistamaan elämää. Voit esimerkiksi osoittaa nastat numerolla ajon aikana, jolloin kirjasto muuntaa (sanoa) nastan 8 oikeaan porttiin ja oikeaan bittinumeroon. Jos koodaat porttikäytön, voit tallentaa kyseisen yleiskustannuksen.

Vaikka et käyttäisikään niitä, vakiokirjastot sisältävät koodin punkkien laskemiseen, jotta voit selvittää nykyisen "ajan" ( soittamalla millis () ). Tätä varten sen on lisättävä joidenkin keskeytyspalvelurutiinien yleiskustannukset.

Jos yksinkertaistat (Arduino Uno) tähän luonnokseen, saat ohjelman muistin käytön 178 tavuun (IDE 1.0: lla). 6):

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

OK, 178 tavua ei ole niin paljon, ja siitä ensimmäiset 104 tavua ovat laitteiston keskeytysvektorit (4 tavua kukin 26 vektorille).

Joten kiistatta tarvitaan vain 74 tavua LEDin vilkkumiseen. Ja näistä 74 tavusta suurin osa on todella kääntäjän luomaa koodia globaalin muistin alustamiseksi. Jos lisäät tarpeeksi koodia kahden LEDin vilkkumiseen:

  int main () {DDRB = bit (5); // nasta 13 DDRB | = bitti (4); // tappi 12 while (true) {PINB = bitti (5); // tappi 13 PINB = bitti (4); // nasta 12}}  

Sitten koodin koko kasvaa 186 tavuun. Joten voit siis väittää, että LEDin vilkkuminen vaatii vain 186 - 178 = 8 tavua.

Joten 8 tavua LED: n vilkkuminen. Kuulostaa melko tehokkaalta minulle.


Jos sinulla on kiusaus kokeilla tätä kotona, minun on huomautettava, että vaikka yllä oleva lähetetty koodi vilkkuu kaksi LEDiä, se tekee sen todella nopeasti. Itse asiassa ne vilkkuvat 2 MHz: ssä - katso kuvakaappaus. Kanava 1 (keltainen) on nasta 12, kanava 2 (syaani) on nasta 13.

Rapid blinking of pins 12 and 13

Kuten näette, lähtöliittimillä on neliöaalto, jonka taajuus on 2 MHz. Nasta 13 muuttaa tilaa 62,5 ns (yksi kellojakso) ennen nasta 12 johtuen koodin nastojen vaihtamisjärjestyksestä.

Joten ellei sinulla ole paljon parempia silmiä kuin minulla, et näet todella vilkkuvan vaikutuksen.


Huvittavana lisänä voit itse vaihtaa kaksi nastaa samaan ohjelmatilaan kuin vaihtaa yksi tappi.

  int main () {DDRB = bitti (4) | bitti (5); // aseta nastat 12 ja 13 lähtöön, kun (true) PINB = bitti (4) | bitti (5); // vaihtaa nastat 12 ja 13} // pääpää  

Tämä kokoaa 178 tavua.

Tämä antaa sinulle korkeamman taajuuden:

Very rapid blinking of pins 12 and 13

Nyt olemme jopa 2,66 MHz: n nopeudella.

Tämä on järkevää. Joten sisällytetäänkö standardikirjastot vain otsikoihin automaattisesti rakennuksen aikana? Ja kuinka pystyit * olemaan * sisällyttämättä niitä?
Linkittäjä poistaa aggressiivisesti koodin, jota ei käytetä. Jos ei kutsuttu "init ()" (kuten tavallinen "main ()" tekee, tiedostoa wiring.c (jossa on "init") ei linkitetty. Tämän seurauksena keskeytyskäsittelijöiden käsittely ( "millis ()", "mikros ()" jne.) jätettiin pois. Luultavasti ei ole erityisen käytännöllistä jättää sitä pois, ellei sinun tarvitse koskaan ajastaa asioita, mutta tosiasia on, että luonnos kasvaa kooltaan riippuen siitä, mitä laitat siihen. Jos esimerkiksi käytät Serial-ohjelmaa, sekä ohjelmamuisti että RAM saavat osuman.


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...