pic user schrieb:> Trotzdem ist die Verwendung von mulhi3 für mich> merkwürdig.
Das dürfte einfach das Resultat des verqueren Codes sein.
1
*(char*)(&cfg-(unsignedint)&cfg_ee)
Wenn du von einem Pointer auf ein Struct einen Integer-Wert abziehst,
muss ja von der Adresse das Ergebnis von (Integer-Wert * sizeof(Struct))
abgezogen werden. Da ist deine Multiplikation.
Für mich macht deine ganze Pointer-Arithmetik keinen Sinn.
> cfg_ee ist ein Strukt im EEprom, cfg ist dasselbe Strukt im Ram.
Und warum sollte dann überhaupt irgendein Bedarf bestehen, die Adressen
der beiden irgendwie miteinander zu verrechnen?
pic user schrieb:> Der Grund wieso ich die vorgefertigten Funktionen nicht verwenden will> ist die Codegröße.
Und auch das klingt für mich ziemlich unsinnig.
> Das dürfte einfach das Resultat des verqueren Codes sein.
schein so zu sein.
> Wenn du von einem Pointer auf ein Struct einen Integer-Wert abziehst,> muss ja von der Adresse das Ergebnis von (Integer-Wert * sizeof(Struct))> abgezogen werden. Da ist deine Multiplikation.
Wobei, ich habe mulh3 nicht nachfollzogen scheint aber ein *3 zu sein.
Aber das Strukt ist 18 bytes groß und es bekommt 18 als input.
> Für mich macht deine ganze Pointer-Arithmetik keinen Sinn.>> cfg_ee ist ein Strukt im EEprom, cfg ist dasselbe Strukt im Ram.> Und warum sollte dann überhaupt irgendein Bedarf bestehen, die Adressen> der beiden irgendwie miteinander zu verrechnen?
Weil mit dem Array im Ram gearbeitet wird welches vom EEprom
initialisiert
wird. Das Array sind eigentlich statische Werte, welche im
Konfigurationsmodus geändert sowie dann als ganzes ins EEprom
gespeichert werden.
>> pic user schrieb:>> Der Grund wieso ich die vorgefertigten Funktionen nicht verwenden will>> ist die Codegröße.>> Und auch das klingt für mich ziemlich unsinnig.
Code hat jemand anders geschrieben, ich wurde gebeten die Softwäre zu
ändern, mehr Funktionalität reinzubringen, und von 1.5kbyte sind es
derzeit
2150byte welche ich nocht auf die 2k Grenze runterbringen muss.
Danke vielmals für deinen Support.
Zum Scluss noch der Code:
for(EEAR = (unsigned
int)&cfg_ee;EEARL-(uchar)((uint)&cfg_ee+sizeof(cfg));CAST(char*,cfg)[EEA
RL++-(uchar)(uint)&cfg_ee]=~EEDR) EECR|=(1<<EERE); // copy EEprom to
data
6f4: 82 e0 ldi r24, 0x02 ; 2
6f6: 90 e0 ldi r25, 0x00 ; 0
6f8: 9f bb out 0x1f, r25 ; 31
6fa: 8e bb out 0x1e, r24 ; 30
6fc: 68 2f mov r22, r24
6fe: 6e 5e subi r22, 0xEE ; 238
700: 48 2f mov r20, r24
702: 50 e0 ldi r21, 0x00 ; 0
704: 11 c0 rjmp .+34 ; 0x728 <main+0x7c>
706: e0 9a sbi 0x1c, 0 ; 28
708: 3e b3 in r19, 0x1e ; 30
70a: 2d b3 in r18, 0x1d ; 29
70c: 83 2f mov r24, r19
70e: 90 e0 ldi r25, 0x00 ; 0
710: 84 1b sub r24, r20
712: 95 0b sbc r25, r21
714: e0 91 c9 00 lds r30, 0x00C9
718: f0 91 ca 00 lds r31, 0x00CA
71c: e8 0f add r30, r24
71e: f9 1f adc r31, r25
720: 20 95 com r18
722: 20 83 st Z, r18
724: 3f 5f subi r19, 0xFF ; 255
726: 3e bb out 0x1e, r19 ; 30
728: 8e b3 in r24, 0x1e ; 30
72a: 86 17 cp r24, r22
72c: 61 f7 brne .-40 ; 0x706 <main+0x5a>
Das großflächige Entfernen von Leerzeichen und Zeilenumbrüchen im
Quellcode wird aber keinen Flash sparen. Das macht den Code nur noch
unsleserlicher, als er eh schon ist. Und ich kann mir auch nicht so
recht vorstellen, daß du mehr sparst, wenn du die gesamte Funktionalität
in den Schleifenkopf steckst.
Mir scheint da aber auch ein logischer Fehler drin zu sein. Bei jedem
Schleifendurchlauf inkrementierst du i und dekrementierst es wieder. Da
du es als Abbruchkriterium nutzt, müßte das eine Endlosschleife ergeben.
Ich sehe im Assemblercode auch keine Stelle, an der er wieder aus der
Schleife rauskommt.
Sven P. schrieb:> Es gibt übrigens auch fertige Routinen in der avr-libc für sowas. Die> sollte man auch tunlichst verwenden, wegen der Zeigerproblematik.
Irgendwann wurde die EEPROM-Lib auf indirekten Funktionscall umgestellt
und hat riesig Flash verbraucht.
Ich hab daher meine eigene Funktion geschrieben.
Da Schreiben und Lesen viel gemeinsam hat, habe ich beides in eine
Funktion gepackt. Das spart nochmals Code. Obendrein wird unnützes
Schreiben vermieden. Man kann also immer die gesamte Struct sichern,
auch wenn sich nur ein Element geändert hat.
pic user schrieb:> Dies reduziert leider auch die Anzahl> der gewonnen bytes, leider.
Lass einfach die Hacks. Das ist Käse, nur um ein paar Bytes zu sparen!
Verursachen diese paar Bytes mehr denn wirklick Probleme ?
Oder ist's von der Sorte "Ich weis da was besser als der Compiler und
will auf Biegen nd Brechen das Byte sparen"?
Wenn dich die Multiplikation sooo nervt oder wirklich absolut
inakzeptabel ist, dann verabschiede dich von deiner alten Toolchain! Und
verwende stattdessen was zeitgemässes wie zB avr-gcc 4.7.1.
Der macht die Multiplikation nicht mehr per libgcc-Aufruf, zumindest
falls der µC über MUL verfügt.
@Peter Dannegger
Danke, ein wirklich netter code, und er zeigt mir auch wie man das
mit den ATOMIC_BLOCK machen sollte. Nach ein paar defines konnte ich
es mit -std=c99 compilieren. Beides werde ich in Zukunft nutzen.
Gegenüber der AVR Lib erspart er 20 byte code (version 4.3.3 von GCC)
Inzwischen ist der Code auch mit der realen HW getestet und läuft
soweit.
@ Johann L. (gjlayde)
Der Unterschied ist, ob das Programm in den Prozessor reinpasst oder
nicht.
pic user schrieb:> @ Johann L. (gjlayde)> Der Unterschied ist, ob das Programm in den Prozessor reinpasst oder> nicht.
Lohnt sich denn -mcall-prologues? Das bringt idR nur was bei extrem
teuren Funktionen wie float-Berechnungen. Andsonsten hat man eher
billige Prologe, und mit -mcall-prologues wird der Code gerne mal
größer.
Neben -Os gibt's noch weitere Optionen die man antesten kann wie
-fno-split-wide-types, -fno-inline-small-functions, -morder1 bzw.
-morder2 und natürlich generell intelligentere Unsetzung.
Gibt es denn ein nicht verhuntzes, übersetzbares Beispiel für den Code
von oben?