Hinweis: Das Forum wird geschlossen! Neue Registrierungen sind nicht mehr möglich!

 Zurück zu Pro-Linux   Foren-Übersicht   FAQ     Suchen    Mitgliederliste
IRQ Serielle Schnittstelle
Gehen Sie zu Seite 1, 2  Weiter
 
Neuen Beitrag schreiben   Auf Beitrag antworten    Pro-Linux Foren-Übersicht -> Hardware
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
macke_a
Gast





BeitragVerfasst am: 24. Aug 2007 8:26   Titel: IRQ Serielle Schnittstelle

Hallo!

Ich habe ein Problem mit meiner seriellen Schnittstelle. Es passiert relativ häufig das mein Empfangspuffer Daten erhält er diese aber nicht an mir weiter leitet!

Dabei habe ich ein zeitliches Raster von 50ms in dem ich Daten bekomme, eingestellt.

Nun kommt es vor das sich mein BS sich erst nach 300ms meldet und mir dann den gesamten Puffer übergibt. Ich muss aber die Daten im 50ms Takt auswerten!! Was kann ich dagegen machen? Soll ich die IRQ Priorität verändern? Habt Ihr ne schlaue Idee für mich!

Gruss macke_a
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 24. Aug 2007 8:36   Titel:

Ist das ein Echtzeitprozess? Wenn nein, kannst du dich nicht auf ein bestimmtes Zeitraster verlassen.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 24. Aug 2007 8:56   Titel:

Hallo Janka,
was verstehst bzw. wie definierst Du Echtzeitprozess ?
 

macke_a
Gast





BeitragVerfasst am: 24. Aug 2007 11:28   Titel:

Hallo !?

Hat denn keiner eine Idee, wie ich mein Problem des langsamen Puffers entgegen wirken kann ? Was soll man verändern, damit der Puffer sich schneller meldet?

Gruss macke_a
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 24. Aug 2007 13:17   Titel:

Ein Echtzeitprozess ist einer, der zumindest in bestimmten Anteilen unter SCHED_FIFO oder SCHED_RR läuft.

$ man sched_setscheduler

Mit der normalen Einstellung SCHED_OTHER kann der Prozess jederzeit von anderen Prozessen unterbrochen werden, da alle dieselbe Priorität haben. Nice-Level helfen nicht, da ein Prozess, der viel tut (der, der schnell sein muss), mit der Zeit immer weiter ausgebremst wird, um die anderen Prozesse mal ranzulassen. Wenn man das nicht will, muss man SCHED_FIFO oder SCHED_RR benutzen.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 27. Aug 2007 15:23   Titel:

Hallo Janka...

Dein Komentar war:
Ein Echtzeitprozess ist einer, der zumindest in bestimmten Anteilen unter SCHED_FIFO oder SCHED_RR läuft.

Ich programmiere Navigationsgerät das unter Linux arbeitet, um!
Wie bekomme ich das jetzt raus unter welchen Bedingungen der Echtzeitprozess arbeitet?
Was muss ich machen um an diese Information zu gelangen ?

Gruss macke_a
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 27. Aug 2007 21:06   Titel:

Du solltest in den Quellcode gucken. Da sollte irgendwo (hoffentlich auch entsprechend kommentiert) zumindest ein Aufruf von sched_setscheduler mit SCHED_FIFO oder SCHED_RR drin sein. Wenn nicht, muss du dir das Programm vornehmen, kapieren was es macht, evtll vorhandene Busy-Loops ausbauen und danach(!) dieses Programm um einen sched_setscheduler-Aufruf in main() ergänzen.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 28. Aug 2007 15:35   Titel:

Hallo !
Ein Aufruf von sched_setscheduler mit SCHED_FIFO oder SCHED_RR ist nicht in meinem Programm - code vorhanden!

Jetzt bleibt mir eigentlich nur noch die Möglichkeit den sched_setscheduler-Aufruf in main() selber zu verwirklichen. Oder was bleibt sonst noch an Möglichkeiten über?

Es nervt mich so langsam, das der Puffer meiner seriellen nicht schneller reagiert!
Mit Prioritäten etc.. kann ich auch keine nennenswerten Veränderungen hervorrufen?

Gruss macke_a
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 28. Aug 2007 19:48   Titel:

macke_a hat folgendes geschrieben::
Hallo !
Ein Aufruf von sched_setscheduler mit SCHED_FIFO oder SCHED_RR ist nicht in meinem Programm - code vorhanden!

Dann muss der da rein.

Zitat:

Jetzt bleibt mir eigentlich nur noch die Möglichkeit den sched_setscheduler-Aufruf in main() selber zu verwirklichen. Oder was bleibt sonst noch an Möglichkeiten über?

Da ist er zumindest am einfachsten aufgehoben. Ich hab' mal vor Jahren ein EPROM-Programmierinterface am Parallelport zusammengelötet, da war dann nur eine einzelne Funktion mit nanosleep(10ms) zwischen SCHED_FIFO und SCHED_OTHER untergebracht, um eine Zelle im EPROM zu exakt 10ms lang zu programmieren.

Zitat:

Es nervt mich so langsam, das der Puffer meiner seriellen nicht schneller reagiert!
Mit Prioritäten etc.. kann ich auch keine nennenswerten Veränderungen hervorrufen?

sched_setscheduler stellt erhöhte Prioritäten ein. Aber eben statische, keine dynamischen, wie man sie mit "nice" festlegen kann. Letztere sind nur Empfehlungen an den Scheduler, und wenn der Prozess viel tut, und der Rechner auch sonst ausgelastet ist, wird er halt dynamisch niedriger priorisiert. Selbst bei einem wenig ausgelasteten Rechner ist so eine Konstruktion immer wackelig -- Pfusch.

Wenn du eine garantierte Antwortzeit benötigst, müssen die beteiligten Prozesse SCHED_FIFO oder SCHED_RR benutzen.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 29. Aug 2007 16:08   Titel:

Hallo Janka,
ich habe die folgenden Einstellungen bei mir in der Software gemacht:

void setprio()
{ struct sched_param *sch;
sch->sched_priority = 1;

if (sched_setscheduler(0, SCHED_FIFO, sch) != 0)
{ /* Fehler */ }
}

Dieses Unterprogramm rufe ich unmittelbar nach meiner main - Routine auf. Da ich eine Navigationssystem verwende und ich dieses dementsprechend nicht mit einem "normalen PC" vergleichen kann , habe ich jetzt das Problem das mein Programm beim aufrufen gar nicht mehr funktioniert bzw. das System anfängt instabil zu werden. Ich habe den Eindruck, das dieser Programm ihm zu viel Ressourcen wegnimmt!

Was kann ich jetzt machen ?

Das sched_priority = 1 habe ich bereits auf andere Werte (-19 bis + 19) gesetzt, allerdings habe ich immer wieder das selbe Problem. Meine selbst erstellten Programme auf dem Navi funktionieren nicht mehr!

Gibt es vielleicht eine andere sanfte Methode das mein Betriebssystem nicht so beeinflußt?

Gruss macke_a
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 29. Aug 2007 16:30   Titel:

macke_a hat folgendes geschrieben::
Hallo Janka,
ich habe die folgenden Einstellungen bei mir in der Software gemacht:

void setprio()
{ struct sched_param *sch;
sch->sched_priority = 1;

if (sched_setscheduler(0, SCHED_FIFO, sch) != 0)
{ /* Fehler */ }
}

Ähem. Das muss

Code:

void setprio()
{
  struct sched_param sch;
  sch.sched_priority = 1;

  if (sched_setscheduler(0, SCHED_FIFO, &sch) != 0)
     { /* Fehler */ }
}

heißen. Dein Code erzeugt im besten Fall einen SIGSEGV, im schlechtesten überschreibt er irgendwas wichtiges. Lies dir erstmal ein Buch zu C durch!

Zitat:

Dieses Unterprogramm rufe ich unmittelbar nach meiner main - Routine auf. Da ich eine Navigationssystem verwende und ich dieses dementsprechend nicht mit einem "normalen PC" vergleichen kann , habe ich jetzt das Problem das mein Programm beim aufrufen gar nicht mehr funktioniert bzw. das System anfängt instabil zu werden. Ich habe den Eindruck, das dieser Programm ihm zu viel Ressourcen wegnimmt!
Was kann ich jetzt machen ?

Du musst das Programm hinsichtlich der Ressourcenverschwendung untersuchen! Bisher hat der Scheduler der Ressourcenverschwendung Einhalt geboten, indem er das Programm (wegen Ressourcenverschwendung) runtergewertet hat, mit statischer Priorität macht er das natürlich nicht mehr. Habe ich doch bereits oben geschrieben.

Vermutlich wird im Programm ständig ein Eingang (serielle Schnittstelle z.B.) nichtblockierend auf Daten abgefragt, ohne danach eine "Schonzeit" zu warten, in der andere Prozesse mal den Prozessor benutzen dürfen.

Wenn dein Programm so aussieht:

Code:

Scheife {
 Timer hochzählen
 Timer abgelaufen? Ja, dann raus mit Fehler
 Nichtblockierendes Lesen
} bis Daten komplett gelesen


hast du eine schöne Busy-Loop gebastelt. Die macht das System immer langsam. So muss das aussehen:

Code:

Schleife {
 select(Eingabegerät, Timer) abgelaufen? Ja, dann raus mit Fehler.
 Nichtblockierendes Lesen
} bis Daten komplett gelesen

Dann kann der Kernel, während der Prozess im select() wartet, den Prozessor einem anderen Prozess zuteilen.

$ man select
$ man poll

Zitat:

Das sched_priority = 1 habe ich bereits auf andere Werte (-19 bis + 19)

Ähm. Du liest dir Manpages aber auch mal durch? Da steht eindeutig drin, dass Werte zwischen 0 und 99 erlaubt sind.

Zitat:

Gibt es vielleicht eine andere sanfte Methode das mein Betriebssystem nicht so beeinflußt?

Wenn dein Programm wackelig steht, ist es Unsinn, ein Haus drumrumzubauen, damit der Wind es nicht umpustet. Spätestens wenn jemand ein Fester aufmacht (sic!), fällt das Ding um.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 01. Sep 2007 11:28   Titel:

Hallo Janka...
Diesen Programmteil habe ich jetzt mit eingebunden:

Code:
void setprio()
{
  struct sched_param sch;
  sch.sched_priority = 1;

  if (sched_setscheduler(0, SCHED_FIFO, &sch) != 0)
     { /* Fehler */ }
}


Die Folge ist ein Absturz des Navi. Es erfolgt ein Software Reset nach Aufruf meines Programms.

Die Abfrage meines seriellen Schnittstelle erfolgt mittels

Code:
Schleife {
 select(Eingabegerät, Timer) abgelaufen? Ja, dann raus mit Fehler.
 Nichtblockierendes Lesen
} bis Daten komplett gelesen


Der Timer steht auf 0 Sekunden Warte Zeit, d.h. nach dem Überprüfen aller spezifizierten Filedeskriptoren kehrt select sofort wieder zurück.
Der "select Code Teil" läuft in einer while(1) Schleife...
Vermutlich wird das ein Problem sein..??? Ich habe das aber extra gemacht, da meine empfangenden Daten in einem Zyklus von 10 - 50ms Sekunden kommen.
Ich will bzw. ich muss die Daten so schnell wie möglich auswerten!!

Ich glaube da könnte meine Probleme? Was meinst Du Janka ?

Gruss macke_a

Ach und erstmal besten Dank für Deine Mithilfe!!! Es mag zwar etwas schwierig mit mir sein, aber wenn man mit einem Linux BS noch nie umgegangen ist, braucht man jede Menge Starthilfe. Bücher sind Theorie, die Praxis ist dann doch anders!


[/code]
 

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 02. Sep 2007 8:41   Titel:

Da liegt das Problem. Wenn du select sagst, es soll nicht warten, hast du eine busyloop. Bei SCHED_OTHER wird dein Prozess dadurch automatisch immer weiter runtergewertet. Du wirst dadurch also nicht schneller, sondern langsamer. Bei SCHED_FIFO kann mit so einer busyloop kein anderer Prozess mit normaler Priorität mehr arbeiten und der Rechner "steht". (Der Kernel und dein Prozess laufen aber noch). => Stell bei select() die tatsächliche Timeout-Zeit ein, also irgendwas *über* 50ms. Wenn die Daten früher anliegen, kommt auch select() früher zurück.


Du kannst dir auch eine Shell über einen Wrapper mit SCHED_FIFO noch etwas höher priorisieren als deinen Testprozess (danach execve("/bin/sh")), dann kannst du den Testprozess mithilfe dieser Shell abbrechen. Die Shell verhält sich bei SCHED_FIFO ordentlich, hat keine busyloops. Wie gehst du an das Gerät ran? Serielle Konsole oder Netzwerk? Im letzteren Fall muss du auch noch den sshd (oder telnetd etc) auf dem Gerät höher priorisieren, damit du es noch bedienen kannst, wenn dein Prozess Mist baut.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

macke_a
Gast





BeitragVerfasst am: 03. Sep 2007 10:28   Titel:

Hallo Janka,

danke für die Info.

Ich arbeite jetzt mit einem Intervall von 100ms für den select Aufruf.
Jetzt habe ich noch ein weiteres anliegen.

Den select Aufruf habe ich in einer while Schliefe laufen. Ist das in Ordnung?
Oder wäre es besser einen Timer zu definieren, denn ich alle 100ms aufrufe?

Was ist Deine Meinung? Wie programmier ich dies am besten?

Ausschnitt while Schleife / Timer

Code:
      wait.tv_sec  = 0;
      wait.tv_usec = 10000;                                          
                                                          
      FD_SET(fd1,&rt);                                        
      FD_SET(fd2,&wt);
      select(fd1 + fd2 1,&rt,&wt,NULL,&wait);   
      if(FD_ISSET(fd1i,&rt)) { InitPipe(); }            
      if(FD_ISSET(fd2,&wt)) { }      


Nochmals Vielen Dank für Deine Mithilfe!!

Gruss macke_a
 

macke_a
Gast





BeitragVerfasst am: 03. Sep 2007 10:30   Titel:

Sorry, kleiner Druckfehler

wait.tv_usec = 100000;

if(FD_ISSET(fd1,&rt)) { InitPipe(); }
 

Beiträge vom vorherigen Thema anzeigen:   
     Pro-Linux Foren-Übersicht -> Hardware Alle Zeiten sind GMT + 1 Stunde
Gehen Sie zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehen Sie zu:  

Powered by phpBB © phpBB Group
pro_linux Theme © 2004 by Mandaxy