Guten Abend Community!
Ich habe mal eine Frage und zwar möchte ich einen Analog/Digitalwandler
an einen Atmega64 nutzen.
Das ist ein 2MS ADC mit 8bitigem Parallel Interface. Zur Steuerung
werden 3 Leitungen genutzt, mit denen man jede Wandlung initialisieren
muss (macht er leider nicht automatisch). Nun muss ich das natürlich so
schnell wie möglich machen und entsprechend wohl tunen:-/
Leider ist der qC so voll, dass die PINs auch noch an unterschiedlichen
Ports liegen.
Und dann auch noch die UND/ODER Verknüpfungen für Setzen/Lesen der
PIN-Pegel...
Und Schleife fürs warten auf Signale...
Geht das nicht schneller? Nicht dass ich dann wirklich noch mit ASM
anfangen muss :-(
Gibt es keine Anweisung, damit er sich möglichst viele Register für
diese eine Funktion leer hält (lieber Stack nutzt) und so die
Verknüpfungen/Schleifen evtl. schneller werden?
Ich kenne nur REGISTER (Variable wird im Register gehalten, habe aber
keinen Zähler), STATIC und habe mir auch schon Atmels "efficent C
coding" durchgelesen, was aber eigentlich zu 99% im MC AVR-Tut (besten
Dank an der Stelle! :-)) erwähnt wird.
Hat einer ne Idee? Ich weiß, ist n bissel allgemeingültig, gell?
> Und dann auch noch die UND/ODER Verknüpfungen für Setzen/Lesen der> PIN-Pegel...
Mach dir deswegen keine Sorgen. Das optimiert dir der Compiler
alles auf einen einfachen "Set Bit am Port".
> Gibt es keine Anweisung, damit er sich möglichst viele Register für> diese eine Funktion leer hält (lieber Stack nutzt) und so die> Verknüpfungen/Schleifen evtl. schneller werden?
Der AVR-gcc macht das eigentlich sehr gut.
>Mach dir deswegen keine Sorgen. Das optimiert dir der Compiler>alles auf einen einfachen "Set Bit am Port".
Wenn ich mir die .lss anschaue dann macht er das ja leider gerade nicht
in jedem Fall :-(
AVRStudio scheint auhc beim disassemblen nicht wirklich toll zu sein,
Schleifen werden da nicht wirklich verständlich dargestellt...
Kreige ich leider nicht wieder reproduziert, habe schon n bissel mehr an
dem Code rumgewerkelt.
Es gibt ja in der AVRLibC (stdint.h) auch die FAST Typen, der für mich
interessante wäre int_fast8_t. Ich konnte aber nirgendwo finden, wieos
die nun schneller sein sollen?
Das hat mit "schneller sein" nichts zu tun. Das sind ISO-C-Typedefs.
int_fast8_t ist der schnellste Integer-Datentyp, der mindestens 8 Bit
breit ist, nichts weiter. Es ist bei AVR vermutlich einfach ein typedef
für char.
Ich hätte mal noch 2 andere Fragen :-)
1. Gibt es eine Datei oder ein Programm, dass einem die Cycles für einen
bestimmten Codeabschnitt raussucht? Per .lss und OpCode-Table ist dass
doch immer recht nervig.
2. Wie viel Overhead erzeugen ISRs? Werden dort alle, nur die für die
AVRLibC Kommunikation oder nur die innerhalb der ISR veränderten
Register gepusht/popt?
Das ist echt net leicht schneller zu werden... Einige Konstanten scheint
er weiterhin partout aus dem Flash holen zu wollen grummel
> 1. Gibt es eine Datei oder ein Programm, dass einem die Cycles für einen> bestimmten Codeabschnitt raussucht? Per .lss und OpCode-Table ist dass> doch immer recht nervig.AVR Studio im Simulator.
Dort gibt es eine 'Stopuhr'
Du setzt einen Breakpoint auf den Anfang der interessierenden
Sequenz, setzt die Stopuhr zurück. Breakpoint ans Ende der
Sequenz. Programm laufen lassen und bei erreichen des Breakpoints
die 'Stoppuhr' ablesen.
> 2. Wie viel Overhead erzeugen ISRs? Werden dort alle, nur die für die> AVRLibC Kommunikation oder nur die innerhalb der ISR veränderten> Register gepusht/popt?
Lass dir vom Compiler ein Assembler Listing erzeugen,
dann weist du es genau.
> Das ist echt net leicht schneller zu werden... Einige Konstanten> scheint er weiterhin partout aus dem Flash holen zu wollen *grummel*
Wie meinst du das?
Normalerweise haben die meisten Schwierigkeiten dabei, Konstanten
ins Flash zu verlegen. Der umgekehrte Fall ist eher selten.
Ich meinte das so:
Ich möchte einen PIN zusätzlich an/aus schalten. Wenn ich das in C wie
gewohnt mache (PORTA&=(1<<PA1) werden ASM 2 Anweisungen erzeugt (IN+OR)
Deshalb lade ich beim Funktionsbeginn den Portzustand in Buffer
Variablen, die ich per REGISTER in ein Register legen lass und diesen
Wert schreibe ich dann immer auf den Port zurück. Dadurch wird nur 1 ASM
Anweisung erzeugt.
An einer Stelle funktioniert das aber nicht:
ADC_CPORT=bufRDlow;
9be: 30 93 65 00 sts 0x0065, r19
Da wird nun ein STS (2 Takte da Flashzugriff) gemacht obwohl die
Konstante wunderbar in einem Register sein könnte. Wie treibe ich ihm
das bloß aus?
> Ich möchte einen PIN zusätzlich an/aus schalten. Wenn ich das in C wie> gewohnt mache (PORTA&=(1<<PA1) werden ASM 2 Anweisungen erzeugt (IN+OR)
Das ergibt keinen Sinn. Erstens benutzt du & statt |, zweitens würde ich
in diesem Fall noch eine dritte Anweisung erwarten, nämlich out,
drittens macht GCC daraus normalerweise (angenommen, | statt & war
gemeint) ein sbi PORTA, PA1. Vielleicht Optimierungen aus?
> Deshalb lade ich beim Funktionsbeginn den Portzustand in Buffer> Variablen, die ich per REGISTER in ein Register legen lass und diesen> Wert schreibe ich dann immer auf den Port zurück. Dadurch wird nur 1> ASM Anweisung erzeugt.
Ich würde erwarten, dass in beiden Fällen jeweils nur eine ASM-Anweisung
erzeugt wird. Im ersten sowieso und im zweiten weil die Variable
vermutlich komplett wegoptimiert wird und dann dasselbe wie im ersten
Fall draus wird.
> An einer Stelle funktioniert das aber nicht:> ADC_CPORT=bufRDlow;> 9be: 30 93 65 00 sts 0x0065, r19>> Da wird nun ein STS (2 Takte da Flashzugriff) gemacht obwohl die> Konstante wunderbar in einem Register sein könnte.
Was für ein Flashzugriff? Was für eine Konstante? Die angegebene
Instruktion kopiert den Inhalt von r19 an die Adresse 5 im RAM. Du
solltest vielleicht erstmal nachschauen, was die ASM-Instruktionen
eigentlich machen, bevor du einfach irgendwas schlussfolgerst.
Entschuldige, ich meinte natürlich nicht Flash sondern SRAM, war gestern
etwas kaputt.
Optimierung steht im MakeFile auf S, das ist doch ausreichend oder muss
dort 0..3 stehen? Wäre natürlich ärgerlich aber mein Fehler ;-)