Expérimentations de Migen sur APF27 avec debian

Article transféré sur le blog du FLF.

Publié dans Non classé | Marqué avec , , | Laisser un commentaire

À poil le GravityLight !

Suite à mes premiers tests du GravityLight, je ne pouvais pas laisser une belle boîte comme ça sans la démonter. Surtout que contrairement aux vendeurs de prisons dorées, deciwatt a réalisé un produit qui est facilement démontable.

gravity_ouvert_face

Premier étonnement : tout est mécanique. Les seules pièces d’électroniques sont les leds et résistance permettant de limiter le courant dans la led rouge.

gravitylight_ouvert_pile

Pour détecter un poids trop lourd, on voit bien sur cette dernière photo le gros ressort actionnant un contact permettant de commuter la led rouge.

gravitylight_moteur

La production d’électricité est réalisée par un simple moteur ferrite.

Le réglage de la puissance se fait au niveau de l’axe du moteur, en montant/abaissant de moteur on peut sélectionner le diamètre de couplage pour changer la vitesse de rotation du moteur.gravitylight_grand_axe

gravitylight_petit_axe

L’ensemble donne une impression d’assez bonne qualité, par contre je n’y brancherais pas mon téléphone pour le recharger. Il faudrait pour cela créer un adaptateur, et surtout avoir beaucoup de patience 😉

Publié dans Non classé | Marqué avec | Laisser un commentaire

Premiers tests du GravityLight

Une fois le GL déballé, la première chose à faire pour tester notre GravityLight est de trouver un point d’accroche suffisamment solide et suffisamment haut pour pouvoir l’accrocher, chose relativement facile dans un appartement plein de poutres.

gravitylight_accroche_poutre

Deuxième chose à faire (et plus compliqué) est de pouvoir remplir le sac fourni avec une charge de 8 à 12 kg. Si on met moins de 8kg ça marche pas, mais si on en met trop on risque de tout casser. Comme je suis pas à la campagne, pas moyen de mettre du sable ou du gravier comme expliqué sur la notice. Du coup il a fallu faire avec les moyens du bord : patates et riz !

gravitylight_poids

Mais dans le volume imparti par le sac ça n’a pas été suffisant, j’ai donc du y ajouter le poids de la connaissance : HTML5, pour que le pendule commence à descendre correctement.

Je suis assez surpris de l’engin, le système n’est pas si simpliste. Le gros bouton trois positions permet de régler la vitesse de descente du poids, et donc la puissance délivrée.

gravity_lum_faible
Position I, faible éclairement
gravitylight_forte_lum
Position III, «fort» éclairement

Un système permet de détecter que le poids est trop élevé au moyen d’un astucieux ressort placé au niveau de l’accroche de l’engin. Si le poids est trop élevé une led rouge va s’allumer.

gravitylight_rouge

Comme je l’avais expliqué dans ma précédente note, il est possible d’utiliser le courant généré pour y brancher un appareil électronique (bon faut pas être trop gourmand quand même parce qu’on peut pas compter sur beaucoup plus de 40mA). La tension délivrée (mesurée) est d’un peu moins de 9v, et le branchement de l’adaptateur va désactiver la led d’éclairage pour concentrer toute l’énergie sur l’adaptateur.

gravitylight_adapt

Ce qui est rigolo, c’est que si on branche juste l’adaptateur sans aucun appareil de branché dessus, la charge va se mettre à descendre rapidement (circuit ouvert). Et si on veut mesurer le courant de cours circuit avec un ampèremètre, la charge stoppe complètement sa course. Et du coup je n’ai pas encore pu mesurer correctement le courant délivré par l’engin.

Au prochain épisode copé va devoir se cacher les yeux car je vais mettre l’engin à poil ! On va s’attaquer à son démontage. Peut-être mettrais-je des photos de la bête démontée le 14 février par solidarité avec les dessinateurs 😉

Publié dans Non classé | Marqué avec , , | Un commentaire

Déballage du GravityLight

Après plus d’une années d’attente, le voici enfin arrivé dans ma boite aux lettres : le GravityLight !

Le GravityLight permet tout simplement de générer de l’électricité à partir de la gravité. C’est une révolutiontm ! Plus besoin de pédaler, brancher une prise, avoir du soleil ou du vent pour avoir de l’électricité, il suffit de remonter le pendule. Certaines mauvaises langues diront que ça n’est qu’une resucée des vieilles pendules de nos grands mères … et ils auront raison !

Concrètement c’est une idée qui a germée dans la tête de deux vieux anglais qui cherchaient une solution pour éclairer les chaumières non connectés au réseau électrique. Le but principale était d’éviter l’utilisation de lampes à pétroles et autres bougies qui sont un fléaux pour les jeunes poumons dans ces populations.

On voit beaucoup de projet d’éoliennes et panneaux solaires dans ses villages reculés, mais ces solutions posent toutes le même problème de stockage d’énergie. Les batteries coûtent très cher et ne sont pas durable, elles s’usent assez vite.

Du coup l’idée toute bête (mais révolutionnairetm je vous dis) est de ressortir le vieux systèmes de pendule des horloges de grand mère pour les coupler à un générateur de courant (alternateur).

De cette manière, il suffit de remonter un poids (environ 12kg max pour le GravityLight) pour avoir de la lumière pendant au moins 30 minutes. Les poumons sont conservés, pas besoin d’acheter du pétrole ou des bougies et pas besoin d’avoir à attendre le soleil (sic) pour recharger une batterie.

Pour mener à bien leur projet, nos deux anglais on fait une levée de fonds en crowfunding sur indiegogo. Occasion que je n’ai évidemment pas loupé il y a 1 an et demi. L’objectif de prix de la chose était de moins de $10. Mais évidemment, en tant qu’européen bien grassouillet il fallait donner un peu plus pour pouvoir espérer en recevoir un chez soit ($75).

La conception et la production s’étant bien déroulée dans les temps, tous les financeurs qui avaient donnés suffisamment de $$ on donc pu recevoir leur précieux GravityLight, dans une belle boite en carton made in china.

gravitylight boite fermée

gravitylight_boite_ouverte

La boite contient l’engin en lui même avec un gros bouton 3 positions permettant à mon avis de régler la puissance, un petit sac, un gros sac et une courroie avec les attaches permettant d’y fixer les sac.

gravitylight_contenu

En plus de ces éléments essentiels on trouve aussi un adaptateur de prise d’alimentation standard permettant de brancher un appareil électronique pour le recharger. Grâce à une prise astucieusement placée à l’arrière de l’appareil.

gravitylight_arriere

Je n’ai pas encore eu le temps de lui trouver un point d’accroche assez solide pour pouvoir faire des tests de production d’électricité, mais ça ne saurait tarder … suite au prochain épisode.

Publié dans écologie | Marqué avec , , , | Laisser un commentaire

PeripheralOnDemand, ISE et la ligne de commande.

POD (PeripheralOnDemand) est un outils écrit en python permettant de générer un design pour les FPGA d’armadeus sans avoir à faire du VHDL/Verilog. Cet utilitaire permet d’intégrer des «composants virtuels» disponibles sur étagère et de générer le design.

POD peut-être utilisé en ligne de commande pour créer un projet, mais il peut aussi être scripté via l’argument -s de la commande pod :


$ pod -s monscript.pod

On trouve un certain nombre de scripts POD dans le projet armadeus dans le répertoire firmware/pod_scripts/.

Par exemple si nous avons besoin d’utiliser le gsm ou le gps de la carte APF51dev il faudra générer des uarts dans le FPGA au moyen du script apf51_gsm_gps_firmware.pod :


$ pod -s apf51_gsm_gps_firmware.pod
create apf51_gsm_gps_firmware
Project apf51_gsm_gps_firmware created
POD:apf51_gsm_gps_firmware> $ selectplatform standard.apf51
[INFO]   : No platform in project
Component platform added as apf51
Component imx51_wb16_wrapper added as imx51_wb16_wrapper00
Component rstgen_syscon added as rstgen_syscon00
Component irq_mngr added as irq_mngr00

POD:apf51_gsm_gps_firmware> $ addinstance components.uart16750 gsm_uart
Component uart16750 added as gsm_uart

POD:apf51_gsm_gps_firmware> $ addinstance components.uart16750 gps_uart
Component uart16750 added as gps_uart

POD:apf51_gsm_gps_firmware> $ connectpin gsm_uart.interrupt.int_o.0 irq_mngr00.irq.irqport.0

POD:apf51_gsm_gps_firmware> $ connectpin gps_uart.interrupt.int_o.0 irq_mngr00.irq.irqport.1

POD:apf51_gsm_gps_firmware> $ connectpin gps_uart.uart.srx_pad_i.0 apf51.fpga.IO_L40P_M3DQ6_3

POD:apf51_gsm_gps_firmware> $ connectpin gps_uart.uart.stx_pad_o.0 apf51.fpga.IO_L42N_GCLK24_M3LDM_3

POD:apf51_gsm_gps_firmware> $ connectpin gsm_uart.uart.srx_pad_i.0 apf51.fpga.IO_L39P_M3LDQS_3

POD:apf51_gsm_gps_firmware> $ connectpin gsm_uart.uart.stx_pad_o.0 apf51.fpga.IO_L41P_GCLK27_M3DQ4_3

POD:apf51_gsm_gps_firmware> $ connectpin gsm_uart.uart.cts_pad_i.0 apf51.fpga.IO_L41N_GCLK26_M3DQ5_3

POD:apf51_gsm_gps_firmware> $ connectpin gsm_uart.uart.rts_pad_o.0 apf51.fpga.IO_L39N_M3LDQSN_3

POD:apf51_gsm_gps_firmware> $ autoconnectbus
setting base address 0x0 for  irq_mngr00.swb16
setting base address 0x20 for  gsm_uart.swb16
setting base address 0x40 for  gps_uart.swb16
No addressing value in this type of bus
Bus connected

POD:apf51_gsm_gps_firmware> $ generateintercon imx51_wb16_wrapper00.mwb16
Intercon with name : imx51_wb16_wrapper00_mwb16_intercon Done
Component imx51_wb16_wrapper00_mwb16 added as imx51_wb16_wrapper00_mwb16_intercon

POD:apf51_gsm_gps_firmware> $ generateintercon rstgen_syscon00.candroutput
Intercon with name : rstgen_syscon00_candroutput_intercon Done
Component rstgen_syscon00_candroutput added as rstgen_syscon00_candroutput_intercon

POD:apf51_gsm_gps_firmware> $ generatetop

Mapping for interface mwb16:
Address  | instance.interface             | size
---------------------------------------------------------
0x0 |               irq_mngr00.swb16 |          8
0x08 |                       --void-- |         24
0x20 |                 gsm_uart.swb16 |         32
0x40 |                 gps_uart.swb16 |         32
---------------------------------------------------------
[INFO] : port gsm_uart.uart.dsr_pad_i is void. It will be set to '0'
[INFO] : port gsm_uart.uart.ri_pad_i is void. It will be set to '1'
[INFO] : port gsm_uart.uart.dcd_pad_i is void. It will be set to '0'
[INFO] : port gps_uart.uart.cts_pad_i is void. It will be set to '0'
[INFO] : port gps_uart.uart.dsr_pad_i is void. It will be set to '0'
[INFO] : port gps_uart.uart.ri_pad_i is void. It will be set to '1'
[INFO] : port gps_uart.uart.dcd_pad_i is void. It will be set to '0'

Top generated with name : top_apf51_gsm_gps_firmware.vhd
POD:apf51_gsm_gps_firmware> $ synthesis.selecttoolchain ise
POD:apf51_gsm_gps_firmware> $ synthesis.generateproject
Make directory for imx51_wb16_wrapper
Make directory for rstgen_syscon
Make directory for irq_mngr
Make directory for uart16750
Make directory for imx51_wb16_wrapper00_mwb16
Make directory for rstgen_syscon00_candroutput

Constraint file generated with name : firmware/pod_scripts/apf51_gsm_gps_firmware/synthesis/apf51_gsm_gps_firmware.ucf

TCL script generated with name : apf51_gsm_gps_firmware.tcl

POD:apf51_gsm_gps_firmware> $ driver.selecttoolchain armadeus

Ce script a permit de générer tout le projet qui est maintenant disponible pour ISE. Pour simplifier son utilisation pod a généré un script tcl firmware/pod_scripts/apf51_gsm_gps_firmware/synthesis/apf51_gsm_gps_firmware.tcl que l’on peut «sourcer» dans la console tcl d’ISE pour générer le bitstream.

Cependant nous devons quand même lancer l’énorme programme qu’est ISE Webpack pour lancer le script. Ce qui est réellement très fastidieux. Jusqu’ici nous étions contraint de le faire à cause d’un bug d’ISE qui empêchait de charger le fichier de contraintes *.ucf correctement.

Ce bug a été patché dans la dernière release de POD et nous pouvons maintenant générer le bitstream en ligne de commande directement. Il suffit pour cela de taper les commandes suivantes :


$ cd apf51_gsm_gps_firmware/synthesis/
# pour l'architecture 32bits, sinon c'est settings64.sh
$ source ISE/14.6/ISE_DS/settings32.sh
$ xtclsh apf51_gsm_gps_firmware.tcl 

Le script prend un certain temps à s’exécuter. Une fois terminé nous retrouvons le bitstream dans le répertoire objs/ du projet :


$ ls ../objs/*.bin
../objs/top_apf51_gsm_gps_firmware.bin

Fichier que l’on peut ensuite télécharger directement dans le fpga avec la méthode de son choix.

Publié dans embarqué, informatique | Laisser un commentaire

Xénomai sur APF28, avec un kernel moderne (3.8)

Cher journal,

Je t’écris aujourd’hui car je viens de voir une news passer sur LinuxFR disant que le kernel long-term 3.0 de Linux n’est plus supporté car cela fait deux ans qu’il est sorti.

Deux ans !

Et dire qu’Armadeus se traine encore le support d’antiquités comme le 2.6.29 pour l’apf27 ou le 2.6.35 pour l’APF28. Il est temps de se lancer dans des trucs un peu moderne comme le device tree, et d’utiliser un xenomai récent.

Je vais donc t’expliquer, mon cher journal, ma démarche d’installation d’un xenomai récent sur un kernel Linux 3.8 (donc récent).

Le kernel 3.8 ou l’arrivée du Device Tree

La raison pour laquelle j’avais utilisé un kernel 3.4.6 pour faire mes premières expérimentations de xenomai était que c’est un noyau suffisamment récent pour avoir des technologies moderne, mais c’est un noyau suffisamment «vieux» pour éviter la révolution du Device Tree.

Sauf que le 3.4.6 n’est plus si neuf et si on veux rester un peu dans la course il faut bien s’y mettre un jour à ce fameux dt. Je me suis donc lancé sur le 3.8 car c’est le noyau le plus récent qui est supporté par adeos pour l’architecture arm.

Device tree ?

Le device tree est une technologie qui s’est imposée sur les architectures arm pour Linux. À l’origine sur les autres architectures, nous avions souvent un hard assez uniforme pour un type de processeur, les architectures des cartes mères en x86 se ressemblent en générale par exemple. Cette diversité limité des architectures permettait d’inscrire en dur dans le code de Linux un fichiers source pour chaque plate-forme (cf le répertoire arch/ dans le code de linux).

Intégrer une nouvelle architecture sur un ancien noyau consiste donc à créer un fichier source du nom de la plate-forme, et y décrire les différentes adresses mémoire, les fréquences d’horloges, les lignes d’interruptions, numéro de gpio, composant présent sur chaque bus. Le tout dans des structures C appelées au démarrage. C’est ce qu’on trouve pour Armadeus dans les fichiers suivant par exemple:


# pour le kernel 2.6.35.3 sur APF28
arch/arm/mach-mx28/apf28dev.c
arch/arm/mach-mx28/mach-apf28.c

Le problème avec l’ARM c’est que le nombre d’architectures développées autour ce processeur est pléthorique (voir /arch/arm/ dans le code Linux), et cela commençait à devenir ingérable. C’est pourquoi il a été décidé de séparer la descriptions des architectures avec le codes (générique) de Linux.

L’idée du device tree est de compiler une fois pour toute le noyau linux pour toutes les architectures du processeur et de démarrer Linux en passant la description de la plate-forme en paramètre. Cela se traduit sous uboot par un binaire à télécharger en plus, heureusement la macro est déjà prête comme expliqué sur le wiki il suffit de faire un run update_dtb :


# donner l'adresse mémoire du dt
setenv fdt_addr_r 41000000
# mettre à jour
run update_dtb

Dans l’idéal, quand cela aura été intégré correctement chez Armadeus, il n’y aura plus qu’un seul binaire du noyau linux pour toutes nos cartes et il suffira de charger le bon device tree pour l’APF que l’on utilise. Ce qui sera un véritable gain en maintenance et permettra à armadeus d’être beaucoup plus à jour avec un moindre effort (un seul noyau à supporter pour toutes les cartes).

Mais nous n’y sommes pas encore, c’est un peu une quête du Grââl pour l’instant 😉

Pour l’instant nous en sommes encore à l’étape de bouts de code poussé dans la mainline armadeus et pas encore officiellement supporté. C’est pourquoi il faut encore faire de nombreuses manipulations pour faire tourner un kernel moderne sur l’APF28.

Installation du Kernel 3.8 pour APF28

Comme dans mon billet précédent, il faut «descendre» une vue récente d’armadeus avec git :


$ git clone git://git.code.sf.net/p/armadeus/code apf28

Puis le configurer pour l’APF28 :


$ cd apf28
$ make apf28_defconfig

Cette dernière commande a pour vocation de configurer buildroot pour notre APF28 avec la configuration officiellement supporté par Armadeus. Mais nous, nous voulons un kernel plus récent (le 3.8 si vous suivez encore), donc nous allons devoir modifier tout ça comme expliqué sur le wiki.


Toolchain  --->
     Kernel Headers (Linux 2.6 (manually specified version))  --->
     (3.8) linux version
 ...
 Kernel  --->
     Kernel version (Custom version)  --->
         (3.8) Kernel version
     ... 
     (40008000) load address (for 3.7+ multi-platform image)
     [*]   Device tree support
     (imx28-apf28dev) Device Tree Source file names
     ...
     Linux Kernel Extensions  --->
         [*] Adeos/Xenomai Real-time patch
         (http://download.gna.org/adeos/patches/v3.x/arm/) Adeos patch URL
         (ipipe-core-3.8-arm-1.patch) Path for Adeos patch file
 ...
 System configuration  --->
     (ttyAMA0) Port to run a getty (login prompt) on
 ...

 Package Selection for the target --->
    Real-Time --->
        [*] Xenomai Userspace
        [*]   Install testsuite
...

Ne pas oublier de virer les patches freescales qui trainent encore pour les anciens noyau dans le fichier buildroot/.config :


BR2_LINUX_KERNEL_PATCH="../patches/linux/$(BR2_LINUX_KERNEL_VERSION)"

Le nom du driver de nand a changé depuis la version utilisé par défaut chez Armadeus. Il est donc nécessaire de le changer dans U-Boot pour qu’il passe les bons paramètre à Linux au démarrage. Pour cela il faut modifier le fichier suivant :


buildroot/target/device/armadeus/apf28/apf28-u-boot-2013.04.h

Et à la ligne 153 mettre la valeur suivante :


#define CONFIG_MTDMAP			"gpmi-nand"

Xenomai 2.6.3

Par defaut, la version de xenomai sur armadeus est la 2.6.2.1. Comme on veut le dernier cri on va changer la version à la 2.6.3 en modifiant le package dans :


buildroot/package/xenomai/xenomai.mk

En modifiant la ligne :


XENOMAI_VERSION = 2.6.3

Et comme pour le 3.4.6 il faut virer les patches qui trainent dans ce répertoire :


$ cd buildroot/package/xenomai/
$ rm adeos-00-compatibility_with_armadeus.patch adeos-01-adeos-prevent_system_freeze_on_mxc_with_gpio_generated_interrupts.patch

On modifie toujours busybox :


make busybox-menuconfig

En ajoutant l’option suivante:


Shells  --->
        Choose your default shell (ash)  --->
    --- ash
    ---   Ash Shell Options
          ...
          [*]   Builtin getopt to parse positional parameters 

make

Après toutes ces modifications on peut enfin lancer la compilation générale:

make

Il semble y avoir une erreur étrange avec le packet xenomai, pour être sur qu’il le compile et l’installe, une fois la première compilation complète réaliser il faut relancer une compilation spécifique du package xenomai:


make xenomai-dirclean;make xenomai;make linux;make;cp -v buildroot/output/images/* /tftpboot/

Installation de la cible

L'installation sur la cible est légèrement différente des binaires officiels car nous avons à installer le fameux devices tree. Et le kernel étant récent, il faut aussi changer le nom de l'uart utilisé pour la console:


$ setenv console console=ttyAMA0,115200n8
$ setenv consoledev ttyAMA0
$ setenv fdt_addr_r 41000000
$ saveenv

Si l'ip du serveur tftp est configurée correctement il suffit de faire un update_all pour (presque) tout installer :


run update_all

À ce niveau on peut faire une tentative de boot, mais nous allons rester bloqué à la décompression du kernel :


BIOS> boot

NAND read: device 0 offset 0x400000, size 0x80000
 524288 bytes read: OK

Loading from nand0, offset 0x500000
   Image Name:   Linux-3.8.0-ipipe
   Created:      2013-10-27  14:55:29 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2969768 Bytes = 2.8 MiB
   Load Address: 40008000
   Entry Point:  40008000
## Booting kernel from Legacy Image at 40000000 ...
   Image Name:   Linux-3.8.0-ipipe
   Created:      2013-10-27  14:55:29 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2969768 Bytes = 2.8 MiB
   Load Address: 40008000
   Entry Point:  40008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 41000000
   Booting using the fdt blob at 0x41000000
   Loading Kernel Image ... OK
OK
   Loading Device Tree to 47b33000, end 47b39d9f ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

Patch adéos

D'après Marek Vasut il y a un problème dans le patch adeos pour imx28, il faut modifier le fichier icoll.c dans linux :


$ vim buildroot/output/build/linux-3.8/arch/arm/mach-mxs/icoll.c

Et modifier la ligne 95 :


-    handle_IRQ(irqnr, regs);
+    ipipe_handle_multi_irq(irqnr, regs);

On peut ensuite tout recompiler pour avoir quelques chose de fonctionnel :

 make linux;make;mv -v buildroot/output/images/* /tftpboot/

Testbench Xenomai

On peut valider le bon démarrage de Xenomai au moyen de la commande suivante :

# dmesg | grep Xeno
I-pipe: head domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: scheduling class idle registered.
Xenomai: scheduling class rt registered.
Xenomai: real-time nucleus v2.6.3 (Lies and Truths) loaded.
Xenomai: starting native API services.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.

Pour lancer le testbench complet de Xenomai, ne pas oublier de monter le driver idoine :

modprobe xeno_switchtest

Puis pour lancer le test :

xeno-test

Ce qui donne le résultat suivant sur l'apf28 :


Started child 584: /bin/sh /usr/bin/xeno-test-run-wrapper /usr/bin/xeno-test
+ echo 0
+ /usr/bin/arith
mul: 0x79364d93, shft: 26
integ: 30, frac: 0x4d9364d9364d9364

signed positive operation: 0x03ffffffffffffff * 1000000000 / 33000000
inline calibration: 0x0000000000000000: 375.074 ns, rejected 5/10000
inlined llimd: 0x79364d9364d9362f: 4084.395 ns, rejected 8/10000
inlined llmulshft: 0x79364d92ffffffe1: 94.725 ns, rejected 2/10000
inlined nodiv_llimd: 0x79364d9364d9362f: 167.000 ns, rejected 2/10000
out of line calibration: 0x0000000000000000: 375.174 ns, rejected 3/10000
out of line llimd: 0x79364d9364d9362f: 4084.758 ns, rejected 10/10000
out of line llmulshft: 0x79364d92ffffffe1: 123.900 ns, rejected 1/10000
out of line nodiv_llimd: 0x79364d9364d9362f: 166.625 ns, rejected 4/10000

signed negative operation: 0xfc00000000000001 * 1000000000 / 33000000
inline calibration: 0x0000000000000000: 375.049 ns, rejected 6/10000
inlined llimd: 0x86c9b26c9b26c9d1: 4124.954 ns, rejected 10/10000
inlined llmulshft: 0xd45d172d0000001e: 124.375 ns, rejected 2/10000
inlined nodiv_llimd: 0x86c9b26c9b26c9d1: 166.995 ns, rejected 2/10000
out of line calibration: 0x0000000000000000: 375.187 ns, rejected 4/10000
out of line llimd: 0x86c9b26c9b26c9d1: 4118.808 ns, rejected 10/10000
out of line llmulshft: 0xd45d172d0000001e: 94.737 ns, rejected 3/10000
out of line nodiv_llimd: 0x86c9b26c9b26c9d1: 166.787 ns, rejected 2/10000

unsigned operation: 0x03ffffffffffffff * 1000000000 / 33000000
inline calibration: 0x0000000000000000: 375.012 ns, rejected 7/10000
inlined nodiv_ullimd: 0x79364d9364d9362f: 83.391 ns, rejected 2/10000
out of line calibration: 0x0000000000000000: 375.058 ns, rejected 1/10000
out of line nodiv_ullimd: 0x79364d9364d9362f: 165.141 ns, rejected 4/10000
+ /usr/bin/clocktest -C 42 -T 30
== Tested clock: 42 (CLOCK_HOST_REALTIME)
CPU      ToD offset [us] ToD drift [us/s]      warps max delta [us]
--- -------------------- ---------------- ---------- --------------
  0                  2.7            0.005          0            0.0
+ /usr/bin/switchtest -T 30
== Testing FPU check routines...
== FPU check routines: unimplemented, skipping FPU switches tests.
== Threads: sleeper0-0 rtk0-1 rtk0-2 rtup0-3 rtup0-4 rtus0-5 rtus0-6 rtuo0-7 rtuo0-8
RTT|  00:00:01
RTH|---------cpu|ctx switches|-------total
RTD|           0|        5537|        5537
RTD|           0|        5535|       11072
RTD|           0|        5535|       16607
RTD|           0|        5558|       22165
RTD|           0|        5539|       27704
RTD|           0|        5535|       33239
RTD|           0|        5535|       38774
RTD|           0|        5558|       44332
RTD|           0|        5535|       49867
RTD|           0|        5535|       55402
RTD|           0|        5537|       60939
RTD|           0|        5517|       66456
RTD|           0|        5537|       71993
RTD|           0|        5576|       77569
RTD|           0|        5519|       83088
RTD|           0|        5578|       88666
RTD|           0|        5537|       94203
RTD|           0|        5519|       99722
RTD|           0|        5535|      105257
RTD|           0|        5551|      110808
RTD|           0|        5542|      116350
RTT|  00:00:22
RTH|---------cpu|ctx switches|-------total
RTD|           0|        5537|      121887
RTD|           0|        5578|      127465
RTD|           0|        5517|      132982
RTD|           0|        5537|      138519
RTD|           0|        5578|      144097
RTD|           0|        5519|      149616
RTD|           0|        5578|      155194
RTD|           0|        5535|      160729
RTD|           0|        4657|      165386
+ /usr/bin/cond-torture-native
simple_condwait
relative_condwait
absolute_condwait
sig_norestart_condwait
sig_restart_condwait
sig_norestart_condwait_mutex
sig_restart_condwait_mutex
sig_norestart_double
sig_restart_double
cond_destroy_whilewait
Test OK
+ /usr/bin/cond-torture-posix
simple_condwait
relative_condwait
absolute_condwait
sig_norestart_condwait
sig_restart_condwait
sig_norestart_condwait_mutex
sig_restart_condwait_mutex
sig_norestart_double
sig_restart_double
cond_destroy_whilewait
Test OK
+ /usr/bin/mutex-torture-native
simple_wait
recursive_wait
timed_mutex
mode_switch
pi_wait
lock_stealing
NOTE: lock_stealing mutex_trylock: not supported
deny_stealing
simple_condwait
recursive_condwait
auto_switchback
Test OK
+ /usr/bin/mutex-torture-posix
simple_wait
recursive_wait
errorcheck_wait
timed_mutex
mode_switch
pi_wait
lock_stealing
NOTE: lock_stealing mutex_trylock: not supported
deny_stealing
simple_condwait
recursive_condwait
auto_switchback
Test OK
+ start_load
+ echo start_load
+ check_alive /usr/bin/latency
+ echo check_alive /usr/bin/latency
+ wait_load
Started child 640: dohell 900
Started child 641: /usr/bin/latency
== Sampling period: 1000 us
== Test mode: periodic user-mode task
== All results in microseconds
warming up...
RTT|  00:00:01  (periodic user-mode task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     77.333|     87.708|    108.541|       0|     0|     77.333|    108.541
RTD|     44.166|     87.458|    109.958|       0|     0|     44.166|    109.958
RTD|     66.249|     87.583|    109.166|       0|     0|     44.166|    109.958
RTD|     67.624|     87.874|    108.958|       0|     0|     44.166|    109.958
RTD|     68.583|     87.916|    100.583|       0|     0|     44.166|    109.958
RTD|     66.458|     87.791|     95.416|       0|     0|     44.166|    109.958
RTD|     66.916|     87.791|     97.541|       0|     0|     44.166|    109.958
RTD|     67.374|     87.833|     96.749|       0|     0|     44.166|    109.958
RTD|     68.624|     87.833|     98.416|       0|     0|     44.166|    109.958
RTD|     66.749|     87.833|     97.249|       0|     0|     44.166|    109.958
RTD|     67.249|     87.874|     97.916|       0|     0|     44.166|    109.958
RTD|     67.833|     87.874|     96.708|       0|     0|     44.166|    109.958
RTD|     65.999|     87.791|     98.374|       0|     0|     44.166|    109.958
RTD|     67.541|     87.874|     96.749|       0|     0|     44.166|    109.958
RTD|     67.958|     87.833|     95.249|       0|     0|     44.166|    109.958
RTD|     66.874|     87.916|     98.791|       0|     0|     44.166|    109.958
/usr/bin/xeno-test-run-wrapper: /usr/bin/xeno-test: line 1: can't open /tmp/xeno-test-in-584: Interrupted system call
---|-----------|-----------|-----------|--------|------|-------------------------
RTS|     44.166|     87.791|    109.958|       0|     0|    00:00:17/00:00:17

Conclusion

Et voila, mon cher journal, le résultat de toute mon épopée fantastique. La quête fut longue et fastidieuse, et cette procédure mériterait certainement une configuration dédiée chez armadeus.
Que penserais-tu, mon cher journal d'un :

make apf28_xeno3.8_defconfig

Je suis sur que ça intéresserait du monde, on pourrait même envisager de faire une telle cible pour chaque noyau partiellement supporté dans armadeus. Vu les récents commit il semble y avoir pas mal de personnes qui se lance dans la compilation autre que le kernel officiel armadeus.

Publié dans embarqué, informatique | Laisser un commentaire

Xenomai sur APF28

Beaucoup de ceux qui ont travaillé sur microcontrôleur et qui passent sur des systèmes Linux pour l’embarqué sont surpris de tomber sur un système qui n’est pas temps réel.
Alors que l’on était habitué à gérer l’ordonnancement de nos tâches à la main avec un petit scheduler maison, sous Linux il faut se débattre avec les priorités et les réglages de tick d’horloge. Et malgré cela on sait que l’on restera dans du temps réel «mou».

Et oui, Linux n’est pas un système temps réel, on arrive à obtenir de bon résultats avec les dernières versions du kernel mais ça reste du «temps-réel mou».

Pour avoir un système réellement temps réel une technique consiste à s’adjoindre les services d’un deuxième micro-noyau qui lui est temps réel et qui considère Linux comme une tâche subalterne. C’est l’intérêt de xenomai (prononcez Xénomaille 😉 ) qui utilise adeos comme noyau temps réel.

Chez Armadeus les noyaux fournis par défauts pour les cartes ne sont pas directement prévu pour xenomai. Mais après discussion sur le canal IRC du projet et quelques recherches sur le wiki on peut réussir à s’en sortir avec une APF28.

Voici donc un petit tuto de la marche à suivre pour installer Xenomai sur une APF28, j’ai choisi un noyau 3.4.6 de Linux car je savais que quelqu’un l’avait déjà fait avec, mais il faudrait peut-être voir pour un 3.8 qui fonctionne mieux visiblement.

Tout d’abord il faut télécharger le trunk armadeus comme expliqué ici.

$ git clone git://git.code.sf.net/p/armadeus/code apf28

Puis configurer notre «tree» pour une APF28.

$ cd apf28
$ make apf28_defconfig

Un fois que le menu de configuration s'affiche il faut modifier la configuration comme suit:


 Toolchain  --->
     Kernel Headers (Linux 2.6 (manually specified version))  --->
     (3.4.6) linux version
 ...
 Kernel  --->
     Kernel version (Custom version)  --->
         (3.4.6) Kernel version
 
     Linux Kernel Extensions  --->
         [*] Adeos/Xenomai Real-time patch
         (http://download.gna.org/adeos/patches/v3.x/arm/older) Adeos patch URL
         (ipipe-core-3.4.6-arm-4.patch) Path for Adeos patch file
 ...
 System configuration  --->
     (ttyAMA0) Port to run a getty (login prompt) on
 ...

 Package Selection for the target --->
    Real-Time --->
        [*] Xenomai Userspace
...

Ne pas oublier de virer la looongue liste de patchs relatifs au vieux noyau 2.6.x. Le plus simple pour cela est d'éditer directement le fichier .config de buildroot (buildroot/.config) et ne mettre la valeur suivante pour les patch :

 BR2_LINUX_KERNEL_PATCH="../patches/linux/$(BR2_LINUX_KERNEL_VERSION)"

Ainsi que les patches se trouvant dans le package xenomai du buildroot armadeus, qui sont eux aussi spécifiques au vieux noyau officiel:

$ cd buildroot/package/xenomai/
$ rm adeos-00-compatibility_with_armadeus.patch adeos-01-adeos-prevent_system_freeze_on_mxc_with_gpio_generated_interrupts.patch

Il faut de plus modifier busybox :

 $ make busybox-menuconfig

Avec les options suivantes :

Shells  --->
        Choose your default shell (ash)  --->
    --- ash
    ---   Ash Shell Options
          ...
          [*]   Builtin getopt to parse positional parameters 

Puis lancer le make général.

$ make

Si cette erreur survient :

make[1]: /opt/projects/armadeus/apf28_xenomai/buildroot/output/build/xenomai-2.6.2.1/scripts/prepare-kernel.sh : commande introuvable

Il faut forcer la compilation du paquet xénomai en lançant un make dédié:

$ make xenomai

Puis relancer le make général:

$ make

Tout doit s'être déroulé correctement, il suffit maintenant de mettre son APF28 à jour, sous U-Boot ça donne un truc du genre :

BIOS> run update_all

Vu que nous sommes sur un noyau Linux récent les développeur se sont amusés à changer les nom du tty de la console principale, il faut donc le dire à U-Boot sinon on risque de ne pas voir Linux booter :

$ setenv console console=ttyAMA0,115200n8
$ setenv consoledev ttyAMA0

Et là on peut tenter un boot ... jusqu’à tomber sur cette erreur dans Linux :

UBIFS error (pid 1): ubifs_get_sb: cannot open "ubi0:rootfs", error -19
VFS: Cannot open root device "ubi0:rootfs" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
1f00            3072 mtdblock0 (driver?)
1f01             512 mtdblock1 (driver?)
1f02             512 mtdblock2 (driver?)
1f03             512 mtdblock3 (driver?)
1f04             512 mtdblock4 (driver?)
1f05            8192 mtdblock5 (driver?)
1f06          248832 mtdblock6 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Backtrace:
[] (dump_backtrace+0x0/0x110) from [] (dump_stack+0x18/0x1c)
 r6:00008000 r5:c7fad000 r4:c04f2be0 r3:00000002
[] (dump_stack+0x0/0x1c) from [] (panic+0x74/0xf0)
[] (panic+0x0/0xf0) from [] (mount_block_root+0x1c8/0x208)
 r3:00000002 r2:00000001 r1:c7c27f78 r0:c043f6e4
[] (mount_block_root+0x0/0x208) from [] (prepare_namespace+0x94/0x1cc)
[] (prepare_namespace+0x0/0x1cc) from [] (kernel_init+0x128/0x170)
 r5:c0027b84 r4:c04f1d40
[] (kernel_init+0x0/0x170) from [] (do_exit+0x0/0x6dc)
 r5:c00089d4 r4:00000000

Car le nom du driver de NAND a lui aussi changé ! Or ce paramètre est transmis par U-Boot au kernel au moment du boot. Nous allons donc devoir modifier U-Boot pour que Linux démarre correctement et réussisse à charger le rootfs.
L'essentiel de la configuration de U-Boot se trouve dans le header suivant :

buildroot/target/device/armadeus/apf28/apf28-u-boot-2013.04.h 

À la ligne 153 mettre la valeur suivante :

#define CONFIG_MTDMAP			"gpmi-nand"

Puis reconstruire U-Boot avec les commandes suivantes:

$ make uboot-dirclean
$ make uboot

Et enfin reflasher U-Boot sur son APF28:

BIOS> run update_uboot

Un fois tout cela fait on peut booter Linux correctement et avoir Xénomai qui démarre:

$ dmesg | grep Xeno

Par contre il y a encore un problème avec le xeno-test.

$ xeno-test

Mais on me souffle qu'il est plus facile de passer sur un kernel 3.8 avec le trunk du projet Xénomai pour résoudre ce problème ...

Je vais donc retourner discuter sur le canal irc pour me mettre à la page. Suite au prochain épisode...

Publié dans embarqué, informatique, kernel | Laisser un commentaire

Shaarli sur lost-oasis

Shaarli est un script PHP permettant de partager rapidement des liens. Jusqu’ici je ne parvenais pas à faire fonctionner le système RSS/Atom de partage de liens car le fichier rss avait systématiquement cette entête :

?
// tout ce qui est charge ici (generalement des includes et require) est charge en permanence.
?>

Le problème vient de mon hébergeur qui ajoute ça systématiquement au début du fichier RSS. Pour le résoudre il suffit de se rendre dans son espace FTP et de supprimer le contenu du fichier :

/web-martoni.fr/php-include/prepend.php

Et tout rentre dans l’ordre

Pour partager mon shaarli c’est par ici.

Publié dans informatique | Laisser un commentaire

On parle aussi d’effet Streisand, mais je préfère le terme effet flamby c’est plus parlant. Si vous démoulez un flamby puis que vous tapez dessus avec une cuillère ça éclabousse partout. C’est ce que la société linkeo est en train de découvrir à ses dépends 😉

Si vous n’avez rien compris à ce que je viens d’expliquer ci-dessus, faites une petite recherche sur votre moteur préféré avec le nom «linkeo» vous verrez …

Bel exemple de suicide d’une entreprise !

EDIT:

Une petite vidéo parodique sur geek access sur le sujet

Publié le par admin | Laisser un commentaire

Publié le par admin | Laisser un commentaire