Forum: Mikrocontroller und Digitale Elektronik Mico32 Uart ISR Problem


von Bernhard (Gast)


Lesenswert?

Hallo,
ich habe ein Problem mit der ISR eines Uarts im Mico32. Ich möchte über 
den Uart interruptgesteuert Daten empfangen. Die Baudrate beträgt 
250kBd. Ich habe im MSB den Uart hinzugefügt und konfiguriert.
Im main.c habe ich folgendes hinzugefügt:
1
const char *const dmx_in2_INSTANCE_NAME = "dmx_in2";
2
MicoUartCtx_t *DMX_IN2 = (MicoUartCtx_t *)MicoGetDevice(dmx_in2_INSTANCE_NAME);
3
MicoRegisterISR(DMX_IN2->intrLevel, DMX_IN2, myUART_ISR);
4
*((volatile unsigned char *)((DMX_IN2->base)+4)) = 0x01;
und die ISR folgendermaßen:
1
static void myUART_ISR( int intrLevel, void * data )
2
{
3
  MicoUartCtx_t *DMX_IN2 = (MicoUartCtx_t *)MicoGetDevice(dmx_in2_INSTANCE_NAME);
4
  unsigned long uart_char;  
5
  unsigned long  *uart_address_pointer;       
6
  uart_address_pointer = (DMX_IN2->base) ; // UART Receive Buffer    
7
  uart_char = *uart_address_pointer;      // Read received data
8
9
  lcd_string(0,1,"in ISR geschrieben");
10
11
  uart_address_pointer = (DMX_IN2->base) + 8; // offset or UART IIR = 0x8            
12
  uart_char = *uart_address_pointer;         // reading IIR clears all UART interrups          
13
14
return;
15
}
Da ich mir in der ISR den Text "in ISR geschrieben" auf ein LCD 
schreiben lasse, bin ich sicher, dass der Interrupt zwar aufgerufen aber 
nicht mehr verlassen wird, das Programm bleibt stehen.
Hat vielleicht jemand eine Idee woran das liegen könnte?

Vielen Dank
Bernhard

von Won K. (Firma: Outside the Asylum) (the_sane)


Lesenswert?

Kann es sein, daß während gemütlich aufs LCD geschrieben wird, die 
nächsten Daten ankommen und die ISR erneut aufrufen?

von Bernhard (Gast)


Lesenswert?

Won K. schrieb:
> Kann es sein, daß während gemütlich aufs LCD geschrieben wird, die
> nächsten Daten ankommen und die ISR erneut aufrufen?

Natürlich, diese Zeile ist nur zum Testen dazugekommen, so kann ich 
sicher sein, dass ich überhaupt in die ISR komme. Ursprünglich habe ich 
nicht in das Display geschrieben, da habe ich nur gesehen, dass das 
Programm stehen geblieben ist.

von Bernhard (Gast)


Lesenswert?

Kurzes Update,
so wie es aussieht, bleibt das Programm nicht einfach stehen, sondern 
durchläuft permanent die ISR.
Getestet habe ich folgendermaßen:
Ich schreibe in der ISR auf das LCD zuerst "in ISR geschrieben" und 
gleich darauf an die selbe Stelle "1111111111111111".
Somit sollten nach einmaligen Durchlauf der ISR die Einser im Display 
stehen bleiben. Nur sehe ich ein permanentes neuschreiben zwischen den 
beiden Texten. Dies bedeutet, dass die ISR permanent durchlaufen wird 
obwohl ich mit einem externen Gerät nur ein Byte sende, somit die ISR 
nur einmal durchlaufen werden sollte.
Kann es sein, dass das Löschen des Interruptflags mit
1
  uart_address_pointer = (DMX_IN2->base) + 8; // offset or UART IIR = 0x8            
2
  uart_char = *uart_address_pointer;         // reading IIR clears all UART interrups

nicht korrekt ist?

LG
Bernhard

von statistik (Gast)


Lesenswert?

Wo wird das Interruptflag gelöscht?

von Bernhard (Gast)


Lesenswert?

Laut Datenblatt des Mico32 Uarts wird der Interrupt mit
1
 uart_address_pointer = (DMX_IN2->base) + 8; // offset ror UART IIR = 0x8            
2
  uart_char = *uart_address_pointer;         // reading IIR clears all UART interrups
gelöscht
"The THRE interrupt is cleared by either reading the IIR register or 
writing to the THR FIFO in FIFO mode or THR register in non-FIFO mode."

und das IIR Register liegt an der Base - Adr  + 0x08 des Uarts.

von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Moin,

ggf. werden die Zugriffe auf uart_address_pointer wegoptimiert. Mach 
uart_char und uart_address_pointer mal volatile.

Schau dir mal das erzeugte Assembler-Listing an oder nimm einen 
Debugger, da müsste man deutlich sehen können ob das Register gelesen 
wird oder nicht.

Sebastian

von Bernhard (Gast)


Lesenswert?

Sebastian B. schrieb:
> ggf. werden die Zugriffe auf uart_address_pointer wegoptimiert. Mach
> uart_char und uart_address_pointer mal volatile.

Super, das wars!
Danke

von Bernhard (Gast)


Lesenswert?

Hallo,
nachdem das Löschen des Interrupts nun funktioniert, stehe ich leider 
bereits vor dem nächsten Problem.
Für die Datensynchronisation möchte ich auf den Break Interrupt 
überprüfen, folgender Auszug aus dem Datenblatt:

"Break interrupt. BI is set to logic 1 whenever SIN is low for longer 
than a whole data frame (the time of start bit + data bits
+ parity bit + stop bits). If SIN is still low after BI is reset to 
logic 0 by reading LSR, BI is not set to logic 1 again. Since
break is also a framing error, FE is also set to 1 when BI is set."

Das BI Bit ist das 5. Bit im Line Status Register (LSR), dieses Register 
hat die Adresse  + 0x14.
Somit sollte ich doch mit
1
  uart_address_pointer = (DMX_IN2->base) + 0x14; // offset fuer Line Status Register
2
  if (*uart_address_pointer & 0x10)    // break erkannt
3
  {
4
5
  }
Zugriff auf dieses Register haben. Leider steht in dem Register immer 
0xFF. Somit ist die Überprüfung immer true.
Habe ich da irgendetwas übersehen?

Danke
Bernhard

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
Noch kein Account? Hier anmelden.