mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RTOS Ethernet


Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hab mich grad mal mit freeRTOS eingearbeitet. Momentan scheint es so, 
dass dieses OS einen relativ großen Overhead besitzt, so dass bei einem 
AT91SAM9263 die Ethernet Packete nicht mehr in der passenden Zeit 
abgearbeitet werden können.

Bei einer Datenrate von 6MBit/s läuft alles gut, aber bei einer 
Datenrate von 20MBit/s bekomm ich Buffer-Not-Available Interrupts. Diese 
Fehlermeldungen treten bereits nach sehr kurzer Zeit auf (< 1s). Der 
Task wird genau wie in den Beispielanwendungen über eine Semaphore 
informiert, dass ein neues Pkt angekommen ist. Beim Aufruf 
(xSemaphoreGiveFromISR) in der ISR hab ich auch sehr viele Anfragen, die 
angeben, dass die Queue bereits voll ist. Auch varriert die Anzahl der 
Aufrufe der ISR von den Aufrufen des eigentlichen Tasks (hier sind es 
nämlich einige weniger, was auch die BNA-Fehler erklärt).

Die ankommenden Pakete werden zur Zeit nur gesucht und anschlíeßend 
sofort wieder gelöscht, so dass die DMA wieder Zugriff darauf hat. Es 
finden also keine TCP/IP Stack Operationen statt. Ohne RTOS läuft dieser 
Code einwandfrei.

Als ganz minimalistisches Beispiel hab ich einfach mal im Ethernet-Task 
bei jedem ankommenden Pkt alle zur Verfügung stehenden Buffer 
gelöscht... dann bekomm ich zwar keine Buffer-Not-Available 
Fehlermeldungen, aber die  Queue (xSemaphoreGiveFromISR) wird trotzdem 
ab und zu als voll angezeigt.

Hat hier jmd schon andere (bessere) Erfahrungen sammeln können mit 
freeRTOS? Gibt es andere RTOS die schneller sind?

Gruß
Bernd

Autor: PimpIt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Kern wird schon laufen, ich denke ungesehen der Treiber ist zu lahm 
und eigentlich auch nicht Teil des Kerns. Ich würde mal sagen: Treiber 
optimieren ;-)

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit Treiber meinst du wahrscheinlich meinen hinzugefügten Code: Hier ist 
die komplette Task


low_level_input() function:
if( xRxSemaphore == NULL )
   vSemaphoreCreateBinary( xRxSemaphore );

/* Access to the emac is guarded using a semaphore. */
if( xSemaphoreTake( xRxSemaphore, netifGUARD_BLOCK_TIME ) )
{
    j = StartSearch; 
    /* find start SOF */
    while(((Emac_RxBufDesc[j].status & EMAC_RXBUF_SOF_MASK) == 0) || 
  ((Emac_RxBufDesc[j].address & EMAC_RXBUF_SW_OWNED) == 0))
    {
  j++; 
  if(j >= EMAC_RX_N_BUFS)
  j=0; 
    }

    Startbuf = j; 
    /* find EOF */
    while(((Emac_RxBufDesc[j].status & EMAC_RXBUF_EOF_MASK) == 0) || 
  ((Emac_RxBufDesc[j].address & EMAC_RXBUF_SW_OWNED) == 0))
    {      
  j++; 
  if(j >= EMAC_RX_N_BUFS)
  j=0; 

    }

     Endbuf = j; 
     StartSearch = Endbuf + 1; 
     if(StartSearch >= EMAC_RX_N_BUFS)
         StartSearch = 0; 
    
     /* delete all used buffers */
     j = Startbuf; 
     for(i=0; i<12; i++)
     {
        Emac_RxBufDesc[j].address &= ~EMAC_RXBUF_SW_OWNED;
        if(j == Endbuf)
          break;
   
       j++;
       if(j >= EMAC_RX_N_BUFS)
       j=0; 
     }

     xSemaphoreGive( xRxSemaphore );

     return(pbuf); /* da nicht definiert == NULL */
}


Diese Funktion wird wie in den mitgelieferten Beispieln aufgerufen:
for( ;; )
{
   do
   {
    /* move received packet into a new pbuf */
   pbuf = low_level_input( );

   if( pbuf == NULL )
   {
     /* No packet could be read.  Wait a for an interrupt to tell us 
     there is more data available. */
     vEmac_WaitForInput();
    }

    } while( pbuf == NULL );
}

Gruß
Bernd

Autor: PimpIt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha,

kannst du mal dein xSemaphoreGive( xRxSemaphore ); entfernen ? Das wäre 
dann schon der erste Fehler.

Wer blockt denn in der Task den Emac_RxBufDesc vor dem Interrupt ? Ich 
kenn den Aufbau jetzt nicht, sieht aber nach einem Ringbuffer aus der 
vom Interrupt/DMA geschrieben und von der Task gelesen werden soll !?

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in der Task wird hier auf das Semaphore gewartet:
void vEmac_WaitForInput( void )
{
/* Just wait until we are signled from an ISR that data is available, or
   we simply time out. */
   xSemaphoreTake( xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT );
}

In der ISR dazu wird, falls ein Pkt received worden ist, dem Task 
signalisiert, dass es was zum arbeiten gibt
xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, pdFALSE );

>kannst du mal dein xSemaphoreGive( xRxSemaphore ); entfernen ? Das wäre
>dann schon der erste Fehler.
ich dachte für den Zugriff auf den Emac holt man sich zuerst eine 
Semaphore und am Schluss gibt man diese wieder zurück, damit diese 
Ressource wieder vorhanden ist.

In der Init für den Emac gibt man der DMA den ersten Buffer bekannt.
typedef struct
{
  unsigned int address;    // receive buffer address
  unsigned int status;    // status
} EMAC_RXBUF_HDR;
Der letzte Buffer im "Buffer-Array" besitzt ein ein Flag, welches 
angibt, dass jetzt weider im ersten Buffer gespeichert werden muss, 
falls dieser frei ist für die DMA.

Gruß
Bernd

Autor: PimpIt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du lässt dir über xSemaphore vom Interrupt den Empfang signalisieren ? 
Rufst du nach

xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, pdFALSE );

Auch diese yieldWasWeissIch Funktion auf ?

> ich dachte für den Zugriff auf den Emac holt man sich zuerst eine
> Semaphore und am Schluss gibt man diese wieder zurück, damit diese
> Ressource wieder vorhanden ist.

Wo wird denn xRxSemaphore abgefragt/geblockt ? Die DMA sollte ja einfach 
in den Speicher blasen ohne auf sowas zu achten !? Dann hättest du 
Probleme mit Overflows und wenn du die DMA blockst dann mit Underflows, 
wenn die Task zu lahm ist.

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Auch diese yieldWasWeissIch Funktion auf ?
das müsste diese sein, die ganz zum schluss von der isr aufgerufen wird.
if( xSwitchRequired )
{
   portYIELD_FROM_ISR();
}

>Wo wird denn xRxSemaphore abgefragt/geblockt
hab mir gad nochmal ein anderes beispiel angeschaut, und die haben diese 
xRxSemaphoren-Geschichte auch nicht dabei; hab es jetzt komplett 
weggelassen, leider aber noch ohne Erfolg.

Autor: PimpIt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergrößer einfach mal das EMAC_RX_N_BUFS !?

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
momentan ist EMAC_RX_N_BUFS = 150 -> jeder dieser Buffer beinhaltet 
128Byte (entspricht einem DMA-Transport).

Nachdem der Fehler sehr schnell kommt (weniger als 1sec), wird eine 
Vergrößerung nichts bringen; zumal ohne RTOS es ja einwandfrei läuft.

Gruß
Bernd

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaub nicht, dass es an meinem Code liegt, sondern eher, dass bei 
der Portierung von einem SAM7 (beispieldateien von freeRTOS) auf einen 
SAM9 irgendetwas innerhalb des Kernels verändert werden muss.

Beim Durchsuchen der portable.h und portmacro.h sind mir aber keine 
großartigen Eingriffe die verschieden wären, aufgefallen.

Der Instruction-Cache ist auch enabled und funktioniert (hab es ohne 
diesem probiert, und der Prozessor arbeitet um einiges langsamer...).

Gruß
Bernd

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich dachte für den Zugriff auf den Emac holt man sich
> zuerst eine Semaphore und am Schluss gibt man diese
> wieder zurück, damit diese Ressource wieder vorhanden ist.

Das ist eine Möglichkeit, ein Semaphor zu verwenden.

Eine andere ist, einer Task ein Signal zu geben, dass es eine Aufgabe zu 
erledigen gibt. Wird gerne eingesetzt, wenn der Signalgeber eine 
Interrupt-Serviceroutine ist, die schnell das Allernötigste erledigt und 
die längere Auswertung einer Task überlässt.

Das "Verriegeln" des Emac gegen konkurrierende Zugriffe kann trotzdem 
erforderlich sein. Es kann dann aber nicht mit demselben Semaphor 
erledigt werden.

Näheres über Semaphore hier: 
http://de.wikipedia.org/wiki/Semaphor_(Informatik)

Übrigens heißt es "der" oder "das Semaphor".

> ich glaub nicht, dass es an meinem Code liegt, sondern eher,
> dass bei der Portierung von einem SAM7 (beispieldateien von
> freeRTOS) auf einen SAM9 irgendetwas innerhalb des Kernels
> verändert werden muss.

Dann bau doch erst mal ein einfacheres FreeRTOS-Beispiel, das dir zeigt, 
ob der Kernel prinzipiell läuft. Damit kannst du dann auch die 
Semaphor-Mechanismen studieren.

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eine andere ist, einer Task ein Signal zu geben, dass es eine Aufgabe zu
>erledigen gibt. Wird gerne eingesetzt, wenn der Signalgeber eine
>Interrupt-Serviceroutine ist, die schnell das Allernötigste erledigt und
>die längere Auswertung einer Task überlässt.

unter welchem Begriff / Namen fällt diese Art einem Task zu 
signalisieren, dass es eine Aufgabe gibt?


>Dann bau doch erst mal ein einfacheres FreeRTOS-Beispiel, das dir zeigt,
>ob der Kernel prinzipiell läuft. Damit kannst du dann auch die
>Semaphor-Mechanismen studieren.

Das RTOS funktioniert ja prinzipiell - auch die Übergabe mit der 
Semaphore - allerdings ist beides zu langsam... Hab auch gelesen, dass 
man das Semaphor bei einer ISR nicht mehr zurückgeben muss...

Gruß
Bernd

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.