Ist Assembler in der IDE möglich?

Hallo,

wollte mal fragen ob es eine Möglichkeit gibt Assembler Code Stücke in der IDE zuverwenden. Zur Zeit gelingt mir das nicht. Auch in Atmel Studio und dem Micro Plugin gehts nicht. Klappt nur wenn man in Atmel Studio ein neues Projekt als Assembler startet. Jetzt frage ich mich gerade, kann man C und Assembler überhaupt im gleichen Code mischen?

Hallo Doc,
es sollte durchaus möglich sein, Inline Assembler in einem C/Cpp File anzuwenden. Wie sieht dein derzeitiger Ansatz aus?

void loop()
{
asm volatile ("nop");
}

Hallo,

wenn ich nicht die falschen Codezeilen herausgefischt habe, soll das

.org OC1Aaddr
  in     isr_SREG,SREG
  in     isr_tmp,outPORT
  subi   isr_tmp,incrmnt       ; synchr. pos. Flanke
  out    outPORT,isr_tmp
  out    SREG,isr_SREG
  reti

den bisherigen Interrupt Handler ersetzen

ISR(TIMER1_COMPA_vect) {  // Timer 1 Interrupt 
// erzeugt ein Rechtecksignal an mehreren Pins eines Port
  byte temp = OUTPORT;
  temp += INCRMNT;
  OUTPORT = temp;                                 
}

das compilieren scheitert aber schon am dem Punkt von .org OC1Aaddr,
die Semikolons stören dann auch usw.

Es handelt sich zwar immer noch um den Timer Thread, aber nicht direkt um den Timer, dass ist geklärt. Der Assemblercode spart paar CPU Takte, was sich massiv auf die max. Taktfrequenz auswirkt.

Timer1_Frequenzgenerator_010_asm.ino (5.13 KB)

Hallo,

oder fehlt dem noch ein include File für die CPU? (Mega2560)

Meine Tests haben ergeben:
Inlineassembler ist überall möglich, aber unhandlich.

Assembler *.S Dateien sind im Projektordner nicht möglich.

Libs können durchaus *.S Dateien enthalten. Das funktioniert ganz gut.
Eine *.h Datei mit extern Deklarationen ist notwendig.

Hallo,

ich habe den Interrupt Handler "ausgelagert" in eine .h Datei und binde diese mit
#include "Assembler.h" ein.

enthält:

// das soll  ISR(TIMER1_COMPA_vect) {  ersetzen
.org OC1Aaddr
  in     isr_SREG,SREG
  in     isr_tmp,outPORT
  subi   isr_tmp,incrmnt       ; synchr. pos. Flanke
  out    outPORT,isr_tmp
  out    SREG,isr_SREG
  reti

Fehlermeldung beim compilieren:

In file included from Timer1_Frequenzgenerator_010_asm.ino:22:
Assembler.h:2: error: expected unqualified-id before '.' token
Assembler.h:5: error: expected constructor, destructor, or type conversion before '.' token

Der gleiche Fehler wie vorher. Ist der Code falsch?

Das geht nicht!
In *.h Dateien dürfen nur Präprozessor Statements und c/C++ Code stecken.
Von mir aus auch noch Inline Assembler....

Ansonsten gilt in der Arduino Welt:
Assemblercode muss in einer *.S Datei stecken und diese dann in einer Lib.

Nachtrag:
Eine Beispiel Lib im Anhang
Quelle: irgendwo gefunden

AssemblerTestLib.zip (996 Bytes)

Die Arduino IDE ist doch sowieso viel zu schwach. Wenn Du eh schon an Assembler ran gehst, dann nimm doch AVR Studio oder ein make oder sconstruct File. Dann geht das problemlos. Man kann die Arduino Libraries auch ohne IDE einbinden.

Hallo,

mit inline Assembler komme ich nicht klar. Immer wieder wird der punkt angemeckert.
Egal ob .org oder .def
Ich versuche es jetzt mal im Atmel Studio.
Oder ich verwechsel noch grundlegende Dinge. So einfach wie ich dachte ist das nicht.

Doc_Arduino:
Oder ich verwechsel noch grundlegende Dinge.

Dem stimme ich zu, ohne zu wissen wo genau das Problem ist.

Korrektur: (!!)

Egal ob .org oder .def

Diese Bezeichner kennt der Inline Assembler nicht.

Vermutung:
Du willst gar nicht den Inline Assembler nutzen.

Hallo,

um meinen Nebel etwas zu lichten. Egal ob IDE oder Amtel Studio. Ich benötige immer die .h und .s Datei? Richtig?
Das rot markierte ist doch das gleiche wie ISR(TIMER1_COMPA_vect) {
oder nicht? Nicht das ich einen kompletten Irrtum unterliege.

.org OC1Aaddr
in isr_SREG,SREG

in isr_tmp,outPORT
subi isr_tmp,incrmnt ; synchr. pos. Flanke
out outPORT,isr_tmp

out SREG,isr_SREG
reti

.org OC1Aaddr

.org == Origin == Herkunft == Ort

Die Startadresse des Codes.

Ich benötige immer die .h und .s Datei? Richtig?

Nicht *.s, sondern *.S

Und die *.h um es dem Kompiler kund zu tun, was du da an Assembler Code einbinden willst.

(was OC1Aaddr bedeutet... KA ..)

Hallo,

naja, rein von der Bezeichnung her würde es in die Richtung gehen.
OC1Aaddr

OC1A wie Overflow Compare vom Timer 1 Kanal A (meine Vermutung was es bedeuten könnte)

ich werde mich damit mal beschäftigen ...

Edit:
so, OC1Aaddr ist nicht anderes als die Output Compare1A Interrupt Vector Address

Wenn OC1Aaddr ein Ort in der Interrupttabelle ist, dann darf darauf kein Code folgen, außer einem rjmp zu deiner ISR.

Auch scheint mir dein ganzes Verfahren nur brauchbar, wenn ALLES in Assembler geschrieben wird. Denn Arduino kümmert sich selber um den Aufbau der Tabelle.

Hallo,

alles in Assembler möchte ich nun nicht, da müßte man komplett umdenken und lebt nur noch in Bits und Bytes. :slight_smile:
Hatte mal gelesen das es durchaus überlich wäre sein Programm in C zu schreiben und nur wenn es wirklich zeitkritisch wird den Teil in Assembler. Das wäre bei mir nun der Fall.

Oder findest Du Assembler einfacher als C? Ganz ehrlich.

Habe übrigens rausgefunden wo man das alles nachschauen kann, wenn man Atmel Studio installiert hat.
Auf meinem Rechner der Pfad:
C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler

supported-devices.xml mit Notepad++ öffnen, kann man nachschauen wie die Definitionsdatei für seinen µC lautet.
Im Ordner include stehen dann alle Definitionsdateien, passende auch mit Notepad++ öffnen und dann sieht man alle Adressen mit zugehörigen Namen des µC.

Was bedeutet Zeitkritisch? Wurde von Jurs glaube ich bereits angedeutet, wenn es wirklich kritisch wird, solltest du auf avr-gcc umdenken ohne die Arduino-komfort-Routinen. Komfort braucht seine Zeit.

Wieso reicht nicht inline Assembler in einer ISR? Wegen der Sicherung von ein paar Registern auf dem Stack?

Hallo,

ich muß doch nicht den gesamten Code ändern nur weil ich einen Interrupt Handler in Assembler habe möchte.

Inline Assembler würde ich gern bevorzugen, habs aber noch nicht hinbekommen. Vielleicht hat ja jemand eine Idee. Hab den restlichen Tag heute meine Leiterplatte gelötet bis jetzt.

Ich zeig nochmal den gesamten Code wovon ich nur den Interrupt Handler benötige.

[color=#557799].include[/color] [color=#bb4444][b]"m2560def.inc"[/b][/color]

[color=#557799].equ[/color] outDDR = DDRC [color=#888888]; Ausgabe auf PORT C [/color]
 [color=#888888]; ================================[/color]
[color=#557799].equ[/color] outPORT = PORTC
[color=#557799].equ[/color] outMASK = [color=#0000dd][b]0b11100000[/b][/color] [color=#888888]; ==> incrmnt[/color]
[color=#557799].equ[/color] incrmnt = [color=#0000dd][b]0b00100000[/b][/color] [color=#888888]; ==> C5: f, C6: f/2, C7: f/4[/color]
[color=#557799].equ[/color] OCR1 = [color=#0000dd][b]50[/b][/color] [color=#888888]; ==> f = f_CPU/100, Beispiel fuer c[/color]
 [color=#888888]; asm erlaubt 14, bei f_CPU= 16 MHz also f= 571429 Hz[/color]

[color=#557799].def[/color] isr_SREG = [color=#003388][b]r2[/b][/color]
[color=#557799].def[/color] isr_tmp = [color=#003388][b]r16[/b][/color]
[color=#557799].def[/color] tmp0 = [color=#003388][b]r17[/b][/color]

[color=#557799].org[/color] [color=#0000dd][b]0[/b][/color]
 rjmp reset

[color=#557799].org[/color] OC1Aaddr
[color=#888888]; optimierte Routine[/color]
 in isr_SREG,SREG

 in isr_tmp,outPORT
 subi isr_tmp,incrmnt [color=#888888]; synchr. pos. Flanke[/color]
 out outPORT,isr_tmp

 out SREG,isr_SREG
 reti
 
[color=#997700][b]reset:[/b][/color]
 ldi tmp0,outMASK
 out outDDR,tmp0
 ldi tmp0,high(OCR1-[color=#0000dd][b]1[/b][/color])
 sts OCR1AH,tmp0
 ldi tmp0,low(OCR1-[color=#0000dd][b]1[/b][/color])
 sts OCR1AL,tmp0
 ldi tmp0,([color=#0000dd][b]1[/b][/color]<<CS10)+([color=#0000dd][b]1[/b][/color]<<WGM12) [color=#888888]; f_CPU/1, CTC auf OCR1A[/color]
 sts TCCR1B,tmp0
 ldi tmp0,([color=#0000dd][b]1[/b][/color]<<OCIE1A)
 sts TIMSK1,tmp0
 sei
[color=#997700][b]main_loop:[/b][/color]
 rjmp main_loop

Doc_Arduino:
Inline Assembler würde ich gern bevorzugen, habs aber noch nicht hinbekommen.

Schreib die ISR wie in C/C++ und mach dann darin inline Assembler. Der Compiler macht dann vielleicht ein paar mal push/pop. Sieht man dann beim Disassemblieren.