Forum: Compiler & IDEs avr gcc inline Assembler r2 an Variable in C übergeben


von Joachim B. (jar)


Lesenswert?

MCUSR soll in optiboot in r2 gesichert sein,

wie bekomme ich das zum Programmstart in eine C Variable da MCUSR immer 
gelöscht wird.

danke

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

D.h. wenn der Bootloader zum Reset-Vektor der Applikation springt, dat 
R2 einen Wert, den du sichern willst?

Ich les mir jetzt nicht dir Quelle von diesem Loader durch... bissl Info 
muss schon her.

von Joachim B. (jar)


Lesenswert?

> Ich les mir jetzt nicht dir Quelle von diesem Loader durch... bissl Info
> muss schon her.

nee musst du nicht lesen

ich hatte gelesen das MCUSR zwar gelöscht wird es aber eine Kopie in r2 
gibt

Johann L. schrieb:
> D.h. wenn der Bootloader zum Reset-Vektor der Applikation springt, dat
> R2 einen Wert, den du sichern willst?

und somit würde ich gerne r2 an eine C Variable übergeben weil MCUSR ja 
0 ist.

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


Lesenswert?

Eine Möglichkeit:
1
#include <stdint.h>
2
3
__attribute__((__section__(".noinit")))
4
uint8_t mcusr;
5
6
__attribute__((__used__,__unused__,__naked__,__section__(".init3")))
7
static void init_mcusr (void) __asm__ (".Linit_mcusr");
8
9
void init_mcusr (void)
10
{
11
    __asm__ ("sts %0, r2" : "=m" (mcusr));
12
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und wenn die Variable mcusr von anderen Module(n) verwendet werden 
soll, kommt in den Header zum Modul oben noch der passende Proto:
1
#include <stdint.h>
2
3
extern uint8_t mcusr;

von Joachim B. (jar)


Lesenswert?

sicher?

setup:65: error: 'void init_mcusr()' was declared 'extern' and later 
'static'

trotzdem danke

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Eine Möglichkeit:
> #include <stdint.h>
>
> __attribute__((__section__(".noinit")))
> uint8_t mcusr;
>
> __attribute__((_used_,__unused__,__naked__,__section__(".init3")))
> static void init_mcusr (void) _asm_ (".Linit_mcusr");
>
> void init _mcusr (void)
> {
>     _asm_ ("sts %0, r2" : "=m" (mcusr));
> }

das geht mir etwas zu durcheinander,

das hier würde ich in einem ASM file sehen welches ich extra haben 
müsste?:
__attribute__((__section__(".noinit")))

das hier:
__attribute__((_used_,__unused__,__naked__,__section__(".init3")))

.init3 sagt mir nun nix

das steht im Widerspruch
static void init_mcusr (void) _asm_ (".Linit_mcusr");

zu
void init_mcusr()

da meckert der Compiler zu recht

könntest du bitte erklären was wann wohin soll?

wenn ich das alles überblicken würde müsste ich ja hier nicht fragen.

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


Lesenswert?

Joachim B. schrieb:
> setup:65: error: 'void init_mcusr()' was declared 'extern' and later
> 'static'

Das passt überhaupt nicht zu meinem Code.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hast du etwa versucht, init_mcusr aufzurufen?  Davon hab ich nix 
geschrieben!

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Hast du etwa versucht, init_mcusr aufzurufen?  Davon hab ich nix
> geschrieben!

upps, habe es nur


#include <stdint.h>

__attribute__((__section__(".noinit")))
uint8_t mcusr;

__attribute__((_used_,__unused__,__naked__,__section__(".init3")))
static void init_mcusr (void) _asm_ (".Linit_mcusr");

void init_mcusr (void)
{
    _asm_ ("sts %0, r2" : "=m" (mcusr));
}

vor

setup()
{
}

gesetzt

achso.......

ich glaube ich verstehe nun

ich darf es nicht aufrufen?

weil es in der globalen uint8_t mcusr; schon drin ist?

woher kenne ich den Zeitpunkt wann das aufgerufen wird, "r2" kann ja zu 
jedem Zeitpunkt mit mcusr gefüllt werden, aber ich will r2 nach dem 
Bootloader bekommen vor allem anderen!

Deine Lösung scheint ja richtig zu sein, nur......

nochmal

r2 ist eine Sicherung vom MCUSR bevor der bootloader verlassen wird und 
dann will ich r2 bekommen, zu keinem anderen Zeitpunkt

Es nutzt mir nix wenn r2 irgendwo irgendwann global in die C-Variable 
c_var_mcusr geladen wird.

Ich dachte eher an sowas


setup()
{ asm("move r2, c_var_mcusr");
  usw.

oder
setup()
{ asm("ldi c_var_mcusr, r2");
  usw.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

1
int saved_value;
2
3
void save_r2(void)
4
{
5
    register int r2 asm("r2");
6
7
    saved_value = r2;
8
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Joachim B. schrieb:
> ich darf es nicht aufrufen?

Nein.

Die Funktion ist Teil des Startup-Codes.

Ein Aufruf von Hand kann nicht funktionieren da nicht sichergestellt 
ist, dass R2 zu dem Zeitpunkt (nach main) noch den gewünschten Wert 
enthält.  Daher würd ich auch von Markus' Vorschag abraten — auch wenn 
der Code hübscher aussieht.


> weil es in der globalen uint8_t mcusr; schon drin ist?

Sobald du in main bist kannst du direkt auf mcusr zugreifen, du brauchst 
keine Funktion vorher aufrufen!

Du kannst sogar bereits in statischen Konstruktoren, also vor main, auf 
mcusr zugreifen!

> woher kenne ich den Zeitpunkt wann das aufgerufen wird

Der Zeitpunkt ist .init3, siehe vordefinierte Sections bei avr-Tools.

> Bootloader bekommen vor allem anderen!

Du willst es nicht vor der Stack-Initialisierung bekommen :-)

> r2 ist eine Sicherung vom MCUSR bevor der bootloader verlassen wird
> und dann will ich r2 bekommen, zu keinem anderen Zeitpunkt

D.h. du willst R2 im Bootloader auslesen?

Sorry, ich dachte du willst mcusr in der Applikation haben.

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Joachim B. schrieb:
>> ich darf es nicht aufrufen?
> Der Zeitpunkt ist .init3, siehe vordefinierte Sections bei avr-Tools.

also kurz vor dem verlassen des bootloaders? das wäre ja mein Wunsch

> D.h. du willst R2 im Bootloader auslesen?

nein in r2 ist MCUSR gesichert bevor der bootloader verlassen wird

> Sorry, ich dachte du willst mcusr in der Applikation haben.

will es schon in der Applikation als erstes!

probiere ich dann noch mal
1
#include <stdint.h>
2
3
__attribute__((__section__(".noinit")))
4
uint8_t _my_mcusr;
5
6
__attribute__((__used__,__unused__,__naked__,__section__(".init3")))
7
static void init_mcusr (void) __asm__ (".Linit_mcusr");
8
9
void init_mcusr (void)
10
{
11
    __asm__ ("sts %0, r2" : "=m" (_my_mcusr));
12
}

so eingefügt vor setup (das ich den Variablennamen geändert habe sollte 
doch keine Rolle spielen.

Fehler bleibt!

setup:66: error: 'void init_mcusr()' was declared 'extern' and later 
'static'
Arduino_nano1284_Nokia5110_RTC_RC433_SU:41: error: previous declaration 
of 'void init_mcusr()'

: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

Du weisst aber schon, was Startup-Code ist, oder?

von Joachim B. (jar)


Lesenswert?

Kaj schrieb:
> Du weisst aber schon, was Startup-Code ist, oder?

ja, aber bei arduino nicht wirklich, da geschieht mir zu viel im 
Hintergrund, vielleicht muss ich wieder zum AVR Studio zurück.

ändert aber nix an der GCC Fehlermeldung, die verwirrt mich wirklich.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Joachim B. schrieb:
> ändert aber nix an der GCC Fehlermeldung, die verwirrt mich wirklich.

Die Fehlermeldung nennt dir Datei und genauen Zeilennummer der beiden 
widersprüchlichen Deklarationen. Was ist daran jetzt noch verwirrend?

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Joachim B. schrieb:
> Johann L. schrieb:
>> Joachim B. schrieb:
>>> ich darf es nicht aufrufen?
>> Der Zeitpunkt ist .init3, siehe vordefinierte Sections bei avr-Tools.
>
> also kurz vor dem verlassen des bootloaders? das wäre ja mein Wunsch

Also IM Bootloader.

Dann darf es natürlich nicht im StartUp-Code der Applikation sein!

Allerdings hast du dann das Problem, eine Variable des Bootloaders in 
der Applikation zugreifbar zu machen, d.h. die beiden müssen sich über 
die Adresse von mcusr einig sein.

Eine Variable wie mcusr ist eine Variable des Bootloaders, und das 
Symbol ist nicht in der Applikation verfügbar.  Es ist also ziemlich 
sinnfrei, R2 in einer Variablen zu speichern, die in der Applikation 
nicht verfügbar ist.

Wenn R2 im BL gelesen werden soll ("Kurz vor Verlassen des BL" ist für 
mich IM BL) dann musst du natürlich den BL ändern.  Entweder der BL ist 
in Assembler oder in C.  Wenn er in C ist, muss R2 eine globale 
Reg-Variable sein; ansonsten kann der BL nicht sicherstellen, dass R2 
nicht anderwärtig verwendet wird.

Ich hab einfach nicht genug Infos, um deine Frage sinnvoll zu 
beantworten, und deine Antworten sind teilweuise widersprüchlich.

Den BL selbst zu ändern macht nur Sinn, denn mcusr im BL ausgewertet 
wird, du musst also den BL ändern.  Dann kannst du auch MCUSR direkt in 
eine Variable lesen und brauchst keinen Umweg über R2.


>> D.h. du willst R2 im Bootloader auslesen?
>
> nein in r2 ist MCUSR gesichert bevor der bootloader verlassen wird

Ja was denn nun????????????????

>> Sorry, ich dachte du willst mcusr in der Applikation haben.
>
> will es schon in der Applikation als erstes!

Dann geht mein Code (GNU-C99).

> Fehler bleibt!
>
> setup:66: error: 'void init_mcusr()' was declared 'extern' and later
> 'static'
> Arduino_nano1284_Nokia5110_RTC_RC433_SU:41: error: previous declaration
> of 'void init_mcusr()'

Das KANN NICHT SEIN! In meinem Code stehen Deklaration und Definition 
von init_mcusr genau ZWEI ZEILEN auseinander!

Irgendwas bist du da am rumfrickeln wovon ich nix gesagt hab.

von Joachim B. (jar)


Lesenswert?

Oliver S. schrieb:
> Die Fehlermeldung nennt dir Datei und genauen Zeilennummer der beiden
> widersprüchlichen Deklarationen. Was ist daran jetzt noch verwirrend?

schlaue Bemerkung und was hilft die?

Ich sehe selber das es "widersprüchliche Deklarationen" sind aber

Johann L. schrieb:
> Dann geht mein Code (GNU-C99).

behart ja darauf das es nicht an seinem Code liegt!
Dabei finde ich die Fehlermeldung offensichtlich und den Widerspruch 
auch!

Johann L. schrieb:
> Eine Möglichkeit:
> #include <stdint.h>
>
> __attribute__((__section__(".noinit")))
> uint8_t mcusr;
>
> __attribute__((_used_,__unused__,__naked__,__section__(".init3")))
> static void init_mcusr (void) _asm_ (".Linit_mcusr");
>
> void init_mcusr (void)
> {
>     _asm_ ("sts %0, r2" : "=m" (mcusr));
> }

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


Lesenswert?

Joachim B. schrieb:
> Dabei finde ich die Fehlermeldung offensichtlich und den
> Widerspruch auch!

In der von dir gezeigten Fehlermeldung liegen die beiden Locations 41 
Zeilen auseinander!  Meinem Code kommt nicht über 5 Zeilen:

>> __attribute__((_used_,__unused__,__naked__,__section__(".init3")))
>> static void init_mcusr (void) __asm__ (".Linit_mcusr");
>>
>> void init_mcusr (void)
>> {
>>     __asm__ ("sts %0, r2" : "=m" (mcusr));
>> }

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> In der von dir gezeigten Fehlermeldung liegen die beiden Locations 41
> Zeilen auseinander!  Meinem Code kommt nicht über 5 Zeilen:

das ist doch schnuppe wo der im Quellcode sitzt, der wird eh nie 
aufgerufen!

erwähntest du bereits, ergo wird er compiliert zugelinkt und übergibt an 
die globale Variable!

Der Fehler ist weg wenn man logisch so schreibt!

statt:

Johann L. schrieb:
> void init_mcusr (void)
> {
>     _asm_ ("sts %0, r2" : "=m" (mcusr));
> }

einfach:

> static void init_mcusr (void)
> {
>     _asm_ ("sts %0, r2" : "=m" (mcusr));
> }


dann passt die Funktion auch zur Deklaration und ich stelle fest ich 
bekomme zumindest den watchdog reset mit, aber EXTRF PORF sind da schon 
weg

ich tippe mal .init3 ist zu spät

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

ob .init0 1 2 oder 3 ändert nix am watchdog flag

https://code.google.com/archive/p/optiboot/issues/97

hier ist eine ähnliche Meldung

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


Lesenswert?

Joachim B. schrieb:
> setup:65: error: 'void init_mcusr()' was declared 'extern' and later
> 'static'

Hast du den Code in eine andere Funktion kopiert?

Den Code, den ich gepostet hab, darf nicht innerhalb einer anderen 
Funktion stehen!

Der Code steht genauso da wie er gehört.

Im 100% sicher zu gehen:

1) Lege ein neues C-Modul an und mach den Code da rein.  Übersetzt wird 
mit -std=gnu99 -Os etc.

2) In den Modulen, wo du das brauchst, verwendest du als Prototyp
1
extern uint8_t mcusr; // C
2
extern "C" uint8_t mcusr; // C++

Da nur der Wert von R2 ausgelesen wird hat die Positionierung des von 
init_mcusr keinen Einfluss auf den Wert von R2.

Aber wenn du eh alles besser weißt bin ich ruas, da kann ich dir nix 
helfen...

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Hast du den Code in eine andere Funktion kopiert?

nein!

> Den Code, den ich gepostet hab, darf nicht innerhalb einer anderen
> Funktion stehen!

ist klar

> Der Code steht genauso da wie er gehört.

bezweifel ich immer noch bei dem Unterschied Definition und Deklaration

void zu static void da meckert IMHO der Compiler zu Recht!
und du klärst den Widerspruch ja nicht auf!

> Im 100% sicher zu gehen:
>
> 1) Lege ein neues C-Modul an und mach den Code da rein.  Übersetzt wird
> mit -std=gnu99 -Os etc.

kan ja sein das es hilft, der Widerspruch static void zu void würde 
bleiben.

> 2) In den Modulen, wo du das brauchst, verwendest du als Prototyp
> extern uint8_t mcusr; // C
> extern "C" uint8_t mcusr; // C++
>
> Da nur der Wert von R2 ausgelesen wird hat die Positionierung des von
> init_mcusr keinen Einfluss auf den Wert von R2.

ich frage mich gerade warum es keinen Unterschied im Ergbnis gibt 
zwischen .init0 bis .init3

Ich würde ja vermuten das die .init0 bis .init3 vordefinierte Labels 
oder Plätze sind wo gcc das plaziert, habe aber noch nicht dazu 
gefunden.

> Aber wenn du eh alles besser weißt bin ich ruas, da kann ich dir nix
> helfen...

ich weiss das ich nix weiss, vielleicht ist mir ja nicht zu helfen

hast du hier mal reingesehen?
https://code.google.com/archive/p/optiboot/issues/97

sieht deinem Code ähnlich nur benutzt er mov und .init0 hat aber auch 
nix gebracht.

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Hast du den Code in eine andere Funktion kopiert?

nun ja in eine extra .c ausgelagert,

Ergebnis fast dito immer nur 8 watchdag reset

warum er nun nicht mehr am

static void init_mcusr(void)

mit

void init_mcusr (void)

meckert verstehe ich nicht, vermutlich weil der das nicht nutzt oder 
wegoptimiert weil es ja nirgens aufgerufen wird?

ich kenne den gcc eher pingelig wenn Deklaration und Definition nicht im 
Typ zusammen passen.

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


Lesenswert?

Joachim B. schrieb:
> Johann L. schrieb:
>> Hast du den Code in eine andere Funktion kopiert?
>
> nein!

Wieso sagt die Fehlermeldung dann dass die fehlerhafte Stelle in einer 
Funktion setup ist?

>> Den Code, den ich gepostet hab, darf nicht innerhalb einer anderen
>> Funktion stehen!
>
> ist klar
>
>> Der Code steht genauso da wie er gehört.
>
> bezweifel ich immer noch bei dem Unterschied Definition und Deklaration
>
> void zu static void da meckert IMHO der Compiler zu Recht!
> und du klärst den Widerspruch ja nicht auf!

Da ist kein Widerspruch. In C ist absolut legitim static nur im Prototyp 
zu schreiben.  Duzu muss der Prototyp natürlich VOR der Funktion stehen, 
ansonsten ist der Prototyp ziemlich witzlos bzw. passt nicht zum 
impliziten Prototyp den die Implementierung darstellt.

>> Im 100% sicher zu gehen:
>>
>> 1) Lege ein neues C-Modul an und mach den Code da rein.  Übersetzt wird
>> mit -std=gnu99 -Os etc.
>
> kan ja sein das es hilft, der Widerspruch static void zu void würde
> bleiben.

Da ist kein Widerspruch.  Das ist C.

>> 2) In den Modulen, wo du das brauchst, verwendest du als Prototyp
>> extern uint8_t mcusr; // C
>> extern "C" uint8_t mcusr; // C++
>>
>> Da nur der Wert von R2 ausgelesen wird hat die Positionierung des von
>> init_mcusr keinen Einfluss auf den Wert von R2.
>
> ich frage mich gerade warum es keinen Unterschied im Ergbnis gibt
> zwischen .init0 bis .init3

Weil R2 nicht verändert wird.  Oder hast du eigenen Init-Code der R2 
verwendet?

Joachim B. schrieb:
> Johann L. schrieb:
>> Hast du den Code in eine andere Funktion kopiert?
>
> nun ja in eine extra .c ausgelagert,
>
> Ergebnis fast dito immer nur 8 watchdag reset

Na das ist doch was du willst!  Der Grund für den Reset ist der WDT.

> warum er nun nicht mehr am
>
> static void init_mcusr(void)
>
> mit
>
> void init_mcusr (void)
>
> meckert verstehe ich nicht,

Weil das C ist.  Übrigens kann ich das auch mit C++ fehlerfrei 
übersetzen.

> vermutlich weil der das nicht nutzt oder
> wegoptimiert weil es ja nirgens aufgerufen wird?

Nein.  Es wird verwendet.  Mach ein Disassembly des Moduls / der 
Applikation und du findest ein STS-Befehl mit R2.

> ich kenne den gcc eher pingelig wenn Deklaration und Definition nicht im
> Typ zusammen passen.

Die passen.

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Wieso sagt die Fehlermeldung dann dass die fehlerhafte Stelle in einer
> Funktion setup ist?

sagt sie nicht, sie steht nur in einer INO Namens setup

bloß weil der Datei den Namen gegeben hatte ist es noch nicht in einer 
Function.

Ich kann (das weisst du sicher) in jeder C Datei Sachen in eine Funktion 
oder ausserhalb einer Function stellen, die Meldung zielte nur auf das 
Modul oder Datei, jedenfalls nicht Funktion.

Johann L. schrieb:
> Da ist kein Widerspruch. In C ist absolut legitim static nur im Prototyp
> zu schreiben.  Duzu muss der Prototyp natürlich VOR der Funktion stehen,
> ansonsten ist der Prototyp ziemlich witzlos bzw. passt nicht zum
> impliziten Prototyp den die Implementierung darstellt.

denn unterscheidet die IDE

im INO gab es die Fehlermeldung im C nicht

im INO war die Fehlermeldung weg als ich beides static void genannt 
hatte, auch wenn das scheinbar egal sein soll.

Johann L. schrieb:
> Na das ist doch was du willst!  Der Grund für den Reset ist der WDT.

aber ich wollte ja wissen was passiert war power on reset oder reset, 
das bekomme ich immer noch nicht aus dem optiboot, übrigens originale 
nanos verhalten sich da mitteilsamer dort funktioniert MCUSR auslesen 
richtig.

Johann L. schrieb:
>> ich kenne den gcc eher pingelig wenn Deklaration und Definition nicht im
>> Typ zusammen passen.
>
> Die passen

will ich dir gerne glauben (danke übrigens auch wenn es noch nicht das 
gewünschte Ergebnis brachte)

Ich erinnere mich aber an Programmiersituationen wo bei doofen Sstr 
Routinen mal unsigned char und mal char bemeckert wird

Für mich ist ein char immer unsigned, wenn ich mich recht erinnere gabe 
es auch mal Compiler die strstr oder strcpy als unsigned char definiert 
hatten, ich komme da regelmäßig durcheinander, für mich ist ein char 
unsigned, aber man darf das nicht überall LAUT sagen da meckern manche 
Compiler.

Ich hatte mich das letzte mal vor 30 Jahren dur ASM Code gewühlt und 
wollte das eigentlich nicht mehr.

Auch wenn es für die Profis ein Klacks ist optiboot zu erweitern 
umzuschreiben, MCUSR zu sichern und zu retten, das ist für mich ja nur 
ein Nebengebiet weil ich optiboot am Arduino migthy 1284p nutzen wollte 
der eben nicht mit Standardbootloader daher kommt, die 1M Baud bei 16MHz 
sind auch ein Schmankerl, aber die Nebenwirkungen MCUSR gelöscht böse.

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


Lesenswert?

Joachim B. schrieb:
> Johann L. schrieb:
>> Wieso sagt die Fehlermeldung dann dass die fehlerhafte Stelle in einer
>> Funktion setup ist?
>
> sagt sie nicht, sie steht nur in einer INO Namens setup

Was immer ein "INO" ist.

> Ich kann (das weisst du sicher) in jeder C Datei Sachen in eine Funktion
> oder ausserhalb einer Function stellen,

Nö, davon weiß ich SICHER nix.

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Nö, davon weiß ich SICHER nix.

C Verweigerer?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dass es keine Rolle spielt, ob in C ein Code innerhalb oder außerhalb 
einer Funktion steht, wusste ich nicht.

Offenbar sind meine Wissenslücken zu groß als dass ich dir noch 
weiterhelfen kann.

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Offenbar sind meine Wissenslücken zu groß als dass ich dir noch
> weiterhelfen kann.

danke du hast es versucht warum das nicht funktioniert kann an einer 
Fehlinfo liegen mit dem r2 oder weil dort eben nicht MCUSR gesichert ist 
oder sie Sicherung schon kaputt ist bis ich an den Code komme.

von Kaj (Gast)


Lesenswert?

Johann L. schrieb:
> Joachim B. schrieb:
>> Johann L. schrieb:
>>> Wieso sagt die Fehlermeldung dann dass die fehlerhafte Stelle in einer
>>> Funktion setup ist?
>>
>> sagt sie nicht, sie steht nur in einer INO Namens setup
>
> Was immer ein "INO" ist.

.ino ist die Dateiendung für (Projekt)Dateien die aus dieser 
Bullshit-Arduino-"IDE" kommen.
Man kann das ino genauso gut durch ein cpp ersetzen.

von Joachim B. (jar)


Lesenswert?

Kaj schrieb:
> Man kann das ino genauso gut durch ein cpp ersetzen.

oder c, der IDE und dem gcc ist es fast egal

ich habe einigen Code von AVR Studio in .ino portiert C ist und bleibt C

von Peter D. (peda)


Lesenswert?

Joachim B. schrieb:
> MCUSR soll in optiboot in r2 gesichert sein,

Die Register sind ungünstig für globale Variablen, die etwas länger 
leben sollen. Spätestens der Startup-Code löscht alle Register.
Speicher es besser in GPIOR0.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Spätestens der Startup-Code löscht alle Register.

Zumindest der Startup-Code der AVR-LibC tut das nicht.

Initialisiert werden FP (R28, R29) und R1.  Einige Register werden bei 
der Initialisierung verwendet, aber R2 gehört nicht dazu.

von Peter D. (peda)


Lesenswert?

Johann L. schrieb:
> aber R2 gehört nicht dazu.

Sorry, mein Fehler.

Dann ist es aber doch egal, wann er r2 ausliest:
1
uint8_t get_r2(void)
2
{
3
  return *(uint8_t*)2;
4
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Dann ist es aber doch egal, wann er r2 ausliest:
1
> uint8_t get_r2(void)
2
> {
3
>   return *(uint8_t*)2;
4
> }

Von sochen Hacks würd ich dringend abraten; einen funktionierenden und 
robusten Code habe ich oben gegeben.

Dein Code funktioniert z.B. nicht für XMega, und er setzt voraus, dass 
in der Call-Chain von get_r2 keine Funktion R2 verwendet.  Prinzipiell 
kannst du das nicht ausschließen.  Auch wenn der von dir gezeigte Hack 
in einer Situation das Erwartete macht, bedeutet das nicht, das er es 
auch in anderen Situationen tut.

von Peter D. (peda)


Lesenswert?

Johann L. schrieb:
> einen funktionierenden und
> robusten Code habe ich oben gegeben.

Naja, von Inline-Assembler kriege ich immer Knoten im Gehirn. Ich 
bevorzuge deshalb plain C, solange möglich.

Außerdem ist ja schon die Übergabe im CPU-Register ein böser Hack. Sowas 
macht man einfach nicht. Die Register gehören dem Compiler.

von Joachim B. (jar)


Lesenswert?

Peter D. schrieb:
> Außerdem ist ja schon die Übergabe im CPU-Register ein böser Hack. Sowas
> macht man einfach nicht. Die Register gehören dem Compiler.

du hast ja so Recht, beim Aruino klappt das ja mit MCUSR auslesen nur 
beim Optiboot nicht und da fand ich den Trick über r2, aber ohne Erfolg!

Den Optiboot neu zu kompilieren wäre eine Nebenbautelle um die ich mich 
echt nicht kümmern will oder sogar kann, dazu habe ich am 1284p zu viele 
offene Fragen.

Ich bin zulange raus aus Assembler.

Wie viel Byte muss ich reservieren für den Bootsektor?
Welche Größe in Worte?
Wie zählt das am 1284p der die 64k überschreitet und 3 Byte für 
Sprungadressen braucht statt 2 Byte
Ist eine Wortangabe (16-bit) für den Bootsektor überhaupt sinnvoll im 
AVR bei 3 Byte Sprungtabellen (24-bit)?
Für welchen Speicherbereich müsste ich den Bootsektor assemblieren?
usw. usf.

Dinge die für mich Grundlagenforschung wären weswegen ich den Optiboot 
nicht anfasse.

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


Lesenswert?

Peter D. schrieb:
> Johann L. schrieb:
>> einen funktionierenden und
>> robusten Code habe ich oben gegeben.
>
> Naja, von Inline-Assembler kriege ich immer Knoten im Gehirn. Ich
> bevorzuge deshalb plain C, solange möglich.

> Außerdem ist ja schon die Übergabe im CPU-Register ein böser Hack. Sowas
> macht man einfach nicht. Die Register gehören dem Compiler.

Find ich schon ok so.  Die Applikation beginnt ja mit dem Startup-Code, 
und der steht für gewöhnlich in Assembler — Bootloader und Startup-Code 
sind beide stark von Architektur und Tools abhängig.  Wem Inline Asm 
nicht gefällt, der kann es natürlich auch gleich Assembler hinklatschem:
1
#include <stdint.h>
2
3
__attribute__((__section__(".noinit")))
4
uint8_t mcusr;
5
6
__asm__ ("
7
  .section .init3,"ax",@progbits
8
  .type .Linit_mcusr, @function
9
.Linit_mcusr:
10
  sts mcusr, r2");

Da es nach Joachims Aussage "egal ist ob Code innerhalb oder außerhalbe 
einer Funktion steht", geh ich mal davon aus, dass die IDE hier ihre 
Finger im Spiel hat und in die Suppe spuckt.  Die Aussage selbst trifft 
ja weder für C noch für C++ zu.

von Carl D. (jcw2)


Lesenswert?

Mega1284 braucht für seine 64k-Befehls-Worte keine 3Byte Adressen. Nur 
bei Zugriff über LPM/SPM werden Bytes addressiert und das fehlende Bit 
16 (0..15 sind in Z) muß in RAMPZ abgelegt werden. Quasi Banking.

von Oliver S. (oliverso)


Lesenswert?

Johann L. schrieb:
> Da es nach Joachims Aussage "egal ist ob Code innerhalb oder außerhalbe
> einer Funktion steht", geh ich mal davon aus, dass die IDE hier ihre
> Finger im Spiel hat und in die Suppe spuckt.

Nee, tut sie nicht. Das Arduino-Gedöns ist schon C++, bis auf die 
Datei-Endungen. Was Joachim etwas unglücklich formuliert wohl ausrücken 
wollte, ist, das die fragliche Deklaration außerhalb einer Funktion 
steht.

Ansonsten hast du natürlich Recht damit, daß dein Wissensstand in 
keinster Weise vergleichbar mit seinem ist, und Hilfe daher schwierig 
ist ;)

Oliver

von Joachim B. (jar)


Lesenswert?

Johann L. schrieb:
> Da es nach Joachims Aussage "egal ist ob Code innerhalb oder außerhalbe
> einer Funktion steht",

Der Code innerhalb einer *.c Datei oder *.cpp Datei kann doch ausserhalb 
einer Funktion stehen, soweit wie ich es weiss müsste der Code doch 
trotzem compiliert werden und zugelinkt werden.

Oliver S. schrieb:
> Nee, tut sie nicht. Das Arduino-Gedöns ist schon C++, bis auf die
> Datei-Endungen. Was Joachim etwas unglücklich formuliert wohl ausrücken
> wollte, ist, das die fragliche Deklaration außerhalb einer Funktion
> steht.

genau so meinte ich das

> Ansonsten hast du natürlich Recht damit, daß dein Wissensstand in
> keinster Weise vergleichbar mit seinem ist, und Hilfe daher schwierig
> ist ;)

da gehe ich konform, gerade bei Assembler bin ich zu lange raus, aber 
Code innerhalb eines Moduls oder einer Function hat doch NIX mit Code 
innerhalb einer Datei zu tun oder sollte ich so sehr daneben liegen?

LG jar

von Joachim B. (jar)


Lesenswert?

Oliver S. schrieb:
> Ansonsten hast du natürlich Recht damit, daß dein Wissensstand in
> keinster Weise vergleichbar mit seinem ist, und Hilfe daher schwierig
> ist ;)

ich könnte aber dazu lernen, so ganz unerfahren auch in ASM bin ich 
nicht, nur hatte ich die letzten Sachen in ASM in Hex auf Karopapier für 
den LH5803 '85 gemacht und noch etwas '87 für den 6502 und kann was mit 
nop, jnz, bne, rti und rts anfangen.

: Bearbeitet durch User
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.