Eigenes Modul hinzufügen: Unterschied zwischen den Versionen

Aus Ethersex_Wiki
Wechseln zu: Navigation, Suche
K (Debug-ausgaben)
K (timer Erläuterung ergänzt)
 
(Eine dazwischenliegende Version von einem anderen Benutzer wird nicht angezeigt)
Zeile 65: Zeile 65:
 
Um dein Modul zur grafischen Konfiguration hinzuzufügen (make menuconfig), brauchst du im Ordner deines Moduls eine Datei namens config.in, beispielsweise mit folgendem Inhalt:
 
Um dein Modul zur grafischen Konfiguration hinzuzufügen (make menuconfig), brauchst du im Ordner deines Moduls eine Datei namens config.in, beispielsweise mit folgendem Inhalt:
 
  dep_bool_menu 'Genius module' DEINGENIALESMODUL_SUPPORT $TCP_SUPPORT
 
  dep_bool_menu 'Genius module' DEINGENIALESMODUL_SUPPORT $TCP_SUPPORT
 +
Dieser Eintrag bedeutet, dass du dein Modul nur dann aktivieren kannst, wenn TCP_SUPPORT aktiviert ist. Weiters wird hier noch ein Untermenü angelegt. Um dein Modul ohne Abhängigkeiten und ohne zusätzlichem Menü aktivieren zu können solltest du folgende Methode wählen:
 +
bool 'Genius module' DEINGENIALESMODUL_SUPPORT
  
 
Dieses musst du, analog zum Makefile, in $(TOPDIR)/config.in hinzufügen:
 
Dieses musst du, analog zum Makefile, in $(TOPDIR)/config.in hinzufügen:
Zeile 88: Zeile 90:
 
* '''net_init''' - zum Initialisieren von Netzwerkanwendungen.  Die Funktionen werden nach den ''init''-Funktionen ausgeführt.
 
* '''net_init''' - zum Initialisieren von Netzwerkanwendungen.  Die Funktionen werden nach den ''init''-Funktionen ausgeführt.
 
* '''startup''' - diese Funktionen werden vor Aufruf der Mainloop gestartet.  Der Sendmail-Service sendet hier beispielsweise die Startnachricht.
 
* '''startup''' - diese Funktionen werden vor Aufruf der Mainloop gestartet.  Der Sendmail-Service sendet hier beispielsweise die Startnachricht.
* '''timer''' - Periodisch wie bei mainloop. Beispiel timer(50, function()).
+
* '''timer''' - Periodisch (alle 20ms) wie bei mainloop. Beispiel: timer(50, function()) ruft function() alle 50*20ms auf, also 1x pro Sekunde.
 
* '''header''' - nicht dokumentiert
 
* '''header''' - nicht dokumentiert
  

Aktuelle Version vom 14. Februar 2011, 23:27 Uhr

Hier findest du die wichtigsten Informationen, um dein eigenes Modul entwickeln zu können. Beachte bitte auch den projektweit gültigen coding style und weitere Infos wie unter Pins in Ethersex definieren.

Lizenz

Damit dein Modul mit ethersex veröffentlicht werden kann, musst du deinen Code unter eine GPLv3-kompatible Lizenz stellen. Füge dazu am besten folgenen Lizenzkopf in jede deiner Quellcode Dateien (*.h,*.c) ein:

/*
*
* Copyright (c) 2009 by DEIN_NAME <DAVOR@DANACH.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
  • Vergiss nicht, DEIN_NAME durch deinen Namen zu ersetzen.

Richtiges Verzeichnis

Du kannst dein Modul in eines der Verzeichnisse „hardware“, „services“ oder „protocols“ einsortieren. Wenn dein Modul mehrere dieser Kategorien erfüllt, muss das Modul eventuell in kleinere Untermodule aufgeteilt werden. Genaue Beschreibungen findest du im jeweiligen Verzeichnis in der Datei "content.txt". Wenn du dir nicht sicher bist, wo dein Modul genau einsortiert werden sollte, frag in der Mailingliste nach.

Die 3 Kategorien grob umrissen:

  • Hardware: Module, die es ermöglichen externe Hardware anzusteuern.
  • Services: Module, die Anwendungen/Daemons/Services realisieren.
  • Protocols: Module, die Protokolle implementieren.

Dateien in Make-Prozess aufnehmen

Du hast in einem beliebigen Unterverzeichnis eine Datei hinzugefügt und möchtest natürlich, dass das Make-System diese jetzt auch mit berücksichtigt. Dazu musst du ein Makefile erstellen, welches beispielsweise wie folgt aussehen kann:

TOPDIR ?= ../..
include $(TOPDIR)/.config

$(DC3840_SUPPORT)_SRC += hardware/camera/dc3840.c

##############################################################################
# generic fluff
include $(TOPDIR)/scripts/rules.mk

Anstelle der Variable, die auf _SRC endet, kannst du eine der folgenden Alternativen wählen:

  1. Die Datei soll immer mit eingelinkt werden.
    SRC += Pfad/deinedatei.c
  2. Die Datei soll in Abhängigkeit von einer Konfigurationsoption aus Menuconfig mit eingebunden werden.
    ${DEINGENIALESMODUL_SUPPORT}_SRC += Pfad/deinedatei.c
  3. Die Datei soll in Abhängigkeit von einer Konfigurationsoption mit eingebunden werden, wenn der ECMD-Parser aktiviert ist.
    ${DEINGENIALESMODUL_SUPPORT}_ECMD_SRC += Pfad/deinedatei.c

Abhängig von der Ordnertiefe des von dir angelegten Ordners musst du selbstverständlich die Zahl der ../ betreffend TOPDIR anpassen.

Weiterhin musst du dein Makefile dem eigentlichen Makefile in $(TOPDIR) bekannt machen, indem du es folgendermaßen hinzufügst:

SUBDIRS += hardware/camera

Menuconfig

Um dein Modul zur grafischen Konfiguration hinzuzufügen (make menuconfig), brauchst du im Ordner deines Moduls eine Datei namens config.in, beispielsweise mit folgendem Inhalt:

dep_bool_menu 'Genius module' DEINGENIALESMODUL_SUPPORT $TCP_SUPPORT

Dieser Eintrag bedeutet, dass du dein Modul nur dann aktivieren kannst, wenn TCP_SUPPORT aktiviert ist. Weiters wird hier noch ein Untermenü angelegt. Um dein Modul ohne Abhängigkeiten und ohne zusätzlichem Menü aktivieren zu können solltest du folgende Methode wählen:

bool 'Genius module' DEINGENIALESMODUL_SUPPORT

Dieses musst du, analog zum Makefile, in $(TOPDIR)/config.in hinzufügen:

source hardware/camera/config.in

Funktion beim Boot und Periodisch aufrufen lassen

  1. Du hast ein neues Modul entwickelt, dieses Enthält eine Initialisierungsfunktion, die beim Start der Ethersex-Firmware aufgerufen werden muss.
  2. Dein Modul enthält eine Funktion, die nach Möglichkeit ständig wieder aufgerufen wird (bzw. möglichst oft, soviel Rechenzeit wie die anderen Applikationen die ebenfalls ihre Dienste verrichten sollen, übrig lassen)

Hierzu gibt es die Ethersex Meta-Bereiche, die du evtl. bereits am Ende der einen oder anderen C-Datei entdeckt hast. Diese haben grundsätzlich den folgenden Aufbau:

/*
  -- Ethersex META --
  mainloop(stella_process)
  init(stella_init)
*/

Diese Zeilen, am Dateiende eingefügt, sorgen dafür, dass die Funktion stella_init einmal beim Start der von dir modifizierten Ethersex-Firmware aufgerufen wird und die Funktion stella_process' möglichst oft. Du kannst in den Meta-Bereich auch mehrere init-Direktiven aufnehmen, etc.

Weitere Direktiven sind:

  • initearly - funktioniert wie init. Die Funktionen werden nur vor init aufgerufen. Dies ist bei Abhängigkeiten praktisch, in der Regel solltest du jedoch init verwenden.
  • net_init - zum Initialisieren von Netzwerkanwendungen. Die Funktionen werden nach den init-Funktionen ausgeführt.
  • startup - diese Funktionen werden vor Aufruf der Mainloop gestartet. Der Sendmail-Service sendet hier beispielsweise die Startnachricht.
  • timer - Periodisch (alle 20ms) wie bei mainloop. Beispiel: timer(50, function()) ruft function() alle 50*20ms auf, also 1x pro Sekunde.
  • header - nicht dokumentiert

Bei den aufzurufenden Funktionen muss bei init(<fkt>) die Funktion ohne Klammern und bei timer(<int>, <fkt>()) mit Klammern geschrieben werden.

Debug-Ausgaben

Für eingebettete Systeme zu programmieren kann manchmal ziemlich nervenaufreibend sein. In der Regel hat man nicht die nötige Hardware (JTAG) um step-by-step Debugging durchführen zu können. Der ethersex Core bietet dir einige Debug-Ausgabefunktionen an um zumindest über syslog oder die serielle Schnittstelle den Programmablauf mitverfolgen zu können.

Folgende Debugfunktionen kannst du nutzen, nachdem du core/debug.h inkludiert hast:

  • void debug_printf(s, args...); // Syntax wie bei printf aus der standard C library
  • char* debug_binary(uint8_t); // Gibt eine 8 Byte lange Zeichenfolge von 0/1 zurück, die den integer repräsentiert

Folgende Debug Funktionen kannst du nutzen, nachdem du protocols/syslog/syslog.h inkludiert hast:

  • void syslog_sendf(s, args...); // Syntax wie bei printf aus der standard C library