Mein Problem ist folgendes: Wenn Ich den Interrupt (siehe markierte
Zeile)
auskommentiere passt genau das was ich möchte, also sendet er seine
Daten.
Wenn ich nun nun den Interrupt aktivieren sendet er nichts mehr.
Das kann ich mir gerade nicht Erklären und im Manual seh ich auch gerade
kein Punkt der das Problem beschreibt.
Kann mir jemand Erklären was ich falsch mache ??
viele grüße
Lassi
Hängt natürlich davon ab, was der ISR macht oder nicht macht - wenn der
z.B. die Interruptquelle nicht löscht, steht der Interrupt immer wieder
an.
Ich kenne den SAM selber nicht, aber wenn Du beim ST UART über DMA
fahren willst, musst Du eine ganze Latte Andere Dinge im DMA Block
konfigurieren, und der aufgerufene ISR nach Transmit Ende ist ein
Anderer als der UART Tx ISR (nämlich einer aus der DMA Engine). Ist das
beim SAM enger gekoppelt?
Mehr Code, den Du teilen wolltest? ;-)
Hallo rac,
also ein anderer Interrupt sollte nicht anstehen, bzw den müsste ich
sehen.
1
IrqState*HandleIrq(IrqState*state)
2
{
3
IPSR_Typetype;
4
type.w=__get_IPSR();
5
6
switch(type.b.ISR)
7
{
8
case0:
9
case1:
10
case2:
11
break;
12
case3:
13
case4:
14
case5:
15
case6:
16
HandleFaultIrq(type.b.ISR,state);
17
break;
18
case11:
19
state=HandleSysCall(state);
20
break;
21
case15:
22
state=NextTask(state);
23
break;
24
case24:
25
PrintString("Interrupt\n");
26
UartIRQ();
27
break;
28
default:
29
HandleFaultIrq(type.b.ISR,state);
30
break;
31
}
32
33
returnstate;
34
}
Also Interrupts bis der Nummer 6 oder kleiner sind Faults oder ähnlichem
und haben die höchste Priorität. 11 sind System/Supervisor Aufrufe.
15 ist ein Takt für Threading und der Interrupt 24 ist allgemein Uart.
Mit der Methode HandleFaultIRQ wird zurzeit nur eine Debug-Ausgabe
gemacht, also wenn ein andere Interrupt als Erwartet kommt sollte ich
das mit bekommen.
Zu dem DMA allgemein:
>At the end of a transfer, the PDC channel sends status flags to its associated>peripheral.>These flags are visible in the peripheral status register>(ENDRX, ENDTX,RXBUFF, and TXBUFE).>Refer to Section 26.4.3 and to the associated peripheral user interface.
Der PDC sind sehr eng mit der eigentlichen Peripherie verknüpft.
Es gibt aber auch noch DMAC die sind deutlich komplexer, aber stehen
auch nicht überall zur Verfügung.
Also die Bits werden immer im Status-Register gesetzt. Die Interrupts
sind auch auf die Peripherie bezogen und werden darüber gehandelt.
Also das Ding macht mich noch mal Wahnsinnig. Es kann verdammt viel,
aber fürs verstehen brauch man ein weile.
viele grüße
Lassi
Hinweis: Mann muss ein bissel aufpassen es gibt den PDC den ich benutze
für DMA und es gibt den DMAC für DMA.
Warum steht doch alles in der Referenz.
Interessant wäre wie du den PDC konfigurierst ?
Diesen müssen einige Adressen etc. übergeben werden.
Der Start des Transfers erfolgt über die entsprechende Peripherie. Damit
auch die Steuerung wenn die nächsten Daten transferiert werden müssen.
Hallo,
@damarco:
mehr konfiguriere ich nicht und wenn ich diese Zeile weg lasse
funktioniert das auch alles bestens:
1
UART->UART_IER=UART_IER_ENDTX;
Wenn ich aber die Zeile drinne lasse, um den Interrupt zu empfangen.
Geht nichts mehr und ein senden ist nicht mehr möglich. Ich kann auch
nicht sagen ob ein Fault oder ähnliches passiert, weil ich nichts mehr
senden kann.
Eine Möglichkeit ist das ein Interrupt immer und immer wieder ausgeführt
wird, aber das zu überprüfen ist halt etwas schwieriger.
Hallo,
ich hab gerade den letzten Beitrag geschrieben, aber ich dann hab ich
mal die Theorie verfolgt mit dem Interrupt. Und ja es wirft immer den
Interrupt so bald er aktiviert wird und ich bin davon ausgegangen das er
erst kommt wenn man wenigsten den PDC aktiviert.
Das muss ich wohl irgendwo überlesen haben.
So für alle, wenn jemand anderes das Problem hat.
//setzt aktiviert den Interrupt obwohl der Transfer schon läuft
10
UART->UART_IER|=UART_IER_ENDTX;
Vielleicht solltest du die Reihenfolge nochmal überdenken
Ich würde den Interrupt in der ISR auch wieder deaktivieren.
Wird das UART_SR nicht gelöscht wenn man es ausließt ?
Christoph L. schrieb:> case 24:> PrintString("Interrupt\n");> UartIRQ();> break;> default :> HandleFaultIrq(type.b.ISR,state);> break;
...
>Interrupt 24 ist allgemein Uart.
...
> Mit der Methode HandleFaultIRQ wird zurzeit nur eine Debug-Ausgabe> gemacht,
Und wo werden die Ausgaben von PrintString und HandleFaultIrq
hingeleitet? An den UART? :-)
Hallo,
@damarco
Ja die Reihenfolge kann sein das die bei kleinen Datenmengen nicht
passt.
Ich hab das jetzt mit 6 Byte und Baudrate von 115200 getestet hab.
Wichtig ist nur das TNCR bzw. TCR etwas ungleich 0 drinnen steht.
Der Interrupt wird eignetlich UartIRQ wieder deaktiviert.
Die IER (Interrupt Enable Register) aktivieren den Interrupt und zum
deaktivieren muss man in das IDR (Interrupt Disable Register) schreiben.
Find ich schöner, weil man dann nicht so sehr mit Bitmanipulationen
arbeiten muss, aber das ist wohl Geschmackssache.
Ach und soweit ich weiß werden die Statusregister nicht gelöscht beim
lesen, aber ich lasse mich gerne korrigieren. Das 1400 Seiten Manual hab
ich noch nicht ganz durch :)
@Beric
Ja die werden direkt in das UART_THR-Register geschrieben dort geht es
noch nicht über dem PDC, weil ich das Problem hab das der PDC nicht aus
dem Flash Daten lesen kann und da müssen die Ausgaben erst in den RAM.
Ich bin deshalb gerade beim Umbau der ganzen Architektur, weil ich
möchte nicht das ganze im Interrupt machen sondern in eigenen Task ...
Das ganze hat wohl mit dem NVIC zutun, wenn der aktiviert wird geht's
wohl los ob man will oder nicht.
Christoph L. schrieb:> @Beric> Ja die werden direkt in das UART_THR-Register geschrieben
...und dannn wird, sobald das erste Byte von PrintString
("Interrupt!") verschickt wurde, ein Interrupt ausgelöst. Die
Interruptroutine wird aufgerufen und macht PrintString ("Interrupt!").
Sobald davon das 'I' verschickt worden ist, kommt ein Interrupt usw usw?
Eric B. schrieb:> Christoph L. schrieb:>> @Beric>> Ja die werden direkt in das UART_THR-Register geschrieben>> ...und dannn wird, sobald das erste Byte von /PrintString/> ("Interrupt!") verschickt wurde, ein Interrupt ausgelöst. Die> Interruptroutine wird aufgerufen und macht PrintString ("Interrupt!").> Sobald davon das 'I' verschickt worden ist, kommt ein Interrupt usw usw?
Das ist die "theory of operation." Deswegen muß der Tx Interrupt Handler
darüber Buch führen, wieviele Zeichen noch ausstehen, und den Sonderfall
"letztes Zeichen gesendet" anders behandeln. In der Regel wird hier (bei
synchronem Transmit) eine Sempahore signalisiert, auf die die Task, die
den Output macht, wartet. Hier gibt es jede Menge Möglichkeiten, Dinge
(falsch oder richtig) Anders zu machen; z.B. kann es Fälle geben (Full
Duplex Protokoll), in denen die sendende task nicht wartet, bis der
Output durch ist und in der Zwischenzeit weitere Zeichen hinten anhängt,
das muß dann sauber synchronisiert werden.
Beim printf() wird aber in der Regel die __write() callback Funktion auf
den UART umgleitet, und die ist synchron.
Es gibt auch eine Variante dieser Implementation, bei der die task, die
den printf initiiert, nicht selber das erste Zeichen sendet, sondern nur
einen Tx Interrupt forciert, und der sendet eben das erste Zeichen statt
dem Zweiten.
Aber der Thread ging ja ursprünglich über Tx und DMA, und dort ist es ja
so, daß der DMA Engine ein Zeiger auf den String und die Länge übergeben
wird, und DMA macht das Ganze dann völlig autark und generiert erst dann
einen Interrupt, wenn der Transmit komplett durch ist.
Ruediger A. schrieb:> Das ist die "theory of operation." Deswegen muß der Tx Interrupt Handler> darüber Buch führen, wieviele Zeichen noch ausstehen, und den Sonderfall> "letztes Zeichen gesendet" anders behandeln.
Das hilft dir aber nichts wenn der Interrupthandler selber immer wieder
neue Zeichen zum verschicken hinzufügt!
Hallo:
@Beric:
>Die Interruptroutine wird aufgerufen und macht PrintString ("Interrupt!").>Sobald davon das 'I' verschickt worden ist, kommt ein Interrupt usw usw?
Ja und nein. Ja es könnte ein Interrupt kommen, aber nein es kommt
keiner, weil ich den Interrupt deaktiviert habe.
@Rac:
Aber ich muss zugeben das ich gerade das Problem der Synchronisierung
habe. Weil ich brauch wirklich ein Speicherbereich im Ram und der muss
irgendwann mal freigegeben werden. Das heißt gerade das ich ein Task
anhalten muss bis der Sendevorgang von dem Task fertig ist.
viele grüße
Lassi
Eric B. schrieb:> Ruediger A. schrieb:>>> Das ist die "theory of operation." Deswegen muß der Tx Interrupt Handler>> darüber Buch führen, wieviele Zeichen noch ausstehen, und den Sonderfall>> "letztes Zeichen gesendet" anders behandeln.>> Das hilft dir aber nichts wenn der Interrupthandler selber immer wieder> neue Zeichen zum verschicken hinzufügt!
Hä? Verstehe ich nicht, deine Anmerkung.
Der Pseudocode ist (variante 2):
Applikation:
{
Hinterlege String und Stringlänge in Struktur;
Triggere Tx Interrupt;
<optional: Warte auf ISR Signal, s.o.>
}
Tx ISR:
{
wenn Stringlänge = 0
{
// nichts tun, weil keine Zeichen mehr zu senden sind
<optional: Signalisiere Applikation End Of Transmission>
}
else
{
<sende nächstes Zeichen> // das triggert den nächsten ISR
Stringlänge -= 1;
}
}
Was soll daran nicht funktionieren oder mir nichts helfen? Das ist
Standard 0815 Code in Transmittern, der in Hunderten von Treibern seit
Jahrzehnten funktioniert.