Own module

From Ethersex_Wiki
Jump to: navigation, search

Here you can find the most relevant information in order to develop your own module. Note also the project-wide coding style and other information as described in define pins in ethersex.

License

In order to publish your module with Ethersex you have to put your code under a GPLv3-compatible license. At best include the following license header in each of your source code files (*.h, *.c):

/*
*
* Copyright (c) 2012 by YOUR_NAME <FIRST@SIR.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
*/

Don't forget to replace YOUR_NAME with your Name.

proper directory

You can place your module in one of the directories „hardware“, „services“ or „protocols“. If your module fulfills several of these categories, the module may be divided into smaller sub-modules. Detailed descriptions can be found in each directory in the file "content.txt". If you're not sure where to put your module, ask on the mailing list.

the three categories roughly outlined:

  • Hardware: modules to control external hardware.
  • Services: modules implementing applications/daemons/services.
  • Protocols: modules implementing protocols.

include files in make-process

Let's assume you've added a file in a subdirectory. In order to make the file known to the make-system you need to create a Makefile, which can look like the following example:

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

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

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

Instead of the variable, which ends on _SRC, you can choose one of the following alternatives:

  1. the file should be linked always.
     SRC += path/yourfile.c 
  2. the files inclusion depends on a config option in Menuconfig.
    ${YOURBRILLIANTMODUL_SUPPORT}_SRC += path/yourfile.c 
  3. the files inclusion depends on another config option, if the ecmd parser is enabled.
    ${YOURBRILLIANTMODUL_SUPPORT}_ECMD_SRC += path/yourfile.c 

Depending on the depth of the folder you have created, the path to your folder must of course adapt the number of ../ to your folder.

Furthermore, you have to include the directory of your module in the appropriate Makefile (/hardware/Makefile /protocols/Makefile or /services/Makefile).

Example: /hardware/Makefile:

SUBSUBDIRS += hardware/camera

You can also add this entry in the corresponding custom.mk file (e.g. /hardware/custom.mk).

This has the advantage that any changes in *custom.mk are not tracked by git.

With this solution you can add own modules without committing them and still be able keep the repository up-to-date.

Menuconfig

To add your module for graphical configuration (make menuconfig), you need a file in your module folder called config.in, for example, with the following contents:

dep_bool_menu 'brilliant module' YOURBRILLIANTMODUL_SUPPORT $TCP_SUPPORT

This entry creates a submenu and you can activate your module only if TCP_SUPPORT is enabled. To activate your module without dependencies and without an additional menu to choose from you should use be following method:

bool 'brilliant module' YOURBRILLIANTMODUL_SUPPORT

Analogous to the Makefile you have to include your config.in in $(TOPDIR)/config.in:

source hardware/camera/config.in

starting functions after boot and periodically

  1. You have developed a new module, that contains an initialization function which should be called after boot.
  2. Your module contains a function that is constantly called if possible (or as often as possible, at least as much computing time is left over by the other application which run as a service.

Therefore are the Ethersex Meta areas, maybe you've already discovered them at the end of some C-files. It basically has the following structure:

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

These lines, inserted at end of a file, ensure that the function stella_init is called once at the start of your modified Ethersex-Firmware and the function stella_process is called as often as possible. You can include multiple init, mainloop and ... directives in the meta area.

Other directives are:

  • initearly - works like init. The functions are called just before init. This is useful for dependencies, in general, you should use, however, init.
  • net_init - to initialize network applications. The functions are called after the init functions.
  • startup - these functions are started before calling the mainloop. The Sendmail service for example sends the start message.
  • timer - Periodically (every 20ms) as in mainloop. Example: timer(50, function()) calls function() every 50*20ms, thus 1x per second.
  • header - header file containing the prototypes of the functions above. Included from the code generated by meta.

the functions must be called in case of init without parentheses init(<fkt>) and the timer directive without brackets timer(<int> <fkt>()) .

debug output

Programming for embedded systems can be quite unnerving sometimes. Normally you do not have the necessary hardware (JTAG) for step-by-step debugging. The Ethersex core offers you some debug output functions to at least observe the program flow via syslog or the serial interface.

The following debug functions are available after you include core/debug.h in your files:

  • void debug_printf(s, args...) // syntax like printf from the standard C library
  • char* debug_binary(uint8_t) // returns an 8 Byte long string of 0/1, which represents the integer

The following debug functions are available after you include protocols/syslog/syslog.h in your files:

  • void syslog_sendf(s, args...) // syntax like printf from the standard C library