Hallo,
ich habe ein kleines Problem (welches vermutlich irgendwo schon bis in's
letzte Detail erklärt ist... nur finde ich diese Stelle nicht).
Programmiersprache ist C++ (gcc-avr), µC ist ein ATmega32u4
Ich habe ein paar Arrays im C++-Teil meines Projektes. Diese folgen
durchweg diesem Schema:
Ich muss in einem kleinen inline-assembly Teil auf vier verschiedene
davon zugreifen, d.h. ich kann nicht einfach den g++ die Addresse in's
Z-register (bzw. X/Y) schieben lassen sondern muss irgendwie "direkt" an
die Adresse herankommen.
1
"ldi r30, pm_lo8(data) \n\t"
2
"ldi r31, pm_hi8(data) \n\t"
3
"lds r16, (offset) ; range [0..255] ! \n\t"
4
"asr r16 ; shift down by two bits \n\t"
5
"asr r16 ; so range is [0...63] \n\t"
6
"add r30, r16 ; add offset \n\t"
7
"adc r31, r0 ; add carry (and r0=0) \n\t"
8
"lpm r17, Z ; load value into r17 \n\t"
Dabei habe ich verschiedene Probleme:
1. Wenn ich das Array ohne einen (zusätzlichen) 'volatile' anlege,
bekomme ich einen 'undefined reference "data"'... und ich verstehe nicht
warum?!
2. Es ist bestimmt ein dummer (Verständnis-)Fehler, aber die Werte die
ich in 'r17' erhalte, sind nicht die aus dem Array sonder
"irgendeinwasauchimmer"...
Es ist nicht das erste Mal, dass ich Assembler schreibe, wohl aber für
AVR... Wenn also jemand so freundlich wäre, mir das Brett vorm Kopf
abzumontieren? Ich würde gern verstehen, was ich da Dümmliches tue...
Vielen lieben Dank,
Stefan
Stefan F. schrieb:> "asr r16 ; shift down by two bits> \n\t"> "asr r16 ; so range is [0...63]> \n\t"
Das hätte natürlich ein "lsr" sein sollen... asr macht es nicht
besser... :-P
Stefan F. schrieb:> Ich muss in einem kleinen inline-assembly Teil auf vier verschiedene> davon zugreifen, d.h. ich kann nicht einfach den g++ die Addresse in's> Z-register (bzw. X/Y) schieben lassen
Warum nicht?
> 1. Wenn ich das Array ohne einen (zusätzlichen) 'volatile' anlege,> bekomme ich einen 'undefined reference "data"'... und ich verstehe nicht> warum?!
Meine Vermutung: Wenn du aus dem C++-Code nicht darauf zugreifst und es
auch in den Operandenlsten deines asm-Blocks nicht erwähnst, meint der
Compiler, es wäre unbenutzt und wirft es raus.
Rolf M. schrieb:> Meine Vermutung: Wenn du aus dem C++-Code nicht darauf zugreifst und es> auch in den Operandenlsten deines asm-Blocks nicht erwähnst, meint der> Compiler, es wäre unbenutzt und wirft es raus.
Könnte so sein, ja. Compiler sind halt ziemlich doof, halten sich aber
für intelligent, sogar für so intelligent, um die Einschübe der wirklich
Intelligenten (also der Menschen) missachten zu dürfen...
Naja, zumindest, bis man ihnen klar gemacht hat, was sie nicht
missachten dürfen...
Rolf M. schrieb:> Stefan F. schrieb:>> Ich muss in einem kleinen inline-assembly Teil auf vier verschiedene>> davon zugreifen, d.h. ich kann nicht einfach den g++ die Addresse in's>> Z-register (bzw. X/Y) schieben lassen>> Warum nicht?
Weil es dafür zu viele sind. Ich habe drei Addressregister die ich mir
"vorfüllen" lassen könnte (X,Y,Z). Ich habe aber vier Arrays auf die ich
zugreifen muss.
>> 1. Wenn ich das Array ohne einen (zusätzlichen) 'volatile' anlege,>> bekomme ich einen 'undefined reference "data"'... und ich verstehe nicht>> warum?!>> Meine Vermutung: Wenn du aus dem C++-Code nicht darauf zugreifst und es> auch in den Operandenlsten deines asm-Blocks nicht erwähnst, meint der> Compiler, es wäre unbenutzt und wirft es raus.
Es wird aus dem C++-Code ebenfalls darauf zugegriffen. Es ist also
vorhanden. Sogar in derselben Source-Datei. Und der Zugriff aus C++
funktioniert.
Interessant...
... es funktioniert, wenn ich dies tue:
1
extern"C"
2
{
3
PROGMEMvolatileconstuint8_tdata[64]=
4
{
5
...
6
};
7
8
volatileuint8_toffset=0;
9
}
1
"ldi r30, lo8(data) \n\t"
2
"ldi r31, hi8(data) \n\t"
3
"lds r16, (offset) ; range [0..255] ! \n\t"
4
"lsr r16 ; shift down by two bits \n\t"
5
"lsr r16 ; so range is [0...63] \n\t"
6
"add r30, r16 ; add offset \n\t"
7
"adc r31, r0 ; add carry (and r0=0) \n\t"
8
"lpm r17, Z ; load value into r17 \n\t"
Mit lo8()/hi8() anstelle von pm_lo8()/pm_hi8() bekomme ich jetzt die
richtige Adresse und die richtigen Daten aus dem Array. Das Array liegt
aber definitiv im PROGMEM. Siehe "lpm"... Zugriff auf der C++-Seite
erfolgt über pgm_read_byte_near().
Hmm,... jetzt habe ich zwar eine funktionierende Lösung allerdings beißt
sich diese mit dem was ich dazu in "diverser" Dokumentation finde...
Das mit dem "volatile" ist auch irritierend. /me --> confused... :-)
c-hater schrieb:> Könnte so sein, ja. Compiler sind halt ziemlich doof, halten sich aber> für intelligent, sogar für so intelligent, um die Einschübe der wirklich> Intelligenten (also der Menschen) missachten zu dürfen...>> Naja, zumindest, bis man ihnen klar gemacht hat, was sie nicht> missachten dürfen...
viell blahblah abba keine hilfe1
anung schenst du ja nicht zu habben