Hallo,
ich versuche gerade, den Capture Interrupt des Timers TC1 bei einem
SAMD11 zu testen. Der Timer selbst läuft problemlos, aber beim
compilieren des Interrupt-Handlers bekomme ich die Warning , dass das
Interrupt-Flag TC1->COUNT16.INTFLAG.bit.MC0 "read only" sei. Wie kann
das sein, im Datenblatt ist es explizit als R/W angegeben? Die
Schreibfunktion brauche ich doch, um das Flag am Ende des Handlers
wieder zu löschen.
1
voidTC1_Handler()
2
{
3
if(TC1->COUNT16.INTFLAG.bit.MC0)
4
{
5
PORT->Group[0].OUTTGL.reg=1<<16;
6
TC1->COUNT16.INTFLAG.bit.MC0=1;//clear interrupt flag
Mike schrieb:> im Datenblatt ist es explizit als R/W angegeben?
Ja da hast du recht, ABER...
Wenn du mal im ASF schaust
(ASF/sam0/utils/cmsis/samd11/include/component/tc.h), dann sind die Bits
in INTFLAG mit
Technischer Hintergrund: Diese Bitfeld-Operation liest erst das Wort ins
Register, setzt dort das Bit, und schreibt das Register anschliessend
zurück. Damit werden automatisch alle gesetzten Flag-Bits gelöscht,
nicht nur das gewünschte, da jedes gesetzte Flag-Bit als 1 gelesen und
als 1 zurückgeschrieben wird.
Um ein Flag-Bit gezielt zu löschen, darf man nicht vorher lesen, sondern
man schreibt einfach eine 1 nur an die betreffende Bitposition.
> Du solltest die Register INTENCLR und INTENSET nutzen.
Die dienen doch zum Aktivieren bzw. Deaktivieren des Interrupts. Das
Interrupt Flag ist aber etwas anderes. Letzteres scheint kein Enable
bzw. Clear-Register zu haben.
Ich habe den .bit - Zugriff mal durch einen registerweiten ersetzt:
1
TC1->COUNT16.INTFLAG.reg=TC_INTFLAG_MC0;//clear interrupt flag
Das scheint zu funktionieren. Ich war der Meinung, der Compiler würde da
das Gleiche draus machen
Mike schrieb:> Die dienen doch zum Aktivieren bzw. Deaktivieren des Interrupts.
AH ja, ok - hast recht.
Hab nochmal nachgeschaut, schreiben einzelner Bits geht nicht in
INTFLAG,
doch der Registerweite Zugriff (Write) ist erlaubt:
1
__IOTC_INTFLAG_TypeINTFLAG;/**< \brief Offset: 0x0E (R/W 8) Interrupt Flag Status and Clear */
Mike schrieb:> Das scheint zu funktionieren. Ich war der Meinung, der Compiler würde da> das Gleiche draus machen
Manche Cortexe können per Bitbanding Einzelbits schreiben. Aber selbst
wenn der verwendete µC das unterstützt (M0 nicht, M0+ optional) löst das
nicht das Problem. Denn Bitbanding wird von der Hardware auch nur in
eine automatische read-modify-write Operation mit getrennten Lese- und
Schreiboperationen aufgelöst, so dass das erwähnte Problem erhalten
bleibt.
Und ob es einen Compiler gibt, der eine Bitfeldoperation in Bitbanding
umsetzt, wäre auch eine Frage.
A. K. schrieb:> Mike schrieb:>> Das scheint zu funktionieren. Ich war der Meinung, der Compiler würde da>> das Gleiche draus machen>> Manche Cortexe können per Bitbanding Einzelbits schreiben. Aber selbst> wenn der verwendete µC das unterstützt (M0 nicht, M0+ optional) löst das> nicht das Problem. Denn Bitbanding wird von der Hardware auch nur in> eine automatische read-modify-write Operation mit getrennten Lese- und> Schreiboperationen aufgelöst, so dass das erwähnte Problem erhalten> bleibt.>
? Du sagst also, dass Bit Banding auf dem Mo+ (wo verfügbar) anders
implementiert ist als im M3?
Aus dem Buch Yiu M3, Kapitel "Memory Systems: "One of the most important
advantages or properties of bit-band operation is that it is atomic. In
other words, the READ-MODIFY-WRITE sequence can not be interrupted by
other bus activities." Es ist also garantiert, dass die Anderen Bits im
selben Word während der Operation unverändert bleiben (beim M3+).
> Und ob es einen Compiler gibt, der eine Bitfeldoperation in Bitbanding> umsetzt, wäre auch eine Frage.
Nicht so sehr eine Frage des Compilers, mehr der Zugriffsbibliothek auf
die Peripherie, oder?
Ruediger A. schrieb:> Aus dem Buch Yiu M3, Kapitel "Memory Systems: "One of the most important> advantages or properties of bit-band operation is that it is atomic. In> other words, the READ-MODIFY-WRITE sequence can not be interrupted by> other bus activities." Es ist also garantiert, dass die Anderen Bits im> selben Word während der Operation unverändert bleiben (beim M3+).
Bei einem Interrupt "Lösch" Register, dass mit einem 1 Bit das
entsprechende Flag löscht würdest Du da trotzdem ein Problem haben.
Denn Du liesst nicht eine Null sondern eine 1 ein, und damit löscht die
abschließende Schreibaktion auch die anderen Flags mit.
Beispiel: Im Flag Register sind 2 Flag Bits gesetzt (z.B. UART Frame
Error und Break detect). Jetzt willst Du z.B. das Frame Error Bit
alleine löschen, aber da das Break Bit auch 1 gelesen wird, würde es
automagisch mit gelöscht werden.
Abhilfe ist das korrekte Schreiben nur des Frame Bits (alle anderen Bits
sind null).
Das geht so aber nicht mit den Bitfield Sachen, weswegen die für
Register Schreibaktionen eher unglücklich sind. Daher ist es korrekt das
sie als "read only" markiert sind.
Ruediger A. schrieb:> ? Du sagst also, dass Bit Banding auf dem Mo+ (wo verfügbar) anders> implementiert ist als im M3?
Nein.
> Aus dem Buch Yiu M3, Kapitel "Memory Systems: "One of the most important> advantages or properties of bit-band operation is that it is atomic.
Es ist aus Sicht des Programmierers atomic. In dem Sinn, als es nicht
aus mehreren Befehlen besteht und nicht unterbrochen werden kann. Es
besteht aber trotzdem aus getrennten Lese- und Schreiboperationen. Nur
werden die nicht unterbrochen.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka16401.html
Gilt für alle Cortex-M mit Bitbanding.
> In> other words, the READ-MODIFY-WRITE sequence can not be interrupted by> other bus activities." Es ist also garantiert, dass die Anderen Bits im> selben Word während der Operation unverändert bleiben (beim M3+).
Falsche Schlussfolgerung. Die Interrupt-Flags des Timers werden nicht
durch Busoperationen gesetzt. Sondern vom Peripheriemodul selbst, auf
das der Core zugreift.
Ausserdem ist hier nicht nur wichtig, dass es atomar ist. Sondern auch,
dass es das tut, was du willst. Auch wenn vor der ganzen Operation ein
weiteres Bit von der Hardware gesetzt wird, geht es flöten.
> Nicht so sehr eine Frage des Compilers, mehr der Zugriffsbibliothek auf> die Peripherie, oder?
Der Compiler sieht eine Bitfeldoperation und muss die in Code umsetzen.
An dieser Aufgabe ist keine Zugriffsbibliothek beteiligt, sondern nur
eine Definition der Register des IO-Moduls als struct/union/bitfield.
Um das den Compiler machen zu lassen, müsste der wissen, dass der
Prozessor Bitbanding kann und dass das betreffende IO-Modul in
entspreichenden Adressbereich liegt. Und selbst dann würde dir das hier
nicht weiterhelfen.
A. K. schrieb:> Manche Cortexe können per Bitbanding Einzelbits schreiben. Aber selbst> wenn der verwendete µC das unterstützt (M0 nicht, M0+ optional) löst das> nicht das Problem. Denn Bitbanding wird von der Hardware auch nur in> eine automatische read-modify-write Operation mit getrennten Lese- und> Schreiboperationen aufgelöst, so dass das erwähnte Problem erhalten> bleibt
Mehrere LPC mit M0 z.B. LPC11A können mit SFR Einzelbits atomar
schreiben und auch toggeln das hat mit Bitbanding nichts zu tun. Auch
die LPC mit M0+ z.B. LPC800 machen das so z.B.
MOVS R0, #10000B ; R0=bit.Px_4
LDR R1, NOT0
loop
STR R0, [R1] ; NOT0_bit.P0_4 = 1 (toggle)
BL delay
A. K. schrieb:>>> Nicht so sehr eine Frage des Compilers, mehr der Zugriffsbibliothek auf>> die Peripherie, oder?>> Der Compiler sieht eine Bitfeldoperation und muss die in Code umsetzen.> An dieser Aufgabe ist keine Zugriffsbibliothek beteiligt, sondern nur> eine Definition der Register des IO-Moduls als struct/union/bitfield.>> Um das den Compiler machen zu lassen, müsste der wissen, dass der> Prozessor Bitbanding kann und dass das betreffende IO-Modul in> entspreichenden Adressbereich liegt.
Naja, es wäre ja auch denkbar, dass bereits die peripheral lib auf den
Bitband Aliases arbeitet, z.B. so:
(bestehender Code)
Damit müsste man nicht dem Compiler zu viel "Intelligenz" zumuten und
könnte sogar feingranuliert dort die Aliases einsetzen, wo sie Sinn
machen.
> Und selbst dann würde dir das hier> nicht weiterhelfen.
Ok, ACK, Argument akzeptiert. Jims Erklärung macht an der Stelle Sinn,
Danke!
Lothar schrieb:> Mehrere LPC mit M0 z.B. LPC11A können mit SFR Einzelbits atomar> schreiben und auch toggeln das hat mit Bitbanding nichts zu tun.
Auch der hiesige Controller besitzt bei den Flags die Möglichkeit, sie
gezielt zurückzusetzen, indem nicht vorher gelesen sondern genau und nur
dort eine 1 geschrieben wird. Das hatte ich freilich bereits am Anfang
beschrieben. Nur weiss der Compiler nichts von besonderen Eigenschaften
des Flags-Registers.
Ruediger A. schrieb:> Naja, es wäre ja auch denkbar, dass bereits die peripheral lib auf den> Bitband Aliases arbeitet, z.B. so:
Yep. Aber er hat keine Lib verwendet, sondern das Register per Bitfeld
angesprochen.