[AVR32] NGW100 - ttyS0 mit select() -> FD_SET Segmentation fault

Gast #1676462
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!
1
#include <stdio.h>
2
#include <string>
3
#include <unistd.h>
4
#include <fcntl.h>
5
#include <errno.h>
6
#include <stdlib.h>
7
#include <termios.h>
8
#include <unistd.h>
9
#include <sys/ioctl.h>
10
#include <sys/time.h>
11
#include <sys/types.h>
12
#include <iostream>
13
#include <fstream>    
14
#include <sys/select.h>
15

16
using namespace std;
17

18
int open_input_source(int);
19
int read_input_source(int, int);
20

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

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

37
   ofstream npbOutFile("FILE_OUT.001",ios_base::trunc);
38
   if (npbLogFile.fail()) {
39
      
40
      cout << "Programmabruch!\n";
41
      
42
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
43
      npbLogFile  << "time" << " Programmabruch!\n";
44
      npbLogFile.close();
45
      
46
      exit(1);
47
   }
48
   npbOutFile.close();
49

50

51
   /* Serielle Schnittstelle öffnen & konfigurieren */
52
   fd = open_input_source(port);
53
   
54
   /* Schleife zum einlesen von Daten an der Schnittstelle */
55
   while (loop) {
56
      
57

58
      Timeout.tv_usec = 0;   // Millisekunden
59
      Timeout.tv_sec  = 3;   // Sekungen
60

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

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

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

84
      if (FD_ISSET(fd, &readfs)) {
85
   errorNpb = read_input_source(fd, errorNpb);
86
                    
87
   if (errorNpb = 0)
88
      sleep(10);
89
   else if (errorNpb > 3) {
90
      cout << "\nFehler beim einlesenen!\n";
91

92
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
93
      npbLogFile  << strTimestamp << " Fehler beim einlesenen!\n";
94
      npbLogFile.close();
95
   }   
96
      }
97
   }
98

99
   close(fd);    // serielle Schnittstelle schließen
100
   return 0;
101
}
102

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

107

108
int open_input_source(int port) {
109
   int fd;
110
   struct termios options;
111

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

132
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
133
      npbLogFile  << strTimestamp << " Fehler! Programmabruch!\n";
134
      npbLogFile.close();
135
      exit(1);
136
   }
137
   
138
   /* wenn serieller Port geöffnet, dann Port konfigurieren */  
139
   else if (fd >= 0) {
140
      fcntl(fd, F_SETFL, 0);
141
      
142

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

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

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

166
      tcflush(fd, TCIOFLUSH);
167

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

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

176
   exit(1);
177
      }
178

179
      fcntl(fd, F_SETFL, FNDELAY);
180
      fcntl(fd, F_SETFL, 0);
181
      
182
      return fd;
183
   }
184
}


Schon mal vielen Dank an euch.

Gruß
Uwe
Gast #1696204
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?
1
U-Boot> printenv
2
baudrate=115200
3
ethaddr=00:04:25:1C:88:84
4
bootdelay=1
5
ethact=macb0
6
serverip=172.24.41.2
7
tftpip=172.24.41.2
8
eth1addr=00:04:25:1C:88:85
9
filesize=131B8C
10
bootcmd=mmcinit; ext2load mmc 0:1 0x10400000 /boot/uImage; bootm
11
bootargs=root=/dev/mmcblk0p1 rootwait
12
stdin=serial
13
stdout=serial
14
stderr=serial
15

16
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'
1
~ # stty -a -F /dev/ttyS0
2
speed 9600 baud; rows 24; columns 80;
3
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
4
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
5
lnext = ^V; flush = ^O; min = 0; time = 0;
6
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
7
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
8
-iuclc -ixany -imaxbel
9
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0
10
ff0
11
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
12
echoctl echoke


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

Gruß Uwe
Persönliche Seite #1696223
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?
Gast #1696572
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ß
Gast #1697221
Lesenswert?

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

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


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

3
Child terminated with signal = 0xb (SIGSEGV)
4
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ß
Gast #1699943
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.
Gast #1707922
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
Gast #1711480
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

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