direkt in ein Register des Tiny5 schreiben

OP #7935254
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

#7935256
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
(Firma: 1984now) #7935271
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?

#7935272
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
Angehängte Dateien:
: Bearbeitet durch User
(Firma: 1984now) #7935320
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.

#7935323
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
#7935325
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
OP #7935347
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.

#7935418
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)
#7935437
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.

OP #7935544
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{}

OP #7935873
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?

#7935928
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
#7935962
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
#7936008
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.
Persönliche Seite #7936021
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/

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren