ATmega und USB, suche Tutorial

Am 22.12.2010 07:21, schrieb Heiko Lechner:

Selbst das finde ich in C angenehmer: while (PORTB & (1 weil man ohnehin nur Bits setzt, löscht und durch die Gegend schiebt.

...

Wieso? "printf" geht auch mit kleinen µC an LCD. Dateisysteme sind auch nur Bibliotheksfunktionen.

Auch nur bedingt. Sachen wie "Timer initialisieren" gehören sowieso in Funktionen, die man dann bei Bedarf tauscht und die einfachen Bitpfriemeleien lassen sich oft sehr komfortabel in Makros schreiben.

Seit ich vom PIC16F84 weg bin, habe ich Assembler nicht mehr geschrieben.

Falk

Reply to
Falk Willberg
Loading thread data ...

Gute Idee. Sowas wie einen Makro-assembler, der noch ein paar simple Kontrollstrukturen für Schleifen und Funktionen hat und Variablen, die von der Registerbreite unabhängig sind. Nehmen wir noch Zeiger und Strukturen dazu, ist C fertig ;-)

Falk

Reply to
Falk Willberg

Am 22.12.2010 00:07, schrieb Jan Kandziora:

...

Ich schätze, das ist eher die Regel.

Im aktuellen Projekt arbeite ich mit mindestens drei weiteren SW-Entwicklern zusammen. Geplante Stückzah ist

Reply to
Falk Willberg

Und so sprach Jan Kandziora:

Kann ich so nicht nachvollziehen. Einen Cortex-M3 möchte *ich* nicht in Assembler bearbeiten. Zumal ein guter Kompiler deutlich effektiver optimieren kann, als ein ASM-Hacker...

Roland

Reply to
Roland Ertelt

Bei den Consumer-Massenprodukten im Regal des Discounters (z.B. denen mit den Y-Kabeln) waere es da wohl in guter Gesellschaft.

Micha

Reply to
Michael Baeuerle

Es gab ab 1974 an der ETH Lausanne von Prof. Nicoud

formatting link
den Versuch CALM "Common Assembly Language for Microprozessors" zu etablieren.

Wurde wohl ursprünglich für die experimentellen schweizer SMAKY-Tischcomputer verwendet:

formatting link
Die wollten natürlich von 8080 auf Z80/6809 und später

68000 den verfügbaren leistungsstärkeren CPUs folgen ohne daß man jeweils das OS neu schreiben mußte. Vgl. Kildall und PL/M für CP/M.

Zitat: "I rather dislike C and this sort of language which hide away the machine from you". Basierte ursprünglich auf der Einsicht, daß die damaligen

8 Bit CPUs recht ähnlich waren. Aber zu hohe Hardwarenähe war beim Übergang auf 16 Bit CPUs dann wohl tödlich weil da die Einheitlichkeit verlorenging. Wurde in den 80er Jahren bekannter, brachte es bis zur DIN-Norm.

Literatur dazu stapelt sich hier schon: Nicoud, Wagner "Major Microprocessors A Unified Approach using CALM" Noth Holland 1987 Schnell, Hoyer "Mikrocomputerfibel" Vieweg 3. Auflage 1987 Zeltwanger "Genormte Assemplersprache für uPs" Elektronik 8/1988

Werde bei Gelegenheit mal einen historischen Artikel in der omiösen Zeitschrift darüber bringen.

MfG JRD

Reply to
Rafael Deliano

Jan Kandzioraschrieb: "

Ja man kann auch alles falsch machen, was aber keine Begründung für die Argumentation ist. Es ist auch nicht unüblich, wenn mehrere Leute an dem gleichen Modul arbeiten, sowohl gleichzeitig als auch zeitversetzt. Bereits wenn einer krank wird, muss ein anderer, vielleicht aus einer anderen Abteilung, oder auch ein Firmenfremder, sich kurzfristig darin einarbeiten, oder alles bleibt für ein paar Wochen liegen. Wenn der dann den Aufwand für seine Einarbeitung abschätzt, bekommt der Projektleiter einen dicken Hals. Modularisierung lößt nicht alles, eher Teamfähigkeit und verantwortungsbewußtes Denken, oder über den Tellerand hinausblicken, vielleicht auch mal selbst ein Projekt leiten zu müssen.

Hoher Kostendruck ist in DE immer, und Zeitdruck sowieso. Letzterer bestimmt, wie viele Leute mitarbeiten müssen, um das Projekt in absehbarer Zeit zum Ende zu bringen. Projekte mit z.B. grafischem Display gibt es genügend (nein da liegen keine Bitmaps im Speicher) und der Einsatz eines fetten und trägen Linux schraubt die Prozessorauswahl gleich um mehrere Stufen nach oben incl. Dominoeffekt (BGA, Multilayer, 1,8V etc.). Dazwischen gibt es also eine Menge Projekte, die vermutlich ein paar hundert kBytes brauchen (dieses Beispiel erhebt keinen Anspruch auf Vollständigkeit).

Dirk

Reply to
Dirk Ruth

Wenn es wirklich so wäre, gäbe es in C-Programmen niemals Asm-Einschübe zu Optimierung. Es gibt sie aber, und zwar massenhaft, insbesondere auch im Bereich der µC. Damit fällt Unkenntnis des wahren Sachverhaltes als Entschuldigung aus.

Also: Die Aussage ist eine bewußte Lüge, verbreitet wider besseren Wissens.

Reply to
Heiko Nocon

Naja, ich finde:

wait: sbrc PORTB,PORTB5 rjmp wait ; machwas rjmp wait

deutlich einfacher lesbar. Außerdem weiß ich dann sofort zuverlässig, daß ich eine Latenz von 2..4 Takten und einen Jitter von 3 Takten vom Ereignis bis zum "machwas" habe.

Wie ein C-Compiler das übersetzt, muß ich hingegen raten oder im Compilat nachschauen und kann mich auf nichts verlassen, denn schon andere Optionen für denselben Compiler können ein abweichendes Zeitverhalten bewirken, was andere Compilerversionen oder andere Compiler machen, steht sogar völlig im Dunkeln.

Reply to
Heiko Nocon

Und so sprach Heiko Nocon:

Die einzigen Assembler-Einschübe, die bem M3 wirklich "nötig" sind, ist für Nested-IRQ.

Den Ball gebe ich mal zurück mit: Du verwendest die falschen Kompiler (-schalter).

Roland

Reply to
Roland Ertelt

Nö. Das Beispiel braucht unendlich viele Takte. Richtig ist das da:

wait: sbrs PORTB,PORTB5 rjmp ende ; rcall machwas (Oder Call, je nachdem wo machwas liegt) rjmp wait ende:

Ist vielleicht auch falsch. Assembler ist halt fehlerträchtiger, wie man sieht.

Und wenn ich noch char *text="Hallo Welt"; int feld[256];

in machwas(text,feld) setze, geht es mit dem pushen und poppen erstmal richtig ab ;-)

Das stimmt natürlich. Für Dinge, die exaktes Timimg voraussetzen, ist Assembler oft unumgänglich.

Ich behaupte auch nicht, das Assembler grundsätzlich die schlechtere Wahl sei. Ich widerspreche nur der Behauptung, daß C für µC ungeeignet ist.

Falk

Reply to
Falk Willberg

Am 22.12.2010 schrub Heiko Nocon:

Die meisten ASM-Einschübe rühren aber daher, daß der entsprechende Konstrukt oder Zugriff in C nicht realisierbar ist. Bestes Beispiel: nicht-memory-mapped-IO.

Umgekehrt ist es ein Fakt, daß ein guter C-Compiler wirklich besser optimieren kann, denn er kann die Eigenschaften ganzer Befehlssequenzen und ihre Abarbeitung in der CPU (interne Parallelisierung) besser berücksichtigen! Sicher kann ein guter Programmierer das für den einen oder andere Prozessor auch, aber so ein Compiler kann das eben für mehrere Prozessor-Varianten und ist ausdauernder.

He, hola, komm' mal 'runter.

Josef

--
These are my personal views and not those of Fujitsu Technology Solutions!
Josef Möllers (Pinguinpfleger bei FTS)
 Click to see the full signature
Reply to
Josef Moellers

Wenn ich von einem anderen Prozessor komme frage ich mich zuerst, was sbrc denn wohl wirklich macht.

Aber, egal was es macht, die obige Whileschleife ist das nicht.

Wenn du das brauchst, ist Assembler unabdingbar. Sind Deine Programme voll mit zeitkritischem Code? Wenn nicht, dann tue ich...

... , optimiere das und binde es inline ein. Die Kommunikation mit dem Operator geht dann dennoch mit printf und dergleichen.

--
Gruß, Raimund
Mein Pfotoalbum 
 Click to see the full signature
Reply to
Raimund Nisius

Wie die anderen Poster sehe ich das anders. Wir sind hier zwar ein kleines Team, aber ich lege schon Wert darauf, dass zumindest einer meiner Mitarbeiter meine Projekte bearbeiten kann.

Das hat jetzt auch nichts mit C oder Pascal zu tun.

Meine Kritik an bestimmten Programmierbeispielen bezieht sich auf sowas:

(stammt alles aus dem Powerswitch Beispiel bei OVDEV.AT)

--------------------------------------------------- function btbool(data:word;bit:word):boolean; begin asm pusha mov ax,&data mov bx,&bit bt ax,bx jnc @zero mov &result,1 jmp @out @zero: mov &result,0 @out: popa end; end;

procedure TForm1.Button4Click(Sender: TObject); var i,status:integer; begin if Assigned(udev) then begin status:=getstatus; label5.Caption:=inttostr(status); label5.Visible:=true; for i:=low(cb) to high(cb) do cb[i].Checked:=btbool(status,i); end; statusbar1.Panels[0].Text:=usb_strerror; end;

-------------------------------------------------------

Hier insbesondere die Function btbool, die offenbar nur prüft, ob das Bit Nr. bit in data gesetzt ist. Die hier gezeigte Lösung ist einfach nur krank. Warum formuliert man das nicht einfach sauber in Pascal? Es gibt überhaupt keinen Grund, hier inline asm einzusetzen.

anderes Beispiel:

--------------------------------------------------------- USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; uchar status = eeprom_read_byte(EEPROM_LOCATION);

static uchar replyBuf[2];

usbMsgPtr = replyBuf;

if(rq->bRequest == 0){ /* ECHO */ replyBuf[0] = rq->wValue.bytes[0]; replyBuf[1] = rq->wValue.bytes[1]; return 2; } if(rq->bRequest == 1){ /* GET_STATUS -> result = 2 bytes */ replyBuf[0] = status; replyBuf[1] = computeTemporaryChanges(); return 2; } if(rq->bRequest == 2 || rq->bRequest == 3){ /* SWITCH_ON or SWITCH_OFF, index = bit number */ uchar bit = rq->wIndex.bytes[0] & 7; uchar mask = 1 bRequest == 2){ /* SWITCH_ON */ status |= mask; needChange = !isOn; }else{ /* SWITCH_OFF */ status &= ~mask; needChange = isOn; } if(rq->wValue.bytes[0] == 0){ /* duration == 0 -> permanent switch */ actionTimers[bit] = 0; eeprom_write_byte(EEPROM_LOCATION, status); }else if(needChange){ /* temporary switch: value = duration in 200ms units */ actionTimers[bit] = rq->wValue.bytes[0]; } } computeOutputStatus(); return 0; }

------------------------------------------------------------------------- Ich bin jetzt in GCC nicht so fit, dass ich das alles auf Anhieb verstehe, aber ich habe den Eindruck, dass hier auch einiges herumgezaubert wurde um Eindruck zu schinden.

Die Sache mit dem rq erschließt sich mir dabei nicht so ganz. Offenbar gibt es hier 8 Bytes, die vom Treiber zurückgegeben werden. Warum werden die nicht einfach ausgelesen und verarbeitet? Statt dessen wird mit einer Class rq herumgewurschtelt...

Und: Was in aller Welt soll die Scheiße mit dem EEProm hier?

Und der Schwachsinn mit den actionTimers?

In Main() steht dazu:

----------------------------------------- for(;;){ /* main event loop */ wdt_reset(); usbPoll();

if(TIFR & (1

Reply to
Stefan Brröring

Das sehe ich anders. Ich habe 20 Jahre lang 8031 und 15 Jahre lang PIC ausschließlich in asm programmiert und bin vor einigen Jahren auf AVR und Winavr umgestiegen.

Seitdem habe ich noch nicht die Notwendigkeit gesehen, asm in meine C-Programme einzubauen...

Früher, zu Basic Zeiten auf dem TRS-80 oder dem PC-XT mit 8088 und 4,77 MHz war das etwas anderes. Oder bei meinem Sharp-Basic Taschenrechner.

Gruß

Stefan DF9BI

Reply to
Stefan Brröring

ich vermute eher, du kannst kein C, hast dich nicht mit dem API des obdev-USB-treibers auseinandergesetzt *und* auch nicht über die konkrete applikation nachgedacht:

das ist keine class, sondern eine struct. und die macht hier sehr viel sinn, weil die einzelnen werte in diesem 8-byte-ding festgelegte bedeutungen haben, also bildet man sowas in C als struct ab. das ist keine schwarze magie, sondern lehrbuchgemäß.

der kommentar drüber mit "permanent" veranlaßt mich, zu vermuten, daß man die einzelnen kanäle "temporär" (bis zum power-off) oder permanent schalten kann, und die permanenz wird wohl durch speicherung im eeprom erreicht werden.

herauszufinden, daß das so ist, hat übrigens ca 3 klicks bis ins vusb-wiki zur API-doku gebraucht.

die doku zu dieser USB-implementation weist darauf hin, daß man die USB-transfers nicht interrupten darf. also wird das flag, das der timer setzt, gepollt.

ich glaub eher, es kann einen sowieso verwirrten leser nicht entwirren.

nein, es gibt wirklich keinen grund, über VUSB zu schimpfen, nicht nur wegen des geschenkten gauls, sondern weil es definitiv zu den gut designten und dokumentierten open-source-projekten gehört.

cm.

--
** christian mock in vienna, austria -- http://www.tahina.priv.at/
> www.flamingtext.com
 Click to see the full signature
Reply to
christian mock

mag sein...

Ich hab mir jetzt mal das Beispiel mit dem Remotecontrol angesehen.

Dort sieht das so aus:

------------------------------------------------------------------- static uchar replyBuffer[8]; /* we don't need to store much status because we don't implement multiple * chunks in read/write transfers */

uchar usbFunctionSetup(uchar data[8]) { uchar len = 0;

if(data[1] == 0){ /* ECHO */ len = 2; replyBuffer[0] = data[2]; replyBuffer[1] = data[3]; }else if(data[1] == 1){ /* poll data available */ len = 1; replyBuffer[0] = fifoSize(); }else if(data[1] == 2){ /* read data */ if(fifoSize()){ len = 8; fifoRead(replyBuffer); } } usbMsgPtr = replyBuffer; return len; }

-----------------------------------------------------------------------

gefällt mir gleich viel besser...

Gruß

Stefan DF9BI

Reply to
Stefan Brröring

Ich finde pures ASM gerade bei den kleinen AVRs sehr praktisch. Durch die huebsche Architektur sind die gut in Assembler zu programmieren und der kleine Speicher begrenzt den Einsatz auf Projekte die als ganzes ueberschaubar bleiben. Wenn dann die Anwendung auch noch speziell auf die Hardware zugeschnitten ist, spielt es oft keine Rolle wenn die Firmware nicht 1:1 auf andere Architekturen portierbar ist. Ausserdem hat man mit ASM bessere Kontrolle und besseren Ueberblick ueber das Echtzeitverhalten.

Grosse Sachen sind in C dagegen viel einfacher zu realisieren, mit weniger Fehlern, uebersichtlicher und deutlich portabler. Das Gemisch mit Inline-ASM ist halt fuer den Bereich dazwischen die geeignete Loesung. Ab einem gewissen Punkt ist vielleicht sogar C++ sinnvoll wenn die Firmware _richtig_gross_ wird.

Wenn man Strom sparen muss, laesst man einen AVR heute auch nicht unbedingt mit 20MHz laufen ...

Micha

Reply to
Michael Baeuerle

Das ist ein herkömmlicher "Type cast". Das ist ganz normale C-Syntax um einen Datenwurm zu strukturieren. Wäre Dir anstelle von "rq->bRequest" "data[3]" lieber? Oder "data[BREQUEST]"? Immerhin kann man bRequest nicht auf andere Datenwürmer loslassen. Wenn überhaupt würde ich bemeckern, daß der Funkion nicht schon (usbRequest_t *) übergeben wird. Denn beim Aufruf kann man sich noch überlegen, ob der Wurm wirklich ein usbRequest_t sein soll.

Der Wert soll wohl über Stromlose Zeiten erhalten bleiben. Und EEPROM lesen ist was anderes, als Instruction oder Data zu lesen. So ganz kannst Du Dich auch in C nicht von der Hardware abheben.

8 unabhängige Rückwärtszähler. Nicht allzu genau, falls computeOutputStatus halbwegs vorhersagbare Ausführungszeit hat.

Hätte vielleicht mal ein Interrupt werden sollen...

Ich bin nicht verwirrt.

--
Gruß, Raimund
Mein Pfotoalbum 
 Click to see the full signature
Reply to
Raimund Nisius

Dirk Ruth schrieb:

Ich sprach nicht blumig von Kostendruck, sondern von den Kosten, die ein Selbstbau und Komplettentwicklung auf µC gegenüber einem Einkauf eines fertigen (z.B. ARM-)Boards und Entwicklung von Software und (soweit notwendig) Peripheriemodulen verursacht.

Das ist ganz klar stückzahlabhängig. Bei geringer Stückzahl lohnt es sich einfach nicht, ein "fettes" µC-Board samt Software selbst zu entwickeln.

Ich glaube meine Meinung dazu ist in der Gruppe hier bekannt. Wenn man solche Boards selbst designen will sollte man dazu einen sehr guten Grund haben. Wenn die Stückzahl nicht extrem hoch liegt, kriegt man die Entwicklungskosten nimmer wieder rein.

Mit freundlichem Gruß

Jan

Reply to
Jan Kandziora

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.