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

Et pourquoi pas gouzi-phone ?

L’académie française aime proposer des traductions d’anglicismes bizarrement alambiqués que personne n’utilise jamais. En informatique ces traductions sont en général particulièrement loufoques. On ne compte plus les articles s’en moquant.

Dans le cas du «smartphone» l’académie française nous a évité la traduction littérale québécoise de «téléphone intelligent» et a préféré le qualificatif d’«ordiphone». En effet, je peux vous garantir qu’un téléphone n’a rien d’intelligent, même s’il y a un ordinateur dedans, cela reste une brique de métal, plastique et silicium qui exécute stupidement ce que les programmeurs lui ont demandé de faire. Finalement, qualifier d’ordiphone un téléphone-avec-un-ordinateur-dedans n’est pas si mal, mais on peut certainement faire mieux.

Ayons un regard extérieur sur les gens possédant un ordiphone, que font ils principalement avec ?

Image d'un caresse-phone en train d'être chatouillé
Gouzi gouzi

Ils le caressent bien sûr ! Du coup pourquoi ne pas parler de «téléphone-à-caresser» ou mieux, de «caresse-phone» ?

Mais les experts pointilleux me feront remarquer à raison que ça n’est pas de cette façon que l’on fait des caresses. Là on est plutôt dans la chatouille.

Parfait disons «chatouille-phone» ou plutôt «gouzi-phone» alors. De cette manière on se rapproche plus des réalités de l’usage des «ordiphones» non ?

Ça me fait penser que mon téléphone-machine-à-laver est en train de rendre l’âme, du coup je vais devoir me pencher sur l’achat d’un gouzi-phone moi aussi 😉

Publié dans En bref, humeur, informatique | Laisser un commentaire

Flattez moi !

Flattr est un système de micro-dons en ligne. Il suffit de s’inscrire sur le site de flattr puis d’assigner une somme mensuelle d’argent que vous souhaitez donner.

Au gré de vos pérégrinations sur le web vous pouvez ensuite décider de «flattr» (flatter) un article, une vidéo, une image, … En cliquant sur le bouton flattr identique au bouton se trouvant au bas de cet article.

Chaque fin de mois, le flattr divisera la somme que vous avez assignée par le nombre le flattr que vous avez fait et donnera l’argent correspondant à chacune des personnes flattées.

De cette manière il est possible de faire des micro-dons pour financer une cause, une idée ou simplement un site internet qui vous plaît sans qu’il soit parasité par de la publicité (qui est un veritable fléaux) et sans avoir de minimum de don.

Par exemple si vous pensez que les œuvres du domaine public numérisées par la BNF doivent rester accessible à tout les citoyens librement (sachant que la numérisation a été payée par nos impôts tout de même) vous pouvez aller flatter l’article de la quadrature du net qui dénonce l’affaire pour les soutenir :

Non à la privatisation du domaine public par la Bibliothèque nationale de France !

Si un de mes articles vous plaît beaucoup vous pouvez aussi bien sur le flatter, en cliquant sur le bouton vert en bas de l’article. Par contre pas moyen de me taxer si vous voyez des fôtes d’orthographes 😉

Publié dans Non classé, politique | Laisser un commentaire

Genèse d’un pilote Linux (Part3)

Nous voici dans l’écriture proprement dite du driver. Comme expliqué
auparavant, nous allons nous inspirer du driver du ds1374. La stratégie
consiste à copier/coller le code rtc-ds1374.c puis en modifier le code:

$ cp linux-2.6.38.8/drivers/rtc/rtc-ds1374.c
linux-2.6.38.8/drivers/rtc/rtc-mcp7940x.c 

Puis chercher/remplacer tous les ds1374 par mcp7940x dans
le fichier rtc-mcp7940x.c nouvellement créé. Ce qui se fait dans vim par la
commande :%s/ds1374/mcp7940x/g

Une fois cela fait on va pouvoir commencer à adapter notre driver. 

Notre chip mcp7940x est un composant qui se connecte sur le bus I²C pour
«exporter» une interface d’horloge nommé RTC. Le rôle du driver est donc de
faire le liens entre le bus i²c et la RTC. On peut résumer cela visuellement
avec l’image suivante

Dessin représentant le driver du mcp79400

On commence toujours la lecture d’un driver par la fin, passons sur le nom
de l’auteur et la licence. Et intéressons nous à la connexion au bus.

On charge le driver en le connectant au bus i²c, pour se faire, on utilise
la structure i2c_driver que l’on ajoute sur le bus au moment du
chargement du driver:


static int __init mcp7940x_init(void)
{
	return i2c_add_driver(&mcp7940x_driver);
}

Structure que l’on supprime au déchargement du driver bien évidemment:


static void __exit mcp7940x_exit(void)
{
	i2c_del_driver(&mcp7940x_driver);
}

Cette structure déclare un certain nombre de fonctions et de structures
propres au mcp7940x:


static struct i2c_driver mcp7940x_driver = {
	.driver = {
		.name = "rtc-mcp7940x",
		.owner = THIS_MODULE,
	},
	.probe = mcp7940x_probe,
	.suspend = mcp7940x_suspend,
	.resume = mcp7940x_resume,
	.remove = __devexit_p(mcp7940x_remove),
	.id_table = mcp7940x_id,
};

Ce qui nous intéresse particulièrement pour l’instant c’est le
probe et le driver.name. En effet c’est tout
simplement le point d’entrée de notre driver. Une fois le driver chargé dans
le kernel, Linux observe le bus i²c et guette le nom des périphériques (struct
devices) que l’on charge dessus. Dès qu’un périphériques avec le nom
« rtc-mcp7940x » se pointe, le kernel appel la fonction de probe
mcp7940x_probe.

La structure de description du périphérique présent physiquement sur le bus
est quelques chose qui doit être chargé dans le noyau. En règle générale les
périphériques du bus i²c ne sont pas plug&play et sont donc présent sur la
carte électronique dès le démarrage du kernel.

C’est pour cette raison qu’on a l’habitude de charger les devices dans le
fichier dit de «plate-forme». Dans le cas de l’apf51dev, ce fichier de
plate-forme se nomme apf51dev-baseboard.c et se trouve dans le
répertoire

buildroot/output/build/linux-2.6.38.8/arch/arm/mach-mx5/

Dans ce fichier, le device se déclare simplement avec sont adresse sur le
bus, et son nom bien sur:


static struct i2c_board_info apf51dev_i2c2_devices[] __initdata = {
	{
		I2C_BOARD_INFO("mcp79400", 0x6f),
	},
};

Revenons à notre probe

 static int mcp7940x_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct mcp7940x *mcp7940x;
	int ret;

	mcp7940x = kzalloc(sizeof(struct mcp7940x), GFP_KERNEL);
	if (!mcp7940x)
		return -ENOMEM;

C’est la fonction d’initialisation de notre driver. C’est dans cette
fonction que l’on va démarrer le mcp7940x et allouer la mémoire pour la
structure mcp7940x. C’est aussi dans cette fonction que l’on va rattacher
notre driver à l’interface RTC.

L’interface Linux pour la RTC est extrêmement simpliste dans notre cas. En
effet on cherche juste à lire l’heure et la date dans le composant et à
l’écrire (Le mcp7940x à plein d’autre fonctionnalités mais mon besoin n’est
que l’heure). Nous n’aurons donc que les fonctions read_time et
set_time à écrire dans la structure rtc_class_ops
du driver:


static const struct rtc_class_ops mcp7940x_rtc_ops = {
	.read_time = mcp7940x_read_time,
	.set_time = mcp7940x_set_time,
};

Structure que l’on enregistre à la fin de la fonction probe:


	mcp7940x->rtc = rtc_device_register(client->name, &client->dev,
	                                  &mcp7940x_rtc_ops, THIS_MODULE);
	if (IS_ERR(mcp7940x->rtc)) {
		ret = PTR_ERR(mcp7940x->rtc);
		dev_err(&client->dev, "unable to register the class device\n");
		goto out_free;
	}

L’écriture de la fonction read_time se résume ensuite à lire
les valeurs des registres du composant au moyen de la fonction
i2c_smbus_read_byte_data() et de renseigner la structure
rtc_time
passée en paramètre.

Et pour la fonction set_time on fait l’inverse. On récupère
les valeurs se trouvant dans la structure rtc_time
passée en paramètre et on écrit les valeurs dans le composant au moyen de la
fonction i2c_smbus_write_byte_data().

Et voila !

En réalité le driver n’est que partiellement écrit vu que le composant
dispose de bien plus de fonctionnalités que simplement lire/écrire l’heure.
Le driver pourrait notament être étendu pour gérer les deux alarmes, la
gestion du signal de clock de sortie et surtout la SRAM, qui permet de stocker
des variables quand l’appareil est éteint.

Et non ça n’est pas terminé ! Il reste encore à publier ce driver pour
armadeus, et plus (mainline kernel) si affinité !

Maintenant publions le tout

Maintenant que nous avons écrit notre driver, l’objectif va être de le publier sur le git Armadeus. Pour cela il faut que nous finalisions le patch que nous avions commencé dans la partie 2 de cet article. Si tout a bien été fait dans la partie 2 il n’y a plus qu’à rafraichir le patch quilt:

$ cd buildroot/output/build/linux-2.6.38.8/
$ quilt refresh
Refreshed patch 450-armadeus-add_mcp7940x_rtc_driver.patch

Puis modifier l'entête du patch pour y mettre son nom (pour qu'on connaisse le coupable ;):


$ vim patches/450-armadeus-add_mcp7940x_rtc_driver.patch

et


Add mcp79400 Linux driver

Signed-off-by: Fabien Marteau 

---

Index: linux-2.6.38.8/drivers/rtc/Kconfig
...

Notre patch est prêt, on peut maintenant le proposer à la communauté Armadeus en le postant sur la liste de diffusion
armadeus-forum@lists.sourceforge.net.

Bon j'avoue, vu que j'ai les droits sur le git je l'ai commité directement 😉 Mais, pour ceux qui n'ont pas les droits, c'est la procédure qu'il faudrait respecter. Du coup pour voir le code complet du driver c'est par

Publié dans embarqué, informatique, kernel | 2 commentaires

Genèse d’un pilote Linux (Part2)

Dans l’épisode précédent nous avons pu démontrer
fonctionnement du MCP79400 sur une AFP51, nous
allons maintenant pouvoir l’intégrer au kernel Linux avec un driver adequate.

Plongée dans l’univers du kernel: fouinons !

L’idée consiste à écrire le moins possible de code et à copier au maximum ce
qui existe déjà dans le kernel. Pour cela un petit tour dans le code de Linux
s’impose. Dans le cas d’Armadeus le code du kernel (patché pour
le projet se trouve dans le répertoire
buildroot/output/build/linux-2.6.38.8 on peut aussi browser le net
à la recherche de driver similaire, mais il est important d’essayer de coller au
kernel utilisé.

Le MCP79400 est une RTC, et nous avons de la chance l’api RTC est déjà
supporté depuis longtemps dans Linux, donc nous avons une bonne documentation
dans le code : Documentation/rtc.txt

Mais comme on ne veut surtout pas se fouler, l’objectif est de trouver un
composant très proche du notre et de le recopier à coup de
cherher/remplacer.

Résumons:

  • Notre composant est une rtc: allons voir dans le répertoire
    Drivers/rtc/ si nous n’y trouverions pas notre bonheurs.
  • $ ls linux-2.6.38.8/drivers/rtc
    class.c           rtc-ds1511.c    rtc-max8998.c       rtc-rs5c313.c
    hctosys.c         rtc-ds1553.c    rtc-mc13xxx.c       rtc-rs5c348.c
    rtc-ab8500.c      rtc-ds3232.c    rtc-mpc5121.c       rtc-rx8581.c
    rtc-at32ap700x.c  rtc-ds3234.c    rtc-mrst.c          rtc-s35390a.c
    rtc-at91rm9200.c  rtc-efi.c       rtc-msm6242.c       rtc-s3c.c
    rtc-at91sam9.c    rtc-ep93xx.c    rtc-mv.c            rtc-sa1100.c
    rtc-au1xxx.c      rtc-fm3130.c    rtc-mxc.c           rtc-sh.c
    rtc-bfin.c        rtc-generic.c   rtc-mxc_v2.c        rtc-starfire.c
    rtc-bq32k.c       rtc-imxdi.c     rtc-nuc900.c        rtc-stk17ta8.c
    rtc-bq4802.c      rtc-isl12022.c  rtc-omap.c          rtc-stmp3xxx.c
    rtc-cmos.c        rtc-isl1208.c   rtc-pcap.c          rtc-sun4v.c
    rtc-coh901331.c   rtc-jz4740.c    rtc-pcf2123.c       rtc-sysfs.c
    rtc-davinci.c     rtc-lib.c       rtc-pcf50633.c      rtc-test.c
    rtc-dev.c         rtc-lpc32xx.c   rtc-pcf8563.c       rtc-twl.c
    rtc-dm355evm.c    rtc-m41t80.c    rtc-pcf8583.c       rtc-tx4939.c
    rtc-ds1216.c      rtc-m41t94.c    rtc-pl030.c         rtc-v3020.c
    rtc-ds1286.c      rtc-m48t35.c    rtc-pl031.c         rtc-vr41xx.c
    rtc-ds1302.c      rtc-m48t59.c    rtc-proc.c          rtc-wm831x.c
    rtc-ds1305.c      rtc-m48t86.c    rtc-ps3.c           rtc-wm8350.c
    rtc-ds1307.c      rtc-max6900.c   rtc-pxa.c           rtc-x1205.c
    rtc-ds1374.c      rtc-max6902.c   rtc-r9701.c
    rtc-ds1390.c      rtc-max8925.c   rtc-rp5c01.c
  • Le nombre de composant supporté est relativement élevé, voyons voir ceux
    qui sont piloté par bus i²c comme le notre :
  • 
    $ grep -Rn "i2c.h" *
    rtc-bq32k.c:12:#include  <linux/i2c.h>
    rtc-ds1307.c:16:#include <linux/i2c.h>
    rtc-ds1374.c:23:#include <linux/i2c.h>
    rtc-ds1672.c:12:#include <linux/i2c.h>
    rtc-ds3232.c:21:#include <linux/i2c.h>
    rtc-fm3130.c:13:#include <linux/i2c.h>
    rtc-isl12022.c:14:#include <linux/i2c.h>
    rtc-isl1208.c:14:#include <linux/i2c.h>
    rtc-m41t80.c:17:#include <linux/i2c.h>
    rtc-max6900.c:15:#include <linux/i2c.h>
    rtc-max8925.c:13:#include <linux/i2c.h>
    rtc-max8998.c:16:#include <linux/i2c.h>
    rtc-pcf8563.c:17:#include <linux/i2c.h>
    rtc-pcf8583.c:16:#include <linux/i2c.h>
    rtc-rs5c372.c:13:#include <linux/i2c.h>
    rtc-rx8025.c:26:#include <linux/i2c.h>
    rtc-rx8581.c:16:#include <linux/i2c.h>
    rtc-s35390a.c:14:#include <linux/i2c.h>
    rtc-x1205.c:20:#include <linux/i2c.h>
    
  • Cela réduit déjà le nombre cela reste élevé. Le composant de chez Dallas
    DS1374 semble néanmoins assez intéressant car il est court et
    surtout il est déjà utilisé dans certain projet Armadeus
    donc bien connu.

Notre nouveau driver devrait donc pouvoir s’insérer dans ce répertoire sans
problème, appelons le rtc-mcp7940x.c histoire de coller aux autres.
Pour l’ajouter, trois fichiers doivent-être modifiés:

  • drivers/rtc/KConfig: Pour ajouter le driver dans le
    menuconfig de linux
  • [...]
    	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.
    
    config RTC_DRV_MCP7940X
    	tristate "Microchip MCP7940X"
    	depends on RTC_CLASS && I2C
    	help
    	  If you say yes here you get support for Microchip
    	  MCP7940x real-time clock chips.
    	  The alarm functionality is not supported.
    
    	  This driver can also be built as a module. If so, the module
    	  will be called rtc-mcp7940x.
    
    config RTC_DRV_BQ32K
    [...]    
  • drivers/rtc/Makefile:
  • [...]
    obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o
    obj-$(CONFIG_RTC_DRV_MCP7940X)	+= rtc-mcp7940x.o
    obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
    [...]
  • drivers/rtc/rtc-mcp7940x.c: le source du driver proprement
    dit

Un bon développeur kernel porte le quilt chez Armadeus.

On vient juste de voir quels fichiers il était nécessaire de modifier pour
ajouter notre driver, néanmoins notre objectif final est quand même de partager
ce driver et, dans un premier temps, de le proposer à la communautée d’Armadeus
Project. Pour cela nous allons avoir besoin de réaliser un patch.

Le kernel utilisé pour le projet armadeus est déjà noyé de patches, si bien
qu’il est difficile de gérer son pauvre petit patches parmis les autres. Il est
donc conseillé d’utiliser le programme Quilt pour gérer des piles
de patche.

quilt est relativement bien intégré au projet; pour s’en servir
il est nécessaire de quiltifier Linux avec la commande
suivante à la racine du projet :

$ ./scripts/quiltify
--- What do you want to quiltify today ? ;-)
1) Linux
2) Buildroot
3) U-Boot
\> 1

Le script va empiler tous les patches nécessaire au projet armadeus puis
recompiler Linux. Une fois fait nous n’avons plus qu’à nous rendre dans
l’arborescence du code:

$ cd buildroot/output/build/linux-2.6.38.8
buildroot/output/build/linux-2.6.38.8$ quilt applied
[...]
442-freescale-0034-ENGR00126692-3-1-add_drivers_mxc_directory.patch
442-freescale-0034-ENGR00126692-3-add_hw-events_and_srtc_drivers.patch
442-freescale-0034-ENGR00126692-3-add_hw-vpu_driver.patch
442-freescale-0034-ENGR00126692-3-add_iim_driver.patch
442-freescale-0034-ENGR00126692-3-add_mx23_mx25_mx28_security_stuff.patch
442-freescale-0197-ENGR00131650-add_scc2_and_sahara_drivers_without_rng.patch
442-freescale-0535-ENGR00136875-1-Add-function-pgprot_writethru.patch
442-freescale-0536-ENGR00136875-2-make-video-buffer-cacheable-to-improv.patch
444-armadeus-sunrpc-silent_annoying_svc_message_when_mounting_NFS_drives.patch
445-armadeus-add_freescale_mxc_dvfs_driver.patch
446-armadeus-add_freescale_ipu3_driver.patch
447-armadeus-add_freescale_ipu_based_framebuffer_driver.patch
448-armadeus-pps51-adding_HX8369_display_driver.patch
449-armadeus-add_pps51_baseboard.patch
[...]

La commande quilt applied affiche tous les patches appliqués au
noyau. Pour ajouter notre driver nous allons donc créer un nouveau patche:

$ quilt new 450-armadeus-add_mcp7940x_rtc_driver.patch

Et ajouter les fichiers que nous allons modifier avant de les
modifier.


$ quilt add drivers/rtc/Makefile
$ quilt add drivers/rtc/Kconfig
$ quilt add drivers/rtc-mcp7940x.c

Nous sommes maintenant prêt à écrire le code proprement dit, comme nous allons le voir dans le prochain épisode

[À suivre …]

Publié dans embarqué, informatique, kernel | 2 commentaires

Genèse d’un pilote Linux (Part1)

  • — Quelle heure il est ?
  • — l’heure d’t’acheter un MCP79400.
  • — Rhaa, mais y a pas le driver pour Linux !
  • — Tu sais ce qui te reste à faire…

Un MCP79400 est une RTC de chez microchip.
Une RTC est un composant qui permet de garder l’heure sur un système, même
quand celui-ci est éteint (on utilise généralement une pile bouton pour
alimenter le chip).

C’est un composant assez classique, qui d’habitude est bien reconnu par
Linux. Hélas pour
nous il se trouve que ce n’est pas le cas du MCP79400 dont nous avons besoin
pour un projet.

Bon c’est pas tellement dramatique, une RTC est un composant
relativement simpliste en général. C’est l’occasion de réveiller un peu ce
blog et de raconter un peu ma vie palpitante de développeur de pilotes pour
Linux 😉

Branchons le composant sur une AFP51Dev

La première étape dans le développement de driver consiste en général à réaliser un petit montage
électronique pour essayer de communiquer avec.

Le MCP79400 communique au moyen d’un bus i²c, manque de chance, la carte de
développement APF51Dev ne possède pas de connecteurs avec
l’i²c. On le trouve par contre sur le connecteur caméra CSI, il faut donc
faire un petit montage aérien pour extraire les deux signaux SDA et SCL du CSI
et les souder sur un plaque d’essais avec un MCP79400.

photo du branchement du mcp79400 sur une apf51dev

Premier contact avec le chip

Ok nous avons branché le mcp79400, nous allons maintenant essayer de voir
comment se comporte la bestiole sur le bus i²c.

Ce qui est bien avec le bus i²c c’est qu’il existe de nombreux outils permettant
de l’utiliser en mode utilisateur (userland) hérité du projet lm-sensors.

La carte étant démarrée, nous allons tout d’abord scanner le bus i²c numéro 1
sur lequel se trouve notre composant au moyen de la commande i2cdetect :


Welcome to the Armadeus development environment.
armadeus login: root
\# i2cdetect 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n] 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- UU -- 38 -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 6f 
70: -- -- -- -- -- -- -- --   

On voit qu’il y a plusieurs composants sur ce bus, un rapide coup d’œil dans
la datasheet de l’apf51dev
nous apprend qu’il s’agit de l’interface audio wolfson (WM8960) à l’adresse 0x1a,
du DVI à l’adresse 0x38 et du PMIC (wolfson) en 0x36. Les caractères UU signifient que le chip est utilisé par un driver, donc qu’il n’est pas possible d’y toucher avec des outils en userland.

Notre MCP79400 se retrouve bien en 0x6F comme donné dans la datasheet. On va
donc pouvoir commencer à essayer de lui parler.

La table des registres de la datasheet indique que le premier registre
(0x00) contient les secondes ainsi que la commande st pour débuter le
comptage. Lisons d’abord la valeur avec i2cget:


\# i2cget -y 1 0x6f 0x02 b
0x00

Maintenant si on écrit une valeur puis qu’on la relit:


\# i2cset -y 1 0x6f 0x00 0x02 b
\# i2cget 1 0x6f 0x00 b
0x02

Puisque nous arrivons à relire la valeur que nous venons d’écrire nous
pouvons confirmer que l’accès i²c est fonctionnel en lecture/écriture, ce qui
est déjà pas mal !

Voyons voir maintenant si le composant fonctionne en démarrant le comptage du
temps au moyen du bit de start st:


\# i2cset -y 1 0x6f 0x00 0x82 b
\# i2cget -y 1 0x6f 0x00 b
0x83
\# i2cget -y 1 0x6f 0x00 b
0x84
\# i2cget -y 1 0x6f 0x00 b
0x84
\# i2cget -y 1 0x6f 0x00 b
0x85
\# i2cget -y 1 0x6f 0x00 b
0x85
\# i2cget -y 1 0x6f 0x00 b
0x85
\# i2cget -y 1 0x6f 0x00 b
0x86

Bingo, notre composant semble bien compter les secondes correctement. Nous
allons donc pouvoir embrayer sur l’écriture du driver Linux à proprement
parler.

[Par ici la suite …]

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