Hallo, MCU: ATMega168, GCC habe in meinem Code 3 globale Flags, bei denen ich nur Bits schreibe, lösche und abfrage. Wollte meinen Code nun hinsichtlich Geschwindigkeit und Größe optimieren und die GPIOR0-2 register nutzen. Habe es zunächst so probiert: #define flags1 GPIOR0 #define flags2 GPIOR1 #define flags3 GPIOR2 dadurch wurde der Code sogar leicht größer! Habe dann hier: http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung gelsen und das ganze so probiert register uint8_t counter8_1 asm("r2"); das ist offensichtlich falsch, ich erhalte die fehlermeldung: invalid register name for 'flags1' wie geht es richtig? dankeschön
Versuchs einfach mal mit Bitvariablen:
1 | #include <avr\io.h> |
2 | // Access bits like variables:
|
3 | |
4 | struct bits { |
5 | uint8_t b0:1; |
6 | uint8_t b1:1; |
7 | uint8_t b2:1; |
8 | uint8_t b3:1; |
9 | uint8_t b4:1; |
10 | uint8_t b5:1; |
11 | uint8_t b6:1; |
12 | uint8_t b7:1; |
13 | } __attribute__((__packed__)); |
14 | |
15 | #define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
|
16 | #define SBIT(x,y) SBIT_(x,y)
|
17 | |
18 | #define blabla SBIT( GPIOR0, 0 )
|
19 | #define blublu SBIT( GPIOR1, 7 )
|
20 | #define blibli SBIT( GPIOR2, 6 )
|
21 | |
22 | |
23 | void test( void ) |
24 | {
|
25 | blabla = 1; |
26 | blublu = 0; |
27 | blibli = 1; |
28 | |
29 | if( blabla && !blublu ) |
30 | blibli = 0; |
31 | }
|
Allerdings ist nur GPIOR0 bitadressierbar. Peter
@ Peter
> Allerdings ist nur GPIOR0 bitadressierbar.
Kannst du das erläutern ?
Wenn ich in Assembler denke, dann sieht doch der Mechanismus so aus:
IN R16, GPIORx
Register R16 manipulieren und dann ggf.:
OUT GPIORx, R16
oder die direkte Abfrage eines einzelnen Bits mit
SBIS GPIORx, y ; Skip if Bit.y in I/O Register is set
SBIC GPIORx, y ; Skip if Bit.y in I/O Register is cleared
(mit der Einschränkung, dass dies nur mit I/O Adresse 0-31 funktioniert,
beim attiny25 liegen GPIOR0 - GPIOR2 bei 0x11 - 0x13, sollte also
funktionieren)
Habe ich da Wesentliches übersehen ?
@ ubbut
Ich verwende auch gerne freie I/O-Register als volatile-Variablen,
denn bezahlt habe ich sie schließlich.
Das gewinnt einige zusätzliche Bytes - die nebenbei noch schnell im
Zugriff sind.
Nach meiner Erinnerung wurde der Programmcode dadurch auch immer kürzer.
Probleme hatte ich immer mit den neuern mc's, wenn ich z.B. Timer
explizit
im Register PRR abgeschaltet habe - dann waren die zugehörigen Register
nicht mehr nutzbar.
mfg
Michael S.
Michael S. wrote: > (mit der Einschränkung, dass dies nur mit I/O Adresse 0-31 funktioniert, > beim attiny25 liegen GPIOR0 - GPIOR2 bei 0x11 - 0x13, sollte also > funktionieren) Es ging aber um den ATMega168. Peter
Hallo, habe gerade nochmal rumprobiert und zwar nicht die Lösung, aber zumindest wahrscheinlich den Grund dafür gefunden, dass mein Code größer wird. Beim ersetzen von zwei Flag Variablen durch die GPIORx regiter wird der Code tatsächlich kleiner, bei einer bestimmten aber erheblich größer. Die entsprechende Variable verwende ich im Code stellenweise auch so: array[1 & flag_variable] könnte das der Grund sein?
Der Hauptgrund dürfte darin liegen, dass die GPIORx wahrscheinlich wie alle anderen I/O-Register "volatile" sind, und daher nicht auf CPU-Register optimiert werden. Bei Operationen wie "Bit setzen" und "Bit abfragen" stört das nicht. Bei anderen hingegen schon.
@ Peter, stimmt auffallend. Für meine Zwecke sind die Tinys meist völlig ausreichend. Bei den Megas macht der Einsatz von I/O-Registern offensichtlich keinen rechten Sinn mehr, der Speichergewinn in nicht nennenswert - und die Vorteile im einfacheren Zugriff entfallen. Beim Mega168 liegen ausser PORTD und GPIOR0 tatsächlich alle Register oberhalb der Adresse 31. Man lernt halt immer wieder dazu. Michael S.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.