High-Register-Adressen der 16bit-Timer?

LotadaC

Sehr aktives Mitglied
22. Jan. 2009
3.547
70
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Hi,

Wie Euch allen klar sein sollte, benötigen die 16bit-Timer für den Zähler, die Output Compare Register und das etwaige Input Capture Register je 2 Bytes. Um inkohärente Ergebnisse beim auslesen bzw falsche Compare Events beim schreiben (oder falsche Überläufe beim schreiben des Zählers) zu vermeiden besitzen diese 16bit-Register einen Synchronisationsmechanismus. Es existiert (je 16bit-Timer?) ein(!) Pufferregister, in welches beim auslesen eines low-Registers gleichzeitig der Inhalt des dazugehörenden high-Registers kopiert wird, bzw dessen Inhalt beim beschreiben eines low-Registers in das dazugehörende high-Register kopiert wird.
Daraus leitet sich die "Faustregel" ab, beim schreiben erst das high-Register zu beschreiben (genauer: den Wert im Puffer zu parken), und danach das low-Register (und damit beide synchron) zu beschreiben. Und beim lesen eben erst das low-Register zu lesen (wodurch das high-Register automatisch im Puffer landet), und danach den Wert des high-Registers aus dem Puffer zu lesen.

Soweit ist das nichts neues.
Beim Tiny10 sind das dann folgende Adressen:
  • TCNT0H = 0x29
  • OCR0AH = 0x27
  • OCR0BH = 0x25
  • ICR0H = 0x23

Warum nun eigentlich diese 4 Adressen? Nach der obigen Erklärung ist es schlichtweg egal, in welches der 4 high-Register man den Wert schreiben läßt. Er landet so oder so oder so oder so im selben Puffer, und wird dann durch schreiben des low-Register zu dessen(!) high-Register geschrieben. Und beim auslesen dieser 4 Adressen liest man denselben Puffer aus, darin steht halt immer die Kopie des high-Bytes, dessen korrespondierendes low-Byte zuletzt ausgelesen wurde.

Ich habe versucht, das im Simulator des Studios (6.1.2730) nachzuvollziehen, beim schreiben paßt das, aber beim lesen ist das nach dem Simulator nicht so (konkret habe ich TCNT0L auslesen lassen, und danach OCR0AH, was auch genau so erscheint - ich hätte aber die Werte von TCNT0L/H erwartet)

Liege ich jetzt irgendwo falsch, oder ist das ein (weiterer) Simulatorbug?

Hmm... vielleicht mal real die Veränderungen über die serielle ausgeben lassen, mit echter Hardware...?

Und wie ist das bei ICs mit mehreren 16bit-Timern? Haben die dann einen gemeinsamen Buffer, oder jeder Timer einen eigenen?
 
Hi,

Und wie ist das bei ICs mit mehreren 16bit-Timern? Haben die dann einen gemeinsamen Buffer, oder jeder Timer einen eigenen?

also ich tippe mal die haben den Atmel Blockweise aufgebaut (wie Module) weil die sich bei der Chipentwicklung dadurch ne Menge Arbeit sparen. Also tippe ich mal weiter das es pro 16Bit-Timer ein Temp-Register gibt und nicht für alle 16Bit-Timer eins. Damit kann man dann einfach den 16Bit-Timer-Block in den Chip setzen, Leitungen dran und fertig. Die Arbeit die man sich damit spart wird wohl allemal das bischen eingesparte Chipfläche aufwiegen. Außerdem hat man wegen weniger quergezogenen Leitungen weniger Übersprechen im Chip und hat damit bei hohen Frequenzen weniger Probleme.

Ist jetzt mal ne starke Vermutung aber ich lasse mich gern überraschen :rolleyes:

Gruß
Dino
 
Das mit den "kopierten" Modulen usw macht Sinn, ok...
Aber die andere Sache, 4 Registeradressen auf dasselbe Pufferregister zu "verdrahten" ist doch auch unnötig aufwändig. Hätte man doch ebenso mit 4 Namen für dieselbe Konstante (Adresse des Buffers) machen können. Wären 3 Registeradressen frei.
(OK, im Mega8 gibt es 3 oder 4 reservierte Register (ungenutzt), und trotzdem mußten (warum auch immer) sie diesen Klimmzug mit dem Baudratenregister machen...).

Hmm... stellt sich noch die Frage, welches "initial value" der Buffer hat, bzw ob überhaupt...
(beim IR-Sperrfeuer-Programm hat es allerdings jedesmal funktioniert, obwohl überall nur die low-Register beschrieben wurden. Die High-Register sind zwar 0, aber beim beschreiben der low Register wird ja der initiale Buffer in die high-Register kopiert. Also muß der sehr wahrscheinlich mit 0 initialisiert werden, beim Reset)
...aber beim lesen ist das nach dem Simulator nicht so (konkret habe ich TCNT0L auslesen lassen, und danach OCR0AH, was auch genau so erscheint - ich hätte aber die Werte von TCNT0L/H erwartet)...
Noch eins drauf:
Direkt nach dem lesen von OCR0AH habe ich jetzt ICR0L beschreiben lassen: Dabei landet tatsächlich der Wert von TCNT0H im ICR0H. Das Lesen von TCNT0L scheint also korrekt TCNT0H in den Buffer übertragen zu haben - aber das lesen von OCR0AH liefert nicht den Wert aus dem Buffer...
 
...Daraus leitet sich die "Faustregel" ab, beim schreiben erst das high-Register zu beschreiben (genauer: den Wert im Puffer zu parken), und danach das low-Register...
...Nach der obigen Erklärung ist es schlichtweg egal, in welches der 4 high-Register man den Wert schreiben läßt...
Hatte inzwischen in irgend'nem Datenblatt sogar den expliziten Hinweis gefunden, daß wenn mehreren 16bit-Registern (direkt nacheinander) das gleiche high-Byte zugewiesen soll, nur das erste beschrieben werden muß (und danach nur noch die low-Register), eben weil es danach weiterhin im Puffer verbleibt.
Zum Auslesen habe ich nichts, derart sauber formuliertes gefunden.

Wenn alle Lese- und Schreiboperationen auf die high-Register immer über denselben Puffer gehen, braucht dieser (Puffer) nicht bis zu 4 Adressen (das konkret zu beschreibende high-Register wird ja durch das verwendete low-Register festgelegt, egal über welche high-Adresse man den Puffer vorher gefüllt hatte)...

Hmm... ist sicher, daß diese high-Register adresstechnisch immer(!) über der 0x1F-Grenze liegen (also nicht direct Bit accessible sind?)
 
Ok, ich habs gefunden:
DB Tiny10 schrieb:
Accessing the low byte triggers the 16-bit read or write operation. When the low byte of a 16-bit register is written by the CPU, the high byte stored in the temporary register, and the low byte written are both copied into the 16-bit register in the same clock cycle. When the low byte of a 16-bit register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read. Not all 16-bit accesses uses the temporary register for the high byte. Reading the OCR0A/B 16bit registers does not involve using the temporary register.

Also beim Schreiben nutzen alle (TCNT, OCR, ICR) das Temporary Register, beim Lesen nur TCNT und ICR. Beim Tiny2313 ebenso, auf Seite 91 ist das in Figure 43 auch gut erkennbar...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)