Zephyr est un OS temps réel, compact, destiné à l’Internet des objets. C’est un projet collaboratif de la Linux Foundation.
Dans cet article nous allons le tester sur une base PC à l’aide de l’émulateur qemu
.
Le kernel Zephyr est un noyau de taille réduite disponible à ce jour pour les architectures x86, ARM v7 (Cortex M) et ARC (Arduino).
Il est placé sous licence Apache v2.0.
Ses principales caractéristiques sont :
L’environnement de développement peut être :
Dans notre cas nous allons travailler sur Linux (Ubuntu 16.04 LTS) sur une machine 64 bits.
Installons tout d’abord les prérequis de la machine de développement :
cch@cch-acer:~$ sudo apt-get install git make gcc gcc-multilib g++ libc6-dev-i386 g++-multilib python3-ply [sudo] Mot de passe de cch : Lecture des listes de paquets... Fait Construction de l'arbre des dépendances Lecture des informations d'état... Fait g++ is already the newest version (4:5.3.1-1ubuntu1). g++ passé en « installé manuellement ». gcc is already the newest version (4:5.3.1-1ubuntu1). gcc passé en « installé manuellement ». gcc-multilib is already the newest version (4:5.3.1-1ubuntu1). git is already the newest version (1:2.7.4-0ubuntu1). libc6-dev-i386 is already the newest version (2.23-0ubuntu3). libc6-dev-i386 passé en « installé manuellement ». make is already the newest version (4.1-6). make passé en « installé manuellement ». Les paquets suivants ont été installés automatiquement et ne sont plus nécessaires : cryptsetup dropbear-bin dropbear-initramfs dropbear-run spawn-fcgi Veuillez utiliser « sudo apt autoremove » pour les supprimer. The following additional packages will be installed: g++-5-multilib lib32stdc++-5-dev libx32stdc++-5-dev Paquets suggérés : lib32stdc++6-5-dbg libx32stdc++6-5-dbg python-ply-doc Les NOUVEAUX paquets suivants seront installés : g++-5-multilib g++-multilib lib32stdc++-5-dev libx32stdc++-5-dev python3-ply 0 mis à jour, 5 nouvellement installés, 0 à enlever et 68 non mis à jour. Il est nécessaire de prendre 1 291 ko dans les archives. Après cette opération, 19,5 Mo d'espace disque supplémentaires seront utilisés. Souhaitez-vous continuer ? [O/n] Réception de:1 http://fr.archive.ubuntu.com/ubuntu xenial/main amd64 lib32stdc++-5-dev amd64 5.3.1-14ubuntu2 [636 kB] Réception de:2 http://fr.archive.ubuntu.com/ubuntu xenial/main amd64 libx32stdc++-5-dev amd64 5.3.1-14ubuntu2 [608 kB] Réception de:3 http://fr.archive.ubuntu.com/ubuntu xenial/main amd64 g++-5-multilib amd64 5.3.1-14ubuntu2 [978 B] Réception de:4 http://fr.archive.ubuntu.com/ubuntu xenial/main amd64 g++-multilib amd64 4:5.3.1-1ubuntu1 [940 B] Réception de:5 http://fr.archive.ubuntu.com/ubuntu xenial/universe amd64 python3-ply all 3.7-1 [46,2 kB] 1 291 ko réceptionnés en 1s (720 ko/s) Sélection du paquet lib32stdc++-5-dev précédemment désélectionné. (Lecture de la base de données... 330559 fichiers et répertoires déjà installés.) Préparation du dépaquetage de .../lib32stdc++-5-dev_5.3.1-14ubuntu2_amd64.deb ... Dépaquetage de lib32stdc++-5-dev (5.3.1-14ubuntu2) ... Sélection du paquet libx32stdc++-5-dev précédemment désélectionné. Préparation du dépaquetage de .../libx32stdc++-5-dev_5.3.1-14ubuntu2_amd64.deb ... Dépaquetage de libx32stdc++-5-dev (5.3.1-14ubuntu2) ... Sélection du paquet g++-5-multilib précédemment désélectionné. Préparation du dépaquetage de .../g++-5-multilib_5.3.1-14ubuntu2_amd64.deb ... Dépaquetage de g++-5-multilib (5.3.1-14ubuntu2) ... Sélection du paquet g++-multilib précédemment désélectionné. Préparation du dépaquetage de .../g++-multilib_4%3a5.3.1-1ubuntu1_amd64.deb ... Dépaquetage de g++-multilib (4:5.3.1-1ubuntu1) ... Sélection du paquet python3-ply précédemment désélectionné. Préparation du dépaquetage de .../python3-ply_3.7-1_all.deb ... Dépaquetage de python3-ply (3.7-1) ... Traitement des actions différées (« triggers ») pour man-db (2.7.5-1) ... Paramétrage de lib32stdc++-5-dev (5.3.1-14ubuntu2) ... Paramétrage de libx32stdc++-5-dev (5.3.1-14ubuntu2) ... Paramétrage de g++-5-multilib (5.3.1-14ubuntu2) ... Paramétrage de g++-multilib (4:5.3.1-1ubuntu1) ... Paramétrage de python3-ply (3.7-1) ... cch@cch-acer:~$
ll faut maintenant télécharger et installer le SDK à partir du répertoire dédié. L’installeur se présente sous la forme d’une archive auto extractible qui sera exécutée dans le répertoire de test /media/yocto-1504/IoT/zephyr
.
cch@cch-acer:/media/yocto-1504/IoT/zephyr$ wget https://nexus.zephyrproject.org/content/repositories/releases/org/zephyrproject/zephyr-sdk/0.8-i686/zephyr-sdk-0.8-i686-setup.run --2016-05-23 10:51:18-- https://nexus.zephyrproject.org/content/repositories/releases/org/zephyrproject/zephyr-sdk/0.8-i686/zephyr-sdk-0.8-i686-setup.run Résolution de nexus.zephyrproject.org (nexus.zephyrproject.org)… 199.19.213.246 Connexion à nexus.zephyrproject.org (nexus.zephyrproject.org)|199.19.213.246|:443… connecté. requête HTTP transmise, en attente de la réponse… 200 OK Taille : 378809314 (361M) [application/octet-stream] Enregistre : «zephyr-sdk-0.8-i686-setup.run» zephyr-sdk-0.8-i686-setu 100%[==================================>] 361,26M 414KB/s in 5m 16s 2016-05-23 10:56:35 (1,14 MB/s) - «zephyr-sdk-0.8-i686-setup.run» enregistré [378809314/378809314] cch@cch-acer:/media/yocto-1504/IoT/zephyr$
Lançons l’installation du SDK :
cch@cch-acer:/media/yocto-1504/IoT/zephyr$ ./zephyr-sdk-0.8-i686-setup.run Verifying archive integrity... All good. Uncompressing SDK for Zephyr 100% Enter target directory for SDK (default: /opt/zephyr-sdk/): /media/yocto-1504/IoT/zephyr/zephyr-sdk Installing SDK to /media/yocto-1504/IoT/zephyr/zephyr-sdk Creating directory /media/yocto-1504/IoT/zephyr/zephyr-sdk Success [*] Installing x86 tools... [*] Installing arm tools... [*] Installing arc tools... [*] Installing iamcu tools... [*] Installing mips tools... [*] Installing nios2 tools... [*] Installing additional host tools... Success installing SDK. SDK is ready to be used.
On remarque que l’installation concerne les outils pour toutes les architectures supportées. Le SDK installé, nous pouvons maintenant télécharger le code de Zephyr.
cch@cch-acer:/media/yocto-1504/IoT/zephyr$ git clone https://gerrit.zephyrproject.org/r/zephyr zephyr-project Clonage dans 'zephyr-project'... remote: Counting objects: 3026, done remote: Finding sources: 100% (35/35) remote: Total 68647 (delta 0), reused 68626 (delta 0) Réception d'objets: 100% (68647/68647), 22.50 MiB | 331.00 KiB/s, fait. Résolution des deltas: 100% (45258/45258), fait. Vérification de la connectivité... fait. cch@cch-acer:/media/yocto-1504/IoT/zephyr$ ls zephyr-project zephyr-sdk zephyr-sdk-0.8-i686-setup.run
Allons voir le code source téléchargé. Au 1er coup d’oeil on constate une similitude avec le code kernel Linux (en plus léger). Ceci est confirmé avec la présence du système de configuration et de compilation Kbuild
, pour lequel on retrouve des fichiers de configuration Kconfig
et des fichiers Makefile
similaires à ceux de Linux.
Le répertoire samples
offre divers programmes d’exemple qui vont nous servir à réaliser les 1ers tests.
Avant de lancer la 1ère compilation, nous devons définir correctement l’environnement :
cch@cch-acer:/media/yocto-1504/IoT/zephyr$ export ZEPHYR_GCC_VARIANT=zephyr cch@cch-acer:/media/yocto-1504/IoT/zephyr$ export ZEPHYR_SDK_INSTALL_DIR=/media/yocto-1504/IoT/zephyr/zephyr-sdk cch@cch-acer:/media/yocto-1504/IoT/zephyr$ cd zephyr-project cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project$ source zephyr-env.sh cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project$ env | grep ZEPHYR ZEPHYR_SDK_INSTALL_DIR=/media/yocto-1504/IoT/zephyr/zephyr-sdk ZEPHYR_BASE=/media/yocto-1504/IoT/zephyr/zephyr-project ZEPHYR_GCC_VARIANT=zephyr
Commençons par le traditionnel Hello world
.
Tout d’abord positionnons nous dans le répertoire des sources correspondant :
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project$ cd $ZEPHYR_BASE/samples/hello_world/microkernel
Nous pouvons obtenir de l’aide sur les différentes options de compilation à l’aide de make help
:
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ make help Cleaning targets: clean - Remove most generated files but keep configuration and backup files mrproper - Remove all generated files + config + various backup files distclean - mrproper + remove editor backup and patch files pristine - Remove the output directory with all generated files Configuration targets: run Other generic targets: all - Build all targets marked with [*] * zephyr - Build a zephyr application qemu - Build a zephyr application and run it in qemu flash - Build and flash an application debug - Build and debug an application using GDB Supported Boards: To build an image for one of the supported boards below, run: make BOARD= in the application directory. To flash the image (if supported), run: make BOARD= flash make BOARD=altera_max10 - Build for altera_max10 make BOARD=arduino_101 - Build for arduino_101 make BOARD=arduino_101_factory - Build for arduino_101_factory make BOARD=arduino_101_sss - Build for arduino_101_sss make BOARD=arduino_101_sss_factory - Build for arduino_101_sss_factory make BOARD=arduino_due - Build for arduino_due make BOARD=basic_cortex_m3 - Build for basic_cortex_m3 make BOARD=basic_minuteia - Build for basic_minuteia make BOARD=frdm_k64f - Build for frdm_k64f make BOARD=galileo - Build for galileo make BOARD=minnowboard - Build for minnowboard make BOARD=nucleo_f103rb - Build for nucleo_f103rb make BOARD=olimexino_stm32 - Build for olimexino_stm32 make BOARD=qemu_cortex_m3 - Build for qemu_cortex_m3 make BOARD=qemu_x86 - Build for qemu_x86 make BOARD=qemu_x86_iamcu - Build for qemu_x86_iamcu make BOARD=quark_d2000_crb - Build for quark_d2000_crb make BOARD=quark_se_devboard - Build for quark_se_devboard make BOARD=quark_se_sss_devboard - Build for quark_se_sss_devboard make BOARD=stm32_mini_a15 - Build for stm32_mini_a15 Build flags: make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build make V=2 [targets] 2 => give reason for rebuild of target make O=dir [targets] Locate all output files in "dir", including .config make C=1 [targets] Check all c source with $CHECK (sparse by default) make C=2 [targets] Force check of all c source with $CHECK make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections make W=n [targets] Enable extra gcc checks, n=1,2,3 where 1: warnings which may be relevant and do not occur too often 2: warnings which occur quite often but may still be relevant 3: more obscure warnings, can most likely be ignored Multiple levels can be combined with W=12 or W=123 Execute "make" or "make all" to build all targets marked with [*]
On retrouve des options liées à l’utilisation de Kbuild
telle que make V=1
pour avoir un build verbeux, make O=dir
pour générer une compilation out of tree.
make BOARD=
permet de sélectionner la machine cible désirée. Nous ferons ces premiers essais sous qemu
donc nous choisissons la machine qemu_x86
.
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ make BOARD=qemu_x86 Using /media/yocto-1504/IoT/zephyr/zephyr-project/boards/qemu_x86/qemu_x86_defconfig as base Merging /media/yocto-1504/IoT/zephyr/zephyr-project/kernel/configs/micro.config Merging prj.conf # # configuration written to .config # make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel/outdir » GEN ./Makefile scripts/kconfig/conf --silentoldconfig Kconfig Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h UPD include/generated/version.h HOSTCC scripts/gen_idt/gen_idt.o HOSTLD scripts/gen_idt/gen_idt CHK misc/generated/configs.c UPD misc/generated/configs.c CHK include/generated/offsets.h UPD include/generated/offsets.h CHK misc/generated/sysgen/prj.mdef UPD misc/generated/sysgen/prj.mdef LD lib/crypto/built-in.o LD lib/libc/minimal/source/stdlib/built-in.o CC lib/libc/minimal/source/stdout/fprintf.o CC lib/libc/minimal/source/stdout/prf.o CC lib/libc/minimal/source/stdout/sprintf.o CC lib/libc/minimal/source/stdout/stdout_console.o LD lib/libc/minimal/source/stdout/built-in.o CC lib/libc/minimal/source/string/string.o LD lib/libc/minimal/source/string/built-in.o LD lib/libc/minimal/source/built-in.o LD lib/libc/minimal/built-in.o LD lib/libc/built-in.o LD lib/built-in.o CC kernel/microkernel/k_task.o CC kernel/microkernel/k_idle.o CC kernel/microkernel/k_init.o CC kernel/microkernel/k_command_packet.o CC kernel/microkernel/k_move_data.o CC kernel/microkernel/k_ticker.o CC kernel/microkernel/k_memory_map.o CC kernel/microkernel/k_memory_pool.o CC kernel/microkernel/k_irq.o CC kernel/microkernel/k_nop.o CC kernel/microkernel/k_offload.o CC kernel/microkernel/k_event.o CC kernel/microkernel/k_mailbox.o CC kernel/microkernel/k_mutex.o CC kernel/microkernel/k_fifo.o CC kernel/microkernel/k_semaphore.o CC kernel/microkernel/k_timer.o CC kernel/microkernel/k_pipe_buffer.o CC kernel/microkernel/k_pipe.o CC kernel/microkernel/k_pipe_get.o CC kernel/microkernel/k_pipe_put.o CC kernel/microkernel/k_pipe_util.o CC kernel/microkernel/k_pipe_xfer.o CC kernel/microkernel/k_nano.o CC kernel/microkernel/k_server.o LD kernel/microkernel/built-in.o CC kernel/nanokernel/nano_fiber.o CC kernel/nanokernel/nano_lifo.o CC kernel/nanokernel/nano_fifo.o CC kernel/nanokernel/nano_stack.o CC kernel/nanokernel/nano_sys_clock.o CC kernel/nanokernel/nano_context.o CC kernel/nanokernel/nano_init.o CC kernel/nanokernel/nano_sema.o CC kernel/nanokernel/version.o CC kernel/nanokernel/device.o CC kernel/nanokernel/errno.o LD kernel/nanokernel/built-in.o LD kernel/built-in.o CC misc/printk.o LD misc/debug/built-in.o CC misc/generated/configs.o CC misc/generated/sysgen/kernel_main.o LD misc/generated/sysgen/built-in.o LD misc/generated/built-in.o LD misc/built-in.o LD net/built-in.o CC boards/qemu_x86/board.o LD boards/qemu_x86/built-in.o LD boards/built-in.o AS arch/x86/core/i386_sysV_abi/intstub.o AS arch/x86/core/i386_sysV_abi/swap.o CC arch/x86/core/i386_sysV_abi/thread.o LD arch/x86/core/i386_sysV_abi/built-in.o CC arch/x86/core/fatal.o CC arch/x86/core/cpuhalt.o CC arch/x86/core/msr.o CC arch/x86/core/dynamic.o CC arch/x86/core/intconnect.o CC arch/x86/core/excconnect.o CC arch/x86/core/sys_fatal_error_handler.o AS arch/x86/core/crt0.o CC arch/x86/core/atomic.o AS arch/x86/core/cache_s.o CC arch/x86/core/cache.o AS arch/x86/core/excstub.o CC arch/x86/core/strtask.o LD arch/x86/core/built-in.o CC arch/x86/soc/ia32/soc.o LD arch/x86/soc/ia32/built-in.o LD arch/x86/built-in.o LD arch/built-in.o CC drivers/console/uart_console.o LD drivers/console/built-in.o CC drivers/interrupt_controller/i8259.o CC drivers/interrupt_controller/system_apic.o CC drivers/interrupt_controller/loapic_intr.o CC drivers/interrupt_controller/ioapic_intr.o LD drivers/interrupt_controller/built-in.o LD drivers/random/built-in.o CC drivers/serial/uart_ns16550.o LD drivers/serial/built-in.o CC drivers/timer/hpet.o CC drivers/timer/sys_clock_init.o LD drivers/timer/built-in.o LD drivers/built-in.o CC samples/hello_world/microkernel/src/main.o LD samples/hello_world/microkernel/src/built-in.o LINK zephyr.lnk SIDT staticIdt.o LINK zephyr.elf BIN zephyr.bin make[2] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel/outdir » make[1] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project »
La compilation a lieu par défaut dans le répertoire outdir
et nous y trouvons les fichiers zephyr.elf
et zephyr.strip
qui constituent le résultat final.
zephyr.elf
est l’exécutable au format ELF et zephyr.strip
est le même exécutable strippé.
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ file outdir/zephyr.elf outdir/zephyr.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ file outdir/zephyr.strip outdir/zephyr.strip: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$
Nous pouvons maintenant tester l’application dans qemu
:
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ make BOARD=qemu_x86 qemu make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel/outdir » Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h CHK misc/generated/configs.c CHK include/generated/offsets.h CHK misc/generated/sysgen/prj.mdef To exit from QEMU enter: 'CTRL+a, x' [QEMU] CPU: qemu32 Hello World!
On obtient bien le message Hello World attendu. L’image strippé occupe 18 kilo octets.
Prenons un exemple un peu plus consistant, qui comporte 2 tâches et des problèmes de synchronisation basé sur des sémaphores.
Les 2 tâches écrivent Hello World sur la console, mais l’accès à la console est réglé par 2 sémaphores.
Regardons le code :
/* hello.c - Hello World demo */ /* * Copyright (c) 2012-2014 Wind River Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #if defined(CONFIG_STDOUT_CONSOLE) #include #define PRINT printf #else #include#define PRINT printk #endif /* * Microkernel version of hello world demo has two tasks that utilize * semaphores and sleeps to take turns printing a greeting message at * a controlled rate. */ /* specify delay between greetings (in ms); compute equivalent in ticks */ #define SLEEPTIME 500 #define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000) /* * * @param taskname task identification string * @param mySem task's own semaphore * @param otherSem other task's semaphore * */ void helloLoop(const char *taskname, ksem_t mySem, ksem_t otherSem) { while (1) { task_sem_take(mySem, TICKS_UNLIMITED); /* say "hello" */ PRINT("%s: Hello World!\n", taskname); /* wait a while, then let other task have a turn */ task_sleep(SLEEPTICKS); task_sem_give(otherSem); } } void taskA(void) { /* taskA gives its own semaphore, allowing it to say hello right away */ task_sem_give(TASKASEM); /* invoke routine that allows task to ping-pong hello messages with taskB */ helloLoop(__func__, TASKASEM, TASKBSEM); } void taskB(void) { /* invoke routine that allows task to ping-pong hello messages with taskA */ helloLoop(__func__, TASKBSEM, TASKASEM); }
Nous voyons que le code manipule 2 tâches taskA
et taskB
qui se synchronisent à l’aide des sémaphores TASKASEM
et TASKBSEM
. Par contre nous remarquons que ni les tâches ni les sémaphores ne sont définis explicitement.
Ces objets systèmes sont en fait créés par le fichier prj.mdef
:
% Application : Hello demo % TASK NAME PRIO ENTRY STACK GROUPS % ================================== TASK TASKA 7 taskA 1024 [EXE] TASK TASKB 7 taskB 1024 [EXE] % SEMA NAME % ============= SEMA TASKASEM SEMA TASKBSEM
On peut remarquer que ce fichier définit également la priorité des tâches ainsi que la taille de leur stack.
Enfin explorons le fichier prj.conf
qui définit la configuration du kernel retenue :
CONFIG_STDOUT_CONSOLE=y
C’est le fichier Makefile
qui fait le lien entre ces divers éléments, en se basant sur ${ZEPHYR_BASE}/Makefile.inc
:
MDEF_FILE = prj.mdef KERNEL_TYPE = micro BOARD ?= qemu_x86 CONF_FILE = prj.conf include ${ZEPHYR_BASE}/Makefile.inc
Lançons la compilation et étudions quelques points supplémentaires (comme la board par défaut est qemu_x86
, on peut se dispenser de la définir lorsque l’on lance make
) :
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/hello_world/microkernel$ cd ../../synchronization/microkernel/ cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel$ make Using /media/yocto-1504/IoT/zephyr/zephyr-project/boards/qemu_x86/qemu_x86_defconfig as base Merging /media/yocto-1504/IoT/zephyr/zephyr-project/kernel/configs/micro.config Merging prj.conf # # configuration written to .config # make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel/outdir » GEN ./Makefile scripts/kconfig/conf --silentoldconfig Kconfig Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h UPD include/generated/version.h HOSTCC scripts/gen_idt/gen_idt.o HOSTLD scripts/gen_idt/gen_idt CHK misc/generated/configs.c UPD misc/generated/configs.c CHK include/generated/offsets.h UPD include/generated/offsets.h CHK misc/generated/sysgen/prj.mdef UPD misc/generated/sysgen/prj.mdef LD lib/crypto/built-in.o LD lib/libc/minimal/source/stdlib/built-in.o CC lib/libc/minimal/source/stdout/fprintf.o CC lib/libc/minimal/source/stdout/prf.o CC lib/libc/minimal/source/stdout/sprintf.o CC lib/libc/minimal/source/stdout/stdout_console.o LD lib/libc/minimal/source/stdout/built-in.o CC lib/libc/minimal/source/string/string.o LD lib/libc/minimal/source/string/built-in.o LD lib/libc/minimal/source/built-in.o LD lib/libc/minimal/built-in.o LD lib/libc/built-in.o LD lib/built-in.o CC kernel/microkernel/k_task.o CC kernel/microkernel/k_idle.o CC kernel/microkernel/k_init.o CC kernel/microkernel/k_command_packet.o CC kernel/microkernel/k_move_data.o CC kernel/microkernel/k_ticker.o CC kernel/microkernel/k_memory_map.o CC kernel/microkernel/k_memory_pool.o CC kernel/microkernel/k_irq.o CC kernel/microkernel/k_nop.o CC kernel/microkernel/k_offload.o CC kernel/microkernel/k_event.o CC kernel/microkernel/k_mailbox.o CC kernel/microkernel/k_mutex.o CC kernel/microkernel/k_fifo.o CC kernel/microkernel/k_semaphore.o CC kernel/microkernel/k_timer.o CC kernel/microkernel/k_pipe_buffer.o CC kernel/microkernel/k_pipe.o CC kernel/microkernel/k_pipe_get.o CC kernel/microkernel/k_pipe_put.o CC kernel/microkernel/k_pipe_util.o CC kernel/microkernel/k_pipe_xfer.o CC kernel/microkernel/k_nano.o CC kernel/microkernel/k_server.o LD kernel/microkernel/built-in.o CC kernel/nanokernel/nano_fiber.o CC kernel/nanokernel/nano_lifo.o CC kernel/nanokernel/nano_fifo.o CC kernel/nanokernel/nano_stack.o CC kernel/nanokernel/nano_sys_clock.o CC kernel/nanokernel/nano_context.o CC kernel/nanokernel/nano_init.o CC kernel/nanokernel/nano_sema.o CC kernel/nanokernel/version.o CC kernel/nanokernel/device.o CC kernel/nanokernel/errno.o LD kernel/nanokernel/built-in.o LD kernel/built-in.o CC misc/printk.o LD misc/debug/built-in.o CC misc/generated/configs.o CC misc/generated/sysgen/kernel_main.o LD misc/generated/sysgen/built-in.o LD misc/generated/built-in.o LD misc/built-in.o LD net/built-in.o CC boards/qemu_x86/board.o LD boards/qemu_x86/built-in.o LD boards/built-in.o AS arch/x86/core/i386_sysV_abi/intstub.o AS arch/x86/core/i386_sysV_abi/swap.o CC arch/x86/core/i386_sysV_abi/thread.o LD arch/x86/core/i386_sysV_abi/built-in.o CC arch/x86/core/fatal.o CC arch/x86/core/cpuhalt.o CC arch/x86/core/msr.o CC arch/x86/core/dynamic.o CC arch/x86/core/intconnect.o CC arch/x86/core/excconnect.o CC arch/x86/core/sys_fatal_error_handler.o AS arch/x86/core/crt0.o CC arch/x86/core/atomic.o AS arch/x86/core/cache_s.o CC arch/x86/core/cache.o AS arch/x86/core/excstub.o CC arch/x86/core/strtask.o LD arch/x86/core/built-in.o CC arch/x86/soc/ia32/soc.o LD arch/x86/soc/ia32/built-in.o LD arch/x86/built-in.o LD arch/built-in.o CC drivers/console/uart_console.o LD drivers/console/built-in.o CC drivers/interrupt_controller/i8259.o CC drivers/interrupt_controller/system_apic.o CC drivers/interrupt_controller/loapic_intr.o CC drivers/interrupt_controller/ioapic_intr.o LD drivers/interrupt_controller/built-in.o LD drivers/random/built-in.o CC drivers/serial/uart_ns16550.o LD drivers/serial/built-in.o CC drivers/timer/hpet.o CC drivers/timer/sys_clock_init.o LD drivers/timer/built-in.o LD drivers/built-in.o CC samples/synchronization/microkernel/src/main.o LD samples/synchronization/microkernel/src/built-in.o LINK zephyr.lnk SIDT staticIdt.o LINK zephyr.elf BIN zephyr.bin make[2] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel/outdir » make[1] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project »
Étudions tout d’abord la configuration.
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel$ make Using /media/yocto-1504/IoT/zephyr/zephyr-project/boards/qemu_x86/qemu_x86_defconfig as base Merging /media/yocto-1504/IoT/zephyr/zephyr-project/kernel/configs/micro.config Merging prj.conf ...
Celle ci est le résultat de plusieurs éléments :
/media/yocto-1504/IoT/zephyr/zephyr-project/boards/qemu_x86/qemu_x86_defconfig
nano
ou micro
: /media/yocto-1504/IoT/zephyr/zephyr-project/kernel/configs/micro.config
. Ici c’est un micro kernel tel que défini dans le Makefile
prj.conf
, qui définit la configuration propre à l’applicationLe fichier qemu_x86_defconfig
définit les variables de configuration propres à la carte retenue :
CONFIG_X86=y CONFIG_SOC_IA32=y CONFIG_BOARD_QEMU_X86=y CONFIG_CPU_MINUTEIA=y CONFIG_IA32_LEGACY_IO_PORTS=y CONFIG_HPET_TIMER=y CONFIG_HPET_TIMER_IRQ=2 CONFIG_HPET_TIMER_LEGACY_EMULATION=y CONFIG_HPET_TIMER_RISING_EDGE=y CONFIG_PIC_DISABLE=y CONFIG_LOAPIC=y CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_NS16550=y CONFIG_UART_CONSOLE=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=25000000
Le fichier micro.config
sélectionne un kernel de type micro
:
CONFIG_MICROKERNEL=y
Enfin le fichier prj.conf
sélectionne la console :
CONFIG_STDOUT_CONSOLE=y
Au final le fichier de configuration globale outdir/.config
résume la configuration finale du kernel Zephyr.
# # Automatically generated file; DO NOT EDIT. # Zephyr Kernel Configuration # # CONFIG_ARC is not set # CONFIG_ARM is not set CONFIG_X86=y # CONFIG_NIOS2 is not set # CONFIG_SYS_POWER_LOW_POWER_STATE_SUPPORTED is not set # CONFIG_SYS_POWER_DEEP_SLEEP_SUPPORTED is not set CONFIG_ARCH="x86" CONFIG_SOC="ia32" CONFIG_BOARD="qemu_x86" CONFIG_ARCH_DEFCONFIG="arch/x86/defconfig" # CONFIG_IRQ_OFFLOAD is not set # CONFIG_XIP is not set # CONFIG_SOC_ATOM is not set CONFIG_SOC_IA32=y # CONFIG_SOC_QUARK_D2000 is not set # CONFIG_SOC_QUARK_SE is not set # CONFIG_SOC_QUARK_X1000 is not set # # x86 Options # # # x86 Core Options # CONFIG_NESTED_INTERRUPTS=y CONFIG_EXCEPTION_DEBUG=y # # Memory Layout Options # CONFIG_IDT_NUM_VECTORS=256 CONFIG_MAX_IRQ_LINES=128 CONFIG_PHYS_LOAD_ADDR=0x00100000 CONFIG_PHYS_RAM_ADDR=0x00400000 CONFIG_RAM_SIZE=192 # CONFIG_GDT_DYNAMIC is not set # CONFIG_DEBUG_IRQS is not set CONFIG_CPU_MINUTEIA=y CONFIG_CPU_HAS_FPU=y # # Processor Capabilities # # CONFIG_X86_IAMCU is not set # # Floating Point Options # # CONFIG_FLOAT is not set CONFIG_ISA_IA32=y CONFIG_IA32_LEGACY_IO_PORTS=y # CONFIG_CMOV is not set CONFIG_CACHE_LINE_SIZE_DETECT=y CONFIG_CACHE_LINE_SIZE=0 # CONFIG_CACHE_FLUSHING is not set # # Platform Capabilities # CONFIG_NUM_DYNAMIC_STUBS=0 CONFIG_NUM_DYNAMIC_EXC_STUBS=0 CONFIG_NUM_DYNAMIC_EXC_NOERR_STUBS=0 CONFIG_PIC_DISABLE=y # CONFIG_BOARD_BASIC_MINUTEIA is not set CONFIG_BOARD_QEMU_X86=y # # Board Options # # CONFIG_NANOKERNEL is not set CONFIG_MICROKERNEL=y # # General Kernel Options # CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=25000000 CONFIG_SYS_CLOCK_EXISTS=y # CONFIG_INIT_STACKS is not set # CONFIG_RING_BUFFER is not set # CONFIG_KERNEL_EVENT_LOGGER is not set # CONFIG_THREAD_MONITOR is not set CONFIG_KERNEL_INIT_PRIORITY_DEFAULT=40 CONFIG_KERNEL_INIT_PRIORITY_DEVICE=50 # # Security Options # # CONFIG_STACK_CANARIES is not set # # Nanokernel Options # # CONFIG_BUILD_TIMESTAMP is not set # CONFIG_INT_LATENCY_BENCHMARK is not set CONFIG_MAIN_STACK_SIZE=1024 CONFIG_ISR_STACK_SIZE=2048 # CONFIG_THREAD_CUSTOM_DATA is not set # CONFIG_NANO_TIMEOUTS is not set # CONFIG_NANO_TIMERS is not set CONFIG_NANOKERNEL_TICKLESS_IDLE_SUPPORTED=y CONFIG_ERRNO=y # CONFIG_ATOMIC_OPERATIONS_C is not set # CONFIG_NANO_WORKQUEUE is not set # # Microkernel Options # CONFIG_MICROKERNEL_SERVER_STACK_SIZE=1024 CONFIG_MICROKERNEL_SERVER_PRIORITY=0 CONFIG_PRIORITY_CEILING=0 CONFIG_COMMAND_STACK_SIZE=64 CONFIG_NUM_COMMAND_PACKETS=16 CONFIG_NUM_TIMER_PACKETS=10 CONFIG_NUM_TASK_PRIORITIES=16 # CONFIG_WORKLOAD_MONITOR is not set CONFIG_MAX_NUM_TASK_IRQS=0 # # Timer API Options # CONFIG_TIMESLICING=y CONFIG_TIMESLICE_SIZE=0 CONFIG_TIMESLICE_PRIORITY=0 # CONFIG_OBJECT_MONITOR is not set # # Power Management # # CONFIG_SYS_POWER_MANAGEMENT is not set # # Device Drivers # CONFIG_CONSOLE=y CONFIG_CONSOLE_HAS_DRIVER=y # CONFIG_CONSOLE_HANDLER is not set CONFIG_UART_CONSOLE=y CONFIG_UART_CONSOLE_ON_DEV_NAME="UART_0" CONFIG_UART_CONSOLE_INIT_PRIORITY=60 # CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS is not set # CONFIG_RAM_CONSOLE is not set # CONFIG_IPM_CONSOLE_SENDER is not set # CONFIG_IPM_CONSOLE_RECEIVER is not set # CONFIG_UART_PIPE is not set CONFIG_SERIAL=y # # Capabilities # CONFIG_SERIAL_HAS_DRIVER=y # CONFIG_UART_INTERRUPT_DRIVEN is not set # CONFIG_UART_LINE_CTRL is not set # CONFIG_UART_DRV_CMD is not set # # Serial Drivers # CONFIG_UART_NS16550=y # CONFIG_UART_NS16550_PCI is not set # CONFIG_UART_NS16550_DLF is not set CONFIG_UART_NS16550_PORT_0=y CONFIG_UART_NS16550_PORT_0_NAME="UART_0" CONFIG_UART_NS16550_PORT_0_IRQ_PRI=3 CONFIG_UART_NS16550_PORT_0_BAUD_RATE=115200 CONFIG_UART_NS16550_PORT_0_OPTIONS=0 CONFIG_UART_NS16550_PORT_1=y CONFIG_UART_NS16550_PORT_1_NAME="UART_1" CONFIG_UART_NS16550_PORT_1_IRQ_PRI=3 CONFIG_UART_NS16550_PORT_1_BAUD_RATE=115200 CONFIG_UART_NS16550_PORT_1_OPTIONS=0 # CONFIG_UART_K20 is not set # CONFIG_UART_STELLARIS is not set # # Interrupt Controllers # CONFIG_LOAPIC=y CONFIG_LOAPIC_BASE_ADDRESS=0xFEE00000 # CONFIG_LOAPIC_SPURIOUS_VECTOR is not set CONFIG_IOAPIC=y # CONFIG_IOAPIC_DEBUG is not set CONFIG_IOAPIC_BASE_ADDRESS=0xFEC00000 CONFIG_IOAPIC_NUM_RTES=24 # CONFIG_MVIC is not set # # Timer Drivers # CONFIG_HPET_TIMER=y CONFIG_HPET_TIMER_LEGACY_EMULATION=y # CONFIG_HPET_TIMER_DEBUG is not set CONFIG_HPET_TIMER_BASE_ADDRESS=0xFED00000 CONFIG_HPET_TIMER_IRQ=2 CONFIG_HPET_TIMER_IRQ_PRIORITY=4 # CONFIG_HPET_TIMER_FALLING_EDGE is not set CONFIG_HPET_TIMER_RISING_EDGE=y # CONFIG_HPET_TIMER_LEVEL_HIGH is not set # CONFIG_HPET_TIMER_LEVEL_LOW is not set # CONFIG_LOAPIC_TIMER is not set # CONFIG_SYSTEM_CLOCK_DISABLE is not set CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y CONFIG_SYSTEM_CLOCK_INIT_PRIORITY=0 # # Random Generation Configuration # # CONFIG_RANDOM_GENERATOR is not set # CONFIG_TEST_RANDOM_GENERATOR is not set # CONFIG_GROVE is not set # CONFIG_PCI is not set # CONFIG_GPIO is not set # CONFIG_SHARED_IRQ is not set # CONFIG_SPI is not set # CONFIG_I2C is not set # CONFIG_PWM is not set # CONFIG_PINMUX is not set # CONFIG_ADC is not set CONFIG_ADC_INIT_PRIORITY=80 CONFIG_ADC_0_NAME="ADC_0" CONFIG_ADC_0_IRQ_PRI=2 # CONFIG_RTC is not set # CONFIG_WATCHDOG is not set # CONFIG_CLOCK_CONTROL is not set # CONFIG_IPM is not set # CONFIG_AIO_COMPARATOR is not set # CONFIG_QMSI_BUILTIN is not set # CONFIG_QMSI_LIBRARY is not set # CONFIG_QMSI is not set # CONFIG_FLASH is not set # CONFIG_SENSOR is not set # CONFIG_COUNTER is not set # # Networking # # CONFIG_BLUETOOTH is not set # CONFIG_NETWORKING is not set # CONFIG_NET_BUF is not set # # Compile and Link Features # CONFIG_KERNEL_BIN_NAME="zephyr" # CONFIG_HAVE_CUSTOM_LINKER_SCRIPT is not set # CONFIG_VERSION_HEADER is not set CONFIG_CROSS_COMPILE="" # CONFIG_GDB_INFO is not set # CONFIG_LINK_WHOLE_ARCHIVE is not set CONFIG_COMPILER_OPT="" CONFIG_TOOLCHAIN_VARIANT="" # CONFIG_CPLUSPLUS is not set CONFIG_MINIMAL_LIBC=y # CONFIG_NEWLIB_LIBC is not set # CONFIG_MINIMAL_LIBC_EXTENDED is not set # # Debugging Options # # CONFIG_DEBUG is not set # CONFIG_TASK_DEBUG is not set # CONFIG_STACK_USAGE is not set CONFIG_PRINTK=y CONFIG_STDOUT_CONSOLE=y # CONFIG_EARLY_CONSOLE is not set # CONFIG_ASSERT is not set # CONFIG_DEBUG_TRACING_KERNEL_OBJECTS is not set # # Safe memory access # # CONFIG_MEM_SAFE is not set # CONFIG_DEBUGGER_OWNS_FATAL_PROG_EXC_HANDLERS is not set # CONFIG_DEBUG_INFO is not set # CONFIG_GDB_SERVER is not set # # Logging Options # # CONFIG_SYS_LOG is not set # # System Monitoring Options # # CONFIG_PERFORMANCE_METRICS is not set # # Boot Options # # CONFIG_BOOTLOADER_KEXEC is not set CONFIG_BOOTLOADER_UNKNOWN=y # CONFIG_REBOOT is not set # # Cryptography # # CONFIG_TINYCRYPT is not set
Notons également que suite à la configuration la compilation concerne divers éléments dont les principaux sont relatifs :
Lançons l’exécution pour constater l’alternat des 2 tâches qui ont même priorité :
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel$ make qemu make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel/outdir » Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h CHK misc/generated/configs.c CHK include/generated/offsets.h CHK misc/generated/sysgen/prj.mdef To exit from QEMU enter: 'CTRL+a, x' [QEMU] CPU: qemu32 taskA: Hello World! taskB: Hello World! taskA: Hello World! taskB: Hello World! taskA: Hello World! taskB: Hello World! taskA: Hello World! taskB: Hello World! taskA: Hello World! taskB: Hello World! taskA: Hello World! taskB: Hello World! QEMU: Terminated make[2] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel/outdir » make[1] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project »
Zephyr supporte l’utilisation du C++. Pour l’illustrer prenons l’exemple cpp_synchronisation
qui réalise exactement la même chose que l’exemple précédent, mais cette fois avec du code C++.
Le fichier source devient :
/* * Copyright (c) 2015-2016 Wind River Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file C++ Synchronization demo. Uses basic C++ functionality. */ #if defined(CONFIG_STDOUT_CONSOLE) #include #define PRINT printf #else #include#define PRINT printk #endif /** * @class semaphore the basic pure virtual semaphore class */ class semaphore { public: virtual int wait(void) = 0; virtual int wait(int timeout) = 0; virtual void give(void) = 0; }; /* specify delay between greetings (in ms); compute equivalent in ticks */ #define SLEEPTIME 500 #define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000) /* * Microkernel version of C++ synchronization demo has two tasks that utilize * semaphores and sleeps to take turns printing a greeting message at * a controlled rate. */ #include /* * @class task_semaphore * @brief miscrokernel task semaphore * * Class derives from the pure virtual semaphore class and * implements it's methods for the microkernel semaphore */ class task_semaphore: public semaphore { protected: struct _k_sem_struct _sema_internal; ksem_t sema; public: task_semaphore(); virtual ~task_semaphore() {} virtual int wait(void); virtual int wait(int timeout); virtual void give(void); }; /* * @brief task_semaphore basic constructor */ task_semaphore::task_semaphore(): _sema_internal(__K_SEMAPHORE_DEFAULT) { PRINT("Create semaphore %p\n", this); sema = (ksem_t)&_sema_internal; } /* * @brief wait for a semaphore * * Test a semaphore to see if it has been signaled. If the signal * count is greater than zero, it is decremented. * * @return RC_OK on success, RC_FAIL on error */ int task_semaphore::wait(void) { return task_sem_take(sema, TICKS_UNLIMITED); } /* * @brief wait for a semaphore within a specified timeout * Test a semaphore to see if it has been signaled. If the signal * count is greater than zero, it is decremented. The function * waits for the specified timeout * * @param timeout the specified timeout in ticks * * @return RC_OK on success, RC_FAIL on error or RC_TIME on timeout */ int task_semaphore::wait(int timeout) { return task_sem_take(sema, timeout); } /** * * @brief Signal a semaphore * * This routine signals the specified semaphore. * * @return N/A */ void task_semaphore::give(void) { task_sem_give(sema); } /* * * @param taskname task identification string * @param mySem task's own semaphore * @param otherSem other task's semaphore * */ void hello_loop(const char *taskname, task_semaphore& my_sem, task_semaphore& other_sem) { while (1) { my_sem.wait(); /* say "hello" */ PRINT("%s: Hello World!\n", taskname); /* wait a while, then let other task have a turn */ task_sleep(SLEEPTICKS); other_sem.give(); } } /* two tasks synchronization semaphores */ task_semaphore sem_a; task_semaphore sem_b; extern "C" void task_a(void) { /* taskA gives its own semaphore, allowing it to say hello right away */ sem_a.give(); /* invoke routine that allows task to ping-pong hello messages with taskB */ hello_loop(__FUNCTION__, sem_a, sem_b); } extern "C" void task_b(void) { /* invoke routine that allows task to ping-pong hello messages with taskA */ hello_loop(__FUNCTION__, sem_b, sem_a); }
Le fichier prj.mdef
est modifié pour étendre la stack, C++ oblige.
% Application : C++ demo % TASK NAME PRIO ENTRY STACK GROUPS % ================================== TASK TASKA 7 task_a 2048 [EXE] TASK TASKB 7 task_b 2048 [EXE] % SEMA NAME % ============= SEMA TASKASEM SEMA TASKBSEM
tandis que le fichier prj.conf
active le support du C++ et supprime la redirection de stdout sur la console (printk
sera utilisé au lieu de printf
) :
CONFIG_COMPILER_OPT="-O0" CONFIG_CPLUSPLUS=y
Après compilation nous pouvons lancer l’exécution :
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/synchronization/microkernel$ cd ../../cpp_synchronization/microkernel/ cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/cpp_synchronization/microkernel$ make qemu make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/cpp_synchronization/microkernel/outdir » Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h CHK misc/generated/configs.c CHK include/generated/offsets.h CHK misc/generated/sysgen/prj.mdef To exit from QEMU enter: 'CTRL+a, x' [QEMU] CPU: qemu32 Create semaphore 00104aec Create semaphore 00104b00 task_a: Hello World! task_b: Hello World! task_a: Hello World! task_b: Hello World! task_a: Hello World! task_b: Hello World! task_a: Hello World! task_b: Hello World! QEMU: Terminated make[2] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/cpp_synchronization/microkernel/outdir » make[1] : on quitte le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project »
Cela fonctionne parfaitement donc les adeptes du C++ pourront utiliser leur langage favori. La taille de l’image strippée est de 20 kilo octets.
Comme indiqué dans le fichier README
du répertoire samples/net
, nous allons travailler avec 2 terminaux initialisés avec l’environnement Zephyr.
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/net$ cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/net$ cat README Description of various IP stack test applications ================================================= echo_server ----------- The echo server test implements a network server that listens UDP sockets. If that socket receives data, the server reverses the data and sends it back. The echo client can be running in the host system in which case you need to use SLIP to connect to qemu. This usage scenario is described in net/ip/tools/README file. This is the default if you type "make qemu" in echo_server test application directory. The network IP stack hooks right under IP stack (network level) and sends the IP packet to host using SLIP. The layer 2 is the SLIP layer in this case, no radio layer is simulated or used. The echo server qemu instance can also be running against echo client that is running in another qemu. For this you need two terminal windows. In terminal 1 go to echo_server directory and type "make server". This will start the echo server and setup qemu pipes in suitable way and it will also start monitor application that will store the transferred network traffic into pcap file for later analysis. Then in terminal 2 go to echo_client directory and type "make client". This will start the echo client that will start to send data to the server and verify that it has received the data back correctly. In the two qemu case we are simulating the whole radio network meaning that the saved pcap file will contain 802.15.4 network packets. echo_client ----------- The echo client test implements a network client that will send UDP data to the echo server. The client verifies that it has received data to the sent message and that the data is correct. The echo server can be running in the host system in which case you need to use SLIP to connect to qemu. This usage scenario is described in net/ip/tools/README file. This is the default if you type "make qemu" in echo_client test application directory. The network IP stack hooks right under IP stack (network level) and sends the IP packet to host using SLIP. The layer 2 is the SLIP layer in this case, no radio layer is simulated or used. The echo client qemu instance can also be running against echo server that is running in another qemu. This test scenario is described in echo_server chapter above.
Dans le 1er terminal compilons puis lançons le programme echo_server
:
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/net/echo_server$ make server rm -f /tmp/ip-stack-server.in /tmp/ip-stack-server.out /tmp/ip-stack-client.in \ /tmp/ip-stack-client.out mkfifo /tmp/ip-stack-server.in mkfifo /tmp/ip-stack-server.out ln /tmp/ip-stack-server.in /tmp/ip-stack-client.out ln /tmp/ip-stack-server.out /tmp/ip-stack-client.in make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/net/echo_server/outdir » Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h CHK misc/generated/configs.c CHK include/generated/offsets.h To exit from QEMU enter: 'CTRL+a, x' [QEMU] CPU: qemu32 net: net_tx_fiber (0010f1e0): Starting TX fiber (stack 1024 bytes) net: net_rx_fiber (0010f5e0): Starting RX fiber (stack 1024 bytes) net: net_timer_fiber (0010ebe0): Starting net timer fiber (stack 1536 bytes) net: net_driver_slip_open (0010e7e0): Initialized slip driver init_app: run echo server net: net_set_mac (0010e7e0): MAC 5e:25:e2:15:1:1 net: net_set_mac (0010e7e0): Tentative link-local IPv6 address fe80::5c25:e2ff:fe15:101
Le programme exécuté dans la machine virtuelle 1 se met en attente de connexion, en utilisant le driver SLIP. La connexion entre machine client et serveuse se fait au travers des FIFOS /tmp/ip-stack-server.in
et /tmp/ip-stack-server.out
de l’hôte.
Depuis le 2nd terminal compilons puis lançons le client :
cch@cch-acer:/media/yocto-1504/IoT/zephyr/zephyr-project/samples/net/echo_client$ make client make[1] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project » make[2] : on entre dans le répertoire « /media/yocto-1504/IoT/zephyr/zephyr-project/samples/net/echo_client/outdir » Using /media/yocto-1504/IoT/zephyr/zephyr-project as source for kernel GEN ./Makefile CHK include/generated/version.h CHK misc/generated/configs.c CHK include/generated/offsets.h To exit from QEMU enter: 'CTRL+a, x' [QEMU] CPU: qemu32 net: net_tx_fiber (0010f820): Starting TX fiber (stack 1024 bytes) net: net_rx_fiber (0010fc20): Starting RX fiber (stack 1024 bytes) net: net_timer_fiber (0010f220): Starting net timer fiber (stack 1536 bytes) net: net_driver_slip_open (0010ee20): Initialized slip driver init_app: run mcast tester net: net_set_mac (0010ee20): MAC c1:1e:47:15:2:2 net: net_set_mac (0010ee20): Tentative link-local IPv6 address fe80::c31e:47ff:fe15:202
Lorsque la connexion est établie le client envoie ses premiers paquets :
sending: Sending packet send_packet: Trying to send 0x0010a1c0 buflen 932 datalen 884 send_packet: sent 884 bytes Unicast sent 884 bytes Waiting packet net: net_tx_fiber (0010f820): Sending (buf 0010a1c0, len 932) to IP stack net: net_driver_slip_send (0010f820): Sending 932 bytes, application data 884 bytes net: net_rx_fiber (0010fc20): Received buf 0010b240 net: udp_packet_receive (0010fc20): packet received context 0010bfa0 len 932 appdata 0010b288 appdatalen 884 wait_reply: received 884 bytes
qui sont reçus et renvoyés par le serveur :
net: net_rx_fiber (0010f5e0): Received buf 0010a6a0 net: udp_packet_receive (0010f5e0): packet received context 0010b960 len 932 appdata 0010a6e8 appdatalen 884 receive: unicast received 884 bytes data net: net_driver_slip_send (0010d800): Sending 932 bytes, application data 884 bytes
et ainsi de suite :
sending: Sending packet send_packet: Trying to send 0x0010a740 buflen 82 datalen 34 send_packet: sent 34 bytes Unicast sent 34 bytes Waiting packet net: net_tx_fiber (0010f820): Sending (buf 0010a740, len 82) to IP stack net: net_driver_slip_send (0010f820): Sending 82 bytes, application data 34 bytes net: net_rx_fiber (0010fc20): Received buf 0010b7c0 net: udp_packet_receive (0010fc20): packet received context 0010bfa0 len 82 appdata 0010b808 appdatalen 34 wait_reply: received 34 bytes net: net_rx_fiber (0010f5e0): Received buf 0010ac20 net: udp_packet_receive (0010f5e0): packet received context 0010b960 len 82 appdata 0010ac68 appdatalen 34 receive: unicast received 34 bytes data net: net_driver_slip_send (0010d800): Sending 82 bytes, application data 34 bytes
La communication fonctionne correctement.
Si l’on regarde les fichiers Makefile
situés dans les répertoires samples/net/echo_server
et samples/net/echo_client
on constate que pour ces exemples on utilise un kernel de type nano.
# Makefile - echo server that is used in testing # # Copyright (c) 2015 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # NET_IFACE ?= slip MDEF_FILE = prj.mdef KERNEL_TYPE ?= nano BOARD ?= qemu_x86 CONF_FILE ?= prj_$(NET_IFACE).conf include $(ZEPHYR_BASE)/Makefile.inc ifeq ($(CONFIG_NETWORKING_WITH_BT), y) QEMU_EXTRA_FLAGS = -serial unix:/tmp/bt-server-bredr else include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack endif
CIO Systèmes Embarqués – 1 Rue de la Presse, 42 000 Saint-Étienne – contact@ciose.fr – 04 77 93 34 32
CIO Systèmes Embarqués est le nom commercial de la SAS CIO Informatique Industrielle
CIO Informatique Industrielle © 1991-2020 v3.0