Forum: Compiler & IDEs direkt in ein Register des Tiny5 schreiben


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Svensson (svensson)


Lesenswert?

Hallo liebe Gemeinde,

ich möchte auf einem AT Tiny5 direkt mit dem Register PCMSK (0x10) 
arbeiten. Also ungefähr so:
1
PCMSK |= (1<<PCINT0);    //enable pin change interrupt on PB3

Wie macht man so etwas in einem C-Script für avr-gcc?

PCMSK ist doch auch nur eine Definition für irgendetwas, um sich das 
Leben einfacher zu gestalten.

Vielen Dank im voraus

Svensson

von Nemopuk (nemopuk)


Lesenswert?

In jeder halbwegs ordentlichen IDE kannst mit gedrückt gehaltener Strg 
Taste auf PCMSK klicken, dann siehst du, wie es definiert ist. Es ist 
ein Zeiger mit der Adresse des Registers.

Und PCINT0 ist schlicht eine Zahl und zwar die Nummer dieses Bits.

Direkter als
> PCMSK |= (1<<PCINT0);
sowie
> PCMSK &= ~(1<<PCINT0);
geht es in C nicht, weil die Programmiersprache keine gesonderte Syntax 
für Register hat und auch nicht für dem Zugriff auf einzelne Bits. Aber 
keine Sorge, der Compiler ist so schlau, diese Zeile in einen einzigen 
CPU Befehl umzusetzen, auch wenn sie eher nach einer Kombo aus 
read+modify+write back aussieht.

: Bearbeitet durch User
von Svensson (svensson)


Lesenswert?

Okay wenn es in C nicht geht, wie schreibe ich das dann in 
Inline-Assembler um?
1
asm {
2
      "ldi r16,0x4\n"
3
      "mov r10,r16\n"
4
}

von Oliver S. (oliverso)


Lesenswert?

Svensson schrieb:
> Okay wenn es in C nicht geht, wie schreibe ich das dann in

Dann nochmal etwas deutlicher:

Was funktioniert denn an „PCMSK |= (1<<PCINT0);“ nicht?

Oliver

von Svensson (svensson)


Lesenswert?

Ich habe in meiner IDE keine vorgegebene io.h für den Tiny5. In der Doku 
habe ich gelesen, daß PCMSK das Register 0x10 ist.

Ich brauche auch nur diesen einen direkten Befehl, um das eine Bit im 
PCMSK zu setzen. Der Rest ist dann Standard C.

von Oliver S. (oliverso)


Lesenswert?


von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Svensson schrieb:

> Ich habe in meiner IDE keine vorgegebene io.h für den Tiny5.

Dann sorg' dafür, dass du eine hast. Der Tiny5 ist dermaßen 
übersichtlich, das man die zur Not sogar von Hand verfassen könnte. Aber 
warum sollte man? Gibt's ja schließlich fix und fertig von MC.

Musst du halt die IDE wechseln. Welche ist es den derzeit?

von Nemopuk (nemopuk)


Angehängte Dateien:

Lesenswert?

Svensson schrieb:
> Ich habe in meiner IDE keine vorgegebene io.h für den Tiny5.

Aber die avr-libc bringt die Header mit.
1
#define __SFR_OFFSET 0x00
2
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
3
4
#define PCMSK _SFR_IO8(0x10)
5
#define PCINT0 0
6
#define PCINT1 1
7
#define PCINT2 2
8
#define PCINT3 3

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Svensson schrieb:
> Okay wenn es in C nicht geht, wie schreibe ich das dann in

Das hat KEINER geschrieben! Versuchs mal mit sinnerfassendem Lesen!

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Nemopuk schrieb:

> Aber die avr-libc bringt die Header mit.

Ja klar. Deswegen führt nur die Beantwortung meiner Frage, welche IDE 
dee TO eigentlich verwendet (und damit der Frage, welche Toolchain und 
damit wiederum welche Header).

Genau diese eine zentrale Frage wurde vom TO allerdings negativ 
bewertet.

Sprich: Das ist ganz offensichtlich ein Troll, der sich darum sorgt, 
dass sein Troll-Thread zu kurz wird.

von Nemopuk (nemopuk)


Lesenswert?

Nemopuk schrieb:
1
#define __SFR_OFFSET 0x00
2
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
3
#define PCMSK _SFR_IO8(0x10)
Mir fehlt da der Pointer. Aber ich bin ganz sicher, die Zeilen korrekt 
aus den Headern heraus kopiert zu haben. Und war da nicht auch was mit 
volatile?

Vielleicht kann das jemand erklären.

: Bearbeitet durch User
von Nemopuk (nemopuk)


Lesenswert?

Nemopuk schrieb:
> Vielleicht kann das jemand erklären.

Ich hab's selbst gefunden. Ich habe wohl doch die falschen Zeilen 
kopiert.

So sieht es besser aus:
1
#define __SFR_OFFSET 0x00
2
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
3
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
4
#define PCMSK _SFR_IO8(0x10)

Man kann die Definition von PCMSK so zusammen fassen:
1
#define PCMSK (*(volatile uint8_t *)(0x10))

Also ein Zeiger auf ein volatiles 8 Bit Register an Adresse 0x10. So 
hatte ich das auch in Erinnerung.

: Bearbeitet durch User
von Svensson (svensson)


Lesenswert?

Nemopuk schrieb:
> Man kann die Definition von PCMSK so zusammen fassen:
> #define PCMSK (*(volatile uint8_t *)(0x10))
>
> Also ein Zeiger auf ein volatiles 8 Bit Register an Adresse 0x10. So
> hatte ich das auch in Erinnerung.

Danke! Das ist genau das, was ich gesucht hatte. Und schon ist der 
Fehler weg...

Ob S. schrieb:
> Der Tiny5 ist dermaßen
> übersichtlich, das man die zur Not sogar von Hand verfassen könnte.

Das kann man wohl sagen. Das "Programm" ist so ungefähr 20 Zeilen lang. 
Im Grunde ist es ein Luxus-Timer; ist auch nicht mein Ding - ich soll es 
nur kompilieren. Kompliliert sind es 470 Byte, also eher übersichtlich.

Ob S. schrieb:
> Genau diese eine zentrale Frage wurde vom TO allerdings negativ
> bewertet.

Ich habe gar nichts bewertet.

Hintergrund: Ich habe schon den ganzen Tag verplempert, um das 
Miniprogramm zu übersetzen. War schon kurz davor, das gleich in 
Assembler neu zu schreiben. :-(
Beim Atmel Studio 4.19 habe ich wohl vergessen wie es geht, außerdem ist 
der Tiny5 grau in der Liste. Bei avr-gcc (avr8-gnu-toolchain 3.7.x) 
erhalte ich die Meldung, daß beim Tiny5 nur Assembler unterstützt wird. 
Ebenso beim WinAVR. Dann habe ich mir den GCC 10.3 heruntergeladen, aber 
in der 1000+x-seitigen Doku habe ich nur -mmcu=avrtiny gefunden, der 
aber nicht laufen will.
VS mit PlatformIO habe ich mir auch heruntergeladen, aber das ist auch 
nichts für mal eben schnell.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Du hast einfach nur eine hornalte Toolchain. Besorg dir was aktuelles, 
und fertig ist der Lack.

von Svensson (svensson)


Lesenswert?

Nun, die avr8-gnu-toolchain habe ich von Microchip heruntergeladen. Das 
war schon die neueste Version (von 2022).

Den gcc habe ich direkt von der Projektwebsite. Da habe ich extra den 
älteren 10.3 gewählt, weil es doch angeblich mit den neueren irgenwelche 
Probleme gab.

von A. B. (Firma: ab) (bus_eng)


Lesenswert?


von Norbert (der_norbert)


Lesenswert?

Svensson schrieb:
> Den gcc habe ich direkt von der Projektwebsite. Da habe ich extra den
> älteren 10.3 gewählt, weil es doch angeblich mit den neueren irgenwelche
> Probleme gab.


A. B. schrieb:
> aktuell ist gcc-15.2.0 von 2025-08-08

1
~$ find /usr/lib/gcc/avr/ /usr/lib/avr -iname "iotn5*.h" -exec grep -E "tiny|PCMSK" {} \;
2
/* avr/iotn5.h - definitions for ATtiny5 */
3
#ifndef _AVR_ATtiny5_H_
4
#define _AVR_ATtiny5_H_ 1
5
#define PCMSK _SFR_IO8(0x10)
6
#endif /* _AVR_ATtiny5_H_ */
1
~$ avr-gcc -v
2
Using built-in specs.
3
Reading specs from /usr/lib/gcc/avr/5.4.0/device-specs/specs-avr2
4
COLLECT_GCC=avr-gcc
5
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/5.4.0/lto-wrapper
6
Target: avr
7
Configured with: ../gcc/configure -v --enable-languages=c,c++ --prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr CFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong -Wformat ' CPPFLAGS='-Wdate-time -D_FORTIFY_SOURCE=2' CXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong -Wformat ' FCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong' FFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong' GCJFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong' LDFLAGS=-Wl,-z,relro OBJCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong -Wformat ' OBJCXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-Q3AFj7/gcc-avr-5.4.0+Atmel3.6.2=. -fstack-protector-strong -Wformat '
8
Thread model: single
9
gcc version 5.4.0 (GCC)

von Peter D. (peda)


Lesenswert?

Svensson schrieb:
> ich möchte auf einem AT Tiny5 direkt mit dem Register PCMSK (0x10)
> arbeiten. Also ungefähr so:
1
PCMSK |= (1<<PCINT0);    //enable pin change interrupt on PB3
> Wie macht man so etwas in einem C-Script für avr-gcc?

Nicht nur ungefähr, sondern genau so.
Falls eine Fehlermeldung kommt, hast Du noch diese Zeile vergessen:
1
#include <avr/io.h>
Oder das falsche Target ausgewählt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Svensson schrieb:
> Also ungefähr so:
>
> PCMSK |= (1<<PCINT0);    //enable pin change interrupt on PB3
>
> Wie macht man so etwas in einem C-Script für avr-gcc?

Das geht so nicht. In C müssen Anweisungen in einer Funktion stehen.

von Svensson (svensson)


Lesenswert?

Norbert schrieb:
>
1
> Reading specs from /usr/lib/gcc/avr/5.4.0/device-specs/specs-avr2
2
> ...
3
> gcc version 5.4.0 (GCC)
4
>

Sagt mir das, es wird der gcc in Version 5.4.0 benutzt? Dann wäre das 
auch nicht "modern".

A. B. schrieb:
> aktuell ist gcc-15.2.0 von 2025-08-08
>
> https://github.com/ZakKemble/avr-gcc-build/releases/tag/v15.2.0-1

Tausend Dank! Das ist offensichtlich genau das, was ich gleich hätte 
verwenden sollen.

Johann L. schrieb:
> Das geht so nicht. In C müssen Anweisungen in einer Funktion stehen.

Erbsenzähler. :-) Im Zweifel steht es dann in setup{} oder main{}

von Norbert (der_norbert)


Lesenswert?

Svensson schrieb:
> Sagt mir das, es wird der gcc in Version 5.4.0 benutzt? Dann wäre das
> auch nicht "modern".

Das sagt dir, dass das Headerfile für den ATtiny5 bereits dort vorhanden 
ist und nur auf die passende Einbindung wartet.
Bevorzugt per ›io.h‹ und passendem Target.

von Harald K. (kirnbichler)


Lesenswert?

Svensson schrieb:
> Im Zweifel steht es dann in setup{}

Das riecht nach Arduino, und das ist dann kein C, sondern C++.

von Norbert (der_norbert)


Lesenswert?

Harald K. schrieb:
> Svensson schrieb:
>> Im Zweifel steht es dann in setup{}
>
> Das riecht nach Arduino, und das ist dann kein C, sondern C++.

Wobei das hier: ›setup{}‹
nach einem völlig neuen language feature aussieht. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Svensson schrieb:
> Sagt mir das, es wird der gcc in Version 5.4.0 benutzt?

Das sagt dir
1
$ avr-gcc --version

Und selbst wenn es eine v5.4 ist, bereits damals vor fast 10 Jahren 
wurde AVRrc (Reduced Core) schon unterstützt:

https://gcc.gnu.org/gcc-5/changes.html#avr

von Svensson (svensson)


Lesenswert?

Johann L. schrieb:
> Das sagt dir$ avr-gcc --version
>
> Und selbst wenn es eine v5.4 ist, bereits damals vor fast 10 Jahren
> wurde AVRrc (Reduced Core) schon unterstützt:

Ich erhalte als Antwort:
avr-gcc (AVR_8_bit_GNU_Zoolchain_3.7.0.1796> 7.3.0

Also müßte der funktionieren, aber das tut er nicht. Es kommt die 
Meldung, daß nur Assembler unterstützt wird für -mmcu=attiny5.

> das ist dann kein C, sondern C++

Der gcc ist doch ein C-Compiler, der gpp ist doch der Compiler für C++, 
oder?

Außerdem müßte das doch egal sein, denn ein C++-Compiler müßte doch auch 
Standard-C übersetzen können?

von Peter D. (peda)


Lesenswert?

Habs eben probiert mit 5.4.0 (= AS7) und 7.3.0, geht beides:
1
int main(void)
2
{
3
  PCMSK |= (1<<PCINT0);
4
  28:  80 9a         sbi  0x10, 0  ; 16

von Norbert (der_norbert)


Lesenswert?

Peter D. schrieb:
> Habs eben probiert mit 5.4.0 (= AS7) und 7.3.0, geht beides:
> int main(void)
> {
>   PCMSK |= (1<<PCINT0);
>   28:  80 9a         sbi  0x10, 0  ; 16

Das ist aber vermutlich 7.3.0 output, oder?
Der alte 5.4.0 erzeugt zumindest bei mir hier nämlich noch einen ganzen 
Sack mehr. Egal in welcher Optimierungsstufe (O0|O1|O2|Os).
1
#include <avr/io.h>
2
// avr-gcc -Wall -Wextra -pedantic -mmcu=attiny5 -os -o x x.c && avr-objdump -d x > xs.lst
3
4
int main(void) {
5
    PCMSK |= (1<<PCINT0);
6
    return 0;
7
}
1
00000000 <main>:
2
   0:  cf 93         push  r28
3
   2:  df 93         push  r29
4
   4:  cd b7         in  r28, 0x3d  ; 61
5
   6:  de b7         in  r29, 0x3e  ; 62
6
   8:  40 e1         ldi  r20, 0x10  ; 16
7
   a:  50 e0         ldi  r21, 0x00  ; 0
8
   c:  60 e1         ldi  r22, 0x10  ; 16
9
   e:  70 e0         ldi  r23, 0x00  ; 0
10
  10:  e6 2f         mov  r30, r22
11
  12:  f7 2f         mov  r31, r23
12
  14:  60 81         ld  r22, Z
13
  16:  61 60         ori  r22, 0x01  ; 1
14
  18:  e4 2f         mov  r30, r20
15
  1a:  f5 2f         mov  r31, r21
16
  1c:  60 83         st  Z, r22
17
  1e:  40 e0         ldi  r20, 0x00  ; 0
18
  20:  50 e0         ldi  r21, 0x00  ; 0
19
  22:  84 2f         mov  r24, r20
20
  24:  95 2f         mov  r25, r21
21
  26:  df 91         pop  r29
22
  28:  cf 91         pop  r28
23
  2a:  08 95         ret

Edit: Comment korrigiert

: Bearbeitet durch User
von Nemopuk (nemopuk)


Lesenswert?

Norbert schrieb:
> Der alte 5.4.0 erzeugt zumindest bei mir hier nämlich noch einen ganzen
> Sack mehr.

Krass! Das sieht aus, als ob du eine negative Optimierungsstufe 
eingeschaltet hättest.

von Norbert (der_norbert)


Lesenswert?

Man kann's noch ein wenig quetschen… ;-)
1
#include <avr/io.h>
2
// avr-gcc -Wall -Wextra -pedantic -mmcu=attiny5  -o x x.c && avr-objdump -d x 
3
__attribute__ ((OS_main))
4
int main(void) {
5
    PCMSK |= (1<<PCINT0);
6
    __builtin_unreachable();
7
}
1
00000028 <main>:
2
  28:  cd b7         in  r28, 0x3d  ; 61
3
  2a:  de b7         in  r29, 0x3e  ; 62
4
  2c:  40 e1         ldi  r20, 0x10  ; 16
5
  2e:  50 e0         ldi  r21, 0x00  ; 0
6
  30:  60 e1         ldi  r22, 0x10  ; 16
7
  32:  70 e0         ldi  r23, 0x00  ; 0
8
  34:  e6 2f         mov  r30, r22
9
  36:  f7 2f         mov  r31, r23
10
  38:  60 81         ld  r22, Z
11
  3a:  61 60         ori  r22, 0x01  ; 1
12
  3c:  e4 2f         mov  r30, r20
13
  3e:  f5 2f         mov  r31, r21
14
  40:  60 83         st  Z, r22

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Anbei das Lst und Hex bei -Os des 5.4.0
1
#include <avr/io.h>
2
3
int main(void)
4
{
5
  PCMSK |= (1<<PCINT0);
6
  while(1) {
7
  }
8
}

von Norbert (der_norbert)


Lesenswert?

Interessant.
Da musst du tatsächlich einen anderen 5.4.0 als ich haben.
1
/tmp/norbert$ avr-gcc --version
2
avr-gcc (GCC) 5.4.0
3
Copyright (C) 2015 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions.  There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

von Klaus H. (klummel69)


Lesenswert?

Norbert schrieb:
> Das ist aber vermutlich 7.3.0 output, oder?
> Der alte 5.4.0 erzeugt zumindest bei mir hier nämlich noch einen ganzen
> Sack mehr.

Probiers mal Compiler Explorer, bei mir kommt auch mit AVR 5.4.0 die 
schlanke Version raus.

https://godbolt.org/z/9fceGxbMc

Stimmt bei die Compileroption?
Statt "-os" müsste es "-Os" lauten.

von Norbert (der_norbert)


Lesenswert?

Klaus H. schrieb:
> Stimmt bei die Compileroption?
> Statt "-os" müsste es "-Os" lauten.

Verdammt! Genau das war's.
Und das anschließende -o <outfile> hat's dann ohne irgend eine Warnung 
überschrieben. (Auch kein ›s‹ angelegt)

Einmal ohne makefile, schon ist's passiert.

Gutes Auge!

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Svensson schrieb:
> avr-gcc (AVR_8_bit_GNU_Zoolchain_3.7.0.1796> 7.3.0

Also eine von Atmel gepimpte Version.

> Also müßte der funktionieren, aber das tut er nicht. Es kommt die
> Meldung, daß nur Assembler unterstützt wird für -mmcu=attiny5.

Sehr seltsam.  Diese Meldung sollte nur kommen für -mmcu= at90s1200, 
attiny11, attiny12, attiny15 oder attiny28.  Alle anderen Devices 
sollten entweder funktionieren oder komplett abgelehnt werden (specs 
File nicht gefunden etc.)

Und wo man auf jeden Fall drauf achten sollte, ist dass LDS und STS eine 
16-Bit Codierung haben.  Ansonsten: Binutils Bug.

Builds for Windows findet man bei Microchip, Zak Kemble oder

https://sourceforge.net/projects/winavr/files/avr-gcc/

von Klaus H. (klummel69)


Lesenswert?

Norbert schrieb:
> Gutes Auge!

Adler Augen....

Schön wär`s. Der Compiler Explorer hat gemeckert....
Hab deine Option per Copy&Paste eingefügt.

Das ist der Grund, weshalb ich bei lokalen
Compiler-Problemen gerne darauf zurück greife.

von Norbert (der_norbert)


Lesenswert?

Klaus H. schrieb:
> Schön wär`s. Der Compiler Explorer hat gemeckert....
> Hab deine Option per Copy&Paste eingefügt.

Hätte ich mir von avr-gcc auch gewünscht.

Das Verrückte ist, hab gerade in die bash history geschaut. Weiter oben 
hatte ich es erst einmal richtig und im weiteren Verlauf mit 
verschiedenen Optimierungen dann zielsicher durch editieren versaut. ;-)

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
Noch kein Account? Hier anmelden.