Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
2Introduction à RTEMS
Programme
● Histoire● Présentation● Compilation de RTEMS● Développement d'application● Pilotes de périphériques
3Introduction à RTEMS
RTEMS « in a nutshell »
● RTEMS = Real Time Executive for Multiprocessor Systems● Initialement « Missile Systems » puis « Military Systems »● Exécutif temps réel embarqué diffusé sous licence libre
(GPL avec exception)● Ce n'est pas réellement un système d'exploitation car
l'application est « liée » au noyau → un seul processus mais plusieurs threads
● Plus de 20 architectures matérielles supportées● API RTEMS « classique », POSIX● Utilise la chaîne de compilation GNU sur Linux, Windows,
Solaris, (FreeBSD, Mac OS X ?)● RTEMS est en perpétuelle évolution (Git)
4Introduction à RTEMS
Histoire
● 1988 : premiers développements par OAR (On-Line Application Research) sur demande de l'US Army Missile Command
● 1992 : première utilisation non militaire, préféré à pSOS+ par SSC (Superconducting Super Collider)
● 1992 : utilisation des outils GNU● 1994 : code source publié par l'US Army en FTP● 1997 : validation de GNAT/RTEMS● 1998 : portage de la pile TCP/IP FreeBSD sur RTEMS● 1998 : La société OAR reprend la maîtrise du
développement (Joel Sherill)● 2004 : démarrage de http://wiki.rtems.org● 2006 - 2009 : utilisation dans diverses missions spatiales
(Dawn, MRO, ESA/Herschel & Plank, …)● 2012 : sonde NASA Curiosity (mars) → telecom
5Introduction à RTEMS
Curiosity
6Introduction à RTEMS
Licence
● RTEMS utilisent une GPL modifiée avec « linking exception » (voir fichier LICENSE)
● Le but est d'éviter la « contamination » du code applicatif par la GPL
– L'exécutable produit n'est pas soumis à la GPL
– Conséquence, un code « pur » GPL ne peut être intégré à l'arbre RTEMS →il est impossible d'utiliser du code venant de projets GPL (U-Boot, Linux, …) :-(
● La licence utilisé limite les contributions● Communauté réduite, faible collaboration due aux
« marchés » adressés● Les industriels ont leur propre version modifiée et
« validée » (EADS/Astrium, ESA, EDISOFT, …)
7Introduction à RTEMS
Présentation & compilation
8Introduction à RTEMS
Schéma général
9Introduction à RTEMS
Points-clés● RTEMS est un exécutif :
– L'utilisation est plus complexe → configuration par fichiers, pas de « shell » comme sur un OS évolué
– Un seul processus → « équivalent » à un noyau Linux + un seul processus init
– Beaucoup plus petit qu'un OS → en sélectionnant les composants on peut arriver à une taille de quelques dizaines de Ko :-)
– Pas de MMU (sauf exception)
– De nombreuses fonctionnalités sont optionnelles : réseau, système de fichiers, etc.
● RTEMS est léger, < 500K lignes pour la version Git 4.11● RTEMS est bien documenté grâce au Wiki + Doxygen● Pas support de formation en ligne car c'est une des sources
de revenu d'OAR :-)
10Introduction à RTEMS
Pendant ce temps, chez Linux !
11Introduction à RTEMS
Compilation / développement
● Le plus souvent, environnement GNU/Linux● Chaîne croisée « GNU Toolchain » en fonction de
l'architecture cible :– Image VM pour CentOS 6.2 et RTEMS 4.11
– Paquets binaires DEB ou RPM (Fedora/RHEL)
– Construction à partir des sources → rtems-source-builder
● Développement en C/C++/Ada● Mise au point à distance avec GDB● Émulation sur QEMU (x86)
12Introduction à RTEMS
Concepts généraux
● Conception est très modulaire– API (RTEMS, POSIX, ...)
– Bibliothèques ou managers
– SuperCore (couche générique du cœur) utilisée par les API
– Support processeur (CPU)
– Support carte (BSP = Board Support Package)
– Scheduling framework (RMS, RR, DPS, EDF, ...)● Orienté « objet » pour désigner les composants du
système (tâche, sémaphore, ...)
rtems_object_name my_name;
13Introduction à RTEMS
Schéma architecture / managers
14Introduction à RTEMS
Vue en camembert des managers
15Introduction à RTEMS
SDK
● Le SDK est basé sur la chaîne de compilation GNU (GNU toolchain)
– GCC (GNU Compiler Collection) → C, C++, Objective-C, Ada, ...
– BINUTILS : assembleur, éditeur de liens, outils de manipulation des objets (nm, objcopy, objdump, ...)
– NEWLIB : LibC développée par Red Hat pour les systèmes embarqués
● Les nommage suit la règle des compilateurs croisés (préfixe <architecture>-<OS_cible>-) :
i386-rtems4.11-gcc
arm-rtems4.11-gcc
16Introduction à RTEMS
RTEMS source builder
● On charge tout d'abord une copie de l'arbre Git$ git clone git://git.rtems.org/rtems-source-builder.git
● On peut alors vérifier l'environnement et démarrer la production de la chaîne croisée qui sera installée sur un répertoire$ cd rtems-source-builder
$ ./source-builder/sb-check
RTEMS Source Builder - Check, v0.4.0
Environment is ok
$ ../source-builder/sb-set-builder --log=l-build.txt --prefix=<sdk installpath> 4.11/rtems-arm
● La production de la chaîne est assez longue mais on obtient finalement la chaîne sur le répertoire spécifié qui occupe environ 600 Mo
17Introduction à RTEMS
Sources de RTEMS
● Voir RTEMS_GIT_Repository sur le wiki● Inclus les dernières modifications officielles● Basé sur « Autotools »● Nécessite un - long - « bootstrap » pour produire les scripts configure$ export PATH=<sdk install path>/bin:$PATH
$ git clone git://git.rtems.org/rtems.git rtems
$ cd rtems
$ ./bootstrap
18Introduction à RTEMS
Configuration avant compilation
● Avant de compiler, on sélectionne les paramètres :– TARGET : type de CPU (i386, arm, sparc, ...)
– BSP : type de carte pour un processeur donné, exemples● pc386 pour x86 (test)● gumstix, raspberrypi, STM32, etc. pour ARM● Sparc/LEON● ...
– INSTALL_POINT : répertoire d'installation des binaires produits
– Options diverses : activation d'API, C++, réseaux, etc.
● Exemple pour RPi$ mkdir build && cd build
$ ../rtems/configure --target=arm-rtems4.11 --disable-cxx --enable-rtemsbsp=rapsberrypi --prefix=<path>/target_rpi
19Introduction à RTEMS
Options de compilation
● On peut supprimer des fonctionnalités--disable-posix (défaut = YES)
--disable-networking (défaut = YES)
--disable-cxx (défaut = NO) → développement C++
● Par défaut cela ne change pas radicalement la taille de l'exécutable
● La bibliothèque est liée uniquement si une de ses fonctions est utilisée
● La taille dépend du BSP utilisé (x86 = big!!)
20Introduction à RTEMS
Développement d'application
21Introduction à RTEMS
Introduction
● RTEMS permet de développer en C, C++, Ada ● Pour une application on définit (au minimum) :
– La fonction principale Init() ou POSIX_Init()
– La « configuration » (dimensionnement = nombre de threads, pilotes, etc.) → influence sur la taille de l'exécutable
– Un fichier Makefile (ou Makefile.am/Makefile.in)
● L'application (unique) est liée avec le noyau RTEMS → pas de main()
● La conception de de l'application est facilitée par l'existence d'un grand nombre d'exemples :
– Répertoire testsuites/ dans les sources RTEMS
– Projet examples-v2 sur Git
– Listes de diffusion
22Introduction à RTEMS
L'application « Hello World »
● API classique● Une seule tâche d'affichage sur la console
#include <bsp.h>
#include <stdio.h>
#include <stdlib.h>
rtems_task Init (rtems_task_argument ignored)
{
printf( "Hello RTEMS !!\n" );
exit( 0 );
}
23Introduction à RTEMS
Configuration
● En plus du code, on doit définir la configuration de l'application
● Les structures et valeurs sont définies dans rtems/confdefs.h
● L'application définit des paramètres et la constante CONFIGURE_INIT → prise en compte de la configuration
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT
#include <rtems/confdefs.h>
24Introduction à RTEMS
Configuration, pilote
● Le tableau Device_drivers[] correspond à la liste des pilotes à charger pour l'application
● Deux solutions :– Utilisation de la liste pré-définie dans confdefs.h et
sélection par constante(s) →
CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
– Définition de sa propre liste – et donc du tableau - si CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE est définie dans l'application
25Introduction à RTEMS
Configuration, table des pilotes
● Exemple de définition d'une table des pilotes :
#define CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE
#ifdef CONFIGURE_INIT
rtems_driver_address_table Device_drivers[5] = {
CONSOLE_DRIVER_TABLE_ENTRY,
CLOCK_DRIVER_TABLE_ENTRY,
TTY1_DRIVER_TABLE_ENTRY,
TTY2_DRIVER_TABLE_ENTRY,
{NULL, NULL, NULL, NULL, NULL, NULL}
};
#endif
26Introduction à RTEMS
Le fichier Makefile
● On peut utiliser un fichier générique à partir des exemples● On définit tout d'abord les sources et le nom du programme
PGM=${ARCH}/helloworld.exe
# optional managers required
MANAGERS=all
# C source names
CSRCS = helloworld.c
COBJS = $(CSRCS:%.c=${ARCH}/%.o)
27Introduction à RTEMS
Le fichier Makefile, suite.
● On inclut ensuite les règles définies dans RTEMS
include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/leaf.cfg
● Puis les objets et la production de l'exécutable
OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
all: ${ARCH} $(PGM)
$(PGM): $(OBJS)
$(make-exe)
BSP
Macros make
28Introduction à RTEMS
Compilation
● On doit définir la variable d'environnement RTEMS_MAKEFILE_PATH (chemin d’accès au BSP)
$ RTEMS_MAKEFILE_PATH=<path>/i386-rtems4.11/pc386
ou bien
$ RTEMS_MAKEFILE_PATH=<path>/arm-rtems4.11/raspberrypi
$ export RTEMS_MAKEFILE_PATH
$ make
CPU BSP
29Introduction à RTEMS
Fichiers produits
● La compilation produit différents fichiers dans le répertoire o-optimize
– Les fichiers objets .o
– Le fichier exécutable .exe au format ELF
– Un fichier texte .num contenant la liste des symboles et produit par la commande nm
– Un fichier binaire .bin (binaire pur) obtenu par objcopy -O binary sur le fichier .exe réduit
– Un fichier .ralf produit par l'outil bin2boot à partir du fichier .bin et utilisable par Netboot (démarrage par réseau) ou Raspberry Pi
30Introduction à RTEMS
Test de l'application
● Test sur Raspberry Pi → copier le fichier .ralf$ cp helloworld.ralf /media/Boot/kernel.img
● Test avec QEMU (x86)$ qemu -kernel o-optimize/helloworld.exe
● Le répertoire o-optimize correspond à la version produite par défaut (optimisé -O2 + mise au point -g)
● On peut surcharger par :$ make CFLAGS_OPTIMIZE_V=-g
● L’utilisation combinée de -g et -O2 peut compliquer la mise au point !
31Introduction à RTEMS
Configuration de l’environnement
● Certaines configurations sont possibles après la compilation de RTEMS grâce aux fichiers .cfg
● Voir le fichier share/rtems4.11/make/README● Exemples :
– gcc-target-default.cfg
– host.cfg
– lib.cfg
– directory.cfg
– main.cfg
– leaf.cfg
– custom/pc386.cfg
– custom/default.cfg
Configuration GCC (CFLAGS, ...)
Configuration du BSP pc386
Configuration utilisateur
Inclus par tous les Makefile
Inclus par les Makefile « feuilles »
32Introduction à RTEMS
Configuration « custom »
● Les fichier custom/default.cfg est le fichier à utiliser● Exemple : effacement des fichiers « backup » de Emacs lors
d'un make clean.
# Clean EMACS backup files
CLEAN_ADDITIONS = *~
33Introduction à RTEMS
Taille de l’application
● Le fichier .exe produit est très volumineux mais ne reflète pas la taille de l’exécutable.
– Table des symboles
– En-têtes$ ls -l o-optimize/*.exe
-rwxrwxr-x 1 pierre pierre 1367990 1 juil. 10:41 o-optimize/helloworld.exe
● On obtient la taille effective par :$ i386-rtems4.11-size o-optimize/helloworld.exe
text data bss dec hex filename
173537 10544 10660 194741 2f8b5 o-optimize/...
● La taille du code dépend du BSP utilisé– x86 → 173537
– ARM/RPi → 110056
– Sparc/Leon → 123984
34Introduction à RTEMS
API POSIX
● Compatibilité 1003.1b (environ 80% selon RTEMS centre)● Localisé dans cpukit/posix/● L’API POSIX a quelques inconvénients (tâche périodique,
exécutable légèrement plus volumineux, ...) mais aussi d’énormes avantages !
– Simplicité de l’API
– Compétences disponibles (généraliste)
– Portabilité
void *POSIX_Init()
{
printf ("Hello RTEMS/POSIX\n");
}
35Introduction à RTEMS
Pilotes de périphériques
36Introduction à RTEMS
Introduction
● Un pilote permet de normaliser les échanges application / périphérique
● On peut donc accéder directement à la mémoire physique (contrairement à Linux)
● Exemple de pilotage des leds de la Raspberry Pivolatile unsigned int *gpio = (unsigned int *)BCM2835_GPIO_REGS_BASE;
// GPIO setup macros
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
// set, clear & read
#define GPIO_SET *(gpio+7)
#define GPIO_CLR *(gpio+10)
// For GPIO# >= 32 (RPi B+)
#define GPIO_SET_EXT *(gpio+8)
#define GPIO_CLR_EXT *(gpio+11)
37Introduction à RTEMS
Principes des pilotes RTEMS
● API de programmation et d'utilisation « UNIX like » avec des points d'entrée classiques hello_open()
hello_close()
hello_read()
hello_write()
hello_control()→ ioctl()
● La fonction hello_initialize() correspond au chargement (statique) du pilote → « équivalent » à module_init()
● Le nommage utilise le standard UNIX : /dev/hello● L'infrastructure s'appuie sur IO Manager● De nombreux exemples, en particulier le code Milkymist
c/src/lib/libbsp/lm32/shared
38Introduction à RTEMS
Chargement/ajout de pilotes
● La configuration de l'application définit (entre autres) les pilotes chargés (voir confdefs.h) :#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
● Une constante permet de définir les pilotes ajoutés, soit CONFIGURE_APPLICATION_EXTRA_DRIVERS
● Cette constante contient la liste des fonctions du pilote, à définir dans un fichier d'en-tête :
#define HELLO_DRIVER_TABLE_ENTRY \
{ hello_initialize, hello_open, hello_close, hello_read, \
hello_write, hello_control }
● Dans l'application, on ajoute :#define CONFIGURE_APPLICATION_EXTRA_DRIVERS HELLO_DRIVER_TABLE_ENTRY
39Introduction à RTEMS
Initialisation du pilote
● Effectué par hello_initialize()– Création du point d'entrée sur /dev
– Initialisation du matériel, ...
● Exemple de code :rtems_device_driver hello_initialize (rtems_device_major_number major,
rtems_device_minor_number minor __attribute__((unused)),
void *pargp __attribute__((unused))
)
{
rtems_device_driver status;
status = rtems_io_register_name ("/dev/hello", major,(rtems_device_minor_number) 0);
if (status != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred(status);
return RTEMS_SUCCESSFUL;
}
40Introduction à RTEMS
Ouverture et fermeture
● L'intérêt de ces fonctions est limité (car un seul processus) → ne sont pas présentes dans tous les pilotes
● Exemple de code :
rtems_device_driver hello_open(
rtems_device_major_number major __attribute__((unused)),
rtems_device_minor_number minor __attribute__((unused)),
void *pargp __attribute__((unused))
)
{
printk ("hello_open\n");
return RTEMS_SUCCESSFUL;
}
41Introduction à RTEMS
Lecture et écriture
● Principes similaires à UNIX : – on demande la lecture/écriture de N octets via un tampon
– Le pilote retourne le nombre d'octets lus/écrits
● Les données sont traités par une structure de type rtems_libio_rw_args_t définie dans libio.h :typedef struct {
rtems_libio_t *iop;
off_t offset;
char *buffer; /* tampon de transfert */
uint32_t count; /* nombre d’octets à lire/écrire */
uint32_t flags;
uint32_t bytes_moved; /* nombre d’octets lus/écrits */
} rtems_libio_rw_args_t;
42Introduction à RTEMS
Lecture et écriture, suite.
● Exemple de code :rtems_device_driver hello_write(
rtems_device_major_number major __attribute__((unused)),
rtems_device_minor_number minor __attribute__((unused)),
void *pargp
)
{
rtems_libio_rw_args_t *args = (rtems_libio_rw_args_t *) pargp;
printk ("hello_write count= %d, buffer= %s\n", args->count, args->buffer);
args->bytes_moved = args->count;
return RTEMS_SUCCESSFUL;
}
43Introduction à RTEMS
Contrôle (ioctl)
● Comme sur UNIX, on utilise une commande et un tampon de transfert
● Les données sont traitées par une structure de type rtems_libio_ioctl_args_t définie dans libio.h :
typedef struct {
rtems_libio_t *iop;
ioctl_command_t command; /* code commande */
void *buffer; /* données lue/écrites */
int ioctl_return; /* code de retour */
} rtems_libio_ioctl_args_t;
44Introduction à RTEMS
Contrôle (ioctl), suite.
rtems_device_driver hello_control(
rtems_device_major_number major __attribute__((unused)),
rtems_device_minor_number minor __attribute__((unused)), void *pargp
)
{
rtems_libio_ioctl_args_t *args = pargp;
printk ("hello_control, command= %d buffer= %s\n", (int)(args->command), (char *)(args->buffer));
args->ioctl_return = 0;
return RTEMS_SUCCESSFUL;
}
45Introduction à RTEMS
Utilisation depuis l'application
fd = open ("/dev/hello", O_RDWR);
puts( "Init - attempt to read /dev/hello" );
status = read( fd, buf, 10 );
printf ("status= %d errno= %d => %s\n", status, errno, strerror(errno));
puts( "Init - attempt to write to /dev/hello" );
status = write( fd, "data", 10 );
printf ("status= %d errno= %d => %s\n", status, errno, strerror(errno));
puts( "Init - attempt ioctl on /dev/hello" );
status = ioctl (fd, 42, (void *)"a message string");
printf ("status= %d errno= %d => %s\n", status, errno, strerror(errno));
puts( "Init - attempt close /dev/hello" );
status = close (fd);
printf ("status= %d errno= %d => %s\n", status, errno, strerror(errno));
46Introduction à RTEMS
Configuration de l'application
● Il est nécessaire d'ajuster la configuration de l'application– Nombre de pilotes
– Nombre de descripteurs de fichiers
● Exemple :#define CONFIGURE_MAXIMUM_DRIVERS 3
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5
● Voir le pilote GPIO Raspberry Pi !
47Introduction à RTEMS
Références
● http://www.rtems.com● http://rtemscentre.edisoft.pt● http://wiki.rtems.org/wiki/index.php/Building_Tools● http://rtems.org/wiki/index.php/APT/Yum_Repository● http://www.rtems.org/wiki/index.php/Quick_Start● http://www.rtems.com/wiki/index.php/GeneralInformation● http://wiki.rtems.org/wiki/index.php/Git_Users● http://rtems.org/wiki/index.php/RTEMSMailingLists● http://gedare-csphd.blogspot.fr/2013/05/software-licenses-with-rtems.html● http://irit.fr/ETR13/static/files/sherrill.pdf● http://gedare-csphd.blogspot.fr/2010/12/rtems-adding-new-scheduler.html● http://flightsoftware.jhuapl.edu/files/2013/talks/FSW-13-TALKS/FSW-RTEMS-JoelSherrill-
2013.pdf● Article P. FICHEUX dans LinuxMag HS Raspberry Pi « avancé »