AVR Assembler - IO Port-Switching-Zeiten nicht berechenbar

#4092499
Lesenswert?

Hallo,

ich versuche einen IO-Port zu schalten, brauche dafür ein auf 
1-Clock-Zyklus genaues Timing und genau da liegt das Problem. Leider 
kann ich noch kein Assembler, deshalb versuche ich es in C. Damit es so 
unkompliziert wie möglich ist, sieht mein Code (gekürzt) so aus:

uint8_t off = PORTB;
uint8_t on = PORTB | (1<<PORTB4);

if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;
if (bla) PORTB = on; else PORTB = off;

Das funktioniert auch alles soweit, solange ich 01010101 setze. Setze 
ich allerdings 00001111 fällt mir auf, dass er anscheinend so "klug" 
ist, bei den sich wiederholenden Bits weniger Zyklen zu brauchen als bei 
dauernd wechselnden Bits, als ob es intern so nach 
"IF(differentStatus)Switch" ablaufen würde. Das ist natürlich 
prinzipiell sehr intelligent, aber in meinem Fall müssen die Timings 
halt genau stimmen. Laut ASM macht er es so:

sbrs r24, 1
rjmp .+4
out 0x18, r25
rjmp .+2
out 0x18, r18

Sieht doch für mich als Laie eigentlich genau richtig aus. Dennoch 
brauchen die outs je nach Bitmuster verschieden lange....
Gast #4092505
Lesenswert?

Christian S. schrieb:
> Das funktioniert auch alles soweit, solange ich 01010101 setze. Setze
> ich allerdings 00001111 fällt mir auf, dass er anscheinend so "klug"
> ist, bei den sich wiederholenden Bits weniger Zyklen zu brauchen als bei
> dauernd wechselnden Bits, als ob es intern so nach
> "IF(differentStatus)Switch" ablaufen würde.

zeige dafür bitte brauchbaren code - wo wird denn 01010101 gesetzt?

> Dennoch brauchen die outs je nach Bitmuster verschieden lange....
nein, ein out brauch immer gleich lange. Die Frage ist ob ein out immer 
das richtige ist.

Zeige eine komplette Funktion und den Aufruf dafür.
Gast #4092515
Lesenswert?

>Sieht doch für mich als Laie eigentlich genau richtig aus. Dennoch
>brauchen die outs je nach Bitmuster verschieden lange...

Out ist out! Ob jetzt 8-mal nix 0x00 oder 8-mal was 0xff rausgeschaufelt 
wird, ist dem Befehl gleich.
Moderator Persönliche Seite #4092529
Lesenswert?

Christian S. schrieb:
> uint8_t off = PORTB;
> uint8_t on = PORTB | (1<<PORTB4);
>
> if (bla) PORTB = on; else PORTB = off;
> if (bla) PORTB = on; else PORTB = off;

Dieser Code ist Schwachsinn. Die Variable off enthält den aktuellen 
Zustand von PORTB, die Variable on enthält den aktuellen Zustand, wobei 
zusätzlich PB4 gesetzt ist. Wenn aber das Bit einmal gesetzt wurde, ist 
es auch beim nächsten mal in der Variablen off gesetzt.

Wenn, dann muss das so heißen:
1
if (bla) PORTB |= (1<<PORTB4); else PORTB &= ~(1<<PORTB4);
2
if (bla) PORTB |= (1<<PORTB4); else PORTB &= ~(1<<PORTB4);
3
...

Aber zurück zur eigentlichen Frage, nämlich zu den verschieden langen 
Abarbeitungszeiten: Es liegt nicht an der Portzuweisung, sondern an der 
Abarbeitung der if-Statements. Je nachdem, welche Bedingung TRUE ist, 
sind verschieden viele ifs durchlaufen worden. Das braucht 
unterschiedlich lange Zeiten.

Abhilfe: Eine Tabelle. Vielleicht auch ein switch.
Gast #4092545
Lesenswert?

Noch besser:
Verwendung von Timer-Output-Compare. Das geht zwar nur mit dezidierten 
Timer-Pins, dafür kannst Du Dir aber auch sicher sein, daß da Timing 
passt.

Bei Deiner Software-Lösung darfst Du entweder keine Interrupts verwenden 
oder Du musst sie für die Dauer des Pulses ausschalten.

Gruß, Stefan
Gast #4092562
Lesenswert?

Es gibt die Möglichkeit den Versatz durch die unterschiedlichen 
Laufzeiten durch das auffüllen mit NOPs auszugleichen. In der Praxis 
artet das aber schnell in einen Job für den guten, alten Sisyphos aus.

Soweit mir bekannt benötigen die einfachen out-Befehle 1 Tackt Zyklus, 
ein bedingter Sprung ohne Verzweigung ebenfalls einen Tackt und bei 
Verzweigung 2 Tackte.
#4092607
Lesenswert?

Mittlerweile habe ich das Problem gefunden.

Hier nochmal der Code, auf den es ankommt:

sbrs r24, 1
rjmp .+4
out 0x18, r25
rjmp .+2
out 0x18, r18

Das Problem ist, dass die rjmps manchmal vor und manchmal nach dem out 
ausgeführt werden, was das Timing zerstört. Ich habe es jetzt durch nops 
gelöst, aber das kostet mich insgesamt 3 Takte. Kann man sich diesen 
Iftest irgendwie sparen?

Irgendwie sowas wäre schön:

PORTB = Bit 0 von byte X an Stelle PORTB4 packen
PORTB = Bit 1 von byte X an Stelle PORTB4 packen
PORTB = Bit 2 von byte X an Stelle PORTB4 packen
PORTB = Bit 3 von byte X an Stelle PORTB4 packen
PORTB = Bit 4 von byte X an Stelle PORTB4 packen
PORTB = Bit 5 von byte X an Stelle PORTB4 packen
PORTB = Bit 6 von byte X an Stelle PORTB4 packen
PORTB = Bit 7 von byte X an Stelle PORTB4 packen

Es geht einfach darum, einen UART Sender in Software zu implementieren. 
Dient für mich als Übung.
Gast #4092626
Lesenswert?

mich wunder das es überhaupt ein out gibt. Du willst doch nur ein bit 
setzen. Mit out blockierst du den ganzen Port für andere dinge.

Und bei einen Soft-Uart brauchst du eh pausen. Damit spielt das Timing 
gar keine so grosse rolle.
1
uint8_t data = 0x12;
2
for( uint8_t i = 0; i < 8; ++i ) {
3
   if ( data & 1 ) {
4
       PORTB |= (1<<PB4)
5
   } else {
6
       PORTB &= ~(1<<PB4)
7
   }
8
   data = data >> 1;
9
   us_dalay(xxx);
10
}

damit sollte es schon funktionieren, die schleife könnte man auch noch 
aufdröseln aber da man eh warten muss sehen ich kaum sinn drin. In 
diesem code sollte auch kein OUT mehr vorhanden sein.

Wie schnell willst du denn übertragen?
Gast #4092627
Lesenswert?

Christian S. schrieb:
> Mittlerweile habe ich das Problem gefunden.

Das Problem ist klar erkennbar. Wenn ich Dir ungebeten einen Rat geben 
darf, fange erst mal an C zu lernen, eine LED zu toggeln und das 
Datenblatt zu lesen. So in einem halben Jahr vielleicht schreibst Du mal 
eine Software UART. Das bisher gezeigt ist, mit Verlaub, grosser Murks. 
:-)
#4092636
Lesenswert?

Ich bin jetzt erfolgreich bei 1 MBit mit dem internen 8 MHz Resonator 
und will mal sehen ob 2 möglich sind. Dazu muss jedoch der IF-Test weg. 
Ich denke, aufgrund mancher Äusserungen kann ich auf diesem hohen Niveau 
keine Hilfe erwarten. Kein Problem, hab bisher alle meine Problem auch 
selbst lösen können. Dauert nur etwas länger ^^

Das mit BST und BLD könnte echt mal eine Möglichkeit sein. Habe mich 
immer gefragt, was dieser blöde 1 Bit Speicher soll. Danke :)
#4092646
Lesenswert?

Wenn Du solche Geschwindigkeiten anstrebst (1 Bitlänge = 4 Taktzyklen), 
solltest Du dich mit (Inline-)Assembler beschäftigen. Die von Markus 
Weber vorgeschlagene BST / BLD -Lösung schafft die Geschwindigkeit. Der 
Empfang wird noch lustig, da Du die fallende Flanke des Startbits auf 
einen Taktzyklus genau erkennen must, und nur 6 Takte bis zum Abtasten 
des ersten Datenbits hast.

Mit freundlichen Grüßen - Martin
(Firma: guloshop.de) #4092652
Lesenswert?

Es geht übrigens auch noch schneller:

LSR
OUT
... 8 Mal. -> 4 Mbps

Aber dann wirds etwas schmutzig, weil du vom betreffenden Port nur Bit 0 
für die Ausgabe benutzen kannst. Die übrigen Pins tragen nur Bitabfälle 
nach draußen. :-)

Was natürlich nichts macht, wenn die übrigen Pins des Ports als Eingänge 
verwendet werden. Dann schaltet man nur die Pullups – wenn überhaupt, 
denn bei manchen neueren AVR gibts dafür ja ein eigenes Pullup-Register.

Ach so: Manche AVR können auch mit 16 MHz internem Takt betrieben werden 
(z.B. ATtiny85, ATtiny861A). Vielleicht hilft dir das, die 
Geschwindigkeit noch weiter zu erhöhen...
(Firma: guloshop.de) #4092680
Lesenswert?

Jörg Wunsch schrieb:
> Ansonsten ist es eher unverständlich, warum man für derartige
> Geschwindigkeiten nicht auf die vorhandene Hardware zurückgreift.

Öhm, ja, seh ich genauso. :-)

Christian schreibt oben ja: "Dient für mich als Übung".
Vielleicht plant er auch irgendwas Seltsames und will Worte mit 4 oder 
10 bit Länge senden, dann wirds mit der Standard-Hardware auch wieder 
kompliziert.
Gast #4092957
Lesenswert?

Christian S. schrieb:

> Irgendwie sowas wäre schön:
>
> PORTB = Bit 0 von byte X an Stelle PORTB4 packen
> PORTB = Bit 1 von byte X an Stelle PORTB4 packen
> PORTB = Bit 2 von byte X an Stelle PORTB4 packen
> PORTB = Bit 3 von byte X an Stelle PORTB4 packen
> PORTB = Bit 4 von byte X an Stelle PORTB4 packen
> PORTB = Bit 5 von byte X an Stelle PORTB4 packen
> PORTB = Bit 6 von byte X an Stelle PORTB4 packen
> PORTB = Bit 7 von byte X an Stelle PORTB4 packen
>
> Es geht einfach darum, einen UART Sender in Software zu implementieren.
> Dient für mich als Übung.

Dann übe es bitte in einer Sprache, mit der du volle Kontrolle über das 
Timing hast. C ist keine solche Sprache, Assembler schon. Übrigens hast 
du einen Assembler, ein C-Compiler ist schließlich auch nur ein 
aufgebohrter Assembler, kann aber immer noch native 
Assembler-Instruktionen verstehen.

Was nun dein Problem betrifft, geht die schnellste Lösung so (Byte x sei 
in Register R24, R16 sei unbenutzt/gesichert):

cli                ; 1
in R16,PORTB       ; 1
cbr R16,1<<PORTB4  ; 1 Startbit
out PORTB,R16      ; 1

bst R24,0          ; 1
bld R16,4          ; 1
out PORTB,R16      ; 1
bst R24,1          ;...
bld R16,4
out PORTB,R16
bst R24,2
bld R16,4
out PORTB,R16
bst R24,3
bld R16,4
out PORTB,R16
bst R24,4
bld R16,4
out PORTB,R16
bst R24,5
bld R16,4
out PORTB,R16
bst R24,6
bld R16,4
out PORTB,R16
bst R24,7
bld R16,4
out PORTB,R16

sbr R16,1<<PORTB4  ; 1 Stopbit
sei                ; 1
out PORTB,R16      ; 1


Jedes Bit dauert drei Takte, die gesamte Routine 31 Takte. Die Bitrate 
entspricht einem Drittel des Systemtakts.

Und, bevor du fragst: langsamer geht immer, das ist leicht. Schwierig 
wäre bloß noch schneller. Das geht, zumindest beim AVR8, nichtmal über 
die eingebaute UART-Hardware. Naja, bei den neueren kann man sie im 
SPI-Mode betreiben und erreicht dann bei der Bitrate sogar die Hälfte 
des Systemtaktes und das sogar ohne jegliche Interuptsperre.
Gast #4092981
Lesenswert?

c-hater schrieb:
> Und, bevor du fragst: langsamer geht immer, das ist leicht. Schwierig
> wäre bloß noch schneller.

auch kein Problem. Wenn genug Flash vorhanden ist.
1
switch( data ) {
2
   case 0:
3
       PORTB |= (1<<pb4); //start
4
       PORTB &= ~(1<<pb4); //bit0
5
       PORTB &= ~(1<<pb4); //bit1
6
       PORTB &= ~(1<<pb4); //bit2
7
       PORTB &= ~(1<<pb4); //bit3
8
       PORTB &= ~(1<<pb4); //bit4
9
       PORTB &= ~(1<<pb4); //bit5
10
       PORTB &= ~(1<<pb4); //bit6
11
       PORTB &= ~(1<<pb4); //bit7
12
       PORTB |= (1<<pb4); //stop
13
       break;
14
   case 1:
15
       PORTB |= (1<<pb4); //start
16
       PORTB |= (1<<pb4); //bit0
17
       PORTB &= ~(1<<pb4); //bit1
18
       PORTB &= ~(1<<pb4); //bit2
19
       PORTB &= ~(1<<pb4); //bit3
20
       PORTB &= ~(1<<pb4); //bit4
21
       PORTB &= ~(1<<pb4); //bit5
22
       PORTB &= ~(1<<pb4); //bit6
23
       PORTB &= ~(1<<pb4); //bit7
24
       PORTB |= (1<<pb4); //stop
25
       break;
26
    //usw
27
    //....
28
    case 255:
29
    //...
30
}
Gast #4093031
Lesenswert?

Peter II schrieb:

> [c]

Da lach ich drüber...

> switch( data ) {

OMG. Switch mit 256 Zweigen. Selbst intelligente Compiler können das 
bestenfalls auf 8 Verzweigungen eindampfen (binärer Baum). Verzweigungen 
sind der Tod jeglichen getimeten Codes, wenn man sie einen C-Compiler 
machen läßt. Abgesehen davon kosten sie auch immer überproportional viel 
Rechenzeit.

>        PORTB |= (1<<pb4); //start
>        PORTB &= ~(1<<pb4); //bit0
>        PORTB &= ~(1<<pb4); //bit1
>        PORTB &= ~(1<<pb4); //bit2
>        PORTB &= ~(1<<pb4); //bit3
>        PORTB &= ~(1<<pb4); //bit4
>        PORTB &= ~(1<<pb4); //bit5
>        PORTB &= ~(1<<pb4); //bit6
>        PORTB &= ~(1<<pb4); //bit7
>        PORTB |= (1<<pb4); //stop

Gute Compiler werden das als sbi/cbi übersetzen, also zwei Takte pro Bit 
brauchen. Schlechte Compiler oder auch gute Compiler mit "ungünstig" 
eingestellter Optimierung können da leicht auch mal 3 oder sogar 5 Takte 
pro bit draus machen...
Abgesehen von diesen Betrachtungen ist der Code aber auch noch falsch. 
Das Startbit muß natürlich Low sein, aber das würde ich hier gern als 
Flüchtigkeitsfehler verbuchen wollen und nicht weiter diskutieren.


Worüber ich eher diskutieren würde: der Ansatz mit dem präparierten Code 
natürlich auch in Assembler möglich. Bloß würde ein gelernter 
Asm-Programmierer natürlich keinen binären Baum verwenden, sondern einen 
berechneten Sprung.

Das wäre natürlich auch in C möglich. Aber der Vergleich der beiden 
Routinen zeigt dann ganz deutlich, was ich an C so sehr hasse, den 
Bombast an Syntax, den man benötigt, um einfachste Sachverhalte 
auszudrücken, ohne dass man in der Compilerausgabe vor lauter Warnungen 
die Fehler nicht mehr sehen kann...
Gast #4093043
Lesenswert?

c-hater schrieb:
> OMG. Switch mit 256 Zweigen. Selbst intelligente Compiler können das
> bestenfalls auf 8 Verzweigungen eindampfen (binärer Baum).

sie machen einfach eine Sprungtabelle draus, habe ich schon beim GCC 
gesehen. Sind dann bloss 2 oder 4 takte.

> Gute Compiler werden das als sbi/cbi übersetzen, also zwei Takte pro Bit
sbi/cbi brauchen doch nur 1 Takt?

> Schlechte Compiler oder auch gute Compiler mit "ungünstig"
Compiler die nicht mal cbi/sbi hinbekommen, kann man eh nicht ernsthaft 
einsetzten, damit würde ein Großteil der Programme nicht mehr laufen. 
Man kann sich schon darauf verlassen sie es können.

> Abgesehen von diesen Betrachtungen ist der Code aber auch noch falsch.
> Das Startbit muß natürlich Low sein, aber das würde ich hier gern als
> Flüchtigkeitsfehler verbuchen wollen und nicht weiter diskutieren.
ich war mir auch wegen der Reihenfolge der bits nichts sicher. Es ging 
ja nur ums Prinzip.
#4093068
Lesenswert?

Peter II schrieb:
> sbi/cbi brauchen doch nur 1 Takt?

Hier liegst Du falsch, es sind 2 Takte. Hast es vermutlich mit SBR / CBR 
verwechselt, die brauchen tatsächlich nur einen Takt, arbeiten aber nur 
mit den CPU-Registern, könnten aber auch verwendet werden, ohne daß es 
langsamer wird:
1
CBR r16, 1 << PB4
2
OUT PORTB, r16
3
SBR r16, 1 << PB4
4
OUT PORTB, r16
5
SBR r16, 1 << PB4
6
OUT PORTB, r16
7
CBR r16, 1 << PB4
8
OUT PORTB, r16
9
CBR r16, 1 << PB4
10
OUT PORTB, r16
11
CBR r16, 1 << PB4
12
OUT PORTB, r16
13
CBR r16, 1 << PB4
14
OUT PORTB, r16
15
SBR r16, 1 << PB4
16
OUT PORTB, r16
17
SBR r16, 1 << PB4
18
OUT PORTB, r16
19
SBR r16, 1 << PB4
20
OUT PORTB, r16

-> 2 Takte pro ausgegebenem Bit

Wer's richtig schnell will, berechnet die auszugebenden Bitmuster im 
Vorraus, und schreibt sie nur noch hintereinander raus:
1
OUT PORTB, r6
2
OUT PORTB, r7
3
OUT PORTB, r8
4
OUT PORTB, r9
5
OUT PORTB, r10
6
OUT PORTB, r11
7
OUT PORTB, r12
8
OUT PORTB, r13
9
OUT PORTB, r14
10
OUT PORTB, r15

-> 1 Takt pro ausgegebenem Bit

Mit freundlichen Grüßen - Martin
Gast #4093077
Lesenswert?

Peter II schrieb:

> sie machen einfach eine Sprungtabelle draus, habe ich schon beim GCC
> gesehen. Sind dann bloss 2 oder 4 takte.

Vier mag ich vielleicht noch glauben, zwei nimmer. Bis zum Beweis des 
Gegenteils würde ich das als offensichtliche Schutzbehauptung eines 
C-Gäubigen einstufen.

Bitte Code vorlegen, der diese Behauptung beweisen kann. Bitte mit 
exakter Angabe von Compilerversion und verwendeten Optimierungsoptionen. 
Womit wir gleich beim nächsten Problem wären, der 
C-Kompatibilitätslüge...

> sbi/cbi brauchen doch nur 1 Takt?

Nein, zwei. Ziehe bitte die Lektüre des AVR "instruction set reference 
manual" in Betracht, bevor du Aussagen über das Timing von Instruktionen 
triffst. Es ist ja wirklich nicht schwer, die Instruktion des Interesses 
im Inhaltsverzeichnis anzuklicken und dann bis ganz unten 
runterzuscrollen, wo Atmel schamhaft die wichtigsten Infos 
hinschreibt...
Gast #4093085
Lesenswert?

c-hater schrieb:
>> sbi/cbi brauchen doch nur 1 Takt?
>
> Nein, zwei. Ziehe bitte die Lektüre des AVR "instruction set reference
> manual" in Betracht, bevor du Aussagen über das Timing von Instruktionen
> triffst. Es ist ja wirklich nicht schwer, die Instruktion des Interesses
> im Inhaltsverzeichnis anzuklicken und dann bis ganz unten
> runterzuscrollen, wo Atmel schamhaft die wichtigsten Infos
> hinschreibt...

habe ich gemacht und geschrieben, das wir beide recht haben!
#4093107
Lesenswert?

@Peter II (Gast):

Da muß ich Dir Recht geben. Hatte es selber nicht nachgesehen, mache am 
meisten mit den ATmegas, und da sind es halt 2 Takte. Beim Xmega ist da 
wohl Einiges gemacht worden, da gibt es recht viele Unterschiede, z.B. 
auch bei den SRAM-Zugriffen.

Mit freundlichen Grüßen - Martin
Gast #4093114
Lesenswert?

Peter II schrieb:

> habe ich gemacht und geschrieben, das wir beide recht haben!

Ja, ich wiederum habe das geschrieben, bevor ich deine diesbezüglich 
Antwort gelesen hatte.->Typisches Problem asynchroner Kommunikation, 
kein böser Wille.

Übrigens: Ich wußte tatsächlich nicht, daß die XMegas die Sache in einem 
Takt abfackeln können, bei den Dingern stellt sich ja dank reichlich 
verfügbarer und potenter Hardware nur äußerst selten das Problem, etwas 
derartiges in Software abhandeln zu müssen, bei mir bisher halt noch 
nie.

Trotzdem eine schöne Sache, denn ich habe wirklich etwas neues in diesem 
Thread gelernt, was ich vielleicht irgendwann mal brauchen kann. Und sei 
es nur zur Herstellung der Kompatibilität für Stücken gebrauchter 
Software...
(Firma: guloshop.de) #4093188
Lesenswert?

c-hater schrieb:
> Vier mag ich vielleicht noch glauben, zwei nimmer. Bis zum Beweis des
> Gegenteils würde ich das als offensichtliche Schutzbehauptung eines
> C-Gäubigen einstufen.

Gell, das einzig Gute an C ist der Inline-Assembler. ;-)
Ich geb zu, es gibt Momente, da seh ich das genauso wie du.

Anscheinend klappt es tatsächlich 1:1 mit dem CPU-Takt. Allerdings sind 
dann die Stoppbits jeweils mehr als 10 Takte lang, was natürlich die 
DÜ-Geschwindigkeit in den Keller zieht. Oder gibt es eine 
bessere/schnellere Lösung?
1
init:
2
clr r0
3
clr r1
4
inc r1  ; Annahme: Portpin 0 wird zum Senden verwendet
5

6
next:
7
... ; zu sendendes Byte in r30 erwartet
8
swap r30
9
mov r31,r30
10
andi r31,0x0f
11
ori r31,0x10  ; Startadresse der Ausgabeprozeduren (high)
12
andi r30,0xf0
13
IJMP
14

15
.org 0x1000
16
out PORTB,r0  ; Startbit
17
out PORTB,r0
18
out PORTB,r0
19
out PORTB,r0
20
out PORTB,r0
21
out PORTB,r0
22
out PORTB,r0
23
out PORTB,r0
24
out PORTB,r0
25
out PORTB,r1  ; Stopbit
26
jmp next
27

28
.org 0x1010
29
out PORTB,r0  ; Startbit
30
out PORTB,r1
31
out PORTB,r0
32
out PORTB,r0
33
out PORTB,r0
34
out PORTB,r0
35
out PORTB,r0
36
out PORTB,r0
37
out PORTB,r0
38
out PORTB,r1  ; Stopbit
39
jmp next
40

41
... usw ...
Gast #4093222
Lesenswert?

Markus Weber schrieb:
> Gell, das einzig Gute an C ist der Inline-Assembler. ;-)

wobei die Frage ist warum nicht dafür C verwenden, habe jetzt nichts da 
zu testen was da rauskommt.
1
uint8_t r1 = 0;
2
uint8_t r2 = 1;
3

4
switch( data ) {
5
   case 0:
6
       PORTB = r1;
7
       PORTB = r0;
8
       PORTB = r0;
9
       PORTB = r0;
10
       PORTB = r0;
11
       PORTB = r0;
12
       PORTB = r0;
13
       PORTB = r0;
14
       PORTB = r0;
15
       PORTB = r1;
16
       break;
17

18
    //...
19
}
Gast #4093246
Lesenswert?

könnte das schneller sein?
1
next:
2
... ; zu sendendes Byte in r30 erwartet
3
IJMP;
4
jmp SEND1;
5
jmp SEND2;
6
jmp SEND3;
7
....
8
SEND1:
9
out PORTB,r0  ; Startbit
10
out PORTB,r0
11
out PORTB,r0
12
out PORTB,r0
13
out PORTB,r0
14
out PORTB,r0
15
...
Moderator (Firma: Titel) Persönliche Seite #4093255
Lesenswert?

Warum hoffe ich bei solchen Diskussionen immer, dass der Programmierer 
des Flugzeugs, in dem ich gerade sitze, etwas mehr Erfahrung hatte?

Jörg Wunsch hatte es mal kurz angesprochen, wie es Profis machen: sie 
lesen das Datenblatt ihres Controllers und nehmen eine 
Hardwarekomponente, die so eine Übertragung ohne Prozessorlast abhandeln 
kann...
Mit dem SPI Interface kann ich z.B. ganz problemlos 4MBit/s bei 8MHz 
Takt erreichen. Und habe nebenher Zeit, das nächste Byte vorzubereiten.
Gast #4093263
Lesenswert?

Lothar Miller schrieb:
> Warum hoffe ich bei solchen Diskussionen immer, dass der Programmierer
> des Flugzeugs, in dem ich gerade sitze, etwas mehr Erfahrung hatte?
>
> Jörg Wunsch hatte es mal kurz angesprochen, wie es Profis machen: sie
> lesen dad Datenblatt ihres Controllers und nehmen eine
> Hardwarekomponente, die so eine Übertragung ohne Prozessorlast abhandeln
> kann...
> Mit dem SPI Interface kann ich z.bB. ganz problemlos 4MBit/s bei 8MHz
> Takt erreichen. Und habe nebenher Zeit, das nächste Byte vorzubereiten.

wenn es danach geht, hätte wir für die ersten PC spiele auch 10Jahre 
länger warten müssen. Zum glück gab es damals schon "kreative" 
Entwickler die alles aus der Hardware geholt haben.
(Firma: Vescomp) #4093323
Lesenswert?

Peter II schrieb:
> wenn es danach geht, hätte wir für die ersten PC spiele auch 10Jahre
> länger warten müssen. Zum glück gab es damals schon "kreative"
> Entwickler die alles aus der Hardware geholt haben.

 Ich denke, da liegst du aber gewaltig daneben.
 Nicht die Geschwindigkeit war damals das Problem, sondern mangelnder
 RAM, sowohl bei den uC als auch bei der Videokarten.
 Ich glaube mein Vater hat sein Tandy damals 2000 DM bezahlt, die
 Umrüstung von 4KB(!) auf 16KB RAM hat so um die 500DM gekostet.
Gast #4093498
Lesenswert?

Marc Vesely schrieb:
> Ich denke, da liegst du aber gewaltig daneben.
>  Nicht die Geschwindigkeit war damals das Problem, sondern mangelnder
>  RAM, sowohl bei den uC als auch bei der Videokarten.
>  Ich glaube mein Vater hat sein Tandy damals 2000 DM bezahlt, die
>  Umrüstung von 4KB(!) auf 16KB RAM hat so um die 500DM gekostet.

wenn ich das lesen, klingt es aber nicht nach ram:

http://de.wikipedia.org/wiki/Duff%E2%80%99s_Device
(Firma: Vescomp) #4093529
Lesenswert?

Peter II schrieb:
> wenn ich das lesen, klingt es aber nicht nach ram:
>
> http://de.wikipedia.org/wiki/Duff%E2%80%99s_Device

 ???
 Nix aus der Hardware rausgeholt, einen einfachen loop ausgerollt.
 Und funktioniert auch nur in C, normale Sprachen fallen nicht von
 einem Switch zum nächsten...

 Ihr seid alle so schnell wenns heisst c-hater anzuspucken, aber C
 ist ganz einfach ein Witz von einer Sprache.
Moderator Persönliche Seite #4093540
Lesenswert?

Peter II schrieb:
> wenn ich das lesen, klingt es aber nicht nach ram:

Hat aber nichts mit normalem PC zu tun, sondern mit früher
Videobearbeitung.

https://de.wikipedia.org/wiki/Lucasfilm

Zurück zum Thema des Threads: ich bin gewiss ein großer Verfechter
davon, auch bei Controllern möglichst portable Software in einer
höheren Programmiersprache zu zimmern.  Aber wenn man wirklich auf den
Takt genau etwas machen will, und keinerlei Hardware dafür abstellen
kann (nichtmal einen Timer), dann bleibt in der Tat nur das händische
Auszählen der Takte in einem Stück Assemblercode – egal, ob man das
nun zum eigenen Zeitvertreib oder aus echter Notwendigkeit heraus
tun möchte.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren