Forum: Mikrocontroller und Digitale Elektronik Syntaxfrage Funktionsdefinition mit Optionen


von Veit D. (devil-elec)


Lesenswert?

Hallo,

C++

Man kann doch eine Funktionen entweder erst deklarieren und später 
definieren oder gleich definieren und damit auch deklarieren. Ich hätte 
gern gewusst, wie der Syntax für eine Funktionsdefinition lauten muss 
mit diesen Optionen um sie gleich zu definieren? Ohne vorher deklarieren 
zu müssen.
1
void foo () __asm__("__vector_5") __attribute__((__signal__, __used__, __externally_visible__));

normalerweise irgendwie sowas, aber kompiliert nicht
1
void foo () __asm__("__vector_5") __attribute__((__signal__, __used__, __externally_visible__))
2
{
3
  // ... Code
4
}

man erhält
" an asm-specification is not allowed on a function-definition"

Der Hintergrund ist, ich möchte gern etwas Header only programmieren, 
ohne .cpp.

Beitrag #6237088 wurde von einem Moderator gelöscht.
von Peter D. (peda)


Lesenswert?

Die Syntax von Interrupthandlern ist je nach Target und Compiler 
verschieden.
Daher solltest Du mal beides nennen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

Target wäre AVR ATmega 8Bit und der Compiler avr-gcc 9.3.0. Aktuell 
Atmega2560 und 328P. Mit getrennter Deklaration und Definition in .h. 
und .cpp funktioniert es. Ich hätte es gern, falls möglich, Header only.

Der Ursprung ist von hier: 
https://www.mikrocontroller.net/articles/AVR_Interrupt_Routinen_mit_C%2B%2B

von Peter D. (peda)


Lesenswert?

Veit D. schrieb:
> Der Ursprung ist von hier:

Da wird nur erklärt, wie das Macro ISR intern arbeitet. Im Usercode 
haben die Internas nichts verloren. Es sein denn, man will den 
Unleserlichkeits-Kontest gewinnen.
ISRs werden auch nicht von extern aufgerufen, sondern von der 
Interruptlogik. Daher gehören sie nicht in ein h-File.

von Einer K. (Gast)


Lesenswert?

Peter D. schrieb:
> Daher gehören sie nicht in ein h-File.

Mein reden seit 1840 ...

Eine ISR darf nur einmal definiert werden, darum hat sie in einer *.h 
nichts zu suchen.

Denn:
Eine *.h welche nur einmal eingebunden werden darf, ist Sinnverzerrt.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

jetzt dämmerts, habs kapiert. Danke euch.
Der Hintergrund ist folgender warum ich meine Lib auf Header only 
umbauen wollte.
Ich möchte eine vorhandene Template Klasse/Lib einbinden.
Das funktioniert aber nur wenn meine Lib Header only ist.
Weil ein Template in einer .cpp nicht gebaut werden kann.
Damit sitze ich in der Falle.
Entweder verzichte ich auf die vorhandene "Template Lib" oder ich muss 
mir Gedanken machen wie ich das mit der ISR anderweitig gelöst bekomme.

von Rolf M. (rmagnus)


Lesenswert?

Peter D. schrieb:
> Veit D. schrieb:
>> Der Ursprung ist von hier:
>
> Da wird nur erklärt, wie das Macro ISR intern arbeitet. Im Usercode
> haben die Internas nichts verloren. Es sein denn, man will den
> Unleserlichkeits-Kontest gewinnen.

Der Code wird nicht weniger leserlich dadurch, dass er im Header steht.
Und wenn ich als Anwender wissen will, wie ich die Funktionen benutze, 
schaue ich in die Doku, nicht in den Header.

> ISRs werden auch nicht von extern aufgerufen, sondern von der
> Interruptlogik. Daher gehören sie nicht in ein h-File.

Das wiederum sehe ich auch so.

Veit D. schrieb:
> Entweder verzichte ich auf die vorhandene "Template Lib" oder ich muss
> mir Gedanken machen wie ich das mit der ISR anderweitig gelöst bekomme.

Mir ist das Problem nicht klar. Deine ISR soll ein Template sein? Das 
ergibt irgendwie keinen Sinn. Und wenn sie kein Template ist, warum muss 
sie dann im Header stehen?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

Missverständnis. Die ISR ist kein Template. Geht ja nicht.
Meine SPI Lib ist auch keine Template Klasse.
Alles funktioniert so wie gewollt.

Jetzt möchte ich zum Pin schalten die PinLib von Arduino Fanboy 
einbinden. Seine Lib ist eine Template Klasse.
Kann ich so nicht einbinden, eben weil Templates.
Darum muss meine SPI Lib auch eine Template Klasse sein - Header only.
Ich habe dazu auch schon eine neue Idee die ich im Moment umsetze.
Es geht allgemein darum wie man eine einzige ISR für mehrere Objekte 
einer Klasse verwendet. Zeige ich sobald das fertig. Wenn das nicht 
klappt, dann hat sich mein Problem hier sowieso erledigt. :-)  Dann 
bleibt alles wie es derzeit ist.

Sorry für das Durcheinander. Konnte anfangs nicht erahnen wie verzwickt 
das wird.  :-)

von Veit D. (devil-elec)


Angehängte Dateien:

Lesenswert?

Hallo,

habe es am laufen.  :-)
Ich habe jedoch noch einen Schönheitsfehler drin.
Und zwar muss die ISR den CS Pin wieder auf High setzen wenn alle Daten 
aus dem Buffer sind.
Derzeit setze ich von allen Instanzen den Pin auf High.
Ich würde auch hier gern über den Zeiger auf den Pin vom aktuellen 
Objekt zugreifen.

Mache ich das in einer Trockenübung klappt das. Es blinkt.
1
#include <CombiePin.h>
2
using namespace Combie::Pin;
3
OutputPin<13> pin;
4
5
void setInit (void) 
6
{            
7
  pin.init();
8
}
9
10
void setPinHigh (void) 
11
{            
12
  pin.setHigh();
13
} 
14
15
void setPinLow (void) 
16
{            
17
  pin.setLow();
18
}
19
   
20
void (*ptrFunction)() = nullptr;
21
22
void setup(void)
23
{
24
  ptrFunction = setInit; 
25
  (*ptrFunction)();
26
}
27
28
void loop(void)
29
{
30
  ptrFunction = setPinHigh;  
31
  (*ptrFunction)();
32
  delay(500);
33
  
34
  ptrFunction = setPinLow;  
35
  (*ptrFunction)();
36
  delay(500);
37
}

Mach ich das im Headerfile, kann ich dem Zeiger keinen Funktionnamen 
zuweisen. Auch ein verpacken in eine extra Funktion hilft nicht.
1
void (*ptrFunction)() = nullptr;      // function pointer
2
ptrFunction = slaveSelectHigh;

Was ist dabei anders? Ist das möglich? Wenn ja wie?

Fehlermeldung ist:
1
TwoDevices.ino:13:
2
DevilSpi.h: In instantiation of 'void SpiSlave<csPin, divider>::init() [with unsigned char csPin = 11; unsigned char divider = 32]':
3
TwoDevices.ino:38:16:   required from here
4
DevilSpi.h:94:19: error: cannot convert 'SpiSlave<11, 32>::slaveSelectHigh' from type 'void (SpiSlave<11, 32>::)()' to type 'void (*)()'
5
   94 |       ptrFunction = slaveSelectHigh;
6
      |       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
7
DevilSpi.h: In instantiation of 'void SpiSlave<csPin, divider>::init() [with unsigned char csPin = 12; unsigned char divider = 8]':
8
TwoDevices.ino:39:16:   required from here
9
DevilSpi.h:94:19: error: cannot convert 'SpiSlave<12, 8>::slaveSelectHigh' from type 'void (SpiSlave<12, 8>::)()' to type 'void (*)()'

PS: Die messPin Objekte sind nur für den Datalogger/Oszi drin.

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.