www.mikrocontroller.net

Forum: Compiler & IDEs [AVR32] NGW100 - ttyS0 mit select() -> FD_SET Segmentation fault


Autor: Uwe D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

habe folgendes Problem mit meinem Programm auf dem Atmel NGW100!

Ich kompiliere mein Programm mit "avr32-linux-g++ test.cpp -o test", 
wenn ich es auf dem NGW100 ausführe, bekomme ich ein 'Segemntation 
fault'.

Fehler
- steigt definitiv immer in Funktion main() bei 'FD_SET(fd, &read)' aus!

Fakten
- Quellcode läuft unter Ubuntu 9.10 wunderbar
- ist egal ob mit '-static' oder ohne kompiliert (mit avr32-linux-g++)
- Schnittstelle /dev/ttyS0 ist definitiv die richtige

Folgendes hab ich mal ausprobiert:

- wenn ich mir mal den Integer-Wert von 'fd' ausgeben lasse, bekomme ich 
bei meinem Ubuntu: fd = 3, auf dem Atmel: fd = 716345196 angezeigt, kann 
das sein?

Die Schnittstelle /dev/ttyS0 die ich nutzen will, wird ja Standardmäßig 
vom Bootloader und von der Linux-Konsole zur Ausgabe benutzt. Die 
Linux-Konsole habe ich für die serielle Ausgabe abgeschaltet (in 
/etc/inittab).
Sobald jetzt die Konsole angezeigt wird, kommt auf dem Hyperterminal - 
wie gewollt - kein Pups mehr an.

Muss ich denn vielleicht auch den Zugriff vom Bootloader ausschalten? 
Aber komme ich denn jemals wieder an den Bootloader ran?

Mein NGW100 läuft mit buildroot-2.3.0 von einer SD-Karte.


Hier mal mein Code, die Funktion zum auslesen von Daten an ttyS0, habe 
ich rausgenommen, weil er steigt ja eh vorher aus!
#include <stdio.h>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <iostream>
#include <fstream>    
#include <sys/select.h>

using namespace std;

int open_input_source(int);
int read_input_source(int, int);

int main() {
   int      fd;       // Var für Port
   fd_set   readfs;     // file desciptor für select-Subroutine
   int      loop=1;
   int      res, errorNpb = 0;
   struct   timeval Timeout;   // Konstrukt für Time-Out der select-Subroutine
   int      port=0;     // Port-Auswahl --> hier /dev/ttyS0

   ofstream npbLogFile("FILE_OUT.LOG",ios_base::trunc);
   if (npbLogFile.fail()) {
      cout << "\nFehler! Log-Datei konnte nicht erzeugt werden!\n" <<
        "Programmabruch!\n";
      exit(1);
   }
   npbLogFile.close();

   ofstream npbOutFile("FILE_OUT.001",ios_base::trunc);
   if (npbLogFile.fail()) {
      
      cout << "Programmabruch!\n";
      
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
      npbLogFile  << "time" << " Programmabruch!\n";
      npbLogFile.close();
      
      exit(1);
   }
   npbOutFile.close();


   /* Serielle Schnittstelle öffnen & konfigurieren */
   fd = open_input_source(port);
   
   /* Schleife zum einlesen von Daten an der Schnittstelle */
   while (loop) {
      

      Timeout.tv_usec = 0;   // Millisekunden
      Timeout.tv_sec  = 3;   // Sekungen

      /* Zeitstempel (YYYYMMDDHHMMSS) für LOG-Datei-Werte erzeugen und in Sting 'strTimestamp' ablegen */
      time_t Zeitstempel;
      struct tm *ltime;
      char strTimestamp[15];
      Zeitstempel = time(0);
      ltime = localtime(&Zeitstempel);
      strftime(strTimestamp, 15, "%Y%m%d%H%M%S", ltime);

      FD_ZERO(&readfs);     // geht
      FD_SET(fd, &readfs);   // <-- Segmentation fault
      
      res = select(fd+1, &readfs, NULL, NULL, &Timeout);

      if (res == 0) {
   cout       << "\nZeitüberschreitung! Keine Input-Daten an seriellen Port /dev/ttyS" << port << 
      " vorhanden!\n";
   
   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
   npbLogFile  << strTimestamp << " Zeitüberschreitung! Keine Input-Daten an seriellen Port /dev/ttyS" 
         << port << " vorhanden!\n";
   npbLogFile.close();
}

      if (FD_ISSET(fd, &readfs)) {
   errorNpb = read_input_source(fd, errorNpb);
                    
   if (errorNpb = 0)
      sleep(10);
   else if (errorNpb > 3) {
      cout << "\nFehler beim einlesenen!\n";

      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
      npbLogFile  << strTimestamp << " Fehler beim einlesenen!\n";
      npbLogFile.close();
   }   
      }
   }

   close(fd);    // serielle Schnittstelle schließen
   return 0;
}

/***********************************************************************************/
/* Funktion zum einlesen der Daten hab ich raus genommen, soweit kommt er ja nicht */
/***********************************************************************************/


int open_input_source(int port) {
   int fd;
   struct termios options;

   /* Zeitstempel (YYYYMMDDHHMMSS) für LOG-Datei-Werte erzeugen und in Sting 'strTimestamp' ablegen */
   time_t Zeitstempel;
   struct tm *ltime;
   char strTimestamp[15];
   Zeitstempel = time(0);
   ltime = localtime(&Zeitstempel);
   strftime(strTimestamp, 15, "%Y%m%d%H%M%S", ltime);
   
   /* seriellen Port öffnen */
   switch (port) {
      case 0: fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); break;
      case 1: fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY); break;
      case 2: fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY | O_NDELAY); break;
      case 3: fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_NDELAY); break;
   }
   
   /* wenn serieller Port nicht geöffnet werden konnte, dann Fehlermeldung, Log-Datei-Ausgabe und Programmabruch! */
   if (fd == -1) {
      cout    << "\nFehler! Programmabruch!\n";

      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
      npbLogFile  << strTimestamp << " Fehler! Programmabruch!\n";
      npbLogFile.close();
      exit(1);
   }
   
   /* wenn serieller Port geöffnet, dann Port konfigurieren */  
   else if (fd >= 0) {
      fcntl(fd, F_SETFL, 0);
      

      if (tcgetattr(fd, &options) != 0) {
   cout      << "\nFehler! Programmabruch!\n";

   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
   npbLogFile << strTimestamp << " Fehler! Programmabruch!\n";
   npbLogFile.close();

   exit(1);
      }
 
      cfsetspeed(&options, B9600);       // Geschwindigkeit: 9600 Baud
      options.c_cflag &= ~PARENB;       // kein Paritybit
      options.c_cflag &= ~CSTOPB;       // 1 Stopbit
      options.c_cflag &= ~CSIZE;       
      options.c_cflag |= CS8;         // 8 Datenbits
      options.c_cflag |= (CLOCAL | CREAD);   // CD-Signal ignorieren
      options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);   // nicht Zeilenbasiert, kein Echo, keine Steuerzeichen, 
                  // keine Interrupts
      options.c_oflag &= ~OPOST;       // Setze RAW-Output  
      options.c_cc[VMIN] = 0;         // Warten auf min. 0 Zeichen beim lesen
      options.c_cc[VTIME] = 0;         // Timeout beim lesen "read()" nicht setzen
      

      tcflush(fd, TCIOFLUSH);

      if (tcsetattr(fd, TCSAFLUSH, &options) != 0) {
   cout       << "\nFehler! Programmabruch!\n";

   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
   npbLogFile  << strTimestamp << 
      " Fehler! Programmabruch!\n";
   npbLogFile.close();

   exit(1);
      }

      fcntl(fd, F_SETFL, FNDELAY);
      fcntl(fd, F_SETFL, 0);
      
      return fd;
   }
}


Schon mal vielen Dank an euch.

Gruß
Uwe

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann auch sein, dass du als Bootparamter noch console=ttyS0 drinstehen 
hast. Wenn ja, nimm das auch noch raus. Du hast zwar keine Konsole mehr 
laufen, aber der Kernel meldet sich immer noch auf ttyS0.

Autor: abdo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, kannst du auch dein "read_input_source"-listing zeigen? weil an der 
Programmausführung konnte ich bis jetzt keinen Fehler sehen?
Abdo

Autor: abdo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
abdo schrieb:
> Programmausführung

programmlisting

Autor: Uwe D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

da ich die letzten zwei Wochen sehr wenig Zeit hatte, hier nochmal der 
aktuelle Stand...

1. Console hab ich ausgeschalten, jetzt auch in den 'bootargs', aber was 
ich nicht verstehe, warum wird der Kernel-Prozess immer noch über die 
ttyS0 ausgegeben?
U-Boot> printenv
baudrate=115200
ethaddr=00:04:25:1C:88:84
bootdelay=1
ethact=macb0
serverip=172.24.41.2
tftpip=172.24.41.2
eth1addr=00:04:25:1C:88:85
filesize=131B8C
bootcmd=mmcinit; ext2load mmc 0:1 0x10400000 /boot/uImage; bootm
bootargs=root=/dev/mmcblk0p1 rootwait
stdin=serial
stdout=serial
stderr=serial

Environment size: 294/65532 bytes

2. Habe ich versucht, mit meinem Programm auf die anderen 
UART-Schnittstellen zu zugreifen, hier steigt er dann - wie es natürlich 
auch sein soll - schon mit einer Fehlermeldung beim konfigurieren aus.

3. ich habe mir mal den Rückgabewert von 'fd' anzeigen lassen, nach dem 
die Schnittstelle über die Funktion konfiguriert wurde, der ist 
'716345188' unter Ubuntu war der Wert '3'

4. er scheint die Schnittstelle aber richtig zu konfigurieren, weil nach 
meinem Programmstart ist die ttyS0 auf 9600 Baud und nicht mehr auf 
115200 gesetzt. Hier die Ausgabe von 'stty'
~ # stty -a -F /dev/ttyS0
speed 9600 baud; rows 24; columns 80;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 0; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
-iuclc -ixany -imaxbel
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0
ff0
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke


Vielleicht kann mir jemand von euch weiter helfen... Vielen Dank.

Gruß Uwe

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>warum wird der Kernel-Prozess immer noch über die
>ttyS0 ausgegeben?
Der Kernel nimmt sich immer das erste verfügbare und brauchbare Gerät 
für die Ausgabe, du musst es explizit auf was anderes legen. Zweite 
Serielle Schnittstelle vlt? Hat das NGW100 eine?

>ich habe mir mal den Rückgabewert von 'fd' anzeigen lassen, nach dem
>die Schnittstelle über die Funktion konfiguriert wurde, der ist
>'716345188' unter Ubuntu war der Wert '3
Und du willst uns damit was sagen?

Autor: Uwe D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Wenn ich eine andere Schnittstelle nehme z.B. ttyS3 wird der 
Kernel-Bootprozess nicht mehr ausgegeben, aber funktionieren tut es dann 
immer noch nicht...

2. Naja, da er ja an der Stelle aussteigt, wenn er 'fd' aufruft... 
dachte ich, könnte was damit zu tun haben, das der Wert nicht stimmt.


Danke & Gruß

Autor: Uwe D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich habe jetzt mal den Debugger laufen lassen... bekomme im 
DBG-Clienten folgende Meldung:
warning: .dynamic section for "/usr/lib/libstdc++.so.6" is not at the expected address (wrong library or version mismatch?)

Program received signal SIGSEGV, Segmentation fault.
0x000036b8 in main ()


Der DGB-Server spuckt folgenden Error raus...
Child terminated with signal = b

Child terminated with signal = 0xb (SIGSEGV)
GDBserver exiting

Folgendes ist zu erwähnen, die libstdc++.so.6 war bei mir nach dem 
compilieren des buildroot 2.3.0 nicht dabei, da die Datei aber im 
staging_dir des GNU-Toolchain vorhanden war, hab ich diese nach /usr/lib 
auf dem NGW100 kopiert...

Mit --static kompilieren bringt keine Veränderung.

Ich kompiliere immer mit "avr32-linux-g++ prog.cpp -o prog" oder ist das 
nicht ausreichend?


Vielen Dank & Gruß

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>dachte ich, könnte was damit zu tun haben, das der Wert nicht stimmt.
Woher willst du wissen, dass der Werte nicht simmt? Das ist ein 
File-Descriptor, der ist nicht immer und auf jeder Architektur gleich ;)

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Wert '716345188' für fd sieht trotzdem ziemlich daneben aus.
'fd_set' ist meist ein Array fester Größe (FD_SETSIZE) und FD_SET 
benutzt fd als index in dieses Array. Wenn fd>=FD_SETSIZE ist, dann 
knallts halt. Kann man sich ja einfach in den entsprechenden *.h 
ansehen.

Autor: Uwe D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Problem ist gelöst!

Das "return fd" aus der zweiten Funktion, muss außerhalb der 
if-Anweisung sein, also vor die letzte geschweifte Klammer!

Der AVR32-GNU-Compiler 4.2 macht sonst Probleme.

Danke für eure Hilfe...


Gruß Uwe

Autor: abdo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Uwe D,
kannst du mir Bitte dein Programm auf diese Mail"t.abderrahim@web.de" 
schicken? ich habe auch Probleme mit select und ttyS1 auf dem 
ICnova-OEM, und ich bin ratlos.
Vielen Dank im vorraus.
Abdo

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.