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.
hast du die ISR per NVIC_EnableIRQ(....); NVIC_SetPriority (...); enabled?
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 |
3 | LPC_UART->TER = ( 0x80); // enable transmit ########### |
4 | ############
|
5 | // [DMAS:2][S:1][S:0][rx_irq_flg:-(1)RHR]
|
6 | // must I shift this RHR Rec-Hold Reg away --Pending Rec-Holding Reg
|
7 | /* ########### Fifo-Betrieb oder Modem ??? ################*/
|
8 | // IIRValue >>= (0x01); /* ???skip pending bit in IIR */
|
9 | // [DMA_S:2][S:1][S:0] no RHR get over LSR Reg
|
10 | IIRValue &= ( 0x07); /* check bit 1~3, interrupt identification */ |
11 | if (IIRValue == IIR_RLS) /* Receive Line Status */ |
12 | { /* Line-StausReg*/ |
13 | LSRValue = LPC_UART->LSR; // (0x01) ^ (1 <<0 ) RHR -get over LSR |
14 | /* Receive Line Status*/
|
15 | // * --OVERRUN,Parrity-Err.,FRAMErr---[-RX-FIFO-Error],--/BREAK-Indicator#IRQ*;/
|
16 | if (LSRValue & ( LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI) ) |
17 | {
|
18 | /* There are errors or break interrupt */
|
Hier ist ein Fifo
1 | LPC_UART->LCR = /*0x80*/ (0x03); /*/7-Div,/6-BRK.emit,5Par-set Divisor EnableDLAB = 0 */ |
2 | /* Close Latch für divisor Feq*/
|
3 | // FIFO $07
|
4 | LPC_UART->FCR = ( 0x01 ); // (0x04 | 0x02 ); /* 0x07 Enable and reset TX and RX FIFO. */ |
5 | LPC_UART->FCR = (0x07); // clear receive and transmit FIFOs, trigger level = 1 character |
6 | |
7 | /*############################*/
|
8 | LPC_UART->FCR = ( 0x01 ); // Bit-Map[no/Tx-Fifo-Reset][no/Rx-Fifo-Res][E-Yes] |
9 | LPC_UART->FCR |= (0x40 | 0x01); // bit 6 Trigger Level_1-Stage + [E-Yes]-FifFo-ON |
10 | |
11 | /* Wichtig: $80 Set ******** ##############*/
|
12 | LPC_UART->TER = ( 0x80); // enable transmit ???-->>>Hardware must even in Loop-Back-Mode ?? |
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 | void UARTSend(uint8_t *BufferPtr, uint32_t Length) |
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 */
|
14 | //while-case#1:
|
15 | /// while ( ! (LPC_UART->LSR & LSR_THRE) );// $20 #define THR (1<<5)
|
16 | /* Wait till U0THR and U0TSR are both empty */
|
17 | // wait for Transmit-Shift-Reg.Emty until even Stop-Bit-Emited , see option 2Stop-bit
|
18 | //while-case#(2): [Hold-Reg-buff$20]-->(Shift-Reg.$40)-->
|
19 | while ( (LPC_UART->LSR & LSR_TEMT) == (0x00) );// $40 #define TEMT (1<<6) |
20 | LPC_UART->THR = *BufferPtr; // Feeed THReg. |
21 | #endif
|
22 | BufferPtr++; |
23 | Length--; |
24 | }
|
25 | return; |
26 | }
|
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.