UART zwei mal ausgelöst nach Interrupt?

Gast #7090781
Lesenswert?

Hallo guten Tag,

warum wird mein UART-Interrupt zwei mal ausgelöst wenn ich etwas 
eintippe und Enter drücke? Der Buffer hat dann einmal den ersten 
Buchstaben und einmal den Rest.

Mein Programm soll bei scanfx in eine while(1) Schleife gehen bis eine 
Eingabe erfolgt und ein Empfang-Flag auf 1 setzt.
1
cmd0
2
cmd1
3
scanfx -> while(1)  <-- Eingabe durch Interrupt
4
nutze das eingelesene
5
cmd2
6
cmdn
7
scanfx -> while(1)  <-- Eingabe durch Interrupt

Was mir aufgefallen ist:
Wenn ich in der while-Schleife bin, etwas eintippte und enter drücke 
wird meine Interrupt Funktion 2 mal hintereinander aufgerufen..

Wenn ich eingebe: "test"
wird zuerst das "t" als Eingabe verwendet.
direkt danach scheint die Funtkion nochmal "est" zu erhalten.
Das sehe ich auch an der Ausgabe von "est" und "t"...


hier setze ich den handler:
1
  MSS_UART_set_rx_handler(&g_mss_uart0, uart3_rx_handler, MSS_UART_FIFO_SINGLE_BYTE);

Hier ist der interrupt handler:
1
 
2
g_rx_buff  =  buffer
3
this_uart = mein gewählter UART port

1
void uart3_rx_handler(mss_uart_instance_t *this_uart)
2
{
3
  unsigned int rx_size = MSS_UART_get_rx(this_uart, g_rx_buff, sizeof(g_rx_buff) );
4
  
5
  printf("\n------------------------- [UART RX HANDLER]");
6
  uart_calls_cnt++;
7
  printf("\n-call cnt: %d", uart_calls_cnt);
8
  printf("\n * Size RX char: %d", rx_size);
9
  printf("\n *Your input: ");
10
  printf("  [I]%s[/I]", (char *)g_rx_buff);
11
  uart_handler_flag = 1;
Gast #7090801
Lesenswert?

Aber wenn ich dann "test" eingebe,

 dann wird direkt das "t" erkannt und der Interrupt ausgelöst?
Wird dabei "est" reingeschrieben und dann ebenfalls ein weiterer 
interrupt auslöst?

Will ja nur dass er test komplett einliest.
liegt das "MSS_UART_FIFO_SINGLE_BYTE" ?
Dass der da schon interrupted?

scanfx soll nur eine Ersatz sein für while(1)

So sieht die etwa aus:
1
int flag = 0; // global
2

3
bool scanfx(){
4

5
while(1) { 
6

7
if  ( flag== 1) {
8
return true}
9
else{}
10
}
11
}

DerEinzigeBernd schrieb:
> Du rufst printf IM Interrupt-Handler auf.

Warum? weil diese Funktion viel Zeit kostet?
Ist das ok für einen ersten Debug?
Gast #7090805
Lesenswert?

Ein paar weitere Salamiescheiben werden hilfreich.

Was für einen Microcontroller benutzt du, was für eine API ist das 
MSS_*...

Wo tippst du eine? Auf dem PC mittels Terminal.

Läuft das dann über ein USB-UART-Adapter?


Schickt deine Terminal-Anwendung den Text Zeichenweise raus, oder erst 
wenn Enter gedrückt wird? Aus deiner Beobachtung vermute ich letzteres.

Des weiteren gehe ich davon aus das du einen USB-UART Adapter benutzt.
USB ist paketorientiert und hat auf PC Seite einen Input Buffer.

Deine Terminal Anwendung schickt den gesamten String in einem Rutsch in 
den USB-Input Buffer. Sobald da das erste Zeichen rein kommt, wird 
bereits das erste USB-Packet abgesendet, und der Adapter schickt das 
erste Zeichen aus. [Dein erster Interrupt auf deinem Microkontroller]

Die Restlichen Zeichen liegen im USB-Input Buffer, und werden im 
nächsten USB-Packet an den Adapter gesendet. der dann die Zeichen ohne 
weitere Pause per UART aussendet. [2. Interrupt, bis du den Buffer 
ausliest, sind bereits die restlichen Zeichen angekommen]

USB-Pakete haben ein Timing von 1ms. Da kannst du nichts ändern.
Moderator (Firma: Titel) Persönliche Seite #7090826
Lesenswert?

Bergsfrau schrieb:
> Will ja nur dass er test komplett einliest.
Naja, ein wenig musst du schon noch selber machen. Das nennt sich 
programmieren. Du musst den Strin einlesen, bis du (d)ein 
Terminierungszeichen erkennst (z.B. CR/LF), und kannst dann den 
empfangenen String parsen.

Allein mit "ich will" kommst du nicht ans Ziel.

C.K. schrieb:
> Was für einen Microcontroller benutzt du, was für eine API ist das
Ein SmartFusion FPGA (aka Actel):

https://www.eejournal.com/article/microchip-microsemi-and-atmel-and-actel/

https://www.microsemi.com/product-directory/soc-fpgas/1693-smartfusion

https://www.microchip.com/en-us/products/fpgas-and-plds/system-on-chip-fpgas/smartfusion-2-fpgas

C.K. schrieb:
> Salamiescheiben
Wiederstand gegen die übermäßiege Verwendung des -ie-!   ;-)
Gast #7090850
Lesenswert?

Bergsfrau schrieb:
> DerEinzigeBernd schrieb:
>> Du rufst printf IM Interrupt-Handler auf.
>
> Warum? weil diese Funktion viel Zeit kostet?

Sieh mal, wie viele einzelne Zeichen Du hier für jeden einzelnen 
Interrupt-Aufruf ausgibst:

>   printf("\n------------------------- [UART RX HANDLER]");
>   uart_calls_cnt++;
>   printf("\n-call cnt: %d", uart_calls_cnt);
>   printf("\n * Size RX char: %d", rx_size);
>   printf("\n *Your input: ");
>   printf("  [I]%s[/I]", (char *)g_rx_buff);


Selbst wenn diese printf()-Aufrufe nicht blockieren (d.h. erst 
zurückkehren, bis sie alles ausgegeben haben), dauert die ISR ziemlich 
lange. Es kann also sein, daß beim Einlaufen des nächsten Zeichens bei 
der UART die ISR noch nicht beendet ist, und direkt der nächste 
Interrupt ausgelöst wird.

Und wenn die Aufrufe blockieren (weil Deine Umgebung keinen 
interruptgesteuerten Ausgabehandler mit ausreichend großem Sendepuffer 
hat), dann geht richtig viel Zeit in der ISR drauf; sofern die 
UART-Hardware nicht mehrere empfangene Bytes puffern kann, gehen diese 
unweigerlich verloren.

Also: Nein, das ist auch für "ein erstes Debug" eine ganz schlechte 
Idee.
Gast #7092891
Lesenswert?

Lothar M. schrieb:
> Naja, ein wenig musst du schon noch selber machen. Das nennt sich
> programmieren. Du musst den Strin einlesen, bis du (d)ein
> Terminierungszeichen erkennst (z.B. CR/LF), und kannst dann den
> empfangenen String parsen.

Ok, also wenn ein Interrupt geschieht werde ich mal alle vorhandenen 
Zeichen einlesen.
Die Anzahl der einzulesenden Zeichen werde ich aus dem Rückgabewert von 
MSS_UART_get_rx nehmen.
Bei jedem Element was ich reinschreibe werde ich vergleichen ob '\n' 
vorhanden ist.
Wenn ja ist das das Ende des Strings und ich kann ihn verwenden.

Wenn ein Interrupt kommt stehen die Daten ab Index 0 im Buffer.
Ich muss diese dann an die bereits ausgelesenen Daten anhängen.
Dafür muss die vorherige Position bekannt sein.
1
for ( int i= 0 ; i < (int) rx_size ; i ++){
2
command[index] <= g_rx_buff[i]
3
}
4
index += (int) rx_size;


Udo S. schrieb:
> Wahrscheinlich sind nach der 1. IRQ-Behandlung alle restlichen Zeichen
> schon eingegangen und zum Glück gepuffert worden. Folge der viel zu
> langsamen printf Aufrufe.

Wenn ich printf weglasse geschieht das gleiche.

Wenn ich einen Breakpoint in die ISR setze ist einmal 't' drin und 
einmal 'e' 's' 't' '\n'
Gast #7092894
Lesenswert?

Grade am testen:
Es scheint echt besser zu laufen :D
1
unsigned int rx_size = MSS_UART_get_rx(this_uart, g_rx_buff, sizeof(g_rx_buff));
2
  (void)rx_size;
3

4
  uart_calls_cnt++;
5

6
  uart_handler_flag = 0;
7

8

9
  for (int i = 0; i < (int)rx_size; i++) {
10
    if (g_rx_buff[i] != '\n') {
11
      command[index_uart_read_out_cnt + i]   = g_rx_buff[i];
12
      value_str[index_uart_read_out_cnt + i] = g_rx_buff[i];
13
    } else {
14
      // END OF STRING
15

16
      break;
17
    }
18
  }
19
  // IF END OF STRING:
20
  if (strchr((char *)g_rx_buff, '\n') != NULL) {
21
    memset(&g_rx_buff[0], 0, 128); // clear rx buffer
22
    uart_handler_flag       = 1;   // so the while(1) loop @ scanf () will break and programm will proceed
23
    index_uart_read_out_cnt = 0;
24

25
  } else {
26
    index_uart_read_out_cnt += (int)rx_size;
27
  }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren