Hi,
ich möchte gerne eine Tabelle in den Flash eines ATtiny44 schreiben.
Diese Tabelle wird nur einmal geschrieben und dann nur wieder
ausgelesen.
Das Lesen klappt schon wunderbar nur beim schreiben läuft es nicht so
richtig. Folgender Code:
1
voidwrite_page(){
2
uint16_twert=0x55;
3
4
// Löschen der Page, testweise Page 12
5
asm(
6
"ldi r30, 0x80 \n\t"
7
"ldi r31, 0x01 \n\t"
8
);
9
10
SPMCSR=0b00000011;// Kommando löschen
11
asmvolatile("spm");// ausführen
12
while((SPMCSR&(1<<SPMEN))==1);// warten bis fertig
13
14
15
16
// Füllen des Pagebuffers
17
for(uint8_ti=0;i<=SPM_PAGESIZE;i+=2){
18
asmvolatile(
19
"movw r30, %[page_adresse] \n\t"// adresse innerhalb der page
while((SPMCSR&(1<<SPMEN))==1);// warten bis fertig
28
}
29
30
31
// Schreiben der Page, testweise Page 12
32
asmvolatile(
33
"ldi r30, 0x80 \n\t"// hier wird die page ins Z-Register geladen Page: 12
34
"ldi r31, 0x01 \n\t"
35
);
36
37
SPMCSR=0b00000101;// Kommando für Page schreiben
38
asmvolatile("spm");// ausführen
39
while((SPMCSR&(1<<SPMEN))==1);// warten bis fertig
40
}
Die Funktion läuft ohne Probleme durch, aber im Hex-File ist die ganze
Page leer d.h. 0xFF ! Ich habe ganz nach dem Datenblatt gearbeitet
(Self-Programming) => Löschen, Page befüllen und dann Page wegschreiben.
Die boot.h-Lib klappt auf den Tiny's nicht, habe ich schon ausprobiert.
Sieht irgendjemand den Fehler?
Gruss Daniel
Die Funktion boot_rww_enable () aus der boot.h wird nicht
durchkompiliert. Grund ist, dass es das RWWSRE Bit auf den Tiny's nicht
gibt.
Alle AVR's die im Datenblatt nicht den Unterpunkt "Bootloader" haben,
können diese Funktionen nach meinen Wissen nicht nutzen, somit ist man
auf ein bisschen Assembler angewiesen.
Für Vorschläge bin ich natürlich gerne offen :)
daniel schrieb:> ich möchte gerne eine Tabelle in den Flash eines ATtiny44 schreiben.> Diese Tabelle wird nur einmal geschrieben und dann nur wieder> ausgelesen.
Warum bindest Du die Tabelle nicht in den Programmcode ein? Muss sie zur
Laufzeit erstellt werden? Es gäbe da auch noch das EEPROM...
daniel schrieb:> Die Funktion boot_rww_enable () aus der boot.h wird nicht> durchkompiliert. Grund ist, dass es das RWWSRE Bit auf den Tiny's nicht> gibt.
Bitte schreib' einen Bugreport:
https://savannah.nongnu.org/bugs/?group=avr-libc
Bugs, die keiner kennt, können auch nicht repariert werden.
> Alle AVR's die im Datenblatt nicht den Unterpunkt "Bootloader" haben,> können diese Funktionen nach meinen Wissen nicht nutzen, somit ist man> auf ein bisschen Assembler angewiesen.
Der ganze Bootloader-Code braucht natürlich an manchen Stellen den
inline-Assembler, aber eben dafür ist ja <avr/boot.h> gedacht, dass
sich dieser Code dort befinden kann und ihn nicht jeder aufs Neue
selbst schreiben muss.
irgendwo oben im Code (vor dem ersten Aufruf von boot_rww_enable().
Wenn ich die Beschreibung zwischen einem ATmega48 und einem ATtinyX4
vergleiche, dann scheinen sie beide der gleichen Prozedur zu folgen,
aber dieses Bit (obwohl an der gleichen Stelle) ist umbenannt worden.
Super, vielen Dank für eure Antworten !
Es geht um eine Korrekturtabelle, welche beim flashen des Controllers
einmal mit reingeladen wird. Zurzeit wird die Tabelle ins EEprom
geladen, aber dies ist zu klein, weil ich jetzt gerne eine höhere
Auflösung haben möchte.
Habe gerade gelesen, dass für das Selfprogramming ein Fuse-Bit gesetzt
werden, damit das SPMRC Register aktiviert wird. Leider ohne Erfolg.
Ist mein Code denn soweit korrekt ?
Gruss und 73 Daniel, do1yds
daniel schrieb:> War aber noch ein ziemlich blöder Fehler dabei, den ich hier nicht> nennen möchte :)
Warum nicht? Aber bitte unabhängig davon den avr-libc-Bugreport
einkippen, damit das nicht vergessen wird.
Da meine Memory-Fenster im AVR-Studio nicht funktionieren (aus welchen
Gründen auch immer), habe ich die Hex-Datei mit einem externen Programm
eingelesen. Problem war: ich habe immer die Hex-Files mir angeguckt,
welche auch auf den Attiny vom AVR-Studio programmiert wurden. Aber ich
musste nachdem das Programm durchgelaufen ist, die HEX-Datei aus dem
Flash lesen und dann mit HexViewer angucken. Das war eine kleine
Dummheit.
Bugreport schreibe ich noch, gerade etwas wenig Zeit :)
73 de Daniel
Danke für die Erklärung, ich dachte, es wäre am Beispielcode der
avr-libc was falsch oder dergleichen.
Wenn derartige kleine Dummheiten nicht immer im Wege wären, wäre
Programmierung ja auch ganz einfach. ;-)
Hallo!
Ich möchte den Thread wiederbeleben.
Leider komme ich nicht zum gewünschten Ergebnis. Der Flash wird zwar aus
dem Programm beschrieben, aber eben nicht mit &H55. Ich verwende hier
den ATtiny85.
1
#include<avr/io.h>
2
3
voidwrite_page(){
4
uint16_twert=0x55;
5
6
// Löschen der Page, testweise Page 12
7
asm(
8
"ldi r30, 0x80 \n\t"
9
"ldi r31, 0x01 \n\t"
10
);
11
12
SPMCSR=(1<<PGERS)+(1<<SPMEN);// Kommando löschen
13
asmvolatile("spm");// ausführen
14
while((SPMCSR&(1<<SPMEN))==1);// warten bis fertig
15
16
17
18
// Füllen des Pagebuffers
19
for(uint8_ti=0;i<=SPM_PAGESIZE;i+=2){
20
asmvolatile(
21
"movw r30, %[page_adresse] \n\t"// adresse innerhalb der page
Naja, schön ist auch was anderes. Ich würde die Funktion rein in ASM
schreiben, ist einfacher und deutlich übersichtlicher. Mit doc42055 von
ex. Atmel geht das recht leicht.
Falk B. schrieb:> Naja, schön ist auch was anderes. Ich würde die Funktion rein in ASM> schreiben, ist einfacher und deutlich übersichtlicher.
Ich bin echt überrascht, dass ein Regular von µc.net den Mut hat, sowas
so offen zu schreiben. Das ist neu.
Es gab mehr als genug Threads, wo ähnliche Vorschläge meinerseits
einfach wegzensiert wurden...
Falk B. schrieb:> Naja, schön ist auch was anderes.
Das stimmt, aber hier ging es nicht um Schönheit, sondern um Funktion.
Und der ursprüngliche Code funktionierte bei mir nicht. Über die Art und
Weise unter GCC ASM-Code einzubinden muß man kein Wort verlieren. Ist
wie alles in "C" unausgegorener Mist.
BlaBla schrieb:> Über die Art und Weise unter GCC ASM-Code einzubinden muß man kein Wort> verlieren.
Vor allem nicht, wenn man keine Ahnung davon hat: dann fehlen einem
für solch eine Diskussion nämlich ganz eindeutig die Grundlagen.
Dann macht man das, was der TE am Ende auch getan hat, und lässt
die entsprechenden inline asm statements andere schreiben. (Und
diejenigen, die sie dann schreiben dürfen, können sich freuen, dass
GCC einem so viel Flexibilität bei inline asm in die Hand gibt, dass
man den Optimierungen damit nicht im Weg herumstehen muss.)
Jörg W. schrieb:> Vor allem nicht, wenn man keine Ahnung davon hat: dann fehlen einem> für solch eine Diskussion nämlich ganz eindeutig die Grundlagen.
Das glaube ich nicht. Tatsache ist vielmehr: Die Runtime-Umgebung des
gcc verunmöglicht viele Optimierungen des Codes von ISRs, weil sie
frecherweise alles an sich reißt, was das System an Resourcen (im
konkreten Fall AVR8 natürlich vor allem: Registern) bietet und es keine
einfachen Möglichkeiten gibt, ihr diesen Scheiss abzugewöhnen.
Globally reserved registers wären aber nunmal das, was dem
Interruptsystem der AVR8 am allermeisten helfen könnte, schneller und
bezüglich der Latenz unkritischer zu werden.
Ganz klar: das kann natürlich nur funktionieren, wenn man für den
kompletten Code einer Anwendung die Quelltexte hat und nicht auf
irgendwelche Binaries angewiesen ist (also hinzugelinkte libs)
Dass aber der gcc nichtmal für den Fall, das man tatsächlich vollkommen
über den Code herrscht, Möglichkeiten für die potentiell effektivsten
Optimierungen von ISRs bereitstellt, ist eine absolute Schande.
c-hater schrieb:> Das glaube ich nicht.
Ich auch nicht – ich weiß es. :-)
Unser Nutzer Blabla hat einfach keine Ahnung, was der Inline Assembler
des GCC kann und warum er so extrem parametrierbar ist. Das muss er
auch nicht, denn diese Parametrierbarkeit ist in erster Linie für die
Macher der Bibliothek(en) gut – aber dann muss er diese natürlich auch
benutzen, statt irgendwelchen suboptimalen Code selbst zu hacken (oder
von anderen zu kopieren).
Wie gesagt: er hätte diesen Thread gar nicht aus der Kiste ausbuddeln
müssen, wenn er ihn sich zuvor bis zu Ende durchgelesen hätte. Die
Auflösung des Knotens (die dem TE damals geholfen hatte) steht ja drin.
@Jörg W. (dl8dtl) (Moderator) Benutzerseite
>Unser Nutzer Blabla hat einfach keine Ahnung, was der Inline Assembler>des GCC kann und warum er so extrem parametrierbar ist. Das muss er>auch nicht, denn diese Parametrierbarkeit ist in erster Linie für die>Macher der Bibliothek(en) gut – aber dann muss er diese natürlich auch>benutzen, statt irgendwelchen suboptimalen Code selbst zu hacken (oder>von anderen zu kopieren).
avr gcc inline assembler- Separates the boys from the men.
;-)
Falk B. schrieb:> avr gcc inline assembler- Separates the boys from the men.
Smiley gesehen, dennoch: seine Parametrierung erlaubt es, den damit
injizierten Assemblercode so gut wie's geht an das anzupassen, was
der Compiler selbst erzeugt. Je freigiebiger man dabei die Constraints
formulieren kann, um so größer die Chance, dass der Compiler unnützes
Umspeichern etc. vermeiden kann, weil er die Operanden bereits passend
in den Registern halten kann.
Auf einem klassischen x86 gibt's da ohnehin nicht viel Freizügigkeit,
aber gerade beim AVR-GCC mit seinen vielen Registern kann man an dieser
Stelle durchaus gewinnen.
Jörg W. schrieb:> aber gerade beim AVR-GCC mit seinen vielen Registern kann man an dieser> Stelle durchaus gewinnen.
Und man könnte noch sehr viel mehr gewinnen, wenn man C im Allgemeinen
und den gcc im Besonderen nicht zum Mass aller Dinge und zur unbedingten
Notwendigkeit hochstilisieren würde...
Nein, schon konkurrierende C-Compiler zeigen die furchtbaren
Einschränkungen des gcc insbesondere effizienten Code in ISRs
betreffend.
Pure Asm natürlich sowieso...
Da hilft auch die Parametrierung des Code für Inline-Asm nicht. Es fehlt
einfach nur die Möglichkeit, dem Codegenerator Register komplett zu
entziehen, um wirklich effiziente ISRs schreiben zu können. Die
Konkurrenz kann das seit langem, warum also nicht der gcc?
c-hater schrieb:> furchtbaren Einschränkungen des gcc insbesondere effizienten Code in> ISRs betreffend
… um die es in diesem Thread bloß absolut nicht geht. (Davon abgesehen:
wirklich ineffizient ist er eigentlich nur für extrem kurze ISRs, die
man in der Praxis gar nicht so oft hat, und wenn, dann spricht nichts
dagegen, diese tatsächlich gleich als Assemblercode reinzuwerfen.)
Ansonsten habe ich auch schon „konkurrierende“ Inline-Assembler
gesehen, bei denen man erstmal merkt, was einem so ein GCC wirklich
bietet. Da war nämlich das einzig garantierte Übergabeelement
zwischen C- und Assemblercode globale Variablen. Auf Register kann
man natürlich zugreifen, aber irgendeine Garantie dafür, was man
in welchem Register findet, gab's gar nicht. Kann also schon mit der
nächsten Compilerversion anders sein.
Du kannst mir gern andere Hochsprachen zeigen, die das viel besser
gelöst haben – über pure Assemblerprogrammierung für komplette Projekte
brauchen wir aber nicht mehr zu reden, die Zeiten sind vorbei, den
Aufwand kann und will keiner bezahlen.
ps:
> Die Konkurrenz kann das seit langem, warum also nicht der gcc?
Klar kann der das auch. Das Einzige, was eben nicht geht ist, dabei
eine vorcompilierte Bibliothek dazu zu linken, denn die müsste die
gleiche globale Reservierung des Registers natürlich zu ihrer
Compilezeit gesehen haben. Es steht dir aber allemal frei, die
Bibliothek(en) mit der gleichen globalen Reservierung neu zu
compilieren, wenn du das willst.
Jörg W. schrieb:> c-hater schrieb:>> furchtbaren Einschränkungen
also fast lebensbedrohend, oder wie?
>> des gcc insbesondere effizienten Code in ISRs betreffend>> … um die es in diesem Thread bloß absolut nicht geht. (Davon abgesehen:> wirklich ineffizient ist er eigentlich nur für extrem kurze ISRs, die> man in der Praxis gar nicht so oft hat, und wenn, dann spricht nichts> dagegen, diese tatsächlich gleich als Assemblercode reinzuwerfen.)
Oder man benutzt 8.x, der kann leere ISR's zu einem IRET eindampfen.
Vielleicht lâst man das mit dem Interrupt baer auch gleich, wenn man eh
nur das INT-Flag von a nach b kopieren will, um b (volatile) in der
main-Loop abzufragen. Jede sinnvolle ISR braucht den "overhead" eh.
Ich vermute das ist in 8.x nur drin, weil damit die ewigen Nörgeler
beruhigt werden sollen und weil der Maintaier zeigen wollte, daß es
geht. Beides ist ok, nur bis dIe Zielgruppe das mitbekommt, wird noch
einige Zeit vergehen.