Datum:
Hallo, ich habe einen Attiny 45, der mehrere RGB-Leds ansteuert. Beim kompilieren sagt mir AVR Studio: Program: 1014 bytes (24.8% Full) (.text + .data + .bootloader) Data: 155 bytes (60.5% Full) (.data + .bss + .noinit) Wenn ich nicht einen Teil auskommentiert hätte, wäre der untere Speicher (Data) schon überfüllt. Die Patterns für die Anzeige liegen in Arrays. Diese müssten ja normalerweiße im RAM liegen. Gibt es eine Möglichkeit die irgendwie in den anderen Speicher auszulagern um weiterhin den kleinen Attiny verwenden zu können? Ansonsten müsste ich wohl auf einen etwas größeren Controller setzen, wobei der Atmega8 zB auch nur 1kB hat (4mal so viel)
Datum:
Explizite Zuweisung von unveränderlichen Daten ins Flash wäre sicher ein Weg. Dann noch die Möglichkeit, den einen oder anderen Programmteil zu optimieren. Zeig doch mal Deinen Code. Eigentlich lässt sich da immer was machen. Der müde Joe.
Datum:
Stichworte PROGMEM oder EEMEM
Datum:
Michael N. schrieb: > Die Patterns für die Anzeige liegen in Arrays. > Diese müssten ja normalerweiße im RAM liegen. Die liegen in beidem: im Flash und im SRAM (denn irgendwo her müssen sie ja bei Programmstart ins SRAM geladen werden) Wenn du daher deine Patterns nicht aus dem SRAM bei der Verwendung lädst, sondern gleich aus dem Flash, sparst du den SRAM Speicher als Zwischenstation ein.
Datum:
Michael N. schrieb: > Die Patterns für die Anzeige liegen in Arrays. > Diese müssten ja normalerweiße im RAM liegen. Wenn es sich um konstante Array-Inhalte handelt, würde ich sie in den Flash-Speicher legen und nicht ins RAM. > Gibt es eine Möglichkeit die irgendwie in den anderen Speicher > auszulagern um weiterhin den kleinen Attiny verwenden zu können? Ja, per Assemblerkommando ".db". > Ansonsten müsste ich wohl auf einen etwas größeren Controller setzen, > wobei der Atmega8 zB auch nur 1kB hat (4mal so viel) Du kannst auch 1,30 investieren und auf den pinkompatiblen ATtiny85 umsteigen, der hat 8 K flash und 512 Bytes SRAM. Dann brauchst du dein Programm wahrscheinlich gar nicht anpassen. https://guloshop.de/shop/Mikrocontroller/ATtiny85::16.html
Datum:
Michael N. schrieb: > Gibt es eine Möglichkeit die irgendwie in den anderen Speicher > auszulagern um weiterhin den kleinen Attiny verwenden zu können? Welche Programmiersprache verwendest du? Ich kenne ähnliche Dinge vom PIC12F675. Mit C passen etwas größere Programme gar nicht mehr, Assembler macht dann für die selbe Aufgabe mal die halbe Codegröße. Ich spielte mit den Dingen einfach mal etwas auf dem PICkit1 herum, welches diesen µC enthält. Aufgrund der ohnehin nur kleinen Speicher bleiben die Programme sowohl in C als auch in Assembler sowieso sehr übersichtlich.
Datum:
Programmiert wurde in C. Sicherlich kann man noch ein bisschen was optimieren, aber der größte Teil wird einfach von den Arrays gebraucht. Es soll am Ende 8 Arrays geben (aktuell passen gerade mal 1,5 in den Speicher) mit jeweils ca. 150-250 Byte. (2kB wären also Minimum) Aktuell sieht es wie folgt aus: (Auszug)
//folgender Teil wird per Timerinterrupt immer wieder durchlaufen //serpa[0-2] enthalten Daten für die Schieberegister else { //normales Programm anzeigen if ((pattern_timer_counter>=255) || (pattern_timer_counter>=pattern_pointer[show_program].Data[0])) { pattern_timer_counter=0; serpa[0]=pattern_pointer[show_program].Data[pattern_data_counter]; serpa[1]=pattern_pointer[show_program].Data[pattern_data_counter+1]; serpa[2]=pattern_pointer[show_program].Data[pattern_data_counter+2]; serpa_out(); pattern_data_counter=pattern_data_counter+3; } else { pattern_timer_counter++; } if (pattern_data_counter+3>pattern_pointer[show_program].Length) { pattern_data_counter=1; } } //Die Daten kommen aus folgendem Konstrukt uint8_t pattern1[61]={ 50, 0b10000000,0b00000000,0b00000001, 0b01000000,0b00000000,0b00000010, 0b00100000,0b00000000,0b00000100, 0b00010000,0b00000000,0b00001000, 0b00001000,0b00000000,0b00010000, 0b00000100,0b00000000,0b00100000, 0b00000010,0b00000000,0b01000000, 0b00000001,0b00000000,0b10000000, 0b00000010,0b00000000,0b01000000, 0b00000100,0b00000000,0b00100000, 0b00001000,0b00000000,0b00010000, 0b00010000,0b00000000,0b00001000, 0b00100000,0b00000000,0b00000100, 0b01000000,0b00000000,0b00000010, 0b10000000,0b00000000,0b00000001, 0b01000000,0b00000000,0b00000010, 0b00100000,0b00000000,0b00000100, 0b00010000,0b00000000,0b00001000, 0b00100000,0b00000000,0b00000100, 0b01000000,0b00000000,0b00000010 }; //Das hier war also ein Beispiel mit 61Byte. Soll es später aber wie oben beschrieben auch größer geben (pattern1-pattern8) struct Pattern pattern_pointer[]={ {sizeof(pattern0), pattern0}, {sizeof(pattern1), pattern1}, {sizeof(pattern2), pattern2}, {sizeof(pattern3), pattern3}, {sizeof(pattern4), pattern4}, {sizeof(pattern5), pattern5}, {sizeof(pattern6), pattern6}, {sizeof(pattern7), pattern7}, {sizeof(pattern8), pattern8}, //Zur Vereinfachung hier noch mein Kommentar um sich schneller im Array zurechtzufinden: /****************************************** pattern_pointer[]={Länge_des_Patterns, Pointer_zu_Pattern}; z.B. pattern_pointer[0].Length --> Länge des Pattern0 z.B. pattern_pointer[0].Data[i] --> i-ter Datensatz aus Pattern0 patterni[x]={Speed (bzw Speed*Overflow_time), Patterns....} uint8_t patternn[length]={ Speed, pic1_red, pic1_green, pic1_blue, pic2_red, pic2_green, pic2_blue, pic3_red, pic3_green, pic3_blue }; Length: length%3 has to be 1 (the element for speed) ******************************************/ }; |
Datum:
schiebs - wie schon mehrfach angesprochen - in den Flash und da Kaas is bissn. HTH
Datum:
Wilhelm Ferkes schrieb: > Ich kenne ähnliche Dinge vom PIC12F675. Mit C passen etwas größere > Programme gar nicht mehr, Assembler macht dann für die selbe Aufgabe mal > die halbe Codegröße. Natüüürlich. Wechsel mal deinen Compiler. Der GCC macht aus C Code bestimmt kleineren und besseren Code als 99% aller Forumsteilnehmer hier in Assembler jemals selber schreiben könnten. So ein Ammenmärchen. Schau dir doch mal die Ausgabelistings an, da wird kaum überflüssiges produziert und wenn das in sehr begrenztem Rahmen. Also falls es stimmt was du da erzählst dann benutzt du einen miesen Compiler oder machst böse Dinge (keine Optimierung, nicht-konstante Delays usw.). Denn auch mit dem GCC kann man den Code aufblähen aber dann hat man definitv etwas falsch gemacht. gruß cyblord
Datum:
>Attiny Speicher zu knapp
Was soll ein Projekt mit einem Tiny? Was soll das Sparen von ein paar
cents und gleichzeitig stundenlange Threads ueber den Speicher? Die
Tinies sind guenstige Controller fuer hohe Stueckzahlen. Bei einem
normalen Projekt sollte man sich etwas mehr goennen. Fuer 2 Euro krieg
ich einen Mega32.
Datum:
Delta Oschi schrieb: > Was soll ein Projekt mit einem Tiny? Was soll das Sparen von ein paar > cents und gleichzeitig stundenlange Threads ueber den Speicher? Die > Tinies sind guenstige Controller fuer hohe Stueckzahlen. Bei einem > normalen Projekt sollte man sich etwas mehr goennen. Fuer 2 Euro krieg > ich einen Mega32. Klar, aber ich mache Bastelprojekte gerne zum Beispiel mit dem ATTiny2313; da geht es aber meist darum, dass das ganze Geraffel in ein bestimmtes Gehäuse passen muss. wenn der Tiny genug Ressourcen dazu hat, kann man damit ein bischen Platz auf der engen Lochrasterplatine sparen. Aber oftmals ist einfach Sparen am Speicher das falsche, weil man das mit Debugging wieder aus dem Fenster wirft.
Datum:
cyblord ---- schrieb: > Schau dir doch mal die Ausgabelistings an, da wird > kaum überflüssiges produziert und wenn das in sehr begrenztem Rahmen. Jaja, 99% und kaum überflüssiges. Schau dir mal an was da mit gutem Assembler Code optimiert werden kann... Außerdem sollte man das Problem (zu viel Ramverbrauch) nicht mit einem größeren µC, sondern mit besserer Programmierung lösen, dann hat man in Zukunft auch ein Problem weniger.
Datum:
cyblord ---- schrieb: > Also falls es stimmt was du da erzählst dann benutzt du einen miesen > Compiler Ich benutzte einfach nur den Freeware-Compiler, der beim MPLAB-Paket mit dabei war. Es kam aber in der Ausgabe ein Text, wie: Mit dem professionellen Compiler xyz hätten sie noch 20% Codegröße gespart. Joooaaaa, der kostet auch ein paar Euronen. Aber über Assembler geht da nichts, wenn man den ordentlich beherrscht. So ein µC mit 1k Flash soll ja kein umfangreiches Projekt managen, sondern vielleicht nur eine 7-Segment-Ausgabe.
Datum:
Wilhelm Ferkes schrieb: > Aber über Assembler geht da nichts, wenn man den ordentlich beherrscht. > > So ein µC mit 1k Flash soll ja kein umfangreiches Projekt managen, > sondern vielleicht nur eine 7-Segment-Ausgabe. Und 1kiB Flash-Speicher reichen nicht aus, um so ein Programm in C abzuwickeln?
Datum:
Michael N. schrieb: > uint8_t pattern1[61]={ Wenn ich eric und kbuchegg richtig verstanden habe, solltest du das besser so schreiben:
const uint8_t pattern1[] PROGMEM={ |
Datum:
Stefan Tomanek schrieb: > Und 1kiB Flash-Speicher reichen nicht aus, um so ein Programm in C > abzuwickeln? Kann sein. Jeder codet anders, der eine effektiver als der andere. Zwei Menschen, eine Aufgabe, ergibt zwei unterschiedliche Lösungen, wenn auch mit dem selben Ergebnis.
Datum:
Wilhelm Ferkes schrieb: > Ich kenne ähnliche Dinge vom PIC12F675. Mit C passen etwas größere > Programme gar nicht mehr, Assembler macht dann für die selbe Aufgabe mal > die halbe Codegröße. Also 50% glaube ich nicht. Oder du machst da Milchmädchenrechnungen: Leeres Assemblerprogramm: 0 Byte Flash Leeres C Programm: 250 Byte Flash (oder so ähnlich). Wow, das sind 250/0 = unendlich mal so viel Speicherverbrauch beim C-Programm ;-) Spätestens bei 1kB Codegröße fällt der Unterschied mit ganz großer Sicherheit nicht mehr mit 50% ins Gewicht. Ganz sicher. Diese Erfahrungen beziehen sich auf den AVR-GCC.
Datum:
Simon K. schrieb: > Wow, das sind 250/0 = unendlich mal so viel Speicherverbrauch beim > C-Programm ;-) Geniestreich! Du hast gerade tatsächlich bewiesen, dass C absolut nicht zur Programmierung von µCs taugt! SCNR xD
Datum:
Simon K. schrieb: > Also 50% glaube ich nicht. Oder du machst da Milchmädchenrechnungen: > Leeres Assemblerprogramm: 0 Byte Flash > Leeres C Programm: 250 Byte Flash (oder so ähnlich). Simon, du fantasierst. Assemblerprogramm assembliert: 500 Byte. C-Programm compiliert: 900 Byte. Selbe Aufgabe. Ich portierte den Assemblercode nach C. Und glaub mir: Ich kann das. Habe auch schon richtig große Software für ein industrielles Projekt von 8051 nach ARM7 portiert. Ich habe hier verschiedene PIC-Projekte auf meinem Rechner, kleine Sachen, wo nur ein paar LEDs auf dem PICkit1 gemultiplext blinken und hoch zählen, wo ich einfach nur mal aus Lust und Laune Assembler nach C wechselte, und umgekehrt.
Datum:
Hatte leider die letzten Tage nicht so viel Zeit zum testen. Habe aktuell folgende Lösung (mit der die 4kb vom Attiny locker ausreichen):
struct Pattern { uint8_t Length; uint8_t* Data; }; const uint8_t pattern1[61] PROGMEM={ 50, 0b10000000,0b00000000,0b00000001, //... }; //andere Patterns const struct Pattern pattern_pointer[] PROGMEM={ {sizeof(pattern0), pattern0}, {sizeof(pattern1), pattern1}, {sizeof(pattern2), pattern2}, {sizeof(pattern3), pattern3}, {sizeof(pattern4), pattern4}, {sizeof(pattern5), pattern5}, {sizeof(pattern6), pattern6}, {sizeof(pattern7), pattern7}, {sizeof(pattern8), pattern8}, }; |
verwendet.
Für alle 9 Einträge des letzten Teils (const struct Pattern
pattern_pointer[] PROGMEM={...) wird eine Warnung ausgeworfen und das
Programm funktioniert nicht mehr.
Die Warnung lautet wie folgt:
../pattern.h:178: warning: initialization discards qualifiers from
pointer target type
Was mache ich falsch? (Programm läuft nämlich auch nicht richtig)
Bin leider (noch) kein C-Freak...
Datum:
Michael N. schrieb: > Die Warnung lautet wie folgt: > ../pattern.h:178: warning: initialization discards qualifiers from > pointer target type Die Warnung bezieht sich hierauf > struct Pattern > { > uint8_t Length; > uint8_t* Data; > }; In den Data Member legst du die Adresse von zb pattern0 ab. pattern0 ist aber ein const uint8_t pattern0[61] ... also const. Und genau darauf bezieht sich die Warnung. Du hast einen Pointer auf non-const Daten, mit dem du theoretisch die Daten verändern könntest (das Flash lass jetzt erst mal weg), wenn du wolltest. Der Compiler weißt dich darauf hin.
struct Pattern { uint8_t Length; const uint8_t* Data; }; |
> Was mache ich falsch? (Programm läuft nämlich auch nicht richtig)
Wahrscheinlich sind deine Flash-Zugriffe falsch. Aus dem Bauch heraus
schätze ich mal, dass du ein pgm_read_xxx zu wenig hast.
Um an den Data Pointer zu kommen, musst du einmal pgm_read_xxx benutzen.
Und mit diesem Pointer brauchst du dann einen weiteren pgm_read_byte um
an die Daten zu kommen.
Datum:
Simon K. schrieb: > Wilhelm Ferkes schrieb: > Also 50% glaube ich nicht. Oder du machst da Milchmädchenrechnungen: > Leeres Assemblerprogramm: 0 Byte Flash > Leeres C Programm: 250 Byte Flash (oder so ähnlich). > > Wow, das sind 250/0 = unendlich mal so viel Speicherverbrauch beim > C-Programm ;-) > > Spätestens bei 1kB Codegröße fällt der Unterschied mit ganz großer > Sicherheit nicht mehr mit 50% ins Gewicht. Ganz sicher. > > Diese Erfahrungen beziehen sich auf den AVR-GCC. 1)Was ist das denn für ne Milchmädchenrechnung, ein Programm mit 0 Bytes gibt es per definitionem nicht! 2)bei deinem C Programm, werden automatisch alle Vektoren gesetzt, Stack gesetzt, usw das was man auch bei Assembler machen sollte, in "deinem 0 Byte Programm" mußt du es später noch machen. z.b. Unterprogramm aufrufen, denn spätestens da verbraucht Dein "Assemblerprogramm" plötzlich ,"unendlich" viel Platz gegenüber dem C Programm, das das schon alles erledigt hat. Wenn du schon solche Vergleiche anstellst dann auch richtig.
Datum:
Mikel schrieb: > 1)Was ist das denn für ne Milchmädchenrechnung, ein Programm mit 0 Bytes > gibt es per definitionem nicht! Das leere Programm ist kein Programm? Oho. ;-) Aber wir wollen hier mal keine Milchmädchenhierarchie aufmachen.
Datum:
Also so ganz klappt es noch nicht. Aktuell sieht es nun so aus: Headerdatei:
struct Pattern { uint8_t Length; const uint8_t* Data; }; //... const uint8_t pattern3[4] PROGMEM={ 50, 0b00100000,0b00100000,0b00100000 }; //... const struct Pattern pattern_pointer[] PROGMEM={ {sizeof(pattern0), pattern0}, {sizeof(pattern1), pattern1}, {sizeof(pattern2), pattern2}, {sizeof(pattern3), pattern3}, {sizeof(pattern4), pattern4}, {sizeof(pattern5), pattern5}, {sizeof(pattern6), pattern6}, {sizeof(pattern7), pattern7}, {sizeof(pattern8), pattern8}, }; |
main.c
//... serpa[0]=pattern_pointer[0].Data[show_program*3-2]; serpa[1]=pattern_pointer[0].Data[show_program*3-1]; serpa[2]=pattern_pointer[0].Data[show_program*3]; serpa_out(); //... |
Wie läuft das dann, wenn ich möchte, dass es tatsächlich läuft?^^ Verstehe ich noch nicht ganz...
Datum:
> serpa[0]=pattern_pointer[0].Data[show_program*3-2];
Auf Dinge, die im Flash liegen KANNST du nicht direkt zugreifen. Du
musst die pgm_read_xxx Funktionen zu Hilfe nehmen.
struct Pattern PatternData; // erst mal eine Struktur im SRAM anlegen // damit man mit den Membern eines Pattern // vernünftig arbeiten kann // // erst mal diesen einen Datensatz aus dem Flash ins SRAM kopieren // pgm_read_block( &PatternData, &pattern_pointer[0], sizeof( struct Pattern ) ); // // und über den jetzt im SRAM befindlichen data Pointer von PatternData // auf die eigentlichen Daten zugreifen // serpa[0] = pgm_read_byte( &PatternData.Data[ show_program*3-2 ] ); // // oder eben in einer Schleife // for( i = 0; i < PatternData.Length; i++ ) serpa[i] = pgm_read_byte( &PatternData.Data[i] ); |
http://www.mikrocontroller.net/articles/AVR-GCC-Tu... (eventuell müssen die Pointer noch ein wenig zurechtgecastet werden)
Datum:
Dennis S. schrieb: > Das leere Programm ist kein Programm? Oho. ;-) Über die Frage, ob das Nichts überhaupt existieren kann, haben sich die Philosophen schon vor Jahrtausenden die Köpfe zerbrochen. ;-)
Datum:
Simon K. schrieb: > Wow, das sind 250/0 = unendlich mal so viel Speicherverbrauch beim > C-Programm ;-) Hm X/0 = unendlich. DAS ist neu.
Datum:
cyblord ---- schrieb: > Hm X/0 = unendlich. DAS ist neu. Stimmt, unendlich reicht nicht. Denn selbst nach der unendlichen Addition von 0 wird es immernoch 0 sein. Nicht 1 und auch nicht 250. ;-) Gruß Jobst
Datum:
Jobst M. schrieb: > cyblord ---- schrieb: >> Hm X/0 = unendlich. DAS ist neu. > > Stimmt, unendlich reicht nicht. > > Denn selbst nach der unendlichen Addition von 0 wird es immernoch 0 > sein. Nicht 1 und auch nicht 250. > > ;-) > > > Gruß > > Jobst Außer natürlich du wärst Chuck Norris, der zählte nämlich kürzlich aus Spaß bis unendlich. Zweimal.
Datum:
Besonders interessant fand ich den Übergang von der letzten Zahl zu unendlich ... Bei µCs ist das (bei 8-Bittern) schon bei 255, danach wird das 'Chuck'-Bit gesetzt. ;-) Gruß Jobst
Datum:
Stefan Tomanek schrieb: > Klar, aber ich mache Bastelprojekte gerne zum Beispiel mit dem > ATTiny2313; > da geht es aber meist darum, dass das ganze Geraffel in ein bestimmtes > Gehäuse passen muss. Wenn Du einen Tiny2313 benutzen kannst, kannst Du für das gleiche Geld einen PIC24FV32KA302 nehmen: doppelt so viele Bits; doppelte Taktfrequenz, 16* Flash, 4* RAM; plus viel bessere Debugmöglichkeiten; keine Probleme mit PROGMEM, bessere Peripherie, ... Augen auf beim Controllerkauf! fchk
Datum:
Frank K. schrieb: > Wenn Du einen Tiny2313 benutzen kannst, kannst Du für das gleiche Geld > einen PIC24FV32KA302 nehmen: doppelt so viele Bits; doppelte > Taktfrequenz, 16* Flash, 4* RAM; plus viel bessere Debugmöglichkeiten; > keine Probleme mit PROGMEM, bessere Peripherie, ... Und noch etwas: Keine kostenlosen und vollwertigen Compiler mehr; doppelt so lange Befehle die die vielen Bits auch komplett ausnutzen; kein GCC mehr (kompatibilität ade); noch mehr Programmer zuhause; ... Schuster, bleib bei deinen Leisten.
Datum:
wenns klitzeklein sein soll, nehme ich gerne den attiny85, der hat ja nun wirklich ausreichend Ressourcen für das kleine Ding.
Datum:
Frank K. schrieb: > Wenn Du einen Tiny2313 benutzen kannst, kannst Du für das gleiche Geld > einen PIC24FV32KA302 nehmen: doppelt so viele Bits; doppelte > Taktfrequenz, 16* Flash, 4* RAM; plus viel bessere Debugmöglichkeiten; > keine Probleme mit PROGMEM, bessere Peripherie, ... > > Augen auf beim Controllerkauf! Oder alternativ einfach lernen, wie das funktioniert. Ist manchmal das einfachste.
Datum:
Vielen Dank K. H. Buchegger. Habe deine "Anleitung" oben schon gestern gelesen. Das zeigte mir allerdings, dass es Sinn machen würde mich noch näher mit dem Thema zu beschäftigen, da ich davon absolut keinen Schimmer habe. Deshalb werde ich das Projekt wohl erstmal zurückstellen müssen bis ich genug Zeit hatte mir das anzulesen...
Datum:
Siliziumbrater schrieb: > Frank K. schrieb: >> Wenn Du einen Tiny2313 benutzen kannst, kannst Du für das gleiche Geld >> einen PIC24FV32KA302 nehmen: doppelt so viele Bits; doppelte >> Taktfrequenz, 16* Flash, 4* RAM; plus viel bessere Debugmöglichkeiten; >> keine Probleme mit PROGMEM, bessere Peripherie, ... > > Und noch etwas: > Keine kostenlosen und vollwertigen Compiler mehr; doppelt so lange > Befehle die die vielen Bits auch komplett ausnutzen; kein GCC mehr > (kompatibilität ade); noch mehr Programmer zuhause; ... [ ] Du hast Ahnung von PIC24 Der Microchip C30 Compiler ist ein gcc. Das PicKIT3 kostet 50€ als Original, 20€ als China-Clone; und damit kannst Du alle PIC18/24/dsPIC/PIC32 programmieren und debuggen. Mit welchem 20€ Device kannst Du einen Tiny2313 im Singlestep debuggen? fchk
Datum:
Frank K. schrieb: > Wenn Du einen Tiny2313 benutzen kannst, kannst Du für das gleiche Geld > einen PIC24FV32KA302 nehmen: doppelt so viele Bits; doppelte > Taktfrequenz, 16* Flash, 4* RAM; plus viel bessere Debugmöglichkeiten; > keine Probleme mit PROGMEM, bessere Peripherie, ... > > Augen auf beim Controllerkauf! Naja... du hast sicher Recht, der PIC24FV32KA302 ist echt ein ordentlicher Controller, keine Frage, aber so billig ist der dann auch wieder nicht. Erstens kostet der ATtiny4313/DIP (der modernere Bruder des ATtiny2313) nur halb so viel wie der PIC24FV32KA302. Zweitens ist der PIC eine höhere Gewichtsklasse: du müsstest ihn mit dem ATmega328 vergleichen. Aber auch da wäre der PIC trotzdem noch teurer.
