Fråga:
Vad kan jag göra om jag har slut på Flash-minne eller SRAM?
Peter Bloomfield
2014-02-15 07:09:33 UTC
view on stackexchange narkive permalink

Enligt Arduino-dokumentationen har ATmega328 32KB Flash-minne för bootloader + uppladdad skiss och endast 2KB SRAM för runtime-data. ATmega2560 har en hel del mer, totalt 256KB respektive 8KB.

I båda fallen verkar dessa gränser ganska små, särskilt jämfört med liknande stora konsumentenheter, som smartphones.

Vad kan du göra om du tar slut? T.ex. om din skiss är för stor eller om du behöver bearbeta mycket data (t.ex. strängar) vid körning? Finns det något sätt att utöka Flash eller SRAM?

Försök använda lite variabel optimering. Några olika variabler diskuteras [här] (http://arduino.stackexchange.com/questions/196/when-to-use-different-variable-types)
Använd rätt omfattning för dina variabler om du inte redan gör det, kommer kompilatorn att optimera RAM-användningen för dig när variabler inte används.
Du kan faktiskt använda en Teensy 3.2 (med Teensyduino Software), vilket skulle vara jämförbart med en Arduino. Med tanke på att du har slut på RAM / PROGMEM skulle det betyda att du också är sannolikt att det du försöker göra är att trycka på din Arduino. En Teensy 3.2 är inte så mycket dyrare. men har: 32bit, 72MHz (wtf !?) 256KB FLASH och 64KB RAM och 3x UART. Inte mer programminne som ATmega2560, men RAM och hastighetsökning borde räcka.
Fyra svar:
#1
+30
Peter Bloomfield
2014-02-15 07:09:33 UTC
view on stackexchange narkive permalink

Optimering
Lågnivåprogrammering för inbäddade system skiljer sig ganska från programmering för enheter för allmänt ändamål, till exempel datorer och mobiltelefoner. Effektivitet (när det gäller hastighet och rymd) är mycket viktigare eftersom resurserna är höga. Det betyder att det allra första du ska göra om du tar slut på utrymme är att titta på vilka delar av din kod du kan optimera.

När det gäller att minska programutrymmet (Flash) kan kodstorleken vara ganska svårt att optimera om du inte har erfarenhet, eller om du är mer van vid att programmera för stationära datorer som inte brukar behöva den färdigheten. Tyvärr finns det ingen "magisk kula" -metod som kommer att fungera i alla situationer, även om det hjälper om du seriöst överväger vad din skiss verkligen behöver att ha. Om en funktion inte behövs, ta bort den.

Ibland är det också bra att identifiera var flera delar av din kod är desamma (eller mycket lika). Du kan kanske kondensera dem till återanvändbara funktioner som kan anropas från flera platser. Var dock medveten om att ibland försöker göra koden för återanvändbar faktiskt blir den mer detaljerad. Det är en knepig balans att slå som tenderar att komma med träning. Att spendera lite tid på att se hur kodändringar påverkar kompilatorns utdata kan hjälpa.

Optimering av Runtime-data (SRAM) tenderar att bli lite enklare när du är van vid det. En mycket vanlig fallgrop för nybörjare är att använda för mycket globala data. Allt som deklareras globalt kommer att finnas under hela skissens livstid, och det är inte alltid nödvändigt. Om en variabel bara används i en funktion och den inte behöver bestå mellan samtal, gör den till en lokal variabel. Om ett värde måste delas mellan funktioner, överväg om du kan skicka det som en parameter istället för att göra det globalt. På det sättet använder du bara SRAM för dessa variabler när du faktiskt behöver det.

En annan mördare för SRAM-användning är textbehandling (t.ex. med hjälp av klassen String ). Generellt sett bör du undvika att göra strängoperationer om möjligt. De är massiva minnessvin. Om du till exempel lägger ut massor av text till serie ska du använda flera samtal till Serial.print () istället för att använda strängkompatering. Försök också att minska antalet stränglitterärer i din kod om möjligt.

Undvik även rekursion om möjligt. Varje gång ett rekursivt samtal görs tar stapeln en nivå djupare. Omforma dina rekursiva funktioner så att de blir iterativa istället.

Använd EEPROM
EEPROM används för långvarig lagring av saker som bara ändras ibland. Om du behöver använda stora listor eller uppslagstabeller med fasta data, överväga att lagra den i EEPROM i förväg och bara dra ut vad du behöver när det behövs.

Uppenbarligen är EEPROM ganska begränsat i storlek och hastighet men har ett begränsat antal skrivcykler. Det är inte en bra lösning på databegränsningar, men det kan räcka för att minska belastningen på Flash eller SRAM. Det är också mycket möjligt att ansluta till liknande extern lagring, till exempel ett SD-kort.

Expansion
Om du har tömt alla andra alternativ, kan expansion vara en möjlighet . Tyvärr är det inte möjligt att utöka Flash-minnet för att öka programutrymmet. Det är emellertid möjligt att utvidga SRAM. Det betyder att du kanske kan omformulera din skiss för att minska kodstorleken på bekostnad av att öka datastorleken.

Att få mer SRAM är faktiskt ganska enkelt. Ett alternativ är att använda en eller flera 23K256 marker. De nås via SPI, och det finns SpiRAM-biblioteket som hjälper dig att använda dem. Var bara uppmärksam på att de arbetar vid 3,3 V inte 5 V!

Om du använder Mega kan du alternativt få SRAM-expansionsskydd från Lagrangian Point eller Robusta kretsar .

Du kan också lagra konstant data i programminnet, snarare än SRAM, om du har problem med SRAM-utrymme och ledigt programminne. Se [här] (http://jeelabs.org/2011/05/23/saving-ram-space/) eller [här] (http://www.nongnu.org/avr-libc/user-manual/pgmspace .html)
Ett annat bra alternativ till EEPROM är ett SD-kort. Det tar några IO-portar, men om du behöver ett stort utrymme för, till exempel kartdata eller liknande, kan det vara enkelt att byta ut och redigera med ett anpassat program på en PC.
Människor bör inte uppmuntras att använda SPI SRAM eller RAM-utvidgningar, om de har lite minne. Det är bara slöseri med pengar. Att välja en större MCU skulle vara billigare. Förutom att prestanda kan vara mycket dålig. Man bör först göra en ballpark-uppskattning: om den beräknade RAM-användningen är för nära gränsen, väljer du fel kort / mikrokontroller / utvecklingsplattform. Visst, bra användning (lagring av strängar i flash) och optimering (undviker att använda vissa bibliotek) kan vara sanna spelbytare. Men vid denna punkt ser jag inga fördelar med att använda Arduino Software-plattformen.
#2
+25
sachleen
2014-02-15 09:24:15 UTC
view on stackexchange narkive permalink

När du laddar upp din kod till din Arduino, säg till exempel en Uno, kommer den att berätta hur många byte den använder av 32K tillgängliga. Det är hur mycket flashminne du har (tänk datorns hårddisk). Medan ditt program körs använder det vad som kallas SRAM, och det finns mycket mindre av det tillgängliga.

Ibland kommer du att märka att ditt program beter sig konstigt vid en punkt som du inte ens har rört på ett tag . Det kan vara så att dina senaste ändringar gör att det tar slut på minne (SRAM). Här är några tips om hur du frigör SRAM.

Lagring av strängar i Flash istället för SRAM.

En av de vanligaste sakerna jag har sett är att chipet tar slut minne eftersom det finns för många långa strängar.

Använd funktionen F () när du använder strängar så att de lagras i Flash istället för SRAM, eftersom du har mycket mer av det tillgängligt.

  Serial.println (F ("Denna sträng lagras i flashminne"));  

Använd rätt datatyper

Du kan spara en byte genom att växla från en int (2 byte) till en byte (1 byte). En osignerad byte ger dig 0-255 så om du har siffror som inte går högre än 255, spara en byte!

Hur vet jag att jag har slut på minne?

Vanligtvis kommer du att observera att ditt program beter sig konstigt och undrar vad som gick fel ... Du ändrade ingenting i koden nära den punkt där det trasslar, så vad ger det? Det tar slut på minne.

Det finns ett par funktioner för att berätta hur mycket tillgängligt minne du har.

Tillgängligt minne

Vet du om `F ()` `är en Arduino-specifik funktion eller finns det i AVR-biblioteken? Du kan överväga att nämna "PROGMEM const ..." också.
Du kan också använda bitstrukturer för att ytterligare minska det utrymme som används av dina variabler 5eg om du hanterar massor av booleska).
#3
+17
jfpoilpret
2014-02-15 23:28:24 UTC
view on stackexchange narkive permalink

Förutom vad andra har sagt (som jag håller helt med om), skulle jag rekommendera att läsa denna adafruitartikel om minne; det är välskrivet, förklarar många saker om minnet och ger tips om hur man optimerar det.

I slutet av läsningen tror jag att du skulle få ett ganska fullständigt svar på din fråga.

För att sammanfatta det har du två möjliga optimeringsmål (beroende på var du har minnesproblem):

  • Flash (dvs. Programminne); för detta kan du:
    • ta bort dödkod (t.ex. valfri kod som ingår men inte används) och oanvända variabler (att man också hjälper till med SRAM)
    • ta bort duplicerad kod
    • ta bort bootloadern helt och hållet (du kan vinna mellan 0,5K för en UNO och 2 eller 4K för andra Arduino-modeller); detta har dock några nackdelar
  • SRAM (dvs. stack, heap och statisk data); för detta kan du:
    • ta bort oanvända variabler
    • optimera storleken på varje variabel (t.ex. använd inte långa -4 byte- om du bara behöver int -2 byte)
    • använd rätt räckvidd för dina variabler (och föredra stacken framför statisk data när det är möjligt)
    • minska buffertstorleken till det strikta minimumet
    • flytta konstant data till PROGMEM (dvs. din statisk data förblir i Flash-minne och kopieras inte till SRAM vid programstart); som också gäller för konstanta strängar som du kan använda F () makro)
    • undvik dynamisk allokering om det inte är absolut nödvändigt; du kommer att undvika en fragmenterad hög som kanske inte krymper även efter att du har frigjort minne

Ett ytterligare tillvägagångssätt för att minska SRAM-användning beskrivs också (men används sällan, eftersom den är lite tung vid kodning och inte särskilt effektiv), består den i att använda EEPROM för att lagra data som byggts av ditt program, men inte användas förrän senare när vissa förhållanden uppstår, när data kan laddas tillbaka från EEPROM .

Att ta bort död kod - kompilatorn är _ riktigt_ bra med att hantera detta åt dig - det kommer inte att göra någon skillnad om du har massor av kod som inte någonsin kallas. Om du av misstag ringer kod som du inte behöver, så är det naturligtvis annorlunda.
#4
+9
David Cary
2014-02-16 03:21:35 UTC
view on stackexchange narkive permalink

Det finns två saker att göra om du har slut på lagring:

  • På något sätt "optimera" din kod så att den behöver mindre lagring; eller använder åtminstone mindre av den speciella typen av lagring som du har slut på (och använder mer av den typ av lagring som du fortfarande har gott om). Eller,
  • Lägg till mer lagringsutrymme.

Det finns många tips online om hur man gör det första (och för de allra flesta saker folk gör med Arduino, det inbyggda lagringsutrymmet är mer än tillräckligt efter "optimering"). Så jag fokuserar på det andra:

Det finns 3 saker som använder flash eller SRAM; var och en behöver en något annorlunda metod för att lägga till lagring:

  • variabel lagring: det är möjligt att expandera SRAM, som sachleen redan har påpekat. SRAM, FRAM och NVSRAM är alla lämpliga för snabbt föränderliga variabler. (Även om du i princip kan använda blixt för att lagra variabler, måste du oroa dig för blixtslitage). SPI (ett seriellt protokoll) är det enklaste att ansluta till Arduino. SpiRAM-biblioteket fungerar med Microchip 23K256 seriellt SRAM-chip. Ramtron FM25W256 seriellt FRAM -chip (numera ägs av Cypress) använder också SPI .Cypress CY14B101 NVSRAM använder också SPI.Etc.

  • konstanta data som måste vara kvar nästa gång strömmen slås på: detta är nästan lika enkelt som att utöka SRAM. Det finns många externa EEPROM-, FRAM-, NVSRAM- och FLASH -lagringsenheter tillgängliga. För närvarande är den lägsta kostnaden per MB SD-flashkort (som kan nås via SPI). Ramtron FM25W256 (se ovan), Cypress CY14B101 (se ovan), etc. kan också lagra konstant data. Många expansionsskydd inkluderar en SD-kortplats och flera bibliotek och handledning stöder läsning och skrivning till (flash) SD-kort. (Vi kan inte använda SRAM för detta, eftersom SRAM glömmer allt när strömmen släcks).

  • körbar kod: Tyvärr är det inte möjligt att utöka ett Arduinos Flash-minne för att öka programutrymmet. En programmerare kan dock alltid omformulera en skiss för att minska kodstorleken på bekostnad av att öka datastorleken och få den att gå något långsammare. (I teorin kan du gå så långt som att översätta hela din skiss till något tolkat språk, lagra den versionen av din skiss på ett SD-kort och sedan skriva en tolk för det språket som körs på Arduino för att hämta och utföra instruktioner från SD-kort - Forth på Arduino, en BASIC-tolk, en Tom Napier Picaro-tolk, något applikationsspecifikt språk, etc.).



Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...