AVR ohne Loop

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.

AVR ohne Loop

Beitragvon Mathias » 13. Feb 2018, 17:14 AVR ohne Loop

Was passiert in einem AVR, wen es kein Loop hat ?
In folgendem Beispiel, reagiert nicht mal mehr der Timer.
Passiert da irgend etwas undefiniertes ?
Code: Alles auswählen
begin
  DDRB := %00100000; // Pin 13 Output
 
  // Timer 2
  TCCR2A := %00;               // Normaler Timer
  TCCR2B := %111;              // Clock / 1024
  TIMSK2 := (1 shl TOIE2);     // Enable Timer2 Interrupt.
 
  asm sei end;                 // Interrupts einschalten.
 
//  repeat
//  until 1 = 2;
end
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 13. Feb 2018, 18:50 Re: AVR ohne Loop

Der Controller rennt einfach weiter. Sprich der Programmzähler wird weiter erhöht und auch die im Flash stehenden Befehle ausgeführt. Üblicherweise ist das 0xFF FF. Welchem Befehl das entspricht, darfst Du im instruction set selber rausfinden.

Allerdings können da auch Daten stehen, so schreibt glaube ich der FPC Compiler seine Versionsinfo ans Ende des Programms. Und diese Daten werden gnadenlos als Code interpretiert. Der Controller macht also irgendwas, bestenfalls geht er in eine Endlosschleife, springt wild hin und her oder setzt sich selber in den Sleepmode, schlimmstenfalls aktiviert er irgendwelche Pins und schießt Deine Hardware ab.

Dann kann der Controller bis ans Ende des Flash rennen, wo er vielleicht einen Bootloader findet. Der wird dann aktiv, und wartet entweder auf einen Programmupload oder macht nach einiger Zeit ein Reset.

Kommt der Controller trotz dieser Widrigkeiten am Ende des Flash an, läuft der Programmzähler über und der Controller startet von Anfang an. Bei 32kByte Flash sind das 16k Befehlsworte, bei 8MHz dauert das also gerade mal 2 Millisekunden, wenn der Controller ungebremst durchrennen kann.

tl;dr: Man macht das einfach nicht!
Timm Thaler
 
Beiträge: 572
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.64 FPC3.0.4, Raspbian Stretch Laz1.62 FPC3.0.2 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 13. Feb 2018, 20:06 Re: AVR ohne Loop

tl;dr: Man macht das einfach nicht!
In der Regel nicht, aber wi eschnell hat man Project/Neu gemacht und F9 gedrückt. :mrgreen:
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon FPK » 14. Feb 2018, 20:34 Re: AVR ohne Loop

Timm Thaler hat geschrieben:Der Controller rennt einfach weiter. Sprich der Programmzähler wird weiter erhöht und auch die im Flash stehenden Befehle ausgeführt. Üblicherweise ist das 0xFF FF. Welchem Befehl das entspricht, darfst Du im instruction set selber rausfinden.

Allerdings können da auch Daten stehen, so schreibt glaube ich der FPC Compiler seine Versionsinfo ans Ende des Programms. Und diese Daten werden gnadenlos als Code interpretiert. Der Controller macht also irgendwas, bestenfalls geht er in eine Endlosschleife, springt wild hin und her oder setzt sich selber in den Sleepmode, schlimmstenfalls aktiviert er irgendwelche Pins und schießt Deine Hardware ab.


Nach dem Ende des Hauptprogramms schickt FPC den Controller in eine Endlosschleife, um genau solche Dinge zu verhindern.
FPK
 
Beiträge: 50
Registriert: 21. Mai 2008, 18:38
Wohnort: Erlangen

Beitragvon Mathias » 14. Feb 2018, 22:30 Re: AVR ohne Loop

Nach dem Ende des Hauptprogramms schickt FPC den Controller in eine Endlosschleife, um genau solche Dinge zu verhindern.

wen das so wäre, das müsste doch der Timer-Interrupt weiter laufen ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 14. Feb 2018, 22:38 Re: AVR ohne Loop

FPK hat geschrieben:Nach dem Ende des Hauptprogramms schickt FPC den Controller in eine Endlosschleife, um genau solche Dinge zu verhindern.


Mit Compileroption -al kann man sich ja die Assemblerlistings der einzelnen Units ausgeben lassen.

Da fehlen allerdings noch die Sachen, die der Compiler drumrum baut. Wie zum Beispiel die Initialisierung oder auch sowas wie die Endlosschleife am Ende.

Gibt es eine Compileroption, mit der man sich das komplette Assemblerlisting ausgeben lassen kann? Ohne das Hexfile durch den Disassembler laufen lassen zu müssen? Letzteres ist doch recht mühsam.
Timm Thaler
 
Beiträge: 572
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.64 FPC3.0.4, Raspbian Stretch Laz1.62 FPC3.0.2 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon FPK » 17. Feb 2018, 00:54 Re: AVR ohne Loop

Timm Thaler hat geschrieben:
FPK hat geschrieben:Nach dem Ende des Hauptprogramms schickt FPC den Controller in eine Endlosschleife, um genau solche Dinge zu verhindern.


Mit Compileroption -al kann man sich ja die Assemblerlistings der einzelnen Units ausgeben lassen.

Da fehlen allerdings noch die Sachen, die der Compiler drumrum baut. Wie zum Beispiel die Initialisierung oder auch sowas wie die Endlosschleife am Ende.

Gibt es eine Compileroption, mit der man sich das komplette Assemblerlisting ausgeben lassen kann? Ohne das Hexfile durch den Disassembler laufen lassen zu müssen? Letzteres ist doch recht mühsam.


Nur mit -al wenn die Unit gerade compiliert wird, dem Compiler liegt ja ansonsten auch nur ein Object-File (Binärdaten) vor. Oder eben gleich den Quelltext anschauen: https://svn.freepascal.org/cgi-bin/view ... iew=markup
FPK
 
Beiträge: 50
Registriert: 21. Mai 2008, 18:38
Wohnort: Erlangen

Beitragvon Timm Thaler » 17. Feb 2018, 06:33 Re: AVR ohne Loop

FPK hat geschrieben:Oder eben gleich den Quelltext anschauen: https://svn.freepascal.org/cgi-bin/view ... iew=markup


Ja, würd ich gern, aber ich tue mich schwer, darin was zu finden.

Zum Beispiel baut mir der Compiler bei manchen Multiplikationen ein call fpc_mul_longint ein. Welches erheblich länger dauert wie eine native Multiplikation mittels Hardware-mul. Nun hätte ich mir gern mal angesehen, wie dieses fpc_mul_longint aufgebaut ist, aber ich habe es in den Sourcen nicht gefunden.

Aber danke, anhand des Beispiels hab ich den Befehl
Code: Alles auswählen
avr_cli;
gefunden, der direkt ein CLI einbaut, ohne den Umweg eine Prozedur aufzurufen. Und passend gibt es noch
Code: Alles auswählen
avr_sei();
Die Unit intrinsics muss eingebunden werden.

Wo findet man weitere solche "Geheimbefehle"?
Timm Thaler
 
Beiträge: 572
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.64 FPC3.0.4, Raspbian Stretch Laz1.62 FPC3.0.2 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon FPK » 17. Feb 2018, 11:05 Re: AVR ohne Loop

Timm Thaler hat geschrieben:
FPK hat geschrieben:Oder eben gleich den Quelltext anschauen: https://svn.freepascal.org/cgi-bin/view ... iew=markup


Ja, würd ich gern, aber ich tue mich schwer, darin was zu finden.

Zum Beispiel baut mir der Compiler bei manchen Multiplikationen ein call fpc_mul_longint ein. Welches erheblich länger dauert wie eine native Multiplikation mittels Hardware-mul. Nun hätte ich mir gern mal angesehen, wie dieses fpc_mul_longint aufgebaut ist, aber ich habe es in den Sourcen nicht gefunden.


Ich verwende in solchen Fällen einfach die "Suchen in Dateien"-Funktion von Lazarus mit $(ProjPath)\..\ als Suchpfad. In dem Fall mit dem embedded-Projekt für die rtl (fpc/rtl/embedded/buildrtl.lpi, lässt sich nicht übersetzen, ist aber zum RTL bearbeiten etc. geeignet)


Aber danke, anhand des Beispiels hab ich den Befehl
Code: Alles auswählen
avr_cli;
gefunden, der direkt ein CLI einbaut, ohne den Umweg eine Prozedur aufzurufen. Und passend gibt es noch
Code: Alles auswählen
avr_sei();
Die Unit intrinsics muss eingebunden werden.

Wo findet man weitere solche "Geheimbefehle"?


Wahrscheinlich noch nirgends, ist noch zu neu, ist sicher noch nicht im wiki. Ansonsten eben in der Unit intrinsics.
FPK
 
Beiträge: 50
Registriert: 21. Mai 2008, 18:38
Wohnort: Erlangen

Beitragvon Mathias » 17. Feb 2018, 17:19 Re: AVR ohne Loop

Wo findet man weitere solche "Geheimbefehle"?

Wen man der Cursor auf "intrinsics" und Ctrl+Enter drückt, kommt folgendes:
Code: Alles auswählen
    procedure avr_cli;[INTERNPROC: in_avr_cli];
    procedure avr_sei;[INTERNPROC: in_avr_sei];
    procedure avr_wdr;[INTERNPROC: in_avr_wdr];
    procedure avr_sleep;[INTERNPROC: in_avr_sleep];
    procedure avr_nop;[INTERNPROC: in_avr_nop];

Anscheinend gibt es sogar ein Nop und Sleep.
Aber was wdr ist, kann ich nicht sagen. Weis das sonst wer ?

avr_sei funktioniert.
Jetzt müsste man noch gucken, was sleep genau macht. Ob dies dem Arduino "delayMicroseconds(...); " entspricht.

Wahrscheinlich noch nirgends, ist noch zu neu, ist sicher noch nicht im wiki. Ansonsten eben in der Unit intrinsics.

Ich werde dies im Wiki vermerken. So was muss man fast weiter geben. :wink:

Jetzt habe ich gerade noch etwas entdeckt. wen ich am Programm-Ende folgendes mache,
Code: Alles auswählen
  repeat
  until 1 = 2;
  avr_sei;
end.
wird avr_sein nicht mit kompiliert, anscheinend merkt der Compiler, das er aus dem repeat-until nicht raus kommen kann.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 17. Feb 2018, 18:09 Re: AVR ohne Loop

Ich habe gerade mit avr_sleep; rumprobiert.
Dies macht etwa das gleiche wie avr_nop; .

Hier ist die Verzögerung die selbe, egal ob ich nop oder sleep nehme.
Code: Alles auswählen
  procedure mysleep(t: int32); // Ein einfaches Delay.
  var
    i: Int32;
  begin
    for i := 0 to t do begin
      avr_nop;
    end;
  end;


Noch was habe ich festgestellt, ich kann die for-Schleife leer lassen, die Verzögerung ist etwa gleich, anscheinend hat die Schleife so viel Overhead, das es schon eine Verzögerung gibt.

Erst wen ich etwa 50x hintereinander nop oder sleep schreibe, dann sieht man eine Änderung.

Aber etwas muss doch anders sein zwischen nop und sleep, wen man die Source von cpuinnr.inc anguckt.
Code: Alles auswählen
  in_avr_cli = fpc_in_cpu_first;
  in_avr_sei = fpc_in_cpu_first+1;
  in_avr_wdr = fpc_in_cpu_first+2;
  in_avr_sleep = fpc_in_cpu_first+3;
  in_avr_nop = fpc_in_cpu_first+4;
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 17. Feb 2018, 19:36 Re: AVR ohne Loop

FPK hat geschrieben:Ich verwende in solchen Fällen einfach die "Suchen in Dateien"-Funktion von Lazarus mit $(ProjPath)\..\ als Suchpfad. In dem Fall mit dem embedded-Projekt für die rtl (fpc/rtl/embedded/buildrtl.lpi, lässt sich nicht übersetzen, ist aber zum RTL bearbeiten etc. geeignet)


Ich hab über den kompletten Baum des Laz / FPV Verzeichnisses gesucht, da habe ich ettliche .o gefunden, in denen das anscheinend verwendet wird. Und in generic.inc eine Routine um das abzuhandeln, aber keinen Assemblercode. Ist wirklich nicht so einfach da was zu finden.
Timm Thaler
 
Beiträge: 572
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.64 FPC3.0.4, Raspbian Stretch Laz1.62 FPC3.0.2 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Timm Thaler » 17. Feb 2018, 19:44 Re: AVR ohne Loop

Mathias hat geschrieben:Ich habe gerade mit avr_sleep; rumprobiert.
Dies macht etwa das gleiche wie avr_nop;


Ähm, um den AVR schlafenzulegen, muss man vorher einige Register einstellen. Und auch sicherstellen, dass er wieder aufwacht. Das heisst, einen Timer- oder externen Interrupt scharfschalten.

Mit dem Sleep-Befehl kann man den Controller dann an dieser Programmstelle anhalten. Das heisst, das Programm bleibt hier stehen und der Stromverbrauch sinkt auf ein Minimum. Timer-Zähler, ADC-Wandlung usw. laufen aber weiter. Wird dann ein Timer ausgelöst, wird dessen Interrupt-Routine ausgeführt und danach macht das Programm an der Stelle nach dem Sleep-Befehl weiter.

Ein Sleep ohne Registereinstellung bringt genau das Gleiche wie ein Nop: Nichts, ausser einen Taktzyklus zu verbraten.

Bei Wdt = Watchdog-Reset das Gleiche. Der Watchdog muss vorher eingerichtet werden, und dann muss in regelmäßigen Abständen Wdt aufgerufen werden, um ein Reset zu verhindern.

Die Befehle in der intrinsics sind Kurzschreibweisen für asm cli end;...
Timm Thaler
 
Beiträge: 572
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.64 FPC3.0.4, Raspbian Stretch Laz1.62 FPC3.0.2 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 17. Feb 2018, 20:40 Re: AVR ohne Loop

Wahrscheinlich noch nirgends, ist noch zu neu, ist sicher noch nicht im wiki. Ansonsten eben in der Unit intrinsics.

So neu ist die Unit auch wieder nicht, im Kopf steht 2016.

Ich habe mal begonnen ein Wiki für AVR-Units zu schreiben: http://wiki.freepascal.org/AVR_Embedded_Tutorial_-_Library/de

Vielleicht gibt es in Zukunft noch mehr Units, welche man dokumentieren kann.

Ich hab über den kompletten Baum des Laz / FPV Verzeichnisses gesucht, da habe ich ettliche .o gefunden, in denen das anscheinend verwendet wird. Und in generic.inc eine Routine um das abzuhandeln, aber keinen Assemblercode. Ist wirklich nicht so einfach da was zu finden.

Wen man hinter uses Ctrl+Space drückt, werden alle verfügbaren Units aufgelistet.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3703
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon FPK » 17. Feb 2018, 21:21 Re: AVR ohne Loop

Mathias hat geschrieben:
Wahrscheinlich noch nirgends, ist noch zu neu, ist sicher noch nicht im wiki. Ansonsten eben in der Unit intrinsics.

So neu ist die Unit auch wieder nicht, im Kopf steht 2016.


Im Kopf kann viel stehen :) Relevant ist das svn log:

------------------------------------------------------------------------
r37544 | florian | 2017-11-01 17:33:34 +0100 (Mi, 01 Nov 2017) | 1 line

+ implemented some AVR specific intrinsics
------------------------------------------------------------------------

Timm Thaler hat geschrieben:
FPK hat geschrieben:Ich verwende in solchen Fällen einfach die "Suchen in Dateien"-Funktion von Lazarus mit $(ProjPath)\..\ als Suchpfad. In dem Fall mit dem embedded-Projekt für die rtl (fpc/rtl/embedded/buildrtl.lpi, lässt sich nicht übersetzen, ist aber zum RTL bearbeiten etc. geeignet)


Ich hab über den kompletten Baum des Laz / FPV Verzeichnisses gesucht, da habe ich ettliche .o gefunden, in denen das anscheinend verwendet wird. Und in generic.inc eine Routine um das abzuhandeln, aber keinen Assemblercode. Ist wirklich nicht so einfach da was zu finden.


Nur in *.pp;*.pas;*.inc suchen. Und ja, avr verwendet einfach die generische Version und keine Assembler-Implementierung.
FPK
 
Beiträge: 50
Registriert: 21. Mai 2008, 18:38
Wohnort: Erlangen

• Themenende •

Zurück zu Sonstiges



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

cron
porpoises-institution
accuracy-worried