Hallo Forum,
da Ihr mir bei fscanf() schon so gut geholfen habt. Noch eine Frage:
Ich habe mir folgende Funktion geschrieben um einen GPIO Pin in meinem
Embedded Linux zu überwachen. Das Programm soll später an dieser Stelle
solange hängen bis die Flanke erkannt wurde. Die Flanke ist bereits bei
dem genutzten GPIO auf falling gesetzt. Dieser ist auch ein Input und
das active_low ist auf 0 gesetzt. Wenn ich den Wert des Pins auslese
bekomme ich 0 zurück. Somit sollte keine fallende Flanke auftreten
können (ist ja schon 0)..
Mein Problem ist nun: Wenn ich das Programm ausführe, läuft es so direkt
durch ohne irgendwo zu warten. Die Funktion gibt mir auch schön
ordentlich 0 zurück (Wert des Pins). Achja EPOLL_TIMEOUT ist auf -1 also
unendlich gesetzt.
Folgende Funktion habe ich mir geschrieben um einen "Interrupt" zu
bekommen (ich weiß das mit dem free usw. hatten wir ja schon in
fscanf()..):
1
int_fast8_t
2
get_interrupt_gpio(charconst*constgpionum)//Achtung blocking!! Also extra thread oder process!
So ich glaube ich habe es...
man muss vor dem epoll_wait() das File lesen. Dann hängt er auch an der
Stelle bis die Flanke kommt...
Das was ich vorher gefunden hatte funktioniert auch...:
https://gist.github.com/jadonk/2587524
aber ich denke der Code geht erst einmal durch die Schleife durch und
hängt dann am epoll_wait()..
Dank:
http://wiki.gnublin.org/index.php/GPIO
bin ich drauf gekommen...
So funktioniert es:
1
int_fast8_t
2
get_interrupt_gpio(charconst*constgpionum)//Achtung blocking!! Also extra thread oder process!
furchtbarer Code
was anderes.
Gibts denn keine Abschätzung darüber, wie lang gpionum maximal werden
kann? Da wird ja wohl kaum ein String mit der Textlänge der Bibel
daherkommen.
Nimm deine Abschätzung, gib noch 10 Zeichen dazu und allokier ein
statisches Array mit dieser Länge. Am Anfang der Funktion kann man noch
prüfen ob die allokierte Array-Länge ausreichen wird und gut ists.
Man kann auch alles übertreiben. Nach dem was ich beim kurzen schmöckern
in deinen Links gesehen habe, ist diese 'Zahl' maximal 3 stellig. Ich
hab zb gpionum34 gesehen und geb noch eine Ziffer in Reserve mit dazu.
D.h. für das temporäre "Verschwenden" von 13 (3 + 10) Bytes zwirbelst du
deinen Pi in eine Menge Sonderarbeit für die dynamische Allokierung
rein. Und ich glaube nicht, dass der Pi jemals eine Pinanzahl bekommen
wird, die sich mit einer 12-stelligen Zahl nicht mehr beschreiben lässt.
Zumindest wirst du das ziemlich sicher nicht mehr erleben.
Ist ein Beaglebone ;-)
Ne stimmt schon, ist maximal 3-stellig.
Hab mir nur gedacht ich schreibe es so universal wie möglich. (Bis auf
das read() gibts ja nur unter Linux... aber da jetzt noch close(fd);
dann fopen(...) usw. nur für fscanf() hatte ich keine Lust.
Hab mich damals immer geärgert das mein Prof getch() genutzt hat und auf
dem Mac ging es nicht...
Dafür variable Array Größen mit int array[a]; wobei a auf der Console
eingegeben werden konnte....
Was heißt denn furchtbarer Code? Wie macht man es denn besser?
Ich meine ich kann schon programmieren bzw. ich bekomm es zumindest hin,
dass es das macht was es soll...
Aber womit lernt man denn "guten" Code zu schreiben?
Ich habe gemerkt, dass ich etwas inkonsistent bin mit meiner Art ifs zu
verwenden..
Also immer mal andersrum abgefragt oder mal if else obwohl if genügt
hätte usw. Ich schreibe erstmal alles runter und dann, wenn es geht, vll
noch bissel Lesbarkeit verbessern.
Den Code gab es schon als ich das mit fscanf geschrieben habe. Daher
sind hier auch so viele free() drin. Aber ich glaub ich bin zu faul
alles zu überarbeiten. Habe mittlerweile viel Code für das Projekt.
epolli schrieb:> Was heißt denn furchtbarer Code?
Na ja. SIeh dir das Teil an.
Extrem in die Länge gezogen. Denn Programmfluss kann man nur nach
Intensivstudium erkennen, weil da immer wieder der ganze Sermon mit
Freigeben und return dazwischen liegt.
> Aber womit lernt man denn "guten" Code zu schreiben?
Wenn man die Grundidee dieser eigentlich recht einfachen Funktion in
unter 5 Sekunden erfassen und im Code nachvollziehen kann.
> hätte usw. Ich schreibe erstmal alles runter und dann, wenn es geht, vll> noch bissel Lesbarkeit verbessern.
Das ist eine gute Idee.
Es lohnt sich immer, sich auch mal zurückzulehnen und zu überlegen, wie
man Code anders strukturieren könnte und da einfach mal ein paar Dinge
auszuprobieren.
> sind hier auch so viele free() drin. Aber ich glaub ich bin zu faul> alles zu überarbeiten. Habe mittlerweile viel Code für das Projekt.
Das Problem ist nicht, dass du jetzt deinen Code verstehst. Das Problem
wird in ein paar Wochen/Monaten auf dich zukommen, wenn du das nächste
mal an diesen Code rann musst und dann erst mal nur noch Bahnhof
verstehst.
Hm jetzt hab ich ein komisches Problem.
Wenn ich meine beiden Funktionen (get_value_gpio (die fscanf Funktion)
und get_interrupt_gpio (Funktion von hier) in einer while(1) schleife
laufen lasse (Einfach nur zum Testen..) dann geht es solange ich von
Hand durchsteppe (auch wenn die ganze Schleife immer auf Knopfdruck
wiederholt wird, beliebig oft aber halt "handbetrieb"..)
Wenn ich nun das Programm einfach so starte kommt Plötzlich immer der
Fehler das mein gpio_get_value() -1 zurückgibt also das File (der Pin)
nicht zum öffnen geöffnet werden kann. Und bei der Interrupt funktion
kommt der Fehler das epoll_create1(0) fehlgeschlagen ist mit dem Errno
24 also zu viele Files offen.
Aber ich mach die doch überall wieder zu.
Das einzige ist dieses epoll_create1() da weiß ich nciht wie die
gelöscht werden.
Bzw. habe gelesen das wenn ich den fd close würden die wieder gelöscht
werden. Aber irgendwie...
Anscheinend nicht. Habe auch schon alles nachgeschaut ob ich es irgendwo
nicht zu mache. Aber es werden alle fd zugemacht.
Hm war es nicht.
Er kann wenn es schnell hintereinander ausgeführt wird irgendwann den
Pin nicht mehr öffnen. Also meine /sys/class/gpio/gpio27/value.
Nur wo liegt der Fehler?
Ist es wirklich weil der Kernel mit dem löschen der fd nicht
hinterherkommt??
Oder übersehe ich da irgendwo etwas das ich den Pin nicht mehr
schließe...?
So,
der Fehler muss in der Interrupt Funktion liegen.
Ich habe es mal etwas umgebaut um das ganze besser lesbar zu machen.
Hoffentlich könnt Ihr mir nun helfen.
Ich schließe den Pin wie Ihr seht immer. Aber nach einigen Aufrufen kann
plötzlich epoll_create1() nicht mehr ausgeführt werden. Es gibt mir
errno 24 zurück.
Irgendwie müssen doch die epoll_create1() wieder geschlossen werden.
Aber wie?
1
int_fast8_tget_interrupt_gpio(charconst*constgpionum)//Achtung blocking!! Also extra thread oder process!
Was ist eigentlich schneller?
Oben der Code mit dem epoll()? Oder sowas hier über die gpio-key Treiber
von Linux?
Wobei der GPIO dann im DTO als Key definiert wird und die Debounce-Time
auf 0 gesetzt wird usw.
Ich brauche eigentlich nur etwas, was meine state Machine blockiert bis
der GPIO auf 0 gezogen wurde. Der gpio wird von einem Mikrocontroller
nur sehr kurz auf 0 gezogen und dann wieder auf 1. Der Pin gibt nur an,
das die Daten bereit zum abholen über SPI sind.
uint32_ttrigger_event)//Achtung blocking!! Also extra thread oder process! //TODO Falls der Interrupt schneller bereit sein muss Pfad mit GPIO direkt übergeben also ohne allokieren usw..