<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
    <title>storagebits · #rust</title>
    <subtitle>Firmware, applis TV, un homelab, construits la nuit avec une organisation d&#39;agents IA. Et blok, le carnet d&#39;atelier.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blok.storagebits.workers.dev/fr/tags/rust/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blok.storagebits.workers.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-18T18:05:17-04:00</updated>
    <id>https://blok.storagebits.workers.dev/fr/tags/rust/atom.xml</id>
    <entry xml:lang="fr">
        <title>Test de la NUCLEO-F412ZG avec Hubris et Humility</title>
        <published>2026-10-18T18:05:17-04:00</published>
        <updated>2026-10-18T18:05:17-04:00</updated>
        <author><name>François</name></author>
        <link rel="alternate" type="text/html" href="https://blok.storagebits.workers.dev/fr/blog/hubris-f412/"/>
        <id>https://blok.storagebits.workers.dev/fr/blog/hubris-f412/</id>
        <summary type="html">Porter Hubris, l&#39;OS embarqué d&#39;Oxide Computer, sur une NUCLEO-F412ZG à 100 MHz : ce qui a été touché, du kernel intact aux deux correctifs de Humility, expliqués.</summary>
        <content type="html" xml:base="https://blok.storagebits.workers.dev/fr/blog/hubris-f412/">&lt;p&gt;Le sujet : une NUCLEO-F412ZG, une carte de développement ST à Cortex-M4, et &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/oxidecomputer/hubris&quot;&gt;Hubris&lt;/a&gt;, l’OS embarqué d’Oxide Computer, qui ne la supporte pas de base. Le kernel n’a pas bougé d’une ligne. Il a fallu ajouter la carte, adapter trois drivers, mettre à jour le firmware de la sonde et corriger deux fois Humility, le debugger.&lt;/p&gt;
&lt;figure class=&quot;portrait&quot;&gt;&lt;img src=&quot;nucleo-f412zg.webp&quot; alt=&quot;La carte NUCLEO-F412ZG posée sur un tapis noir, branchée en USB, avec ses LEDs utilisateur verte, bleue et rouge allumées.&quot; width=&quot;1125&quot; height=&quot;1500&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;La NUCLEO-F412ZG, branchée par l&#39;USB du ST-LINK, la sonde intégrée en bas de la carte. Au-dessus, les trois LEDs utilisateur que pilote la tâche pong.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;hubris-humility-c-est-quoi-c-est-qui&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hubris-humility-c-est-quoi-c-est-qui&quot; aria-label=&quot;Anchor link for: hubris-humility-c-est-quoi-c-est-qui&quot;&gt;#&lt;/a&gt;
Hubris, Humility, c’est quoi ? C’est qui ?&lt;/h2&gt;
&lt;p&gt;Hubris est un petit OS en Rust qu’Oxide utilise dans ses serveurs pour le contrôleur de service. Chaque tâche vit dans ses propres régions mémoire, protégées par la MPU. Les tâches, leurs priorités et leurs droits sur les périphériques sont tous déclarés à la compilation, dans un &lt;code&gt;app.toml&lt;/code&gt;. Humility lit la mémoire de la carte à travers la sonde et la traduit grâce aux infos de debug : état des tâches, piles, registres, dumps.&lt;/p&gt;
&lt;p&gt;L’auteur principal, c’est Cliff Biffle. Sa présentation à l’Open Source Firmware Conference 2021 explique pourquoi Oxide a écrit son propre OS. Ce talk est vraiment incroyable, quelle belle pièce d’ingénierie !&lt;/p&gt;
&lt;figure class=&quot;video video-externe video-large&quot;&gt;&lt;iframe src=&quot;https://player.vimeo.com/video/650913348?dnt=1&quot; title=&quot;On Hubris and Humility, Cliff L. Biffle, OSFC 2021&quot; loading=&quot;lazy&quot; allow=&quot;fullscreen; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;figcaption&gt;« On Hubris and Humility: developing an OS for robustness in Rust », Cliff L. Biffle, Open Source Firmware Conference 2021, 43 min.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;On peut aussi citer Bryan Cantrill, cofondateur et CTO d’Oxide, et Adam Leventhal, parmi les grands manitous derrière Hubris. Dans sa présentation sur le debug de Docker en production, à la DockerCon 2015, Cantrill défend une idée simple : un système planté ne se redémarre pas avant d’avoir été débogué, en direct ou d’après une image de sa mémoire, le &lt;em&gt;core dump&lt;/em&gt;. Humility fait les deux : &lt;code&gt;humility tasks&lt;/code&gt; lit la carte en marche, &lt;code&gt;humility dump&lt;/code&gt; sauve son état complet dans un fichier qu’on examine ensuite carte débranchée.&lt;/p&gt;
&lt;figure class=&quot;video video-externe video-large&quot;&gt;&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/AdMqCUhvRz8&quot; title=&quot;Running Aground: Debugging Docker in Production, Bryan Cantrill, DockerCon 2015&quot; loading=&quot;lazy&quot; allow=&quot;fullscreen; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;figcaption&gt;« Running Aground: Debugging Docker in Production », Bryan Cantrill, DockerCon 2015. Docker a retiré la vidéo d&#39;origine en 2018 ; c&#39;est la copie republiée par Cantrill.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;ce-qu-il-a-fallu-patcher&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ce-qu-il-a-fallu-patcher&quot; aria-label=&quot;Anchor link for: ce-qu-il-a-fallu-patcher&quot;&gt;#&lt;/a&gt;
Ce qu’il a fallu patcher&lt;/h2&gt;
&lt;p&gt;Je colle un prompt de mission à Claude : faire tourner Hubris sur cette carte, branchée en USB sur le Mac. Sa cible la plus proche dans le dépôt est une carte Discovery à STM32F407. Le soir même, Hubris tourne à 100 MHz sur la NUCLEO.&lt;/p&gt;
&lt;p&gt;Ce qui a été patché, couche par couche :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Le kernel&lt;/strong&gt; : rien, pas une ligne.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La carte et l’app&lt;/strong&gt; : des ajouts purs. Un fichier de carte de 2 lignes (le nom de la puce pour probe-rs), une description de la puce (1 Mio de flash, 256 Kio de RAM, adresses des périphériques), et l’app elle-même, avec la configuration d’horloge à 100 MHz. La branche ajoute 621 lignes, documentation comprise.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trois drivers partagés&lt;/strong&gt;, environ 150 lignes : &lt;code&gt;stm32fx-rcc&lt;/code&gt; choisit la variante F412 de la bibliothèque de registres, &lt;code&gt;user-leds&lt;/code&gt; pilote les LEDs de la Nucleo sur PB0, PB7 et PB14, et &lt;code&gt;stm32fx-usart&lt;/code&gt; passe sur USART3 (PD8/PD9), le port série virtuel du ST-LINK, cadencé à 50 MHz. Le point délicat : deux variantes de puce du crate &lt;code&gt;stm32f4&lt;/code&gt; ne peuvent pas cohabiter dans une même tâche, et deux de ces drivers forçaient la F407 dans leur &lt;code&gt;Cargo.toml&lt;/code&gt;. Ce choix est passé dans une feature. La Discovery compile à l’identique, revérifié à chaque étape.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La sonde&lt;/strong&gt; : le firmware du ST-LINK, trop ancien, a dû être mis à jour.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Humility&lt;/strong&gt;, le debugger : deux correctifs, détaillés plus bas. Le premier répare Humility face au Hubris le plus récent, quelle que soit la carte. Le second corrige une mesure fausse qu’on voit sur cette carte.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;la-mission-en-tranches&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#la-mission-en-tranches&quot; aria-label=&quot;Anchor link for: la-mission-en-tranches&quot;&gt;#&lt;/a&gt;
La mission, en tranches&lt;/h2&gt;
&lt;p&gt;Le north star du prompt tient en une phrase : « &lt;code&gt;humility tasks&lt;/code&gt; montre toutes les tâches &lt;code&gt;Healthy&lt;/code&gt; sur la NUCLEO-F412ZG, les LEDs utilisateur clignotent sous le contrôle de &lt;code&gt;pong&lt;/code&gt;, et &lt;code&gt;ping&lt;/code&gt; écrit sur le port COM virtuel du ST-LINK. » Cinq tranches, chacune doit finir sur du matériel qui marche : préflight, build de référence, premier allumage sur l’oscillateur interne à 16 MHz, UART, puis 100 MHz.&lt;/p&gt;
&lt;p&gt;Premier arrêt dès la tranche 0. Le firmware du ST-LINK de la carte est en V2J25 ; probe-rs, sur lequel s’appuie Humility, exige J26. Le prompt disait de s’arrêter et de demander. Claude propose de patcher automatiquement, je lui donne le zip téléchargé du site de ST et c’est fait.&lt;/p&gt;
&lt;p&gt;Toutes les tâches sont &lt;code&gt;Healthy&lt;/code&gt;. Claude ne voit pas les LEDs : il lit le registre de sortie de GPIOB plusieurs fois de suite et le voit alterner entre PB14, PB0 et rien, au rythme de &lt;code&gt;pong&lt;/code&gt;. La carte tourne à 100 MHz. Sur 10 secondes, l’horloge de Hubris compte 10 235 ms pour 10,32 s au mur, l’écart étant la latence de connexion de Humility.&lt;/p&gt;
&lt;figure class=&quot;sys sys-horloge&quot;&gt;&lt;div class=&quot;defile&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Arbre d&amp;#x27;horloge de la NUCLEO-F412ZG à 100 MHz, défilable horizontalement&quot;&gt;&lt;svg viewBox=&quot;0 0 760 300&quot; role=&quot;img&quot; aria-labelledby=&quot;horloge-t horloge-d&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;title id=&quot;horloge-t&quot;&gt;Arbre d&amp;#x27;horloge de la NUCLEO-F412ZG à 100 MHz&lt;/title&gt;&lt;desc id=&quot;horloge-d&quot;&gt;Le MCO du ST-LINK fournit 8 MHz en entrée HSE bypass. PLLM 4 donne 2 MHz, PLLN 100 donne un VCO à 200 MHz, PLLP 2 donne SYSCLK à 100 MHz. AHB à 100 MHz, APB1 à 50 MHz pour l&amp;#x27;USART3, APB2 à 100 MHz.&lt;/desc&gt;&lt;defs&gt;&lt;marker id=&quot;hl-fl&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;9&quot; refY=&quot;5&quot; markerWidth=&quot;7&quot; markerHeight=&quot;7&quot; orient=&quot;auto-start-reverse&quot;&gt;&lt;path class=&quot;sys-pointe&quot; d=&quot;M0,0 L10,5 L0,10 z&quot;/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;10&quot; y=&quot;40&quot; width=&quot;118&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;69&quot; y=&quot;60&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;ST-LINK MCO&lt;/text&gt;&lt;text x=&quot;69&quot; y=&quot;84&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;8 MHz&lt;/text&gt;&lt;text x=&quot;69&quot; y=&quot;103&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;carré, pas un quartz&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;158&quot; y=&quot;40&quot; width=&quot;118&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;217&quot; y=&quot;60&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;HSE bypass&lt;/text&gt;&lt;text x=&quot;217&quot; y=&quot;84&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;8 MHz&lt;/text&gt;&lt;text x=&quot;217&quot; y=&quot;103&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;HSEBYP avant HSEON&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;306&quot; y=&quot;40&quot; width=&quot;118&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;365&quot; y=&quot;60&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;PLLM = 4&lt;/text&gt;&lt;text x=&quot;365&quot; y=&quot;84&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;2 MHz&lt;/text&gt;&lt;text x=&quot;365&quot; y=&quot;103&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;entrée VCO 1–2 MHz&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;454&quot; y=&quot;40&quot; width=&quot;118&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;513&quot; y=&quot;60&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;PLLN = 100&lt;/text&gt;&lt;text x=&quot;513&quot; y=&quot;84&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;200 MHz&lt;/text&gt;&lt;text x=&quot;513&quot; y=&quot;103&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;VCO 100–432 MHz&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;602&quot; y=&quot;40&quot; width=&quot;148&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;676&quot; y=&quot;60&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;PLLP = 2&lt;/text&gt;&lt;text x=&quot;676&quot; y=&quot;84&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;100 MHz&lt;/text&gt;&lt;text x=&quot;676&quot; y=&quot;103&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;SYSCLK, max F412&lt;/text&gt;&lt;line class=&quot;sys-fil sys-courant&quot; x1=&quot;128&quot; y1=&quot;77&quot; x2=&quot;156&quot; y2=&quot;77&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;line class=&quot;sys-fil sys-courant&quot; x1=&quot;276&quot; y1=&quot;77&quot; x2=&quot;304&quot; y2=&quot;77&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;line class=&quot;sys-fil sys-courant&quot; x1=&quot;424&quot; y1=&quot;77&quot; x2=&quot;452&quot; y2=&quot;77&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;line class=&quot;sys-fil sys-courant&quot; x1=&quot;572&quot; y1=&quot;77&quot; x2=&quot;600&quot; y2=&quot;77&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;path class=&quot;sys-fil sys-courant&quot; d=&quot;M676,114 V150 H160 V196&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;path class=&quot;sys-fil sys-courant&quot; d=&quot;M390,150 V196&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;path class=&quot;sys-fil sys-courant&quot; d=&quot;M620,150 V196&quot; marker-end=&quot;url(#hl-fl)&quot;/&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;60&quot; y=&quot;200&quot; width=&quot;200&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;160&quot; y=&quot;220&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;AHB ÷1&lt;/text&gt;&lt;text x=&quot;160&quot; y=&quot;244&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;100 MHz&lt;/text&gt;&lt;text x=&quot;160&quot; y=&quot;263&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;cœur, SysTick : 100 000 cycles/ms&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;290&quot; y=&quot;200&quot; width=&quot;200&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;390&quot; y=&quot;220&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;APB1 ÷2&lt;/text&gt;&lt;text x=&quot;390&quot; y=&quot;244&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;50 MHz&lt;/text&gt;&lt;text x=&quot;390&quot; y=&quot;263&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;USART3 : BRR 434 → 115 207 bauds&lt;/text&gt;&lt;rect class=&quot;sys-boite&quot; x=&quot;520&quot; y=&quot;200&quot; width=&quot;200&quot; height=&quot;74&quot; rx=&quot;6&quot;/&gt;&lt;text x=&quot;620&quot; y=&quot;220&quot; class=&quot;sys-titre&quot; text-anchor=&quot;middle&quot;&gt;APB2 ÷1&lt;/text&gt;&lt;text x=&quot;620&quot; y=&quot;244&quot; class=&quot;sys-valeur&quot; text-anchor=&quot;middle&quot;&gt;100 MHz&lt;/text&gt;&lt;text x=&quot;620&quot; y=&quot;263&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;max 100 MHz&lt;/text&gt;&lt;text x=&quot;380&quot; y=&quot;24&quot; class=&quot;sys-note&quot; text-anchor=&quot;middle&quot;&gt;Flash : 3 wait states (90 &amp;lt; HCLK ≤ 100 MHz à 2,7–3,6 V) · régulateur en scale 1&lt;/text&gt;&lt;text x=&quot;380&quot; y=&quot;296&quot; class=&quot;sys-code&quot; text-anchor=&quot;middle&quot;&gt;Relu sur la carte : RCC_PLLCFGR = 0x28401904 · RCC_CFGR = 0x100a · FLASH_ACR = 0x703&lt;/text&gt;&lt;/svg&gt;&lt;/div&gt;&lt;figcaption&gt;La tranche 4 : de 16 MHz sur la HSI à 100 MHz. Chaque constante est justifiée par une section du RM0402 dans le code, et relue dans les registres une fois flashée.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;le-moment-ou-ca-a-casse-savedstate&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#le-moment-ou-ca-a-casse-savedstate&quot; aria-label=&quot;Anchor link for: le-moment-ou-ca-a-casse-savedstate&quot;&gt;#&lt;/a&gt;
Le moment où ça a cassé : SavedState&lt;/h2&gt;
&lt;p&gt;Juste avant le premier allumage, &lt;code&gt;humility tasks&lt;/code&gt; échoue : « expected structure SavedState not found ».&lt;/p&gt;
&lt;p&gt;Pour comprendre, il faut savoir comment Humility lit une tâche. Quand le kernel interrompt une tâche, il range ses registres (r4 à r11, le pointeur de pile, etc.) dans une structure, le champ &lt;code&gt;save&lt;/code&gt; de l’entrée &lt;code&gt;Task&lt;/code&gt; de cette tâche. Humility lit la table des tâches directement dans la RAM de la carte. Pour savoir à quel octet se trouve chaque registre, il a besoin du plan de cette structure, qu’il trouve dans les infos de debug (DWARF) du binaire du kernel. Et il la cherchait par son nom : &lt;code&gt;SavedState&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Le 9 octobre, quatre jours plus tôt, la PR #2704 de Hubris a introduit un trait &lt;code&gt;Arch&lt;/code&gt; pour que le kernel puisse viser plusieurs architectures. La structure de l’ARMv7-M y a pris le nom &lt;code&gt;ArmMSavedState&lt;/code&gt;. Humility ne la trouve plus, et ni &lt;code&gt;humility tasks&lt;/code&gt; ni la lecture des registres d’une tâche ne marchent, quelle que soit la carte.&lt;/p&gt;
&lt;p&gt;Deux façons de s’en sortir. Claude fige d’abord la branche juste avant ce commit et continue, ce qui suffit pour cette carte. C’est dans DECISIONS.md, et ça débloque. Ensuite, le correctif, sur la branche &lt;code&gt;savedstate-by-member&lt;/code&gt; de mon fork de Humility : au lieu de chercher le type par son nom, Humility prend le type du champ &lt;code&gt;save&lt;/code&gt; de &lt;code&gt;Task&lt;/code&gt;, que le DWARF donne directement. Le nom peut changer, le champ reste. Onze lignes ajoutées, quatre retirées, aux deux endroits qui lisaient cette structure : &lt;code&gt;humility tasks&lt;/code&gt; et la lecture des registres. Le correctif marche avec l’ancien kernel et avec le nouveau, testé sur la carte dans les deux cas.&lt;/p&gt;
&lt;h2 id=&quot;le-second-correctif-stackmargin-affichait-des-zeros&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#le-second-correctif-stackmargin-affichait-des-zeros&quot; aria-label=&quot;Anchor link for: le-second-correctif-stackmargin-affichait-des-zeros&quot;&gt;#&lt;/a&gt;
Le second correctif : stackmargin affichait des zéros&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;humility stackmargin&lt;/code&gt; dit, pour chaque tâche, combien de pile elle n’a jamais utilisée. Le principe : au démarrage d’une tâche, le kernel remplit toute sa pile avec un motif, &lt;code&gt;0xbaddcafe&lt;/code&gt;. Humility lit la pile depuis le bas et compte les mots encore intacts : c’est la marge.&lt;/p&gt;
&lt;p&gt;Sur la carte, il affiche une marge de 0 pour &lt;code&gt;jefe&lt;/code&gt;, le superviseur, avec une pile de 152 octets alors que son &lt;code&gt;app.toml&lt;/code&gt; en déclare 2200.&lt;/p&gt;
&lt;p&gt;La MPU d’un Cortex-M4 ne connaît que des régions dont la taille est une puissance de 2. Depuis avril (PR #2458), Hubris découpe la RAM d’une tâche en plusieurs régions contiguës pour moins gaspiller : les 2560 octets de &lt;code&gt;jefe&lt;/code&gt; font 1 Kio + 1 Kio + 512 octets au lieu d’une région de 4 Kio. Une pile peut donc s’étaler sur plusieurs régions. Le kernel a été corrigé en mai (PR #2492) pour la peindre en entier. Humility, lui, ne lisait que la région qui contient le sommet de pile : ici la dernière, où ne tiennent que 152 octets de pile, tous utilisés. D’où la marge de 0.&lt;/p&gt;
&lt;figure class=&quot;sys sys-pile&quot;&gt;&lt;div class=&quot;defile&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;La pile de jefe vue par humility stackmargin, avant et après correction, défilable horizontalement&quot;&gt;&lt;svg viewBox=&quot;0 0 800 300&quot; role=&quot;img&quot; aria-labelledby=&quot;pile-t pile-d&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;title id=&quot;pile-t&quot;&gt;La pile de jefe vue par humility stackmargin, avant et après correction&lt;/title&gt;&lt;desc id=&quot;pile-d&quot;&gt;La RAM de jefe fait 2560 octets répartis en trois régions MPU contiguës. Sa pile de 2200 octets commence à 0x20001400 et son sommet initial est 0x20001C98, dans la troisième région. Avant correction, Humility ne lisait que cette troisième région : 152 octets, tous utilisés, donc une marge de 0. Après correction, il lit les 2200 octets, trouve 1928 octets encore à 0xbaddcafe et une marge de 1928.&lt;/desc&gt;&lt;defs&gt;&lt;pattern id=&quot;pl-peint&quot; width=&quot;6&quot; height=&quot;6&quot; patternUnits=&quot;userSpaceOnUse&quot; patternTransform=&quot;rotate(45)&quot;&gt;&lt;line class=&quot;sys-hachure&quot; x1=&quot;0&quot; y1=&quot;0&quot; x2=&quot;0&quot; y2=&quot;6&quot;/&gt;&lt;/pattern&gt;&lt;/defs&gt;&lt;rect class=&quot;sys-peint-fond&quot; x=&quot;70.0&quot; y=&quot;54&quot; width=&quot;482.0&quot; height=&quot;44&quot;/&gt;&lt;rect fill=&quot;url(#pl-peint)&quot; x=&quot;70.0&quot; y=&quot;54&quot; width=&quot;482.0&quot; height=&quot;44&quot;/&gt;&lt;rect class=&quot;sys-utilise&quot; x=&quot;552.0&quot; y=&quot;54&quot; width=&quot;68.0&quot; height=&quot;44&quot;/&gt;&lt;rect class=&quot;sys-donnees&quot; x=&quot;620.0&quot; y=&quot;54&quot; width=&quot;90.0&quot; height=&quot;44&quot;/&gt;&lt;text x=&quot;198&quot; y=&quot;81&quot; class=&quot;sys-dans&quot; text-anchor=&quot;middle&quot;&gt;0xbaddcafe : 1928 o jamais touchés&lt;/text&gt;&lt;text x=&quot;665&quot; y=&quot;81&quot; class=&quot;sys-dans&quot; text-anchor=&quot;middle&quot;&gt;données&lt;/text&gt;&lt;rect class=&quot;sys-region&quot; x=&quot;70.0&quot; y=&quot;54&quot; width=&quot;256.0&quot; height=&quot;44&quot;/&gt;&lt;text x=&quot;198&quot; y=&quot;44&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;région 1 · 1 Kio&lt;/text&gt;&lt;rect class=&quot;sys-region&quot; x=&quot;326.0&quot; y=&quot;54&quot; width=&quot;256.0&quot; height=&quot;44&quot;/&gt;&lt;text x=&quot;454&quot; y=&quot;44&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;région 2 · 1 Kio&lt;/text&gt;&lt;rect class=&quot;sys-region&quot; x=&quot;582.0&quot; y=&quot;54&quot; width=&quot;128.0&quot; height=&quot;44&quot;/&gt;&lt;text x=&quot;646&quot; y=&quot;44&quot; class=&quot;sys-detail&quot; text-anchor=&quot;middle&quot;&gt;région 3 · 512 o&lt;/text&gt;&lt;line class=&quot;sys-repere&quot; x1=&quot;620.0&quot; y1=&quot;50&quot; x2=&quot;620.0&quot; y2=&quot;168&quot;/&gt;&lt;text x=&quot;624&quot; y=&quot;120&quot; class=&quot;sys-code&quot;&gt;sommet initial 0x20001C98&lt;/text&gt;&lt;line class=&quot;sys-repere&quot; x1=&quot;552.0&quot; y1=&quot;98&quot; x2=&quot;552.0&quot; y2=&quot;108&quot;/&gt;&lt;text x=&quot;548&quot; y=&quot;120&quot; class=&quot;sys-detail&quot; text-anchor=&quot;end&quot;&gt;272 o utilisés&lt;/text&gt;&lt;text x=&quot;70&quot; y=&quot;290&quot; class=&quot;sys-axe&quot; text-anchor=&quot;middle&quot;&gt;0x20001400&lt;/text&gt;&lt;text x=&quot;326&quot; y=&quot;290&quot; class=&quot;sys-axe&quot; text-anchor=&quot;middle&quot;&gt;0x20001800&lt;/text&gt;&lt;text x=&quot;582&quot; y=&quot;290&quot; class=&quot;sys-axe&quot; text-anchor=&quot;middle&quot;&gt;0x20001C00&lt;/text&gt;&lt;text x=&quot;710&quot; y=&quot;290&quot; class=&quot;sys-axe&quot; text-anchor=&quot;middle&quot;&gt;0x20001E00&lt;/text&gt;&lt;text x=&quot;10&quot; y=&quot;174&quot; class=&quot;sys-serie sys-faute-txt&quot;&gt;avant&lt;/text&gt;&lt;line class=&quot;sys-mesure sys-faute&quot; x1=&quot;582.0&quot; y1=&quot;170&quot; x2=&quot;620.0&quot; y2=&quot;170&quot;/&gt;&lt;circle class=&quot;sys-scan sys-scan-avant&quot; cx=&quot;582.0&quot; cy=&quot;170&quot; r=&quot;5&quot;/&gt;&lt;text x=&quot;574&quot; y=&quot;174&quot; class=&quot;sys-detail&quot; text-anchor=&quot;end&quot;&gt;lit 152 o, bute au 1er mot → MARGIN 0&lt;/text&gt;&lt;text x=&quot;10&quot; y=&quot;219&quot; class=&quot;sys-serie sys-sain-txt&quot;&gt;après&lt;/text&gt;&lt;line class=&quot;sys-mesure sys-sain&quot; x1=&quot;70.0&quot; y1=&quot;215&quot; x2=&quot;620.0&quot; y2=&quot;215&quot;/&gt;&lt;g class=&quot;sys-scan-apres&quot;&gt;&lt;circle class=&quot;sys-scan&quot; cx=&quot;70.0&quot; cy=&quot;215&quot; r=&quot;5&quot;/&gt;&lt;/g&gt;&lt;text x=&quot;70&quot; y=&quot;237&quot; class=&quot;sys-detail&quot;&gt;lit 2200 o depuis la base, compte 1928 o de 0xbaddcafe → MARGIN 1928&lt;/text&gt;&lt;/svg&gt;&lt;/div&gt;&lt;figcaption&gt;Relevé sur la carte (humility map, readmem). Humility ne regardait que la région qui contient le sommet de pile. Le kernel, lui, peint toute la pile en 0xbaddcafe sur les trois régions.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           STACKBASE  STACKSIZE  MAXDEPTH  MARGIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;avant  jefe 0x20001c00       152       152       0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;après  jefe 0x20001400      2200       272    1928&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Le correctif, sur la branche &lt;code&gt;stackmargin-multi-region&lt;/code&gt;, descend les régions contiguës qui appartiennent à la même tâche, comme le fait le kernel, avant de mesurer. Le test de non-régression de Humility l’a aussi validé : sur un dump de Sidecar, un vrai switch d’Oxide, l’instantané attendu contenait trois faux « MARGIN 0 ». Après correction, chaque taille de pile égale à l’octet près celle déclarée dans l’&lt;code&gt;app.toml&lt;/code&gt; de ce Sidecar.&lt;/p&gt;
&lt;h2 id=&quot;ou-j-en-suis&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ou-j-en-suis&quot; aria-label=&quot;Anchor link for: ou-j-en-suis&quot;&gt;#&lt;/a&gt;
Où j’en suis&lt;/h2&gt;
&lt;p&gt;La branche &lt;code&gt;nucleo-f412zg&lt;/code&gt; compte cinq commits, avec un DECISIONS.md et un README. Elle est figée avant la PR #2704 ; avec le premier correctif, Humility suit aussi le kernel récent. Les deux correctifs sont sur mon fork de Humility. La suite de tests du kernel sur la F412, la tranche 5 optionnelle, n’est pas faite. Et « tout &lt;code&gt;Healthy&lt;/code&gt; » n’est vrai qu’à moitié : &lt;code&gt;ping&lt;/code&gt; fait exprès une faute toutes les 100 réponses de &lt;code&gt;pong&lt;/code&gt;, comme dans les démos d’Oxide.&lt;/p&gt;
&lt;p&gt;Une piste pour la suite, pas encore faite : un capteur I2C ou SPI derrière une tâche driver. Dans Hubris, un driver est une tâche comme une autre : elle seule a accès aux registres du périphérique, déclarés dans l’&lt;code&gt;app.toml&lt;/code&gt;, et les autres tâches lui parlent par messages. Le driver I2C du dépôt vise les STM32H7 et G0 (plus un driver à part pour le LPC55), le SPI seulement les STM32H7 et le LPC55 : rien pour la famille F4, il faudrait l’écrire pour cette carte.&lt;/p&gt;
&lt;p&gt;À suivre…&lt;/p&gt;
&lt;aside class=&quot;transparence&quot; aria-label=&quot;Comment ce billet a été écrit&quot;&gt;
  &lt;p class=&quot;transparence-titre&quot;&gt;Comment ce billet a été écrit&lt;/p&gt;
  &lt;p&gt;Rédigé par Claude Opus 5.5 à partir de : un prompt de mission, une dizaine de messages et un entretien écrits par François, sa session Claude Code, le dépôt &lt;code&gt;hubris&lt;/code&gt; (5 commits sur la branche &lt;code&gt;nucleo-f412zg&lt;/code&gt;), deux branches Humility (3 commits), les sorties &lt;code&gt;humility&lt;/code&gt; et les registres relus sur la carte.&lt;/p&gt;
  &lt;p&gt;Relu et corrigé par François en 20 min, 6 % du texte réécrit.&lt;/p&gt;
&lt;/aside&gt;
</content>
    </entry>
</feed>
