Forum: Mikrocontroller und Digitale Elektronik Register in C ändern


von Tom (Gast)


Lesenswert?

Moin,

kann mir vielleicht jemand sagen, ob es möglich ist die Register 0-31 
des AVR in C zu beschreiben. Danke!


Gruß Tom

von Falk (Gast)


Lesenswert?

@ Tom

>kann mir vielleicht jemand sagen, ob es möglich ist die Register 0-31
>des AVR in C zu beschreiben. Danke!

Steht in der Doku der libc, such nach Inline Assembler. Aber wozu 
brauchst du das? Sowas ist in C normalerweise nicht nötig.

MFG
Falk


von Peter D. (peda)


Lesenswert?

Nein.

D.h. wenn Du es versuchst, krachts gewaltig.

Dazu hast Du unter C Variablen, damit Du Dich nicht mehr mit Registern 
abquälen mußt.


Peter

von Gast (Gast)


Lesenswert?

Kannst aber auch eine Variable einem Register fest zuordnen, wenn dir 
das weiterhilft.

von Karl H. (kbuchegg)


Lesenswert?

@Tom:
Machs aber eher nicht. Dem Compiler bei der Register Belegung
ins Handwerk zu pfuschen bringt normalerweise nichts ..... ausser
Ärger.

von Tom (Gast)


Lesenswert?

Ich weiß, normalerweise setze ich die Register und Ports nach ihren 
Bezeichnungen aus dem Datenblatt.

Doch habe ich bei einer Software das Problem, dass ich sie nach einem 
bestimmten aufgetretenen Ereignis wieder in den Ausgangszustand bringen 
muss.   Dazu habe ich über den Debugger im I/O View Fenster die 
aktuellen Zustände angeschaut und angepasst. Die sind nun alle so wie zu 
Beginn.

Jedoch zeigt mir das Prozessorfenster andere Werte in den Registern. 
Kann ich irgendwie kontrolieren, in welchem Register des Controllers zum 
Beispiel die UART ihren Platz hat.

Oder gibt es eine Möglichkeit alle Register auf einmal zu löschen, ohne 
den Chip zu resetten?

von Falk (Gast)


Lesenswert?

@ Tom

>Oder gibt es eine Möglichkeit alle Register auf einmal zu löschen, ohne
>den Chip zu resetten?

Tom, du verwechselst die Register der CPU (R0-R31) mit den Special 
Funktion Registers, mit denen die Hardware gesteuert wird. Erstere gehen 
dich als C Programmierer gar nichts an, letztere kannst du ganz normal 
lesen und schreiben wie C-Variablen, die entsprechenden Includes 
avr/io.h bieten alle Namen gemäss Datenblatt.

MFG
Falk


von A.K. (Gast)


Lesenswert?

Mit "Register" hat natürlich jeder an Prozessorregister gedacht. Schätze 
du meinst I/O-Register.

Da gibt's 2 Wege: Alles von Hand entsprechend Urzustand einstellen. Oder 
Watchdog aktivieren, kürzester Timeout, Interrupts abschalten und dann 
ab in die Totschleife. Gibt dann einen wunderschönen Reset und alles ist 
wieder initialisiert.

von Karl H. (kbuchegg)


Lesenswert?

Tom wrote:

> Doch habe ich bei einer Software das Problem, dass ich sie nach einem
> bestimmten aufgetretenen Ereignis wieder in den Ausgangszustand bringen
> muss.

Hast du davon den Quelltext?
Ich versteh noch nicht, wie da C ins Spiel kommt.

Wenn du den Quelltext hast, müsste man den analysieren
und schauen wie man auf C Ebene eine Rücksetzung in den
Anfangszustand hinkriegt. Das heist zb. alle Initialisierungen
in eine eigene Funktion packen. Diese Funktion wird dann von
main() aufgerufen bzw. dann wenn dein bestimmtes Ereignis
eingetreten ist.

Wenn du keinen Quelltext hast, hast du sowieso ein Problem.
Wie willst du es arangieren, dass dein C-Programm sich mit
dem anderen Program gemeinsam im Speicher arangiert.

von Falk (Gast)


Lesenswert?

@ A.K.

>Mit "Register" hat natürlich jeder an Prozessorregister gedacht.

Nö, der OP schrieb schon R0-31. Meinte aber die SFRs. 8-0

MfG
Falk

von Tom (Gast)


Lesenswert?

>Alles von Hand entsprechend Urzustand einstellen.

Hab ich versucht, haut aber nicht hin. I/O Register sehen genauso aus, 
wie beim Start. Jedoch funktioniert der anschließende Verbindungsaufbau 
nicht wie beim Start.

>Wenn du den Quelltext hast, müsste man den analysieren
>und schauen wie man auf C Ebene eine Rücksetzung in den
>Anfangszustand hinkriegt. Das heist zb. alle Initialisierungen
>in eine eigene Funktion packen.

Genauso hab ich es gemacht. Zu Beginn des Verbindungsaufbaus ist nur das 
Baudratenregister gesetzt. Ansonsten nichts. Das krieg ich so auch auch 
wieder hin, nur die Verbindung klappt nicht.


>Watchdog aktivieren, kürzester Timeout, Interrupts abschalten und dann
>ab in die Totschleife. Gibt dann einen wunderschönen Reset und alles ist
>wieder initialisiert.

Das hab ich schon gemacht. Klappt super, so hätt ich das gerne ohne 
Reset, da ich Werte von der alten Verbindung speichern will ohne dazu 
das EEPROM zu verwenden.



von Falk (Gast)


Lesenswert?

@ Tom

>Das hab ich schon gemacht. Klappt super, so hätt ich das gerne ohne
>Reset, da ich Werte von der alten Verbindung speichern will ohne dazu
>das EEPROM zu verwenden.

Das kannst du im SRAM machen, der wird duch einen Watchdog-Reset nicht 
beeinflusst. Aber sinnvollerweise solltest du den Fehler in deinen 
Registereinstellungen suchen, das Ganze kann sicher auch ohne 
Watchdog-Reset gelöst werden.

MFG
Falk




von A.K. (Gast)


Lesenswert?

Werte speichern geht auch ohne EEPROM. Du musst nur das obere Ende vom 
bekannten RAM heruntersetzen (es gibt m.W. eine Compiler/Linker-Option 
dafür). Die Lücke zwischen diesem Wert und dem echten Ende wird vom 
Watchdog-Reset nicht verändert, lässt sich also ggf. als 
Zwischenspeicher nutzen.

von Tom (Gast)


Lesenswert?

Ist das mit dem Speichern im SRAM irgendwo beschrieben?

von Tom (Gast)


Lesenswert?

Kann ich nicht einfach ne Variable iregendwo im Flash ablegen, die nach 
einem Watchdog noch ihren Wert besitzt?

von Steven (Gast)


Lesenswert?

Hatte letztens auch mal versucht was im RAM Speicher abzulegen. Bekamm 
aber immer die Meldung, dass die Adresse, wo ich was ablegen wollte 
schon belegt ist.

Ziemlicher Mist, denn es war nicht mein eigener Code. Hatte den vom 
Studi-Server. War für ne Kommunikation von nem WT12 und nem Mega. 
Funktionierte alles, nur erweitern ließ sich das Teil nicht.

Ja ja, immer doof wenn man das nicht selber geschrieben hat. Aber 
vielleicht kann mir einer von euch sagen, ob in dieser Zeile:

volatile uc_8 rf_buffer_tx[32]__attribute__((section(".buffer_tx")));
//buffer for storing the RF TX data

ein Bereich im das RAM festgelegt wird? Denn der Compuiler gab mir als 
Fehler an, das die Adresse durch den buffer_tx bereits belegt ist.

Wie kann man denn einen bestimmten Bereich im RAM festlegen/zuweisen?


von A.K. (Gast)


Lesenswert?

Wenn man wie hier eine eigene Section verwendet, dann muss die auch vom 
Linker-Script erfasst werden, sonst wird das nichts. Da man aber bei 
AVRs Linker-Script normalerweise nie zu sehen kriegt, hatte ich die 
etwas einfacher handhabbare Methode mit dem oberen Speicherlimit 
empfohlen.

von johnny.m (Gast)


Lesenswert?

> Kann ich nicht einfach ne Variable iregendwo im Flash ablegen,...
Im Flash kann man prinzipiell nur konstante Daten ablegen. Das Flash ist 
nur von der Boot-Section aus beschreibbar, und das auch meist nur 
Page-weise.

von Steven (Gast)


Lesenswert?

Was hat das denn mit dieser Compiler/Linker-Funktion auf sich bzw. wie 
genau soll das funktionieren?

Steht darüber was im Datenblatt?

von A.K. (Gast)


Lesenswert?

Mit -minit-stack=N lässt sich die obere Grenze des von WinAVR 
verwalteten Speichers festlegen. Normalerweise ist das die obere Grenze 
vom RAM. Setzt man diese grenze tifern an, bleibt der Bereich dazwischen 
beim Reset unangetastet und kann mit
   struct uninitialized_vars {
      ....
   } *uninit_ptr = (struct uninitialized_vars *)0xXXXX;
angesprochen werden. Man sollte dann freilich nach Reset kontrollieren, 
wodurch dieser ausgelöst wurde. Denn wenn es fehlende 
Versorgungsspannung war (Brownout-Detector nützlich), dann ist der 
Inhalt Schrott.

Was für ein Datenblatt? Von den AVRs? Da steht Hardware drin, nicht 
Software.

von A.K. (Gast)


Lesenswert?

... Setzt man diese Grenze tiefer an...

von Uhu U. (uhu)


Lesenswert?

Nochmal zurück zur Ursprungsfrage:

> ob es möglich ist die Register 0-31 des AVR in C zu beschreiben

Ja, das ist möglich mit dem inline-Assembler und wird z.B. benötigt, 
wenn man von C aus eine Assembleroutine mit nicht-C-kompatibler 
Parameterübergabe aufrufen will.

Generell muß man dabei folgendes beachten:

- Stackpointer, Programmzähler, Framepointer (falls vorhanden) dürfen 
nicht verändert werden.
- Register, die vom Compiler für register-Variable benutzt werden, 
dürfen nicht verändert werden.
- Alle anderen Prozessorregister stehen zur freien Verfügung.
- Weitere Ausnahmen sind dem jeweiligen Compiler-Manual zu entnehmen. 
Stichworte: 'register allocation', 'calling conventions', ...

'Nicht verändern' bedeutet hier: Der Registerinhalt (ausgenommen PC!) 
nach dem inline-Statement muß gleich dem Inhalt davor sein. Was 
zwischendurch damit gemacht wird, ist dem Programmierer überlassen.

Das Verändern von nicht fest belegten Registern ist deswegen kein 
Problem, weil inline-Ausdrücke Statements sind - also nicht in andere 
Statements eingebaut werden können und der Zustand der nicht fest 
belegten Register zwischen zwei Statements undefiniert ist.

Der Optimierer kann und wird von der Regel, daß der Registerzustand 
zwischen zwei  Statements undefiniert ist, abweichen.
Er ist jedoch schlau genug, inline-Statements in seine 
Registerallokation mit einzubeziehen - man braucht sich darum also nicht 
zu kümmmern. inline-Statements werden vom Optimierer nicht verändert.

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.