Erster Blinkversuch ATmega328

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Erster Blinkversuch ATmega328

Beitrag von Mathias »

Ich habe meinen ersten Versuch mit AVR gemacht.
Wie erwartet blinkt die LED, welche am PIN13 meines Arduino Nano hängt sehr schnell.
Erhöhe ich den sleep von 100 auf 255, dann blinkt die LED wie erwarte ein bisschen langsamer.
Nehme ich aber 256 oder höher, dann hat die LED einen Dauerbrenner.
Wieso komme ich in der Schleife nicht über die Byte-Grenze hinaus, obwohl ich int16 deklariert habe ?

Hat evtl. der FPC 3.0.2-r1:35394 da einen Bug ?

Code: Alles auswählen

program test;
uses
  atmega328p;
 
procedure mysleep(t: int16);
var
  i: int16;
begin
  for i := 0 to t do begin
    asm
      nop;
    end;
  end;
end;
 
begin
  DDRB := 255;
  repeat
    PORTB := 0;
    mysleep(100);
 
    PORTB := 255;
    mysleep(100);
  until 1 = 2;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Erster Blinkversuch ATmega328

Beitrag von kupferstecher »

Kannst du mal das Assemblerlisting hochladen?

Und du hast auch tatsächlich den Wert in mysleep angepasst und nicht den hinter DDRB? 8)

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Erster Blinkversuch ATmega328

Beitrag von Timm Thaler »

Sollte eigentlich gehen. Das Kompilat sieht bei mir so aus:

Code: Alles auswählen

PsTEST_ss_MYSLEEPsSMALLINT:  // Prozedur
   push   r29
   push   r28
   push   r3
   push   r2
   in   r28,61
   in   r29,62
   subi   r28,6
   sbci   r29,0
   in   r0,63
   cli
   out   62,r29
   out   63,r0
   out   61,r28  // bis hierher Vorgeplänkel, Stackpointer sichern, Statusregister sichern
   std   Y+2,r24
   std   Y+3,r25  // Variable übernehmen
   ldd   r2,Y+2
   ldd   r3,Y+3  // Variable t in Register
   cp   r2,r1
   cpc   r3,r1  // Prüfen auf Null, immer bei for-loop
   brlt   .Lj6
   ldi   r18,-1
   ldi   r19,-1  // init i mit Null minus 1, Startwert for-loop
   std   Y+4,r18
   std   Y+5,r19  // i zwischenspeichern
.Lj7:
   ldd   r19,Y+4
   ldd   r20,Y+5  // i wieder holen
   ldi   r18,1
   add   r19,r18
   adc   r20,r1  // i + 1
   std   Y+4,r19
   std   Y+5,r20  // und wieder zwischenspeichern
#  CPU AVR5
   nop  // das NOP
#  CPU AVR5
   ldd   r18,Y+4
   ldd   r19,Y+5  // i wieder rausholen
   cp   r18,r2
   cpc   r19,r3  // und mit t vergleichen
   brlt   .Lj7  // wiederholen solange kleiner
.Lj6:
   subi   r28,-6  // Stackpointer wiederherstellen
   sbci   r29,-1
   in   r0,63
   cli
   out   62,r29
   out   63,r0
   out   61,r28
   pop   r2
   pop   r3
   pop   r28
   pop   r29
   ret  // und fertsch mit Prozedur
 
main:
   call   FPC_INIT_FUNC_TABLE  // Vorgeplänkel für den Controller, Stack einrichten und so
   ldi   r18,-1
   out   4,r18  // DDRB = 255
.Lj10:
   out   5,r1  // PORTB = 0
   mov   r24,r1  // lobyte von 256, könnte auch gleich in r25
   ldi   r26,1  // hibyte von 256
   mov   r25,r26  // muss man nicht verstehen
   call   PsTEST_ss_MYSLEEPsSMALLINT  // Prozedur aufrufen
   ldi   r18,-1
   out   5,r18  // PORTB = 255
   mov   r24,r1
   ldi   r26,1
   mov   r25,r26  // siehe oben
   call   PsTEST_ss_MYSLEEPsSMALLINT  // Prozedur aufrufen
   rjmp   .Lj10  // Endlossschleife
 


Wie man sieht, ist die for-Schleife hier reichlich ineffizient. Das liegt aber am Inline-Assembler. Da speichert der Compiler lieber zwischen, weil er nicht weiss, was an Registern geändert wird.

In r1 steht immer NULL, das wird bei vielen Berechnungen oder Vergleichen für schnellen Zugriff benutzt.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Erster Blinkversuch ATmega328

Beitrag von Timm Thaler »

Kommentiert man das asm aus, werden die Variablen nicht zwischengespeichert und die for-Schleife sieht deutlich angenehmer aus.

Code: Alles auswählen

PsTEST_ss_MYSLEEPsSMALLINT:
   cp   r24,r1
   cpc   r25,r1
   brlt   .Lj6
   ldi   r18,-1
   ldi   r19,-1
.Lj7:
   ldi   r20,1
   add   r18,r20
   adc   r19,r1
   cp   r18,r24
   cpc   r19,r25
   brlt   .Lj7
.Lj6:
   ret
 


Das ist die komplette Prozedur. Das zeigt aber auch, dass man for nicht für genaues Timing verwenden kann, weil je nach verwendbaren Registern und Compilereinstellungen die Schleife jedesmal anders aussehen kann.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

Sollte eigentlich gehen. Das Kompilat sieht bei mir so aus:

Mit was hast du kompiliert ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Erster Blinkversuch ATmega328

Beitrag von Timm Thaler »

Wie meinen?

Ich hab den aktuellen Trunk mit fpcupdeluxe installiert: Laz 1.9.0, FPC 3.1.1, SVN 55979 für win32/win64, dazu den AVR Embedded Crosscompiler.
Kompiliert mit Ziel Embedded-avr-AVR5
Optimierung Stufe 3

Die Optimierung hat entscheidenden Einfluss auf die Schleife, zum Beispiel wird in Stufe 1 und 2 oft eine for-Schleife mit uint16 gemacht, auch wenn die Laufvariable uint8 ist, und in Stufe 3 hat die gleiche Schleife dann uint8.

Aber: Das hat zwar Einfluss auf die Laufzeit und die Speicherbelegung, prinzipiell sollte das Programm jedoch funktionieren.

Hast Du die test.s gefunden? Stell die doch mal hier rein.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

prinzipiell sollte das Programm jedoch funktionieren.

Tut es aber nicht.

Ich habe den es mal so kompiliert:

Code: Alles auswählen

./ppcrossavr -O4 test.pas

Der Fehler ist leider immer noch. :roll:

Ich hab den aktuellen Trunk mit fpcupdeluxe installiert: Laz 1.9.0, FPC 3.1.1, SVN 55979 für win32/win64, dazu den AVR Embedded Crosscompiler.
Kompiliert mit Ziel Embedded-avr-AVR5
Optimierung Stufe 3

Diese Version funktioniert bei mir leider nicht, sobald ich die Unit ATmega328p einbinde, dann kommt folgender Fehler:

Code: Alles auswählen

Projekt kompilieren, OS: embedded, CPU: avr, Ziel: Project1: Exit code 256, Fehler: 1
Free Pascal Compiler version 3.1.1-r20:37407 [2017/10/08] for avr
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Embedded
Compiling Project1.pas
Assembling project1
Linking Project1
/usr/bin/avr-ld: Project1.elf section `.text' will not fit in region `text'
 
 
 
 
 
Project1.pas(32,0) Error: Error while linking

Noch etwas, diese Unit musste ich über Project-Einstellungen manuell mit folgendem Pfad einbinden: /home/tux/fpcupdeluxe/fpcsrc/rtl/embedded/avr/ , ansonsten wird sie gar nicht gefunden.

Musstest du dies auch machen, oder hat es bei dir die Unit automatisch gefunden ?

Dieses Problem habe ich erst kürzlich entdeckt, weil ich bei diesem Thread: viewtopic.php?f=15&t=11044&p=98472&hilit=sloeber#p98472 , die Unit Atmega328p gar nicht eingebunden hatte.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Erster Blinkversuch ATmega328

Beitrag von Timm Thaler »

Ich hab die Unit gar nicht eingebunden bzw. bei Deinem Test ausgeklammert.

Ich geb zu, ich hab einmal mit LazWizardforAVR aus diesem Forum http://forum.lazarus.freepascal.org/index.php?topic=35486.0 ein AVR Projekt erstellt und nutze seitdem immer das gleiche Projekt-Template.

Das kommt davon, wenn man sich seine Infos über Wochen aus verschiedenen Foren zusammensucht und solange probiert, bis man irgendwas Funktionierendes hat, auch wenn man dann nicht mehr weiss, warum es funktioniert.

Achso, bei mir steht unter Projekteinstellungen => Compiler => Benutzerdefinierte noch

-Cpavr5
-Wpatmega328p
-a

Und unter Pfade => andere Units

C:\Tools\Lazarus\fpc\units\avr-embedded\;C:\Tools\Lazarus\cross\lib\avr_embedded\

Damit funktioniert es hier, warum weiss ich nicht.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

Habe habe das Tool gerade probiert und deine Pfade ergänzt.

Code: Alles auswählen

atmega328p.pp(7,4) Fatal: Circular unit reference between ATmega328P and ATmega328P


Hast du keine fertiges Helloworld Project, das du hochladen kannst ?
Dann könnte ich an diesem experimentieren. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

@Timm Thaler

Könntest du mir ein funktionierendes minimal Project hochladen ?
Dann würde ich sicher auch ein wenig weiter kommen. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Erster Blinkversuch ATmega328

Beitrag von kupferstecher »

Hallo Mathias,

im Anhang ein Lazarusprojekt für den Atmega328p. Ich hab mir gerade den neuesten FPC runtergeladen (Rev.37442) und das Projekt erfolgreich kompiliert mit Strg+F9. Um das Programm mit Shift+F9 auch gleich noch hochzuladen musst du die entsprechende Kommandozeile in den Projekteinstellungen unter 'Compilereinstellungen/Compiler-Kommandos/Nachher Ausführen/Befehl' eintragen.

Die Unit atmega328p darf nicht "händisch" eingebunden werden, das geschieht automatisch durch den Kompiler, ihm muss über den Parameter -Wpatmega328p der Controller übergeben werden.

Durch die folgende Kommandozeile kann ich das Projekt auch in der Konsole kompilieren:
"ppcrossavr -O1 -Cpavr5 -Wpatmega328p -XPavr-embedded- Mega328pProject.lpr"

Da ich keinen atmega328p habe, konnte ich das Programm auch nicht testen.
Dateianhänge
Mega328pProject.zip
(4.89 KiB) 94-mal heruntergeladen

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

im Anhang ein Lazarusprojekt für den Atmega328p. Ich hab mir gerade den neuesten FPC runtergeladen (Rev.37442) und das Projekt erfolgreich kompiliert mit Strg+F9. Um das Programm mit Shift+F9 auch gleich noch hochzuladen

Code: Alles auswählen

Fatal: Can't find unit ATMEGA328P used by Mega328pProject

Das komische dabei, wen ich zB. PORTD mit der recht M-Taste anklicke und Deklaration suche, dann öffnet Lazarus die ATmega328P Unit.

In dem Ordner /home/tux/fpcupdeluxe/fpc/units/avr-embedded/rtl befindet sich auch keine atmega328*, bei mir hat es dort nur atmega128* Dateien.

Durch die folgende Kommandozeile kann ich das Projekt auch in der Konsole kompilieren:
"ppcrossavr -O1 -Cpavr5 -WpatmeTasraga328p -XPavr-embedded- Mega328pProject.lpr"

Code: Alles auswählen

Mega328pProject $ /home/tux/fpcupdeluxe/fpc/bin/x86_64-linux/ppcrossavr -O1 -Cpavr5 -Wpatmega328p -XPavr-embedded- Mega328pProject.lpr
Free Pascal Compiler version 3.1.1-r20:37437 [2017/10/10] for avr
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Embedded
Compiling Mega328pProject.lpr
Fatal: Can't find unit system used by Mega328pProject
Fatal: Compilation aborted


Irgendwas stimmt mit meinem Crosscompiler nicht. :roll:

Hast du deinem Lazarus auch mit fpcupdelux erstellt ?
Wen ja, hast du auch folgende Parameter bei "Setup+" ?

Code: Alles auswählen

avr-embedded
  options : -Cpavr51
  subarch : avr51


Da ich keinen atmega328p habe, konnte ich das Programm auch nicht testen.

Kein Arduino Uno oder Nano zur Hand ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Erster Blinkversuch ATmega328

Beitrag von kupferstecher »

Der Befehlssatz muesste avr5 sein, nicht avr51, also:
options : -Cpavr5
subarch : avr5
Auf der Wikiseite AVR gibts einen Link zu den Befehlssaetzen.
Der Befehlssatz muss schon stimmen, aber ob dein Fehler damit zusammenhaengt, weiss ich auch nicht.

Ich hab den Crosscompiler nicht mit Fpcupdelux erstellt, ich kann dir morgen mal meine Vorgehensweise beschreiben.

Arduino hab ich keinen, bisher hab ich mit dem Atmega32 und Atmega8 gearbeitet. Die Unit SerialPort ist uebrigens fuer den Atmega32, eine Anpassung an den Atmega328p sollte aber recht einfach sein, fuer ein erstes "Hello Mathias".

Gruesse~

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erster Blinkversuch ATmega328

Beitrag von Mathias »

Der Befehlssatz muesste avr5 sein, nicht avr51, also:
options : -Cpavr5
subarch : avr5

Ich habe des probiert.

Code: Alles auswählen

Compile Project, OS: embedded, CPU: avr, Target: Mega328pProject: Exit code 256, Errors: 1
AVRStandard.pas(15,3) Error: Assembler avr-embedded-as not found, switching to external assembling


Was mich noch verwundert, bei deinem Project, hat es nirgends ein uses atemga???
Aber wen ich [Alt + up] drücke, dann wird die Unit ATmega328p geöffnet. :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Erster Blinkversuch ATmega328

Beitrag von Timm Thaler »

Mathias hat geschrieben:Was mich noch verwundert, bei deinem Project, hat es nirgends ein uses atemga???


Doch, das sollte unter Projekteinstellungen stehen:

Laz-emb-01.png

Antworten