Moin zusammen,
ich habe in der Firma ein Board-Support-Package für die STM32F10x
geschrieben, bin also nicht ganz unerfahren mit Cortex-M3. Nun habe ich
hier zuhause ein Evalboard mit LPC1768 von Steinert liegen. Clocks sind
eingestellt, PLL0 rennt. Vektortabelle liegt ab $10000000 und ist dem
NVIC auch so bekannt. Der Systicktimer läuft und er generiert mir auch
einen IRQ und landet in der ISR. Nun will ich die UARTs in Betrieb
nehmen.
Ich habe gesetzt:
- Bit in PCONP für UART0 gesetzt
- PCLKSEL für UART0 auf default = CCLK/4 = 25MHz
- PINSEL0 P0.2 und P0.3 auf UART gestellt
- Baudrate und 8N1 eingestellt
- Bit 0 in UART0FCR (use FIFO) ist gesetzt - lässt sich eh nicht
ausknipsen
- Bit 5 (für UART0) in NVIC SETENA gesetzt
Entwicklungsumgebung ist IAR 5.50 mit J-Link von Segger.
Problem:
Ich lege ein Byte in meinen Softwareringpuffer zum Versenden mit UART0,
und setze THREIE in UART0IER. Jetzt sollte - da TransmitHoldingRegister
leer ist - ein IRQ erzeugt werden, damit meine ISR zum Versenden
ausgeführt wird. Es wird aber kein IRQ ausgelöst.
Nun habe ich händisch im Debugger im NVIC das Bit 5 für UART0 in
SETPEND0 gesetzt - und sofort rennt er auf meinen Breakpoint in der ISR.
Hat jemand eine Idee warum der IRQ nicht ausgelöst wird?
thanx, Arne
Details zum LPC17xx gerade nicht im Kopf aber es ist bei UART-Hardware
nicht unüblich, dass der
Hardware-bereit-für-nächstes-Zeichen-senden-Interrupt nur durch den
Zustandswechsel Hold-Reg. voll -> Hold-Reg. leer ausgelöst wird (wäre
damit entgegen der Annahme: "Jetzt sollte - da TransmitHoldingRegister
leer ist - ein IRQ erzeugt werden"). Mögliche Abhilfe: in 'putchar()'
prüfen, ob Interrupt aktiv, wenn ja: Zeichen in Warteschlange
zwischenspeichern, wenn nicht: Zeichen in Hardwareregister und Interrupt
aktivieren. In der ISR nächstes Zeichen aus Warteschlange in TX-Register
oder wenn Schlange leer, Interrupt ausschalten. Kann man beim LPC17xx
wahrscheinlich mittels Hardware-FIFO und/oder DMA noch einiges
erweitern.
Weiss nicht wie es beim AVR ist, aber beim STM32 wird sofort in die ISR
gesprungen, wenn das TransmitHoldingRegister leer ist und der Interrupt
im UART aktiviert ist. Aber der STM32 hat auch keinen FIFO (jedenfalls
kann man wohl nix per SW konfigurieren). Der LPC17xx hat Rx und Tx FIFO.
Hab jetzt was im Manual gefunden... verstanden habe ich es nicht.
> Hardware-bereit-für-nächstes-Zeichen-senden-Interrupt nur durch den> Zustandswechsel Hold-Reg. voll -> Hold-Reg. leer ausgelöst wird (wäre> damit entgegen der Annahme: "Jetzt sollte - da TransmitHoldingRegister> leer ist - ein IRQ erzeugt werden"
Hab es mir dreimal durchgelesen, aber beide Aussagen sind für mich
gleichwertig!
Werde es morgen mal nach Deinem Vorschlag umbauen. Zerhagelt mir mein
schönes API. :-(
Tueftler schrieb:> hast du die ISR per> NVIC_EnableIRQ(....);> NVIC_SetPriority (...);> enabled?
Schrieb ich ja:
- Bit 5 (für UART0) in NVIC SETENA gesetzt.
und Priorität ist per default nach Reset auf 0 -> höchste Priorität.
Ich bin ja auch erst am Einarbeiten mit dem LPC, aber ich verstehe das
Datenblatt so: Man schreibt sein Byte in U0THR. Wenn der FIFO an ist,
kümmert der sich darum, daß das Byte in den FIFO kommt (also kein
eigener Softwareringbuffer erforderlich). Der FIFO schiebt das Byte dann
automatisch raus, wenn UART0 sendebereit ist. Also kein Interrupt zum
Senden erforderlich. Im Datenblatt ist leider nicht beschrieben, wann
THREI0 triggert. Ich vermute aber mal, daß er beim Übergang von THR full
nach empty triggert. Würde sonst ja auch keinen Sinn machen, wenn das
leere THR triggern würde. Wäre sonst ja fast immer am triggern ...
Also eigentlich genau das, was Martin schon geschrieben hatte.
@Michael:
was meinst Du mit "THREI0"?
Hab gestern abend noch dran rumgefummelt, aber es kam nur Quark im
Terminalprg an. Das alte Manual beschrieb noch ein FIFOLVL Register, das
den Füllstand von TX/RX-FIFO angab. Ist im aktuellen Manual nicht drin
und ist im LPC auch nicht "eingebaut" :-(
Arne schrieb:> Soll natürlich @Manfred heissen - mea culpa.
Macht nichts, ich hab mich auch verschrieben :-)
Ich meinte das Bit THRE Interrupt Enable im Register U0IER (für den
UART0). Damit lag ich aber leider falsch.
Weiter unten wird es doch noch beschrieben:
The UARTn THRE interrupt (UnIIR[3:1] = 001) is a third level interrupt
and is activated when the UARTn THR FIFO is empty provided certain
Initialization conditions have been met. These initialization conditions
are intended to give the UARTn THR FIFO a chance to fill up with data to
eliminate many THRE interrupts from occurring at system start-up. The
initialization conditions implement a one character delay minus the stop
bit whenever THRE = 1 and there have not been at least two characters in
the UnTHR at one time since the last THRE = 1 event. This delay is
provided to give the CPU time to write data to UnTHR without a THRE
interrupt to decode and service. A THRE interrupt is set immediately if
the UARTn THR FIFO has held two or more characters at one time and
currently, the UnTHR is empty. The THRE interrupt is reset when a UnTHR
write occurs or a read of the UnIIR occurs and the THRE is the highest
interrupt (UnIIR[3:1] = 001).
Frei übersetzt: Der Interrupt kommt nur, wenn schon mal mindestens 2
Zeichen im FIFO waren und U0THR dann leer wird.
Der Sendestring kommt immer noch stellenweise zerhackt am PC an.
Meine putchar() Funktion füllt nun solange direkt den TxFIFO solange
THRE==1 ist.
Sobald THRE==0 ist, wird das Zeichen in meinen SW-Ringpuffer gelegt und
der THREIE Interrupt aktiviert. Scheint bisher nicht zuverlässig zu
funktionieren.
Es bleibt schwierig...
Ich denke, ich weiss inzwischen wo das Problem liegt.
Mein API schiebt die zu vesendenden Zeichen IMMER einzeln durch eine
Funktion durch. Wenn THRE==1, dann lege ich das Zeichen beim LPC1768
direkt in das THR. Beim nächsten Zeichen ist THRE==0 und ich lege das
Zeichen in meinen SW-Ringpuffer. Nun kommt das Problem, dass ich in der
Funktion nie weiss zu welchem Grad der FIFO gefüllt ist (THRE==0 heisst
1..16 Byte im FIFO), aber zwingend zwei Zeichen im FIFO sein müssen,
damit überhaupt der THRE-Interrupt getriggert wird. Darf das aktuelle
Zeichen noch in den FIFO oder nicht? Mitzählen bringt nichts, da ich ja
nicht weiss wie schnell die Zeichen aus dem Schiebereg. auf die Reise
gehen (könnte man sich errechnen, ist aber wohl zu fehlerhaft). Somit
wäre die Zählung nur ein Schätzeisen.
Habe mir einige Besipiele für LPC17xx und LPC2000 angeschaut. Alle
nudeln das ohne SW-Ringpuffer ab. Entweder sie pollen THRE und legen
dann ein Char in den FIFO (was den FIFO ad absurdum führt) oder sie
schieben max. 16 Byte in den FIFO und warten dann im Hauptprogramm.
Beides sehr primitive "Lösungen"!
Hallo,
ich wollte mal fragen, ob es mittlerweile hier eine Lösung des Problemes
gibt.
Ich selber habe die identische Situation mit der ISR und einem Software
Ringpuffer. Im Terminalprogramm erhalte ich immer nur zwei Zeichen.
Danach funktioniert der uart gar nicht mehr.
Daher wäre ich über weitere Lösungsansätze sehr dankbar.
Vielleicht lässt sich für eine so wichtige Anwendung, wie den UART dann
auch anschließend etwas in der Codesammlung unterbringen.
@Arne: könntest Du mir die Lösung auch zukommen lassen bzw. allen hier.
Alternativ wäre ich auch glücklich wenn ich wüsste was ich ändern muss,
damit das ganze läuft.
Hallo Arne,
ich steh vor dem gleichen Problem und würde mich über deine Lösung
freuen.
Kannst du sie bitte online stellen.
Bestimmt sind auch andere daran Interessiert.
Link:
http://docs.lpcware.com/lpcopen/group___p_e_r_i_p_h__11_x_x___u_a_r_t.html#gac1a9d00d4f324e319e1486138b097874
Da ist glaube ich was für euch dabei..ist zwar vom LPC11x aber
die sind von der Arcitektur fast gleich.
void Chip_UART_SetupFIFOS ... *pRX = &rec_buffer[0]
Das Sratchpad ist auch dabei. via Timer @
Frage:
Habt ihr ein Api Manual als Doxygen Format ? für den LPC1768 Chip.
-----------------------------------------------------------------
Gruss Holger.
Hier der Link:
Wichtig ist hier:
LPC_UART->TER = ( 0x80); // enable transmit #
https://github.com/someone42/hardware-bitcoin-wallet/blob/master/lpc11uxx/usart.c
Ich teste das im Loop-Back-Mode:
LPC_UART->MCR |= ( (1<<4) ) ; /* $10Lopp-Back*/
Im Code ist das IRQ Ident gelesen und danach einmal geschiftet
Diese Shifte verstehe ich nicht
IIRValue >>= (0x01); was soll das ???
Legende:
[DMAS:2][S:1][S:0] [rx_irq_flg:-(1)RHR]
1
LPC_UART->FCR=(0x01);// (0x04 | 0x02 ); /* 0x07 Enable and reset TX and RX FIFO. */
2
LPC_UART->FCR=(0x07);// clear receive and transmit FIFOs, trigger level = 1 character
Das ist wohl nur im auto Hand-Schake via Full-Modem mit Fifo möglich.
also z.B (CTS RTS, DSR DTR CD ect. Criss -Cross DTE DCE)
Das pdf Datenblatt ist wohl geaendert worden...
Link:
Fifo Problem.
http://knowledgebase.nxp.com/showthread.php?t=2231
############################################################
Mit dem Loop-Back teste ich auch noch den Modem-Config.
Ist als Bild auf dem EXAR pdf abgebildet.
Bits für (Opt#2/Int, OPT#1 ). usw.
Auch die Config . IER (Bit#2) bzw. (Bit#3) ist das der exMux für
Hardwire-Modem?? bzw. (LSR Reg. via couppling (Bit#2)- von IER)
########################################################################
1
voidUARTSend(uint8_t*BufferPtr,uint32_tLength)
2
{
3
4
while(Length!=0)
5
{
6
/* THRE status, contain valid data */
7
#if CONFIG_UART_ENABLE_TX_INTERRUPT==1
8
/* Below flag is set inside the interrupt handler when THRE occurs. */
9
while(!(UARTTxEmpty&0x01));
10
LPC_UART->THR=*BufferPtr;
11
UARTTxEmpty=0;/* not empty in the THR until it shifts out */
12
#else
13
/* To_Do: FIFO aktiv via pre prept user app-info from Scratch-Pad */
if(!(tx_data % 16))
% 4 ist für fifo-len = 4
der maximale Fifo ist 14 , warum % 16 ???
?
void UART_Tx(char *BufferPtr, int Length)
{
unsigned char tx_data = 0;
while ( Length != 0 )
{
if(!(tx_data % 16)) // ???
{
while ( !(LPC_UART->LSR & LSR_THRE) );
}
LPC_UART->THR = *BufferPtr;
BufferPtr++;
tx_data ++;
Length--;
}
return;
}
########################################################################
Ich habe das TX IRQ Enable nicht gesetzt, somit muss ich immer
bit 5 & 6 abfragen.
siehe via LSR . Sonst gehen nur 2 Zeichen, ( wohl Buff-Intern ??)wie
ich das mit Loop-Back (Fazit Bem: 14-Byte Fifo + 2 Buff = 16 ??? )
getestet habe.
Um das noch weiter zu testen, nehme ich den TX IRQ Enable noch hinzu.
########################################################################
Anlage Bild ist für den 'Fifo-Size [1,4,8,14] 'bit[1]bit[1] = 14 = 0x0E
########################################################################
Hint zum Umgang mit der IDE.
LPCXpresso Introduction part 2 training video
http://www.youtube.com/watch?v=cLvGwmJAA7k
Hab noch ein Problem gefunden an folgender Stelle:
LPC_UART->THR = *BufferPtr;
// XXX
UARTTxEmpty = 0; /* not empty in the THR until it shifts out */
schreiben auf THR resettet den interupt wenn zwischen den Zeilen ein
Interupt auftritt(XXX) und dieser zu lange braucht und der uart das
zeichen rausgeschrieben hat tritt der IIR_TRHE interupt auf UARTTxEmpty
wird auf 1 gesetzt jedoch gleich nach dem Interrupt auf 0.
Somit bleibt er in der Endlosschleife beim nächsten mal while (
!(UARTTxEmpty & 0x01) ); hängen weil der ISR schon gekommen ist
Leider ist der Fehler in der standard lib, werde ihn noch melden