{"id":1775,"date":"2022-05-17T21:42:31","date_gmt":"2022-05-17T19:42:31","guid":{"rendered":"http:\/\/www.fabienm.eu\/wordpress\/?p=1775"},"modified":"2022-09-22T21:41:12","modified_gmt":"2022-09-22T19:41:12","slug":"rust-sur-longan-nano","status":"publish","type":"post","link":"http:\/\/www.fabienm.eu\/wordpress\/2022\/05\/17\/rust-sur-longan-nano\/","title":{"rendered":"Rust sur Longan Nano"},"content":{"rendered":"\n<p>La <a href=\"https:\/\/longan.sipeed.com\/en\/\">Longan Nano<\/a> est une petite carte de la taille d&rsquo;un pouce munie d&rsquo;un microcontr\u00f4leur \u00e0 c\u0153ur RISC-V le <a href=\"https:\/\/www.gigadevice.com\/microcontroller\/gd32vf103cbt6\/\">GD32VF103CBT6<\/a>. Processeur qui est un clone du fameux stm32 de chez ST, MAIS avec un c\u0153ur RISC-V (alors que le stm32&nbsp;est \u00e0 base de ARM).<\/p>\n\n\n\n<p>Ce qui est bien avec la Longan Nano c&rsquo;est que pour <a href=\"https:\/\/www.seeedstudio.com\/Sipeed-Longan-Nano-RISC-V-GD32VF103CBT6-Development-Board-p-4205.html\">$4.90<\/a> il y a absolument<a href=\"http:\/\/www.fabienm.eu\/wordpress\/?p=1336\"> tout pour faire du d\u00e9veloppement embarqu\u00e9<\/a>: en plus de l&rsquo;\u00e9cran oled couleurs et la LED RGB il y a une interface USB (connecteur usb-c) qui permet d&rsquo;alimenter la carte, la programmer et communiquer par UART. Pour le JTAG par contre il faut un adaptateur externe qui peut cependant \u00eatre tr\u00e8s pratique pour <a href=\"http:\/\/www.fabienm.eu\/wordpress\/?p=1528\">utiliser un debugger<\/a>.<\/p>\n\n\n\n<p>Ce qui est moins bien par contre c&rsquo;est qu&rsquo;elle <a href=\"https:\/\/twitter.com\/BluffJe\/status\/1526637661527613441\">semble en rupture de stock depuis longtemps.<\/a><\/p>\n\n\n\n<p>Bref, c&rsquo;est une \u00abvieille\u00bb carte mais qui est parfaite pour faire du d\u00e9veloppement embarqu\u00e9 sans rien d&rsquo;autre qu&rsquo;un PC et un c\u00e2ble USB. <\/p>\n\n\n\n<p>Pourquoi ne pas tenter de faire du Rust avec alors ? En plus il semble exister des projets de support du langage <a href=\"https:\/\/github.com\/riscv-rust\/longan-nano\">pour cette carte<\/a>. Voila qui pourrait <a href=\"https:\/\/apollolabsblog.hashnode.dev\/demystifying-rust-embedded-hal-split-and-constrain-methods\">d\u00e9mystifier rust pour l&#8217;embarqu\u00e9<\/a> !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Codons mon bon<\/h2>\n\n\n\n<p>La <a href=\"https:\/\/docs.rs\/crate\/longan-nano\/latest\">documentation officielle<\/a> de la cagette nous demande de v\u00e9rifier la version de rust :<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript \">$ rustup <span class=\"hljs-keyword\">default<\/span> stable\n<span class=\"hljs-attr\">info<\/span>: using existing install <span class=\"hljs-keyword\">for<\/span> <span class=\"hljs-string\">'stable-x86_64-unknown-linux-gnu'<\/span>\n<span class=\"hljs-attr\">info<\/span>: <span class=\"hljs-keyword\">default<\/span> toolchain <span class=\"hljs-keyword\">set<\/span> to 'stable-x86_64-unknown-linux-gnu'\n\n  stable-x86_64-unknown-linux-gnu unchanged - rustc 1.58.0 (02072b482 2022-01-11)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Version 1.58, c&rsquo;est bon on est sup\u00e9rieur \u00e0 la 1.36 requise. Comme je veux travailler avec juste le c\u00e2ble usb j&rsquo;utiliserais (ou tenterais d&rsquo;utiliser) <em>dfu-util <\/em>pour programmer le micro. <\/p>\n\n\n\n<p>Il faut juste se compiler une version des binutils comme indiqu\u00e9 dans la doc pour avoir l&rsquo;utilitaire <code>objcopy<\/code> :<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript \">$ git clone https:<span class=\"hljs-comment\">\/\/github.com\/sifive\/riscv-binutils-gdb.git<\/span>\n$ cd riscv-binutils-gdb\n$ .\/configure --target=riscv64-unknown-elf --disable-werror --<span class=\"hljs-keyword\">with<\/span>-python=no --disable-gdb --disable-sim --disable-libdecnumber --disable-libreadline --<span class=\"hljs-keyword\">with<\/span>-expat=yes --<span class=\"hljs-keyword\">with<\/span>-mpc=no --<span class=\"hljs-keyword\">with<\/span>-mpfr=no --<span class=\"hljs-keyword\">with<\/span>-gmp=no\n$ make<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>\u00c7a prend un peut de temps avec ma vieille machine (<a href=\"https:\/\/www.lenovo.com\/fr\/fr\/laptops\/thinkpad\/t-series\/t430\/\">T430<\/a>) mais \u00e7a marche.<\/p>\n\n\n\n<p>On aura \u00e9galement besoin d&rsquo;une toolchain riscv:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript \">$ wget https:<span class=\"hljs-comment\">\/\/static.dev.sifive.com\/dev-tools\/riscv64-unknown-elf-gcc-8.1.0-2019.01.0-x86_64-linux-ubuntu14.tar.gz<\/span>\n$ tar zxvf riscv64-unknown-elf-gcc<span class=\"hljs-number\">-8.1<\/span><span class=\"hljs-number\">.0<\/span><span class=\"hljs-number\">-2019.01<\/span><span class=\"hljs-number\">.0<\/span>-x86_64-linux-ubuntu14.tar.gz<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Et bien entendu, il faudra \u00abdescendre\u00bb le projet <a href=\"https:\/\/github.com\/riscv-rust\/longan-nano\">git hub d&rsquo;exemples<\/a>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php \">$ git <span class=\"hljs-keyword\">clone<\/span> https:<span class=\"hljs-comment\">\/\/github.com\/riscv-rust\/longan-nano.git<\/span>\n$ cd longan-nano\n$ rustup target add riscv32imac-unknown-none-elf<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Puisque visiblement j&rsquo;ai une version B du microcontr\u00f4leur il faut modifier le fichier de configuration .cargo\/config.<\/p>\n\n\n\n<p>Et c&rsquo;est parti mamie :<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs \">$ cargo build --examples --release --all-features<\/code><\/span><\/pre>\n\n\n<p>On extrait maintenant l&rsquo;huile essentiel de notre binaire avec objcopy que l&rsquo;on appelera <em>firmware.bin<\/em> :<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs \">..\/riscv64-unknown-elf-gcc-8.1.0-2019.01.0-x86_64-linux-ubuntu14\/bin\/riscv64-unknown-elf-objcopy -O binary target\/riscv32imac-unknown-none-elf\/release\/examples\/blinky firmware.bin<\/code><\/span><\/pre>\n\n\n<p>Puis on le t\u00e9l\u00e9charge dans la carte au moyen de dfu-util en ayant bien pris soin de mettre le microcontr\u00f4leur en mode \u00abbootstrap\u00bb ( appui sur reset tout en gardant boot0 press\u00e9).<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs \">$  dfu-util -a 0 -s 0x08000000:leave -D firmware.bin\ndfu-util 0.10-dev\n\nCopyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\nCopyright 2010-2021 Tormod Volden and Stefan Schmidt\nThis program is Free Software and has ABSOLUTELY NO WARRANTY\nPlease report bugs to http:\/\/sourceforge.net\/p\/dfu-util\/tickets\/\n\ndfu-util: Warning: Invalid DFU suffix signature\ndfu-util: A valid DFU suffix will be required in a future dfu-util release\ndfu-util: Cannot open DFU device 0a5c:21e6 found on devnum 3 (LIBUSB_ERROR_ACCESS)\nOpening DFU capable USB device...\nDevice ID 28e9:0189\nDevice DFU version 011a\nClaiming USB DFU Interface...\nSetting Alternate Interface #0 ...\nDetermining device status...\nDFU state(2) = dfuIDLE, status(0) = No error condition is present\nDFU mode device DFU version 011a\nDevice returned transfer size 2048\nDfuSe interface name: \"Internal Flash  \"\nFound GD32VF103, which reports a bad page size and count for its internal memory.\nFixed layout based on part number: page size 1024, count 128.\nDownloading element to address = 0x08000000, size = 9388\nErase   \t&#91;=========================] 100%         9388 bytes\nErase    done.\nDownload\t&#91;=========================] 100%         9388 bytes\nDownload done.\nFile downloaded successfully\n<\/code><\/span><\/pre>\n\n\n<p>Et la led clignote \\o\/ !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Le code<\/h2>\n\n\n\n<p>Le code \u00e0 proprement parler du clignotement de led est donn\u00e9 dans le fichier e<a href=\"https:\/\/github.com\/riscv-rust\/longan-nano\/blob\/master\/examples\/blinky.rs\">xamples\/blinky.rs<\/a><\/p>\n\n\n\n<p>Et le c\u0153ur de la boucle de clignotement est donn\u00e9e ci-dessous :<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript \">    <span class=\"hljs-keyword\">let<\/span> mut i = <span class=\"hljs-number\">0<\/span>;\n    loop {\n        <span class=\"hljs-keyword\">let<\/span> inext = (i + <span class=\"hljs-number\">1<\/span>) % leds.len();\n        leds&#91;i].off();\n        leds&#91;inext].on();\n        delay.delay_ms(<span class=\"hljs-number\">500<\/span>);\n\n        i = inext;\n    }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Il y a trois leds (RGB), on se sert de l&rsquo;index i pour parcourir le tableau de leds. On \u00e9teint la led courante puis on allume la suivante et on attend 500ms.<\/p>\n\n\n\n<p>De cette mani\u00e8re, la led va changer de couleur toutes les demi-seconde et nous offrir un clignotement tricolore. <\/p>\n\n\n\n<p>Si l&rsquo;on trouve le clignotement on\/off un peu trop violent, on peut, comme exercice faire en sorte que la couleurs s&rsquo;allume et s&rsquo;\u00e9teigne progressivement avec un code de ce genre :<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript \">    leds&#91;<span class=\"hljs-number\">0<\/span>].off();\n    leds&#91;<span class=\"hljs-number\">1<\/span>].off();\n    leds&#91;<span class=\"hljs-number\">2<\/span>].off();\n\n    <span class=\"hljs-keyword\">let<\/span> count_max:u32 = <span class=\"hljs-number\">1000<\/span>;\n    <span class=\"hljs-keyword\">let<\/span> mut count:u32 = <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-keyword\">let<\/span> mut decount: bool = <span class=\"hljs-literal\">true<\/span>;\n    <span class=\"hljs-keyword\">let<\/span> mut i:usize = <span class=\"hljs-number\">0<\/span>;\n\n    loop {\n        leds&#91;i].on();\n        delay.delay_us(count);\n        leds&#91;i].off();\n        delay.delay_us(count_max - count);\n        <span class=\"hljs-keyword\">if<\/span> decount {\n            <span class=\"hljs-keyword\">if<\/span> count == <span class=\"hljs-number\">0<\/span> {\n                decount = <span class=\"hljs-literal\">false<\/span>;\n                i = (i + <span class=\"hljs-number\">1<\/span>) % leds.len();\n            } <span class=\"hljs-keyword\">else<\/span> {\n                count = count - <span class=\"hljs-number\">1<\/span>;\n            }\n        } <span class=\"hljs-keyword\">else<\/span> {\n            <span class=\"hljs-keyword\">if<\/span> count &lt; count_max {\n                count = count + <span class=\"hljs-number\">1<\/span>;\n            }<span class=\"hljs-keyword\">else<\/span>{\n                decount = <span class=\"hljs-literal\">true<\/span>;\n            }\n        }\n    }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>On aura bien pris soin de descendre la granularit\u00e9 du d\u00e9lais \u00e0 la microseconde puisque c&rsquo;est disponible<a href=\"https:\/\/docs.rs\/gd32vf103xx-hal\/0.5.0\/gd32vf103xx_hal\/delay\/struct.McycleDelay.html#impl-DelayUs%3Cu32%3E\"> dans le HAL du microcontr\u00f4leur<\/a> (GD32VF103).<\/p>\n\n\n\n<p>Voila un clignotement plus doux des LEDs. Et on se rend compte par la m\u00eame occasion que la LED verte est nettement plus puissante que les deux autres.<\/p>\n\n\n\n<iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/vZi1iUFNia8\" title=\"YouTube video player\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"\" width=\"560\" height=\"315\" frameborder=\"0\"><\/iframe>\n\n\n\n<p>Il y a d&rsquo;autres exemples dans le git du projet, notamment pour utiliser le lecteur microSD ainsi que l&rsquo;\u00e9cran, mais je laisse le soin au lecteur de les d\u00e9couvrir par lui m\u00eame \ud83d\ude09<\/p>\n\n\n\n<p>Pour conclure, gr\u00e2ce \u00e0 ce projet, la prise en main de la Longan Nano avec du Rust est vraiment simple et tr\u00e8s peu verbeuse. J&rsquo;avais <a href=\"https:\/\/connect.ed-diamond.com\/Hackable\/hk-033\/un-risc-v-a-bas-cout-pour-monitorer-votre-pc-avec-lcdproc\">eu beaucoup plus de mal \u00e0 la prendre en main<\/a> en C avec tout le bazar de platformio et vscode \u00e0 l&rsquo;\u00e9poque. Mais c&rsquo;est peut-\u00eatre tout simplement parce que la carte est plus mature aujourd&rsquo;hui aussi \ud83d\ude09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ressources<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/gd32v-rust\">gd32vf rust github page<\/a><\/li><li><a href=\"https:\/\/github.com\/riscv-rust\/longan-nano\">longan nano en rust<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>La Longan Nano est une petite carte de la taille d&rsquo;un pouce munie d&rsquo;un microcontr\u00f4leur \u00e0 c\u0153ur RISC-V le GD32VF103CBT6. Processeur qui est un clone du fameux stm32 de chez ST, MAIS avec un c\u0153ur RISC-V (alors que le stm32&nbsp;est &hellip; <a href=\"http:\/\/www.fabienm.eu\/wordpress\/2022\/05\/17\/rust-sur-longan-nano\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[220,219,191],"class_list":["post-1775","post","type-post","status-publish","format-standard","hentry","category-non-classe","tag-gd32vf","tag-longan_nano","tag-rust"],"_links":{"self":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/comments?post=1775"}],"version-history":[{"count":18,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1775\/revisions"}],"predecessor-version":[{"id":1870,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1775\/revisions\/1870"}],"wp:attachment":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/media?parent=1775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/categories?post=1775"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/tags?post=1775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}