Mein Problem ist folgendes, ich versuche eine möglichst kleine UART
Implementation zu bauen, welche keine Einträge in der Interrrupttabelle
braucht, mittels USI zu realisieren indem ich USI über timer0 ctc
tackte.
Nun würde ich die Warteschleife durch ein "sleep" ersetzen wollen.
Der ATtiny soll also durch das USI Overflow Interrupt geweckt werden und
mit der Codeausführung in der nächsten Instruktion beginnen ohne einen
Sprung in die Interrupttabelle.
Ich habe es bisher nicht geschafft einen AVR ohne eben jenen Sprung
aufzuwecken.
Kann mir jemand verraten ob dies möglich wäre? Danke im Vorraus!
EinBastler schrieb:> braucht, mittels USI zu realisieren indem ich USI über timer0 ctc> tackte.
Takt schreibt sich ohne "c". Daran hat auch die
Rechtschreibverschlimmbesserungsreform nichts geändert.
> Nun würde ich die Warteschleife durch ein "sleep" ersetzen wollen.> Der ATtiny soll also durch das USI Overflow Interrupt geweckt werden
Das bringt so gut wie nichts. Damit der Overflow-Int eintreten kann, muß
der Timer0 laufen. Damit geht bloß der am wenigsten stromsparende
Energiesparmodus ("Idle-Mode") und der spart wirklich kaum was.
> Kann mir jemand verraten ob dies möglich wäre?
Ich kann dir genau dasselbe verraten, was auch im Datenblatt steht: Das
ist nicht möglich. Grundsätzlich kann nur ein ausgelöster Interrupt
das Teil wecken. Und da es zwischen der Auslösung des Interrupt und dem
Ansprung des zuständigen Interruptvektors keinerlei
Eingriffmöglichkeiten gibt, ist es unmöglich.
Die Frage ist, warum stört dich das? Schreibst du einfach ein RETI auf
den Vektor und fertig ist der Lack. Naja, falls du unbedingt die paar
Bytes der Vektortabelle eines Tiny für Code brauchst, mußt du halt noch
ein RJMP PC+2 davorschreiben. Insgesamt kostet das also nur 4 Byte. Und
wenn's daran klemmt: Es findet sich garantiert eine Stelle in deinem
Code, wo man die einsparen kann.
Es ging darum keine Warteschleife bauen zu müssen sondern eben nur in
den IDLE Modus zu gehen. Außerdem läuft timer0 ja auch im IDLE Modus und
taktet bei jedem Compare USI hoch bis jener 4bit Counter überläuft.
Wirklich Schade wegen dem Aufwachen, in einem Bootloader gehören sich ja
keine Interrupts.
Ich danke jedenfalls für die Antwort und entschuldige mich für komische
Schreibfehler, aber zu meiner Verteidigung ein Handy mit zerbrochenem
Bildschirm ist nicht Ideal zum Tippen
c-hater (Gast) schrieb:
Hier die Meinung:
> Das bringt so gut wie nichts. Damit der Overflow-Int eintreten kann, muß> der Timer0 laufen. Damit geht bloß der am wenigsten stromsparende> Energiesparmodus ("Idle-Mode") und der spart wirklich kaum was.
Hier die Fakten:
Datenblatt ATTiny13: 3,3 V & 9,6 MHz RC-OSZ
Idle Supply Current ca. 0,9 mA
Active Supply Current ca. 3,6 mA
Hubs schrieb:> Hier die Fakten:>> Datenblatt ATTiny13: 3,3 V & 9,6 MHz RC-OSZ>> Idle Supply Current ca. 0,9 mA> Active Supply Current ca. 3,6 mA
So what? Das ist nichtmal annähernd eine Größenordnung, also wirklich
kaum was.
Du mußt das relativ zu den mit tieferen Schlafmodi möglichen
Einsparungen von mehreren Größenordnungen sehen.
EinBastlee schrieb:> Es ging darum keine Warteschleife bauen zu müssen sondern eben nur in> den IDLE Modus zu gehen.
Aha, jetzt habe ich das verstanden. Es ging primär garnicht darum, Strom
zu sparen.
> Wirklich Schade wegen dem Aufwachen, in einem Bootloader gehören sich ja> keine Interrupts.
Quatsch. Wer erzählt so einen geistigen Dünnschiß? Wer es auch ist: der
Typ hat keine Ahnung.
Was nutzt ein tieferer Schlafmodus wenn er den Zweck verfehlt den Code
kürzer zu machen und die Timer abschaltet was auch die Funktion des
Programmes irgendwie vernichtet...
Außerdem Faktor 4 ist außerdem ein deutliches Ersparnis
Ist doch irgendwie Allgemeinwissen, dass ein guter Bootloader indem
Programmablauf gar nicht mehr eingreifen muss, bei jedem Programmstart
die Interrupttable neu Flaschen ist kein Weg, und ein Muxer für
Interrupts verfälscht den Cycle Count
c-hater schrieb:> Hubs schrieb:>>> Hier die Fakten:>>>> Datenblatt ATTiny13: 3,3 V & 9,6 MHz RC-OSZ>>>> Idle Supply Current ca. 0,9 mA>> Active Supply Current ca. 3,6 mA>> So what? Das ist nichtmal annähernd eine Größenordnung, also wirklich> kaum was.
Das ist eine erhebliche Ersparnis und jeder gute Programmierer nutzt
diese natürlich.
> Du mußt das relativ zu den mit tieferen Schlafmodi möglichen> Einsparungen von mehreren Größenordnungen sehen.
Ich muss gar nichts. Du musst lernen effektiv zu programmieren. Das
Beispiel zeigt, dass z. B. eine Verlängerung der Batterie-/Akkulaufzeit
auf das Vierfache einfach zu erreichen ist.
EinBastler schrieb:> Es geht darum wie ich UART mit USI am kompaktesten Bitbange
Und ein bedingter Sprung braucht jetzt dermaßen viel weniger
Instructions als ein sleep? Kompakt hin oder her, das macht doch den
Code völlig unverständlich und komplexer als nötig.
Läubi .. schrieb:> EinBastler schrieb:>> Es geht darum wie ich UART mit USI am kompaktesten Bitbange>> Und ein bedingter Sprung braucht jetzt dermaßen viel weniger> Instructions als ein sleep? Kompakt hin oder her, das macht doch den> Code völlig unverständlich und komplexer als nötig.
Naja, der Sleep Befehl mit USI würde mir eigentlich alles ersparen...
sbic funktioniert leider nicht mehr mit Addressen ab 0x20... also
bräuchte ich 3 Opcodes
USI erspart mir wenn alles klappt die Hälfte der Opcodes beim Senden und
Empfangen weil ich nichtmal eine for-artige Schleife machen müsste
Eigentlich ist es einfach eine Herausforderung an mich wie klein ich
deen Bootloader (UART mit auto baud) schaffe
EinBastler schrieb:> Es geht darum wie ich UART mit USI am kompaktesten Bitbange, als> Herausforderung hab ich mir einen <64 Opcode Bootloader gesetzt
Nett.
Allerdings: Wenn du das gleich eingangs auch so geschrieben hättest,
wäre die Hälfte des Threads erst garnicht geschrieben worden!
Aber nachdem nun endlich nach einem Dutzend Postings klar ist, das daß
Ziel minimale Codegröße ist, ist auch klar, daß die Idee mit dem Idle
Mode statt der Warteschleife schlicht Schwachsinn ist.
Die Warteschleife kostet genau zwei Opcodes, also 4 Bytes.
Der ganze Kram der nötig ist, um überhaupt in den Idle-Mode zu kommen
und dann auch wieder daraus aufwachen zu können, kostet mindestens 12
Byte. Und außerdem: die Hauptschleife muß ja trotzdem geschlossen
werden! Also 14 Byte.
Selbst wenn es möglich wäre, die vier Byte in der Vektortabelle zu
sparen
(was ja deine Frage war), steht die Rechnung also immer noch 10:4.
Damit erübrigt sich deine Frage unter dem Aspekt des nun endlich
offengelegten Ziels von vornherein, denn die Beantwortung der Frage kann
an der Entscheidung für die richtige Architektur nichts ändern, es
gewinnt in jedem Fall die Warteschleife.
Hier die Welt wie sie " c-hater" wahrnimmt:
> Aber nachdem nun endlich nach einem Dutzend Postings klar ist, das daß> Ziel minimale Codegröße ist, ist auch klar, daß die Idee mit dem Idle> Mode statt der Warteschleife schlicht Schwachsinn ist.
Hier die Realität aus dem 1. Posting:
" ... ich versuche eine möglichst kleine UART Implementation zu bauen,
.."
Hubs schrieb:> Das> Beispiel zeigt, dass z. B. eine Verlängerung der Batterie-/Akkulaufzeit> auf das Vierfache einfach zu erreichen ist.
Ja. Und wie lange hält sich der gemeine µC deiner Meinung nach
typischerweise in einer Schleife in einem Bootloader auf?
Nur damit wir mal eine Vorstellung bekommen, ob der grandiosen
Verlängerung der Batterielaufzeit, die deine hocheffiziente
Programmiererei bewirken wird...
Hubs schrieb:> Das> Beispiel zeigt, dass z. B. eine Verlängerung der Batterie-/Akkulaufzeit> auf das Vierfache einfach zu erreichen ist.
Ja. Und wie lange hält sich der gemeine µC deiner Meinung nach
typischerweise in einer Schleife in einem Bootloader auf?
Nur damit wir mal eine Vorstellung bekommen, ob der grandiosen
Verlängerung der Batterielaufzeit, die deine hocheffiziente
Programmiererei bewirken wird...
Naja, die Verzögerung braucht mindestens 3 Opcodes, weil c-hater nicht
versteht das eine sbic+rjmp PC-1 nicht geht
An c-hater:
Kapierst du nicht, ich kann nicht bei jedem Bootvorgang die
Interrupttabelle umschreiben oder einen Muxer machen weil dies einen
Eingriff in den Programmablauf eines jeden Programmes entspricht?
Und dank USI... welche Hauptschleife?
c-hater schrieb:
> Damit geht bloß der am wenigsten stromsparende Energiesparmodus ("Idle-> Mode") und der spart wirklich kaum was.
und das ist schlicht und ergreifend: FALSCH.
Du hast eine Wahrnehmung die nicht mit der Wirklichkeit übereinstimmt.
Man verfolge einfach nur diesen Thread.
Du zeigst, dass du von der Materie wenig Ahnung hast. Darüber hinaus
sind deine weiteren Einlassungen nur Ablenkungen, Ausreden und
Relativierungen.
Du kannst es nicht, Kleiner.
Warum musst du eigentlich die Interrupttabelle neu flashen? Lese das
jetzt zum zweiten mal hier.
Soweit ich weiß gibt es bei den AVRs doch ein Bit, was man setzen kann,
dass den Offset der Interrupttabelle auf die Boot-Section stellt.
c-hater schrieb:> Ich kann dir genau dasselbe verraten, was auch im Datenblatt steht: Das> ist nicht möglich. Grundsätzlich kann nur ein ausgelöster Interrupt> das Teil wecken. Und da es zwischen der Auslösung des Interrupt und dem> Ansprung des zuständigen Interruptvektors keinerlei> Eingriffmöglichkeiten gibt, ist es unmöglich.
Ist ja schlimm, wenn du so einen schlechten Tag gehabt hast. Dafür
können wir aber allesamt nichts, also trink ein Bier und komm mal wieder
runter.
Zwischen der Auslösung eines Interrupts und dem Sprung in die
Serviceroutine gibt es nun sehr wohl einen Unterschied. Nämlich wenn man
etwa das I-Bit im Statusregister löscht. Dann können Interrupts zwar
ausgelöst werden (es werden nämlich Interruptflags gesetzt), aber die
Serviceroutinen werden eben nicht angesprungen.
Zugegebenermaßen ist die Doku aber an dieser Stelle nicht so vielsagend.
Ich werde es bei Gelegenheit mal testen.
Sven P. schrieb:> Dann können Interrupts zwar> ausgelöst werden (es werden nämlich Interruptflags gesetzt), aber die> Serviceroutinen werden eben nicht angesprungen.
Das Auslösen eines Interrupts ist per Definition das Ausführen
desselben. Interrupt bedeutet unterbrechen, also bedeutet das eine
Unterbrechung auslösen. Und nicht nur anzeigen, dass etwas ausgelöst
werden soll.
> Zugegebenermaßen ist die Doku aber an dieser Stelle nicht so vielsagend.> Ich werde es bei Gelegenheit mal testen.
Die Doku dürfte eindeutig sein, da brauchst Du auch nicht viel
auszuprobieren, ohne aktiviertem I-Flag kein Aufwachen. Da gibt's so
Kandidaten, die in der ISR ein Sleep auslösen und sich dann wundern,
dass trotz aktiviertem Interrupt nix mehr aufwacht...
Das Kürzeste, das geht ist ein RETI in den Interruptvektor zu schreiben.
MWS schrieb:> Sven P. schrieb:>> Dann können Interrupts zwar>> ausgelöst werden (es werden nämlich Interruptflags gesetzt), aber die>> Serviceroutinen werden eben nicht angesprungen.>> Das Auslösen eines Interrupts ist per Definition das Ausführen> desselben. Interrupt bedeutet unterbrechen, also bedeutet das eine> Unterbrechung auslösen. Und nicht nur anzeigen, dass etwas ausgelöst> werden soll.
Je nach Definition...
Man kann ihn auch auslösen und dann bedienen. So jedenfalls in der mir
vertrauten Terminologie. Manchmal werden Interrupts auch garnicht
ausgelöst, sondern angefordert und dann bedient. Dann ists auch schön
eindeutig.
Ich habe es allerdings auch gerade ausprobiert: Es ist tatsächlich das
Anspringen der Serviceroutine entscheidend fürs Aufwachen.
Sven P. schrieb:> Ich habe es allerdings auch gerade ausprobiert: Es ist tatsächlich das> Anspringen der Serviceroutine entscheidend fürs Aufwachen.
Ja, wusste ich. Das Ausführen des Vektors ist entscheidend, im Vektor
kann dann statt eines JMP/RJMP auf die ISR auch einfach nur ein RETI
stehen.
EinBastler schrieb:> Ja, das ich das Abspringen eines ISRs brauche hatte ich.... da ich> kein> reti verwenden kann muss ich wohl weil eine andere Lösung suchen
Wieso nicht?
Weil ich einen Bootloader basteln will und dabei nicht die
Interrupttabelle jedesmal überschreien will und auch keinen Muxer für
Interrupts verwenden sollte
EinBastler schrieb:> Weil ich einen Bootloader basteln will und dabei nicht die> Interrupttabelle jedesmal überschreien will und auch keinen Muxer für> Interrupts verwenden sollte
Es gibt bei den AVRs soweit ich weiß das IVSEL Bit, womit du einfach nur
die Einsprungadressen in den Bootloader schieben kannst. Da muss nix
überschrieben werden? Und was ein Muxer für Interrupts ist, ist die
andere Frage.
Nicht bei den ATtinys...
Naja, es gibt einen Entry Point für Interrupts, wenn nun zwei Programme
laufen muss ein Interrupt an die jeweilige Routine eines der beiden
verteilt werden
Zumindest nicht bei den ATTinys, die keine Bootloader section haben...
Macht ja auch Sinn. Was spricht gegen die Benutzung eines AVRs mit
Bootloader section?
Es geht doch um das Lernen und die Herausforderung bei solchen Dingen,
mit einen ATmega wäre das leicht, der hat dediziertes UART, eine
Bootloadersection,... aber ein ATtiny hat nichts von dem und sowas
trotzdem in 64 Opcodes (2 Pages) oder vielleicht per SPI in 32 Opcodes
(1 Page) ist eine interessante Aufgabe
Hubs schrieb:>> Damit geht bloß der am wenigsten stromsparende Energiesparmodus ("Idle->> Mode") und der spart wirklich kaum was.>> und das ist schlicht und ergreifend: FALSCH.
Man muß halt aufpassen, daß an sich nicht verrennt. Ein Wort kann schon
viel ändern. Geht es um Stromsparen oder Laufzeitverlängerung (durch
Stromsparen).
Hubs schrieb:> Hier die Fakten:>> Datenblatt ATTiny13: 3,3 V & 9,6 MHz RC-OSZ>> Idle Supply Current ca. 0,9 mA> Active Supply Current ca. 3,6 mA
Auch wenn es nur ein Beispiel von vielen ist, es önnen noch ganz andere
Zahlen zustande kommen, so Sieht man hier, daß der Idle 2,7 mA spart.
Jeder tiefere Schalfmodus kann maximal nur noch weitere 0,9 mA sparen.
Soviel zum Stromsparen an sich. Ich glaube das geht in Hubs Richtung.
Geht es um Laufzeitverlängerung (durch Stromsparen), so verdoppelt jede
weitere Halbierung des Reststromes die Laufzeit. Das sheint bei c-hater
der Gedanke zu sein.
Beides geht jedoch an der Frage nach Kompaktheit des TE vorbei.
Idle und die tieferen Sleep-modi sind nicht nur zum Energiesparen da.
Sie erweitern auch das Programmierkonzept und ermöglichen bei geeigneter
Programmierung einen anderen Programmfluß. Ich kann mit Sleep + Timer
definiert warten und trotzdem noch andere Sachen wie ISRs abarbeiten
wenn ich mit einem kleinen Jitter leben kann.
Mit einer Schleife kann ich Präzise warten, darf dann aber keine ISRs
zulassen, oder ich warte und jeder Interrupt verlängert die Wartezeit.
Beides dürfte neben der Kompaktheit ebenfalls relevant sein. Es betrifft
zwar weniger die Programmgröße an sich, aber die Funktionalität einer
Kommunikation kann dadurch beeinträchtigt werden wenn ich dies nicht
berücksichtige.
EinBastler schrieb:> Es geht doch um das Lernen und die Herausforderung bei solchen> Dingen,> mit einen ATmega wäre das leicht, der hat dediziertes UART, eine> Bootloadersection,... aber ein ATtiny hat nichts von dem und sowas> trotzdem in 64 Opcodes (2 Pages) oder vielleicht per SPI in 32 Opcodes> (1 Page) ist eine interessante Aufgabe
Achso, ich dachte es ging hier um was ernsthaftes und sinnvolles. Dann
bin ich wohl raus hier ;-)