www.mikrocontroller.net

Forum: Compiler & IDEs variable/zeiger in GPIOR0 fest registrieren


Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

ich würde gerne eine variable oder einen zeiger fest in dem
register GPIOR0 registrieren. hab aber keine ahnung wie das
gehen soll.
hab schon mehrere sachen ausprobiert, klappt aber nicht.

das geht nicht:
asm(".DEF meins = GPIOR0");
register unsigned char *bytesOfSec asm("meins");   

das auch nicht:
register unsigned char *bytesOfSec asm("GPIOR0");   


muss dazu sagen, ich hab keine ahnung von asm.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GPIOR0 ist ein I/O-Register und kein Rechenregister! Deshalb ist der 
Speicherklassenqualifizierer register sowieso fehl am Platze, weil er 
sich auf den Rechenregistersatz bezieht. I/O-Register sind (im Prinzip 
zumindest, abgesehen von speziellen Maschinenbefehlen zum Zugriff auf 
einen Teil von ihnen) relativ normale SRAM-Zellen und werden auch wie 
solche angesprochen. GPIOR0 ist also nix anderes als z.B. PORTA oder 
TCCR1A...

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm,

dann bringt mir das nix...

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So geht's mit avr-gcc und avr-ld

Du legst die Variable in eine Section und lokatierst wo es eben hin 
soll.

Hier ein Beispiel für ATmega8 und TCNT1 (0x004c)
unsigned char *x __attribute__ ((section ("bar")));

void foo (void)
{
    *x = 0x42;
}

Gelinkt wird mit --section-start bar=0x8004c

Der obige Code wird dann
<foo>:
     198:  e0 91 4c 00   lds  r30, 0x004C
     19c:  f0 91 4d 00   lds  r31, 0x004D
     1a0:  82 e4         ldi  r24, 0x42
     1a2:  80 83         st  Z, r24
     1a4:  08 95         ret

hack as hack can

Das ganze geht auch via Linkersymbol:

 --defsym bazz=0x8004c als ld-Option
extern unsigned char *bazz;

void foo (void)
{
    *bazz = 0x42;
}

Der Code wird wie oben.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...last not least gibt's noch die Version
#define P (*((unsigned char**) (&TCNT1)))

void foo (void)
{
    *P = 0x42;
}

Die allerdings Neuübersetzung braucht, wenn sich die Adresse des SFR 
ändert (oben muss nur neu gelinkt werden).

der Code ist:
<foo>:
     198:  ec b5         in  r30, 0x2c  ; 44
     19a:  fd b5         in  r31, 0x2d  ; 45
     19c:  82 e4         ldi  r24, 0x42  ; 66
     19e:  80 83         st  Z, r24
     1a0:  08 95         ret

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jau,

das sieht sehr gut aus, danke !

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute mal Du brauchst das für

Beitrag "Unbenutztes Register im 8-Bit Atmel?"

Falls es kein 16-Bit-Register gibt, sondern nur 2 zerstreute 
8-Bit-Register, geht das auch (in allen 3 Varianten). Wird nur noch 
etwas mehr Hack, aber der Code ist im Endeffekt der gleiche von Laufzeit 
und Platzbedarf her.

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja,
den beitrag hatte ich auch schon gelesen.
was ich noch nicht ganz verstehe ist, das GPIOR0 register liegt im 
bereich der "working register" wo man schnell drauf zugreifen kann, wenn 
ich aber den code so wie oben beschrieben nutze, benutzt der compiler 
den pointer wie einen pointer auf sram...

das sind hier wären nur 6 clocks, aber ein ganzes register weg...
register unsigned char p asm("r3");  

void foo4 (void){
     cb6:  a2 e4         ldi  r26, 0x42  ; 66
     cb8:  3a 2e         mov  r3, r26
     cba:  08 95         ret

der code bringt 9 clocks:
#define P (*((unsigned char**) (&TCNT1)))

void foo (void)
{
    *P = 0x42;
}

die anderen oben beschriebenen varianten beide 11 clocks.

es gibt da eine variable die long int ist bei mir und teils 6*10^6 oder 
noch öfter geschrieben wird, da ist der geschwindigkeitszuwachs mit 
einer registrierung in einem register enorm. z.b. von 31 sec auf 26 
sec...


ps: bei der linker option fehlte eine 0 glaub ich, bei mir läuft das nur 
so: -Wl,--section-start=bar=0x80002B,--defsym=bazz=0x80001E
(atmega168 bar=GPIOR2 bazz=GPIOR0)

grüße daniel

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel Platte wrote:
> ja,
> den beitrag hatte ich auch schon gelesen.
> was ich noch nicht ganz verstehe ist, das GPIOR0 register liegt im
> bereich der "working register" wo man schnell drauf zugreifen kann, wenn
> ich aber den code so wie oben beschrieben nutze, benutzt der compiler
> den pointer wie einen pointer auf sram...

Klaro, so ist's ja auch auf C-Ebene formuliert und für I/O-Regs bzw IN, 
OUT, SBI, CBI, SBIC, SBIS gibt's AFAIK keine Relocs. Wüsst auch garnet 
wie man das GCC ohne neue Qualifier beibringen sollte (übliches Problem 
bei Harvard-Architektur).

Der Compiler kann nur dann Instruktionen wie IN etc. verwenden, wenn er 
die Adresse kennt. Ok? Bei den ersten 2 Beispielen ist die zur 
Compilezeit nicht bekannt, erst zur Link-Zeit. Dividier für Dich nochmal 
die Schritte auseinander, wie man zu nem hex-File kommt, was da jeweils 
gemacht wird und welche Infos man jeweils hat bzw. nicht hat.

1) Präprozess c->i
2) Compile i->s
3) Assemble i->o
4) Link o->elf
5) Hexify elf->hex

> das sind hier wären nur 6 clocks, aber ein ganzes register weg...
>
>
> register unsigned char p asm("r3");
> 
> void foo4 (void){
>      cb6:  a2 e4         ldi  r26, 0x42  ; 66
>      cb8:  3a 2e         mov  r3, r26
>      cba:  08 95         ret
> 
>
> der code bringt 9 clocks:
>
>
> #define P (*((unsigned char**) (&TCNT1)))
> 
> void foo (void)
> {
>     *P = 0x42;
> }
> 
>
> die anderen oben beschriebenen varianten beide 11 clocks.
>
> es gibt da eine variable die long int ist bei mir und teils 6*10^6 oder
> noch öfter geschrieben wird, da ist der geschwindigkeitszuwachs mit
> einer registrierung in einem register enorm. z.b. von 31 sec auf 26
> sec...
>

Ich vermute mal Du verwendest avr-gcc und avr-binutils.

Falls Du keine (lib-)Funktionen verwendest, die R2-R5 verwenden, kannst 
Du die zum Speichern nehmen als globales Register. Da gcc die eh kaum 
verwendet, ist's nicht dramatisch.

In einigen lib-Funktionen werden diese Regs jedoch verwendet.

0) Überleg Dir GENAU, was es bedeutet, ein GPR zu einem globalen 
Register zu machen!
1) Du übersetzt Dein Projekt mit -ffixed-2 -ffixed-3 -ffixed-4 -ffixed-5
2) Wenn im hex-Dump eins von r2-r5 verwendet wird, geht's so nicht. Evtl 
kommt die Verwendung von call-prologues, das ist wiederum ok.

3) Die Variable p kommt in ein globales Register
   register unsigned long p asm ("r2");

> ps: bei der linker option fehlte eine 0 glaub ich, bei mir läuft das nur
> so: -Wl,--section-start=bar=0x80002B,--defsym=bazz=0x80001E
> (atmega168 bar=GPIOR2 bazz=GPIOR0)

Jo, die VMAs sieht man im map-File und im elf-Dump

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.