tag:blogger.com,1999:blog-5758115847616029162024-03-28T11:37:04.617-07:00Going back to electronic after a 20 years breakmeanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.comBlogger180125tag:blogger.com,1999:blog-575811584761602916.post-81857049314651152222024-01-27T02:50:00.000-08:002024-01-27T05:39:33.340-08:00lnBMP : CH32V3xx support <p> It is painful, but it is beginning to work :</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjETBAL5O3VduufffMmsIL9vkP5BkbADw4byB_To3lxalbLS9KAO4bmYdqOe1GR4b__mkgHqGA_KG8Kvh4qWfQ3myzHiIJ4VqbHk_Mls6I922Ebuug3IeE0BbTUkRrAka6FrUKh-vb0YVUMV9MoCSEwlvFE5XtRrfxXLNkietjTtXrXGJVOXskQWRrjUT3d/s871/ch32_debug.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="871" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjETBAL5O3VduufffMmsIL9vkP5BkbADw4byB_To3lxalbLS9KAO4bmYdqOe1GR4b__mkgHqGA_KG8Kvh4qWfQ3myzHiIJ4VqbHk_Mls6I922Ebuug3IeE0BbTUkRrAka6FrUKh-vb0YVUMV9MoCSEwlvFE5XtRrfxXLNkietjTtXrXGJVOXskQWRrjUT3d/s320/ch32_debug.png" width="320" /></a></div><br /><p>On the picture a RP2040-pico zero running lnBMP and happily debugging a ch32v307 Riscv chip</p><p>(of course it can still debug Arm chips)</p><p><br /></p><p>Perigoso did a lot of work there, only the communication protocol /implementation was missing.</p><p>It is still a bit slow though :(</p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-13707369623598251112024-01-10T23:09:00.000-08:002024-01-11T11:25:42.212-08:00CH32Vxx : WCH_LINKW in riscv mode<p>Edit: There is a much simpler way. Press the Key Button will connecting the USB-C , it will switch between ARM & RISCV</p><p><br /></p><p>I recently bought the WeAct WCHLINK-W, a small dap style debugger </p><p>(both USB & BT)</p><p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqccFYZdAnqMD-9uLh1WXg9IKOdLNw-GHI7lP8zeSp15PbFImHRJSQNcg-JQNa-JvTurHzJ9oBBWFT3zOMahXAIKXoIC6k2i9CcvVmTtBHTCRmL_dtxSKh1wT4CUg0IhTAfPzUq54Hl5tq0Zczn0FQgz6qnYnHi5mkmCFCyVDJzAJDABVFau6pukpGMWSM/s1256/wclinke.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="750" data-original-width="1256" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqccFYZdAnqMD-9uLh1WXg9IKOdLNw-GHI7lP8zeSp15PbFImHRJSQNcg-JQNa-JvTurHzJ9oBBWFT3zOMahXAIKXoIC6k2i9CcvVmTtBHTCRmL_dtxSKh1wT4CUg0IhTAfPzUq54Hl5tq0Zczn0FQgz6qnYnHi5mkmCFCyVDJzAJDABVFau6pukpGMWSM/s320/wclinke.jpg" width="320" /></a></div><br /><p></p><p>At first it is configured in Arm/SWD mode and is being listed as </p><p><span style="background-color: white; font-family: monospace;">1a86:8012 QinHeng Electronics </span>by lsusb.</p><div>On linux, the simpler way to switch it to RiscV mode is to download mountriver community </div><div>Then go to Flash->Configuration</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ4RkJzc8pjETsy9UEdmWwM_a4vg9Mnhs-XaxhZHxyXng3qWcMbK5zMa7Byi_ufD5dlEeSGBCTlmm7Q4ge2EX2l11Z03XQaaNg_xWQiDjCKiYK8eWoQABH5PfbIGN1qGvi5aW0Kv9tk6AEt9RVvtPqKBaKwtoNssW506AlpJw-d6d3i04o3FHUngAlqitj/s447/mounriver.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="447" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ4RkJzc8pjETsy9UEdmWwM_a4vg9Mnhs-XaxhZHxyXng3qWcMbK5zMa7Byi_ufD5dlEeSGBCTlmm7Q4ge2EX2l11Z03XQaaNg_xWQiDjCKiYK8eWoQABH5PfbIGN1qGvi5aW0Kv9tk6AEt9RVvtPqKBaKwtoNssW506AlpJw-d6d3i04o3FHUngAlqitj/s320/mounriver.jpg" width="320" /></a></div><br /><div>Click Query on the "Target Mode" line.</div><div>It should be detected as WCH DapLink</div><div>Switch it to "WCH Link RV", click apply , wait 2 seconds and done!</div><div><br /></div><div>The id of the device has changed and now lsusb should report</div><div><span style="background-color: white; font-family: monospace;">1a86:8010 QinHeng Electronics</span></div><div><br /></div>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-9042310290220780132023-12-23T07:34:00.000-08:002023-12-23T07:34:50.529-08:00lnBMP : rp2040, Not forgotten<p> </p><p>lnBMP : Lots of little issues tackled :</p><p>- Preliminary FreeRTOS awareness through "mon fos M0|M3|M33'</p><p>- Uart <->USB through DMA, that one was a pain</p><p>- Configuration change to map the supported boards depending on the amount of RAM we have.</p><p>But finally, here it is : lnBMP running on a RP2040 in a itsy bitsy case, and it works !</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjWrdb3BqlgEt6sffc2D66Yu3BAAoml3cMJtrqD8W27qyD_pMLlY0c4cbKM6XnDZVJ7Ejph_7M9Xgfr4w72UCb27kJtl3gTrkHz4YfIfw7SJ7it4eBfSmETZAm3oysKbXyQGs4FMCadiilJfvX36IxCiW7Nbu6ORiYu40cNlFZCqs7uCdyGBsI-HSL5rRn4" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="472" data-original-width="705" height="214" src="https://blogger.googleusercontent.com/img/a/AVvXsEjWrdb3BqlgEt6sffc2D66Yu3BAAoml3cMJtrqD8W27qyD_pMLlY0c4cbKM6XnDZVJ7Ejph_7M9Xgfr4w72UCb27kJtl3gTrkHz4YfIfw7SJ7it4eBfSmETZAm3oysKbXyQGs4FMCadiilJfvX36IxCiW7Nbu6ORiYu40cNlFZCqs7uCdyGBsI-HSL5rRn4" width="320" /></a></div><br /><p></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-59569838460637191912023-11-11T07:17:00.003-08:002023-11-11T07:17:38.232-08:00lnBMP + RP2040 ?<p> In the eternal goal of having the smaller debugger possible, i ended up porting the strict minimum of lnBMP on top of the RP2040 chip.</p><p>Tinyusb is available so that part was not problem.</p><p>Clang + Rust, no problem either.</p><p>The pico sdk is providing the basics , already CMake based.</p><p>Using DMA+Uart was a bit more complicated but not that much at the end of the day.</p><p>And ...It works !, expect nice pics of a lnBMP + RP2040 zero in a 3D printed case soon.</p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-81622963337510333992023-10-07T06:34:00.003-07:002023-10-07T06:35:45.762-07:00Reparing the screen of a Quicko T12 soldering iron<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMsgCrOgpXdqcaHQVd1X-q72Fw-3cHST8G6MSwfLAjzB5EiXmvIpYDgz-mhIuVf2d-5a5n2Z8duQKoJS61IomA6zv7vdRYNULNzM9EcSVggvUSwiCgDNBwkoZfSWOz3eAo2lN7-vt3_Lh0n3QR5kR3hFcyL39s6OhNvb_ILp88_GoFFP1DQRsrk8xVgEmi/s279/quicko.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="173" data-original-width="279" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMsgCrOgpXdqcaHQVd1X-q72Fw-3cHST8G6MSwfLAjzB5EiXmvIpYDgz-mhIuVf2d-5a5n2Z8duQKoJS61IomA6zv7vdRYNULNzM9EcSVggvUSwiCgDNBwkoZfSWOz3eAo2lN7-vt3_Lh0n3QR5kR3hFcyL39s6OhNvb_ILp88_GoFFP1DQRsrk8xVgEmi/s1600/quicko.jpg" width="279" /></a></div><br /> <p></p><p>This morning i realized the screen of my soldering iron was broken.</p><p>I like that soldering iron, it is similar to that <a href="https://www.amazon.fr/gp/product/B0BZ4K8R3W/ref=ox_sc_act_title_1?smid=A1VCSXGKXGGF30&psc=1">one</a> with a STC chip and the main power supply included.</p><p>I looked on the net and found this <a href="https://zzncx.top/posts/broken-quicko-t12-952/">post</a></p><p>My T12 control board is slightly different; it is not just connecting the VCC/VDD/SCL/SDA but the whole 30 pins ribbon.</p><p>I removed the whole lcd+ribbon from one of those cheap <a href="https://www.amazon.fr/SSD1306-dAffichage-Auto-Lumineuse-Compatible-Raspberry/dp/B08FD643VZ/ref=d_pd_sim_sccl_4_6/261-9906251-6836418?pd_rd_w=tYui4&content-id=amzn1.sym.c7b1b7f2-a001-454f-89b1-43a36a4eb1af&pf_rd_p=c7b1b7f2-a001-454f-89b1-43a36a4eb1af&pf_rd_r=F4PHFGDAJKF8JF4XHRSP&pd_rd_wg=04Z3y&pd_rd_r=b3bbc491-cd95-40a8-859f-3e6d3add4b95&pd_rd_i=B08FD643VZ&psc=1">LCD screen</a>s i had in the spare box and solder it in place of the original one.</p><p> The screen is smaller than the original one but it's not really a problem. It works fine.</p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-76254474215409794372023-06-25T06:52:00.006-07:002023-06-25T06:52:57.926-07:00clang-17, lto and aggressive optimisations<p>Lately, i updated lnDSO150 to v2.3, in particular its build system to be in sync with how i do things nowadays.</p><p>The main goal is to easily switch between GCC and CLANG-17 (<span> arm or riscv )</span></p><p>The lnDSO150 has one variant (the FNIRSI one) with less flash ( only 64 kB), so i could use every flash gain possible</p><p>Using clang + lto DID provide a nice size reduction (final size was ~ 50 kB for the fnirsi build) and at first it seemed to work alright.</p><p>At first.</p><p><br /></p><p>Then, i realized that it made some underlying problem appear due its aggressive optimization.</p><p>In other words, the bugs were there since day one, but hidden because the software was losing the race against the hardware every time.</p><p><br /></p><p>A couple of examples :</p><p>- On the DSO150, some of the screen GPIO are reprogrammed as input to scan if buttons have been pressed. If you flip the gpio too quickly, the button MAY keep the last state it was when used as output, causing random fake key pressed. Adding a couple of nops fixed the issue.</p><p>- Similarly, the flash driver was racing against the flash hw. Adding a couple of nops fixed the issue, probably not the right fix.</p><p><br /></p><p>It is human to first assume clang+lto is a buggy compiler. That's not the case, it was buggy code.</p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-58920469859445538532023-06-17T08:05:00.003-07:002023-06-17T08:06:57.264-07:00lnBMP + CH32V303!<p> Finally got the PCB (that was my first one)</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuqKwP-anqjl75IgkzZsVZv8F4mC--ROosuXk_C2V0cz052f_gwH4RoBH3uN4HpBuwaTufJRoX_WNILbZZHn4l31BRH1Yv3ht_kJ2Y8ARAi9hLqBxcqdFsFc9C7i3z5ooyL-V0P5UZ9WhUhtmUiq5uNvBj26fAnXKJL6WvRBUZbECXA2eCiGUH58fJgQ/s1249/lnbmpch32.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="938" data-original-width="1249" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuqKwP-anqjl75IgkzZsVZv8F4mC--ROosuXk_C2V0cz052f_gwH4RoBH3uN4HpBuwaTufJRoX_WNILbZZHn4l31BRH1Yv3ht_kJ2Y8ARAi9hLqBxcqdFsFc9C7i3z5ooyL-V0P5UZ9WhUhtmUiq5uNvBj26fAnXKJL6WvRBUZbECXA2eCiGUH58fJgQ/s320/lnbmpch32.png" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>As expected a couple of mistakes (selected footprints too small etc..) but it works!<p></p><p>Since the CH32V303 is running at 140 Mhz, it is faster than the bluepill based one.</p><p>For reference, i did the same PCB for a GD32F303, and it was more complicated.</p><p>The ch32v303 version is much simpler, no need for extra glue. The chip, a 8mhz crystal, couple of resistors and caps and that's it.</p><p><br /></p><p><br /></p><p><br /></p><p>I've also ran into a false problem. The normal BMP just reboots when it asserts, so you dont see that happening.</p><p>The lnBMP halts when it asserts, took me a bit of time to realize that was not due to a problem i introduced.<br /><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-33694929503386322482023-05-01T06:01:00.004-07:002023-05-01T06:02:01.088-07:00lnBMP+CH32V3 : Slowly getting there...<p> It is taking a bit of time, but getting there.</p><p>What has changed since the last time :</p><p>A tinyUSB based DFU <a href="https://github.com/mean00/lnBMP_bootloader_ch32v3x">bootloader</a> for the CH32V3x, a bit quirky but good enough for now</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAqYRjC_ZhAoIdcby32-lNm8M-6xTJ8VJQ72EQVGnjcVeezNraDjiS3_Y1imt4gjpqfjYg9romi__6kt9e8y68ystHjUUjkVQIlrGdD6EzwtU-gvxkOsAc4Fzq1RRPM_llijeAexE9v8wr1wBjsgFG4dKmywrGW2Bi_kt0nfHIXiIrHEwDc9szhVrWHQ/s708/dfu_ch32.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="517" data-original-width="708" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAqYRjC_ZhAoIdcby32-lNm8M-6xTJ8VJQ72EQVGnjcVeezNraDjiS3_Y1imt4gjpqfjYg9romi__6kt9e8y68ystHjUUjkVQIlrGdD6EzwtU-gvxkOsAc4Fzq1RRPM_llijeAexE9v8wr1wBjsgFG4dKmywrGW2Bi_kt0nfHIXiIrHEwDc9szhVrWHQ/s320/dfu_ch32.png" width="320" /></a></div><br /><p>and a small PCB (basically my first one) to host the CH32V303 and provides the pin out i usually use.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf_scAhZPdoxRnqTLpNKhp6-m8jLdeAB4T92lxMRuC88LdNSOipvjtgb5urKbZHm0odp_42ZPtMPiRm4tH5wd3CiF_gc_YxAGZGmWmSE6tgxanzThHu1QiTTD8mvszHjpkbYG5pieYG6ryGQT5UQpcRZel5E2_6DznBXzOM5xNkDt-dDnC_jgMnaxiVw/s639/ch32_pcb.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="318" data-original-width="639" height="159" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf_scAhZPdoxRnqTLpNKhp6-m8jLdeAB4T92lxMRuC88LdNSOipvjtgb5urKbZHm0odp_42ZPtMPiRm4tH5wd3CiF_gc_YxAGZGmWmSE6tgxanzThHu1QiTTD8mvszHjpkbYG5pieYG6ryGQT5UQpcRZel5E2_6DznBXzOM5xNkDt-dDnC_jgMnaxiVw/s320/ch32_pcb.png" width="320" /></a></div><br /><p>Also, i fixed the hosted mode of lnBMP so it behaves like a genuine black magic, i.e. you can have the code running on your PC and use the BMP/lnBMP just as a hardware interface to your board.</p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-89444520531334784722023-03-31T04:41:00.007-07:002023-03-31T04:42:30.881-07:00lnBMP running on a CH32V303<p>The lnBMP is a project using the blackmagic probe core + a gdb remote protocol parser written in rust, on top of the lnArduino framework.</p><p>As it is running on lnArduino, i'm making sure it works also on the CH32v3x chips</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhVTdPp-DWA9huNwGRtkMaw1qT9xTWufwLPLy2TJR_csaJ2MR5MeyG44y55ehWSjwDaghycX5JCId6q-iQbW_6vs8XSupnfdP_XlVqAKUMVjzokn4jKWV9vcwyEUdDzXkE4aqZfXJ75yPmtPhANAPcU-TW3WBrT-LAiERHkV2mCBLF-qyCf6cfrU2UDrQ" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="595" data-original-width="1203" src="https://blogger.googleusercontent.com/img/a/AVvXsEhVTdPp-DWA9huNwGRtkMaw1qT9xTWufwLPLy2TJR_csaJ2MR5MeyG44y55ehWSjwDaghycX5JCId6q-iQbW_6vs8XSupnfdP_XlVqAKUMVjzokn4jKWV9vcwyEUdDzXkE4aqZfXJ75yPmtPhANAPcU-TW3WBrT-LAiERHkV2mCBLF-qyCf6cfrU2UDrQ=s16000" /></a></div><br /><p></p><p>You can see from left to right :</p><p>1- The bluepill board under debug</p><p>2- lnBlackmagic running on a homeboard based on CH32v303</p><p>3- The WCH debugger to debug the CH32V303</p><p>I ported a basic tinyusb driver for the ch32v3x so now it works to some extent!</p><p><br /></p><p>That WCH chip is pretty good, plenty of flash, plenty of ram, 144 Mhz, FPU, plenty of IO and compatible largely with the good ol' STM32F103.</p><p><br /></p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-37314909712439671612023-02-16T23:21:00.001-08:002023-02-17T02:40:13.063-08:00pyDSO: Very simple python app to control your DSO150 and to take snapshot<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc68vIvq7L125XyE613CLOxAiRJg3Irdx4F3GUQnAkT7uzfsm64qpa4c_XB9F-cqtRX3gyuiAGTYxbOzzf5lt4aYG5mRwaVCR2gaxeXpT255HFtztCZJp07jmhszyXk284HuyIec0gk6O38U24T0B79c_MqUTbBYAhLgkmr64BkLj1hviu3A3XRSDF0Q/s4624/fnirsi.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="4624" data-original-width="3472" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc68vIvq7L125XyE613CLOxAiRJg3Irdx4F3GUQnAkT7uzfsm64qpa4c_XB9F-cqtRX3gyuiAGTYxbOzzf5lt4aYG5mRwaVCR2gaxeXpT255HFtztCZJp07jmhszyXk284HuyIec0gk6O38U24T0B79c_MqUTbBYAhLgkmr64BkLj1hviu3A3XRSDF0Q/w150-h200/fnirsi.jpg" width="150" /></a></div>I finally went back to this topic.<p></p><p><b><u>Summary:</u></b></p><p>The main idea is to use a usb CDC/ACM link (~ serial) to control the DSO1505 from your PC. </p><p><br /></p><p><br /></p><p><br /></p><p>Of course, you'll need to connect a micro usb header to the D+/D- pins on the DSO150.</p><p> It is easy to do, the D+/D- spots are neatly marked on the PCB</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ywtrzoMbq3TWl108hDxtzJVx7xs982MLmLABV7-djHMt3CXCphdGoC4Mu2sOdOWokq3-7QLCzbNUNWiWI9PCCTktaNzaSgEdu_R2e_E9f0IZInTuwfgp_G0tepev7SGVk7V1KjrA0UgY3FpLLCJQMZIXxL-3lkU1_mWRemiTNl8so9Ur_yNWLc6Bhg/s488/dso_usb.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="434" data-original-width="488" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ywtrzoMbq3TWl108hDxtzJVx7xs982MLmLABV7-djHMt3CXCphdGoC4Mu2sOdOWokq3-7QLCzbNUNWiWI9PCCTktaNzaSgEdu_R2e_E9f0IZInTuwfgp_G0tepev7SGVk7V1KjrA0UgY3FpLLCJQMZIXxL-3lkU1_mWRemiTNl8so9Ur_yNWLc6Bhg/s320/dso_usb.png" width="320" /></a></div><br /><p><br /></p><p><br /></p><p><b>/!\ if a USB cable is plugged, you may be grounding the DSO , be careful.</b></p><p><b>/!\ The FNIRSI style boards are using these pins to detect the AC/DC setting, you CANNOT use USB on the FNIRSI style boards.</b></p><p>The end result looks like this :</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg582kM2VLgm6c5kD_OQmwJG4XXDs79Hw1VwGlQXxBlwJU-AILgPm8_VjZEUU0UCXG0li-b7j_yJPM3DvUzvaEKnG7Bni3KYHc2v3InP-Y7pp924I67xsvbkMukuC1Y1iII-mJIHj2-tHkJ6XnmhTxgpcAOthF2AvIcDK852brVHAjRfVcG4fTmaa3L7g/s488/pyDSO.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="434" data-original-width="488" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg582kM2VLgm6c5kD_OQmwJG4XXDs79Hw1VwGlQXxBlwJU-AILgPm8_VjZEUU0UCXG0li-b7j_yJPM3DvUzvaEKnG7Bni3KYHc2v3InP-Y7pp924I67xsvbkMukuC1Y1iII-mJIHj2-tHkJ6XnmhTxgpcAOthF2AvIcDK852brVHAjRfVcG4fTmaa3L7g/s320/pyDSO.png" width="320" /></a></div><br /><p><br /></p><p>The app is very basic. It offers simple control (voltage range/time base/trigger) and more importantly the ability to retrieve nice screenshots from the DSO without using you phone (it creates output.png).</p><p>The snapshots are like this :</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAXUa1fvobMBuxaaSVb4YLzGuIpRqZ_7hrheyX3-LahAvtegvowhoy_2wDrSNPVbmq-8MulDwF3_tDHshIpg3t1yZ870siyx0KMdLXSEYUo22DpxL3mVHBJwgNTRegJz409NX3J6seSBidiDtp17Azt83UUpU295yUsdSrFjbylZbbKrWFkR7jzKmxwg/s739/dso_snapshot.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="739" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAXUa1fvobMBuxaaSVb4YLzGuIpRqZ_7hrheyX3-LahAvtegvowhoy_2wDrSNPVbmq-8MulDwF3_tDHshIpg3t1yZ870siyx0KMdLXSEYUo22DpxL3mVHBJwgNTRegJz409NX3J6seSBidiDtp17Azt83UUpU295yUsdSrFjbylZbbKrWFkR7jzKmxwg/s320/dso_snapshot.png" width="320" /></a></div><br /><p><br /></p><p><span style="background-color: white;">The code to run is <span style="font-family: monospace; font-weight: bold;">python_usb_control/graphical_py_app/pyDSO.py</span></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;">You'll need pyQt5+pySerial installed.</span></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"><br /></span><span style="background-color: white;">Under the hood, a very simple protobuf-based RPC is being used, so that it is relatively portable to any language supported by protobuf.</span></span></p><p style="text-align: left;"><span style="font-family: monospace;"><span style="background-color: white;">NB: The pending lnDSO150 code is on github, no formal release yet.</span></span></p><span style="font-family: monospace;"><br /></span>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-30682965988944785232023-02-06T23:25:00.007-08:002023-02-06T23:29:56.479-08:00Rust + CH32V307 + ILI9341 : Small demo video<p>The mandatory youtube-video-or-it-didnt-happen</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/K82YxbDiHHw" width="320" youtube-src-id="K82YxbDiHHw"></iframe></div><br /><p><br /></p><p>(This is the screen test for my power supply)</p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-76769056863823191282023-01-29T06:52:00.003-08:002023-01-29T06:52:29.012-08:00CH32V307 : tinyUsb<p>One of the last big chunk of support for the CH32V3x is now working : Usb</p><p><a href="https://github.com/hathach/tinyusb">TinyUSB</a> has just received a driver for the CH32V307, which was merged in lnArduino</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhawMmejwrzx-vtEqTAdp_gUExtK7Ix1TTrAtFuSVR0PbARa5wjaTZzxU8XJxngAHs6SUulKjsGp4QfEI6C0B1B15zw50zFbhrphWN-mZQC2vZDZ8lQpX7_qAYDg5LdLOEA4K5ADuoDWAySV7qYhJT2DgmwKNKYppqzQ7SO__ccMZsERyXKnxWq2iNFJw" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="264" data-original-width="827" height="127" src="https://blogger.googleusercontent.com/img/a/AVvXsEhawMmejwrzx-vtEqTAdp_gUExtK7Ix1TTrAtFuSVR0PbARa5wjaTZzxU8XJxngAHs6SUulKjsGp4QfEI6C0B1B15zw50zFbhrphWN-mZQC2vZDZ8lQpX7_qAYDg5LdLOEA4K5ADuoDWAySV7qYhJT2DgmwKNKYppqzQ7SO__ccMZsERyXKnxWq2iNFJw=w400-h127" width="400" /></a></div><br /><br /><p></p><p>I modified the driver a bit so it fits better within lnArduino.</p><p>Within lnArduino both high speed and full-speed work, while inside tinyUsb only high speed is working?</p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-69037753622641042162023-01-24T10:23:00.003-08:002023-01-24T10:23:20.342-08:00CH32V307 : FPU + FreeRTOS<h2 style="text-align: left;">Toolchain/Clang</h2><p> Time to enable the FPU!</p><p>I've modified the <span style="background-color: white; font-family: monospace;">LLVM-embedded-toolchain-for-rv32 </span>so that it builds both soft-ftp and hard-fp clang runtimes (it is a bit clunky but works).</p><p><br /></p><h2 style="text-align: left;">FreeRTOS</h2><h4 style="text-align: left;">WCH implementation</h4><p>The FreeRTOS implementation saves this on the task stack : </p><p></p><ul style="text-align: left;"><li>MEPC</li><li><i>[FPU]</i></li><li>Normal regs</li><li>MStatus</li></ul><p></p><p>[FPU] depends on a compilation switch. </p><p>It contains either all the FPU registers (the 32 of them) or nothing. Always.</p><p>This is problematic.</p><p>Saving all those registers is hitting the stack hard and it takes time.</p><p>Furthermore, that happens for all task switches even if the FPU is not used.</p><p>Conversely, if you dont save the FPU registers and use the FPU in 2 different tasks, you'll get data corruption.</p><h4 style="text-align: left;">Naive improvement</h4><p>I implemented a very naive change using the FS bits in mstatus.</p><p>These FS bits can have 2 interesting values : </p><p></p><ul style="text-align: left;"><li>FPU never used (Off, original, clean)</li><li>FPU dirty (i.e. used at some point).</li></ul><p></p><p>So, when the FS bits are "not used", you can skip saving/restoring the FPU registers for that task.</p><p>When they are "dirty", you need to save/restore the FPU registers</p><p>It is a bit naive, but is acceptable imho.</p><p>That involved changing the register layout a bit on the stack to this :</p><ul><li>MEPC</li><li>MStatus</li><li><i>[FPU]</i></li><li>Normal regs</li></ul><div>We have Mstatus available at a fixed position, so it can be checked to see the status of the FS bits.</div><div>The FPU registers are only saved to/out of the stack if the FS bits are dirty.</div><div><br /></div><div>So we get the best of both worlds by paying a very small CPU overhead, mostly due to my ignorance of proper riscv assembly :</div><div><ul style="text-align: left;"><li>~ 0 impact when you dont use the FPU</li><li>No corruption when you use them, but you pay the price</li></ul><div>It can probably be better, as it is now it will get dirty if you use them only once in a task, but it is a good start.</div></div><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><span style="font-family: monospace;"><br /></span>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-81373132473016668562023-01-19T22:06:00.004-08:002023-01-29T08:58:26.124-08:00CH32V307 : Rust + I2C + Clang<p> I2C is still a bit unstable but here we go : CH32V307+SSD1306 + rust + clang !</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjzp45t350zqyxcz8Q8MDreWzrPAvjhR60zlzavCmTqoZxdjR-AhdMXGMea9XYCJCuHkcWaBK2Z6MyoU55r5NMg2H6LuZmdBgLIEiHBxsOT-iPNJZGLFsgxIDr8sELrgXf0O21taRPQf3zCkED2L1u25DjteU90cWmJJqt57YM7IDLxc-IZSi9OyrjQKw" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="539" data-original-width="622" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEjzp45t350zqyxcz8Q8MDreWzrPAvjhR60zlzavCmTqoZxdjR-AhdMXGMea9XYCJCuHkcWaBK2Z6MyoU55r5NMg2H6LuZmdBgLIEiHBxsOT-iPNJZGLFsgxIDr8sELrgXf0O21taRPQf3zCkED2L1u25DjteU90cWmJJqt57YM7IDLxc-IZSi9OyrjQKw" width="277" /></a></div><br /><br /><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjzhklJ6Lf08tIlgExL6zKLIP83ktvSz5zXqaBNkbtoqdXmt-zP7bgt2rTh-ysLjEL64nAznnzJqotgsGkdLg-RqAQgceg9ztt7vPFBS9TWrI4fx8_3TWhMzk0bhGruMKu2HFrYIKkxo_TZ7YLmmvIb7pMTPiZUNg-9fPGK-O5Ovjyhi02QnYs5b8wkiA" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="539" data-original-width="622" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEjzhklJ6Lf08tIlgExL6zKLIP83ktvSz5zXqaBNkbtoqdXmt-zP7bgt2rTh-ysLjEL64nAznnzJqotgsGkdLg-RqAQgceg9ztt7vPFBS9TWrI4fx8_3TWhMzk0bhGruMKu2HFrYIKkxo_TZ7YLmmvIb7pMTPiZUNg-9fPGK-O5Ovjyhi02QnYs5b8wkiA" width="277" /></a></div><br /><br /></div><br /><br /><p></p><p>This is a pic of the simplerSSD1306 rust driver running on the CH32V307 + rnArduino</p><p>NB: The code seems to be significantly larger than the exact same thing built for bluepill / Arm cortex m3 though.</p><p><b>NB:</b> Seems the rust target riscv32-imafc does not exist as of today. So no FPU with rust!</p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-86936468398893524272023-01-16T10:13:00.001-08:002023-01-16T10:13:11.968-08:00CH32V307 : SPI & LCD<p></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">After tackling some riscv/clang issues, i can now say that the compatibility of the CH32V307 with the good old STM32F103 is pretty good. </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">lnArduino works quite well so far, the associated sample code is running okay-ish.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">There are still some stuff to work on though :</div><div class="separator" style="clear: both; text-align: left;">- i2c is unstable</div><div class="separator" style="clear: both; text-align: left;">- the init code/linker script does not seem to be 100% correct</div><div class="separator" style="clear: both; text-align: left;">- rust binaries are really huge (they should be ~ 60 kB, they end up being 300kB, like if the clang LTO was not working).</div><div class="separator" style="clear: both; text-align: left;">- so called hardware fast interrupt seems to be doing nothing at all</div><div class="separator" style="clear: both; text-align: left;">- i still have to figure out how to enable the fpu without hammering the stack on interrupt/context switch</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Overall, the CH323V307 seems to be a valid replacement for the GD32VF103 (which is going into oblivion or so it seems).</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Mandatory pic-or-it-didnt-happen (the exact same driver/code is running also on stm32f103):</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVVZz77jaOyFR-fTSNeOm2js7cBST5F1w1u8lBdV9FgckCMor20G763UIKCo2Mw1Esl0ZVYYK0vn1r3-3PKTrXbuySWLl6L2M7ygmKhcXwJGp88iiA9hu4mh9HN_5jy9rWOsBobXt4VZK-QmZa9U6i9aZWkNXTF8sQxODVnxLuArafz6N2nrelJ0ee2A/s1264/spi_lcd.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="510" data-original-width="1264" height="129" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVVZz77jaOyFR-fTSNeOm2js7cBST5F1w1u8lBdV9FgckCMor20G763UIKCo2Mw1Esl0ZVYYK0vn1r3-3PKTrXbuySWLl6L2M7ygmKhcXwJGp88iiA9hu4mh9HN_5jy9rWOsBobXt4VZK-QmZa9U6i9aZWkNXTF8sQxODVnxLuArafz6N2nrelJ0ee2A/s320/spi_lcd.jpg" width="320" /></a></div><br /> <p></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-65980687157174938662023-01-12T04:55:00.001-08:002023-01-12T04:55:08.899-08:00CH32V307 : Full llvm/clang toolchain<p> Clang /LLVM can be a bit complicated to build especially if you want to use it with riscv32+picolibc.</p><p><br /></p><p>There is an <a href="https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm">arm toolchain build project</a> to build it for arm cores,.</p><p>Fortunately, it is easy to patch to build for rv32imac.</p><p>I posted the patched version on <a href="https://github.com/mean00/LLVM-embedded-toolchain-for-rv32">github</a></p><p>Checkout the project</p><p>then</p><p></p><blockquote><span style="background-color: white; font-family: monospace;">ln -s $PWD/build/_deps/llvmproject-src/llvm/lib lib</span></blockquote><p></p><p>then</p><blockquote><p>mkdir build && cd build && <span style="background-color: white; font-family: monospace;">cmake -G Ninja .. && ninja && </span><span style="background-color: white; font-family: monospace;">ninja package-llvm-toolchain</span></p></blockquote><p>You end up with a full blown LLVM C/C++ toolchain in LLVM.....tar.gz</p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-13534285947549368872023-01-09T10:21:00.002-08:002023-01-09T10:21:33.588-08:00CH32V307 Picolibc to the rescue<p> </p><p>With our shiny new risv32 gcc, let's look at the generated code size.</p><p>The demo is a small graphic demo using a SSD1306</p><p>With vanilla libc build with our shiny riscv32gcc : Code = 50 kB</p><p><br /></p><p>Let's build and install <a href="https://github.com/picolibc/picolibc">picolibc</a></p><p>In order to do so, create a cross.txt containing :</p><p><span style="font-family: monospace;"><i><span style="background-color: white;">[binaries]
</span><br />c = 'riscv64-unknown-elf-gcc'
<br />ar = 'riscv64-unknown-elf-ar'
<br />as = 'riscv64-unknown-elf-as'
<br />ld = 'riscv64-unknown-elf-ld'
<br />strip = 'riscv64-unknown-elf-strip'
<br />
<br />[host_machine]
<br />system = 'unknown'
<br />cpu_family = 'riscv'
<br />cpu = 'riscv'
<br />endian = 'little'
<br />
<br />[properties]
<br />c_args = [ '-nostdlib', '-msave-restore', '-fno-common' ]
<br /># default multilib is 64 bit
<br />c_args_ = [ '-march=rv32imac', '-mabi=ilp32']
<br />needs_exe_wrapper = true
<br />skip_sanity_check = true</i><br />
<br /></span></p><p><span style="font-family: monospace;">make sure our shiny new riscv gcc is in your path, then</span></p><p><span style="font-family: monospace;">mkdir build && cd build && </span><span style="background-color: white; font-family: monospace;">meson --cross-file ../cross.txt .. && ninja && ninja install</span></p><span style="font-family: monospace;">then use --specs=picolibc.specs to compile AND to link.</span><div><span style="font-family: monospace;"><br /></span></div><div><span style="font-family: monospace;">So using our example, what is the result ? </span><span style="font-family: monospace;">30 kB!</span></div><div><span style="font-family: monospace;"><b>50 kB => 30 kB</b></span></div><div><span style="font-family: monospace;"><br /></span></div><div><span style="font-family: monospace;">Not bad!</span></div>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-60299070682205764372023-01-08T06:25:00.002-08:002023-01-08T06:26:15.804-08:00CH32V307 : Using a newer riscv toolchain<p> The CH32V307 (and siblings) has a nice interrupt extension : Fast Interrupt</p><p>As the name implies, it saves/restores more registers automatically before executing the actual interrupt. It is, of course much faster than doing it manually.</p><p>It is used internally by SysTick (maybe SW_Handler too)</p><p>To use it, WCH has modified their GCC 8.2 to add a new attribute : <b> <span style="background-color: white; font-family: monospace;">__attribute__((interrupt("WCH-Interrupt-fast")))</span></b></p><p style="text-align: left;"><u>For example :</u></p><p style="text-align: left;"> <span style="background-color: #eeeeee;"> void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));</span></p><p style="text-align: left;">It is easy to use, but forces you to use the gcc 8.1 based wch compiler (or another compiler that merged the patch) and is causing problem with random gcc and/or clang.</p><p style="text-align: left;">NB : Clang is a better choice, if you use rust, else no LTO for you.</p><p style="text-align: left;">After looking into it, it appears that WCH-Interrupt-fast is about the same as using __attribute__((interrupt(naked))) + exiting the function with "mret"</p><p style="text-align: left;">Doing that, we can use any gcc and it works (or seems to).</p><p style="text-align: left;">Regarding clang, it is a bit more complicated. The naked functions cant use "complicated" C code, so we have to split the function in 2 parts :</p><span style="background-color: #eeeeee;"><span style="font-size: small;">void SysTick_Handler_( void )</span><br /><span style="font-size: small;">{</span><br /><span style="font-size: small;"> SysTick->SR=0;</span><br /><span style="font-size: small;"> if( xTaskIncrementTick() != pdFALSE )</span><br /><span style="font-size: small;"> {</span><br /><span style="font-size: small;"> portYIELD();</span><br /><span style="font-size: small;"> }</span><br /><span style="font-size: small;">}</span><br /><span style="font-size: small;">void SysTick_Handler( void )</span><br /><span style="font-size: small;">{</span><br /><span style="font-size: small;"> GET_INT_SP();</span><br /><span style="font-size: small;"> portDISABLE_INTERRUPTS();</span><br /><span style="font-size: small;"> //SysTick_Handler_();</span><br /><span style="font-size: small;"> asm("jal SysTick_Handler_");</span><br /><span style="font-size: small;"> portENABLE_INTERRUPTS();</span><br /><span style="font-size: small;"> FREE_INT_SP();</span><br /><span style="font-size: small;"> __asm__("mret");</span><br /></span><div style="text-align: left;"><span style="background-color: #eeeeee; font-size: x-small;">}</span></div><div style="text-align: left;">and that compiles with any riscv gcc or clang (and seems to work)</div><div style="text-align: left;"><br /></div><div style="text-align: left;">So now i'm using a brand new 12.2.0 riscv-gcc coming from <a href="https://github.com/riscv-collab/riscv-gnu-toolchain" target="_blank">riscv-gnu-toolchain</a></div><div style="text-align: left;"><br /></div><div style="text-align: left;">The C++/runtime part of clang is problematic. More on that later.</div><p style="text-align: left;"><br /></p><p style="text-align: left;"><br /></p><p style="text-align: left;"><br /></p><p style="text-align: left;"><br /></p><p><b><span style="background-color: white; font-family: monospace;"><br /></span></b></p><p><br /></p><p> </p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-39532707231882165492023-01-04T10:30:00.002-08:002023-01-04T10:30:51.998-08:00CH32V307 : Debugging with vscode<p> This is derived from <span style="background-color: white; font-family: monospace;">https://www.justinmklam.com/posts/2017/10/vscode-debugger-setup</span></p><span style="font-family: monospace;"><br /></span><div><span style="font-family: monospace;">1- Install native debugging plugin gdb/... within vscode</span></div><div><span style="font-family: monospace;">2- Add (and change) the following line to your settings.json pointing to the toolchain binaries (especially the riscv gdb) and the wch-openocd bin folder :</span></div><div><div style="background-color: white; font-family: "Droid Sans Mono", "monospace", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div> <span style="color: #0451a5;">"riscv_openocd_path"</span> : <span style="color: #a31515;">"/opt/wch/MounRiver_Studio_Community_Linux_x64_V130/MRS_Community/toolchain/OpenOCD/bin"</span>,</div><div> <span style="color: #0451a5;">"riscv_gdb_path"</span> : <span style="color: #a31515;">"/opt/wch/MRS_Toolchain_Linux_x64_V1.60/RISC-V Embedded GCC/bin/"</span></div></div></div><div style="text-align: left;"><span style="font-family: monospace;"><span style="background-color: white;"><p>3- Create the launch.json file, adapt the name to your project </p></span></span><span style="font-family: monospace;"><div>{</div><div>"version": "0.2.0",</div><div>"configurations": [</div><div> {</div><div><span style="white-space: pre;"> </span>"name": "riscv_GDB",</div><div><span style="white-space: pre;"> </span>"type": "gdb",</div><div><span style="white-space: pre;"> </span>"request": "launch",</div><div><span style="white-space: pre;"> </span>"cwd": "${workspaceRoot}",</div><div><span style="white-space: pre;"> </span>"target": "${workspaceRoot}/build/lnPowerSupply_CH32V3x_72M.elf",</div><div><span style="white-space: pre;"> </span>"gdbpath" : "${config:riscv_gdb_path}/riscv-none-embed-gdb", </div><div><span style="white-space: pre;"> </span>"autorun": [ </div><div> "target extended-remote | ${config:riscv_openocd_path}/openocd -c \"gdb_port pipe; log_output openocd.log\" -f ${config:riscv_openocd_path}/wch-riscv.cfg",</div><div> "set confirm off",</div><div> "set mem inaccessible-by-default off",</div><div> "set architecture riscv:rv32",</div><div> "set remotetimeout unlimited",</div><div> "set remote hardware-breakpoint-limit 4",</div><div> "mon reset halt",</div><div> "load ",</div><div> "tb main ",</div><div> "b deadEnd "</div><div> ]</div><div> }</div><div> ]</div><div>}</div>
<br /></span></div><div><span style="font-family: monospace;">NB: This WCH OpenOcd daemon is unstable and needs to be restarted at each launch hence the way it is started here.</span></div>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-27962192651693690072022-12-27T11:03:00.007-08:002023-01-09T10:24:50.493-08:00CH32V307 : Self destructing WCH-Link<p> I bought a CH32V307 eval board. </p><p>It's a cheap riscv chip with quite good specs. It looks similar to the STM32F103 or clones.</p><p>The aim is to replace the GD32VF103 as riscv chip, it seems gigadevice is not very interested in it.</p><p>So, i installed the mountriver stuff (standard eclipse based IDE), started it...</p><p>It asked to update the WCHLink, ok please do and.... it broke it!</p><p>It is detected as a WindHead something, which seems to means the bootloader has taken over due to bad firmware.</p><p>After some researches, here is how to repair it:</p><p></p><ol style="text-align: left;"><li> Put a blob of solder on the "ISP" pin of the wch-link to force update mode</li><li> Download <a href="https://github.com/kaidegit/CMSIS-DAPbyWCH">https://github.com/kaidegit/CMSIS-DAPbyWCH</a> /!\ On windows /!\ , install the exe and start it. It does not work with wine.</li><li> Flash the firmware <span style="font-family: monospace;"><span style="background-color: white; color: #54ff54; font-weight: bold;">WCH-Link_APP_IAP_RV.bin</span></span>. It is in in one of the mountriver subfolder (/!\follow the instruction on the link above to flash it /!\)</li><li> Remove the blob of solder</li></ol><p></p><p>Now it works, and i can debug. That's not a good start :(.</p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-76187324601391222322022-12-25T07:09:00.002-08:002022-12-25T07:09:32.672-08:00Let's make a ESR meter : Principle (part 2)<p><br /></p><h2 style="text-align: left;"><b>Overview</b></h2><p>The complete schematic is as follows </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMJqs_JO-BHUf_nXWLXZ4qYLT9kdVtoTTG50v2DlRrzbGdMDxPPtUVmbwSHjVYkk9Y4SITEiU7nEqXR0LQQQvwbgPs39-l_914bgmV2xtXgqVnpyuYv26611AagwYxVl7jmIdJwfCkCyu1-q4y7RuEoZ33L0Mg_7nJQv796pz7gu2uC5ie5Jbhqtp2NQ/s1719/ESR.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="886" data-original-width="1719" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMJqs_JO-BHUf_nXWLXZ4qYLT9kdVtoTTG50v2DlRrzbGdMDxPPtUVmbwSHjVYkk9Y4SITEiU7nEqXR0LQQQvwbgPs39-l_914bgmV2xtXgqVnpyuYv26611AagwYxVl7jmIdJwfCkCyu1-q4y7RuEoZ33L0Mg_7nJQv796pz7gu2uC5ie5Jbhqtp2NQ/w640-h330/ESR.png" width="640" /></a></div><br /><p></p><p>It it made of 4 parts :</p><p></p><ul style="text-align: left;"><li>Sinusoidal signal generation</li><li>Resistance divider (impedance actually)</li><li>Amplification</li><li>Peak detection</li></ul><h2 style="text-align: left;"><b>Sine generation</b></h2><div>The sine is generated using a timer controlled dma feeding the PWM to have a sine envelop on a high frequency signal (see previous post).</div><div>A simple low pass filter will only keep the sine signal and it then goes through the transformer.</div><div>That transformer has been salvaged from an old phone charger.</div><div>It has a 1:20 ratio. So the input signal is ~ 3.3 v peak to peak with ~ 100mA max current, the output is 165 mv peak-to-peak BUT have a 2A max current.</div><div><br /></div><div>Since the voltage is so low, that helps for in-circuit measurement, the voltage is not enough to trigger a diode/ NP junction or most mosfets.</div><div><br /></div><h2 style="text-align: left;">Resistance Divider / Amplification / peak detection</h2><div>The output of the divider is Z/(R9+Z) x VccTransfromer</div><div>Z is the total impedance of the capacitor at ~ 50 khz. </div><div><br /></div><div>It is assumed the cap is high enough so that the ESR part is much bigger than the capacitance at that frequency. That means a capacitor of some uFarad at least.</div><div><br /></div><div>The output is then multipled by 21 and a simple peak detector is used to get the peak value (most of it)</div><div>and it is then fed to an ADC entry of the MCU.</div><div><br /></div><div>Now the fun part begins, how do we get the ESR from the value read by the ADC ?</div><div>(not as simple as it seems)</div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><p></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-58957005359111503482022-12-25T06:47:00.005-08:002022-12-27T21:42:54.897-08:00Reusing your C++ code in rust (embedded)
<b>But why ?</b>
<br />
So you have some working code in c++ and you'd like to reuse in rust (libraries, hal,...) ?<br />
That's not uncommon, that code works and you may not want to spend times re-writing it for no gain
(and also avoid double maintenance)<br />
<br />
<b>Option 1 : Bindgen</b><br />
<br />
Bindgen is nice enough, give it a .h, it will generate automatically the rust bindings for it.<br />
But it comes with some annoying limitations :<br />
- It does not support virtual methods <br />
- The parameters are C/C++ types, not rust types, it feels awkard to use them.<br />
Example : func(usize , void *) vs func( data : &[u8])<br />
- The generated functions are unsafe<br />
<br />
<b>Option 2 ; Dual adaptation layer</b><br />
<br />
The idea here is to create :<br />
1- A first shim layer that exports the C++ API as C api + a void *this parameter.<br />
2- Run bindgen on this shim, that will create unsafe rust with c++ parameters.<br />
3- Create proper rust code that is using that unsafe rust code<br />
<br />
The actual API is the one from the "proper code".<br />
It is *not* unsafe, it is using native rust types.<br />
It is a bit of a pain to write the glue code, but it's very straightforward.<br />
<br />
A sample example available here : https://github.com/mean00/lnArduino/blob/master/rust/rnArduino/src/rn_i2c.rs <br />
c++ I2C -> shim -> rn_i2c_c.rs (bindgen) -> rnI2C.rs (proper)
meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-61314877439866198972022-11-27T23:14:00.003-08:002022-12-25T06:54:44.915-08:00Let's try to make an ESR meter (part 1: AC Signal)<p> I've stumbled upon this : https://ludens.cl/Electron/esr/esr.html</p><p>A 100% hw ESR meter.</p><p>The principle is simple enough : </p><p>- Generate an "AC" signal</p><p>- Go through a transformer to lower voltage/increase current </p><p>- Measure the impedance across the capacitor to measure (and assume ESR >> Z at that fq ?)</p><p>Let's do it with a MCU and a salvaged transformer from a 5v usb power supply.</p><p><br /></p><h2 style="text-align: left;">AC ?</h2><p>Since we are using a transformer, we NEED to use a AC source. DC will just heat the transformer.</p><p>At first i used a sine oscillator made with an opamp, it sort of worked but was very unreliable in terms of replicating the circuit (gain was to be manually tweaked, its oscillation was changing, single fq ...)</p><p>The 2nd try was with a plain square oscillator, driven by the MCU. It worked fine, but caused inductance effect on the transformer because the signal was square. The transformer output signal was very distorted.</p><p>I could have used a CH32F103 or a GD32Fxx, which contain a DAC, but i already soldered a STM32F103 and could'nt be bothered to swap them.</p><p>So what can we use instead ?</p><p><br /></p><h2 style="text-align: left;">PWM to the rescue!</h2><p>We can use PMW + DMA + low pass filter.</p><p>The idea is to modulate the PMW duty cycle with the sine waveform and then filter out the PWM frequency.</p><p>The PWM signal (without filtering) looks like this :</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsr9muWTGeCXKoZnwBtQ1g4bvOk4IyQsG5Y5gtgBuFzikgHLfTtHRfGHpwfAdkctGBzHj6uHlhllrv4B3NeHMwg67F78-NE4tMpPr5hFsnA9N5-qc9kTCqs1V70D_niGLSsrAFeD7ubhpVxrv5Z5rB_xGb8CBUxA-mA0uK-e9dzw7dSEJ0UT0oxlRhQ/s778/pwm.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="418" data-original-width="778" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsr9muWTGeCXKoZnwBtQ1g4bvOk4IyQsG5Y5gtgBuFzikgHLfTtHRfGHpwfAdkctGBzHj6uHlhllrv4B3NeHMwg67F78-NE4tMpPr5hFsnA9N5-qc9kTCqs1V70D_niGLSsrAFeD7ubhpVxrv5Z5rB_xGb8CBUxA-mA0uK-e9dzw7dSEJ0UT0oxlRhQ/s320/pwm.jpg" width="320" /></a></div><p><br /></p><p>And it works fine. I can have a signal very close to a sine at the input at the transformer and as a result something very close to a sine at the output of the transformer.</p><p>We use a PWM base frequency of 1.2 Mhz and generates the table(s) to create a sine at the frequency we want.</p><p>As the base frequency is ALWAYS 1.2 Mhz, we can use fixed RC low pass filter to get our 10k..50k sine signal.</p><p><br /></p><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-14095438099646739042022-10-02T01:12:00.002-07:002022-12-25T06:53:26.436-08:00Mixing C++ and Rust on a small embedded system<p> </p><p>This has been one of my pet project for some times now, mixing lnArduino drivers ( hardwired to STM32F1 / GD32VF1 *AND* FreeRTOS) with rust code.</p><p>Why ? Because rust is fun :).</p><p>There are a lot of gotchas, your mileage may varies, you may disagree with me.</p><p>Below is the current status, in case it helps others. </p><p>I do not pretend to bring you the "truth"/"the right way to do it", this is just my journey so far.</p><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">Building with cmake</h2><div><a href="https://github.com/corrosion-rs/corrosion">Corrosion</a> is a very nice project , that makes mixing Cargo based project and cmake project a breeze.</div><div> . Really no problem here.</div><div><br /></div><h2 style="text-align: left;">Interworking</h2><div>Calling C++ from rust and conversely is a bit hit & miss.</div><div>The current setup i'm using is to use bindgen to generate a first layer of rust binding </div><div><u>AND THEN</u>, on top of that, manually write a very thin rust wrapper to get rid of the unsafe {}, have a cleaner API, and add the missing pieces.</div><div><br /></div><div>For example, bindgen cannot deal with pure virtual c++ function, so you have to add a intermediate layer anyway.</div><div><br /></div><div>foo.h -> bindgen foo.rs -> wrapper foo_rs.rs</div><div><br /></div><h2 style="text-align: left;">Hal</h2><div>The idea behind embedded-hal is to provide a base trait so that you can write more or less "universal" code, whatever your actual MCU/system is. </div><div>Your project will be using embedded_hal + your mcu-hal to create the HAL layer.</div><div><br /></div><div><br /></div><div>That's the theory. </div><div><br /></div><div>The problem is you have to chose between very simple API (arduino style) and a complicated one if you need more features. </div><div>Additionally, it is difficult to use the RTOS provided facilities due to the universal feature of embedded-hal. And if you start to use the mcu-hal specific stuff, you lose the "universal" aspect of it.</div><div><br /></div><h2 style="text-align: left;">Gcc vs LLVM</h2><div>Rust is using llvm. </div><div>If your regular build system is using gcc, it means you'll end up with an executable mixing gcc/g++ objects and llvm objects.</div><div>That raises some nasty issues :</div><div>- Rust crates are sometimes using generics and functions such as core::fmt:: (e.g. through .unwrap() and/or #[debug] are automatically generating some also. That creates tons of small functions to deal with automatically generated code, most of that code never used.</div><div>- LLVM LTO and Gcc LTO do not play nice together (at least on Arm) as far as i can see. That means lto does not work well at all when linking with gcc.</div><div><br /></div><div>Both points taken together means the automatically generated generics will not be purged as unused code and you will end up with a HUGE binary. In my test app, ~ 200 kB extra code (the "expected" code size is 10 kB to 20 kB).</div><div><br /></div><div><br /></div><div>As a result, you basically have a choice between :</div><div><br /></div><div><ul style="text-align: left;"><li> <u>Option 1:</u> Use your own code, being very careful about #[debug], unwrap(), etc.. and generics. In that case the code increase is very small, and rust is very much happily living alongside c+++.</li><li> <u>Option 2: </u>Use public crates, but build EVERYTHING with llvm based compiler (i.e. clang/clang++ for the C/c++ code) AND link with ld.lld. The linker script are a bit different between ld and ld.lld, but it's not difficult to adapt them. Then cross your finger you'll not pull a crate that is a bit messy with its generics.</li></ul></div><div></div><div><br /></div><div><br /></div><div>To be continued.</div><h2 style="text-align: left;"><br /></h2><div><br /></div><div><br /></div><div><br /></div><p><br /></p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0tag:blogger.com,1999:blog-575811584761602916.post-26289982603132555542022-06-06T03:01:00.004-07:002022-12-25T06:54:26.237-08:001.69' ST7789 240x280 rounded corner LCD<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS6eSaYB_Cj23pFNx0dbT4k67x4oaq1ZV9SqDeaCL9lGTBiZKq2Bu0sVVGlUJUxmgs6EidapTO1x2HjbEwuJBWjoCAyBlOxcYKDO7YT9OI1hsucNuGXdHjKt44RfQQ5Es5hcKEvg48ZwNHAhFPhMMRZarZ-k7-eYrl5WCQ7SD9BRLwVkyxJ2_EhVSqcw/s654/169.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="654" data-original-width="445" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS6eSaYB_Cj23pFNx0dbT4k67x4oaq1ZV9SqDeaCL9lGTBiZKq2Bu0sVVGlUJUxmgs6EidapTO1x2HjbEwuJBWjoCAyBlOxcYKDO7YT9OI1hsucNuGXdHjKt44RfQQ5Es5hcKEvg48ZwNHAhFPhMMRZarZ-k7-eYrl5WCQ7SD9BRLwVkyxJ2_EhVSqcw/s320/169.jpg" width="218" /></a></div><br /><p><br /></p><p> That screen is available for ~ 4$ on <a href="https://fr.aliexpress.com/item/1005003776922110.html?spm=a2g0o.order_list.0.0.3f855e5bjdlB5w&gatewayAdapt=glo2fra">ebay</a></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p>It has a few oddities. First the pinout, it is not easy to find but here it is :</p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div style="text-align: left;">1 GND<br />2 LEDK (connect to ground)<br />3 LEDA (connect to VCC with a few ohms resistor, like 10 Ohms)<br />4 VCC<br />5 GND<br />6 GND<br />7 DC<br />8 CS<br />9 SCL (SPI Clock)<br />10 SDA (SPI Data)<br />11 RESET<br />12 GND</div></blockquote><p>Second, it is a bidirectional SPI, meaning only 2 pins are used:</p><p>Clock and Data</p><p>Data is used for both as MOSI and MISO depending on the command.</p><p>On those screen, reading is seldom used, so you could just use it as MOSI.</p><p>The logical screen is a plain square 240x280 box, some pixels are just not physically there.</p><p> </p>meanXhttp://www.blogger.com/profile/06014075701578370344noreply@blogger.com0