Posts

Showing posts with the label RISCV

RISCV memory access

 This is a small summary of why accessing memory when debugging a riscv cpu is complicated. It is work in progress, the current code is available on swindle's github. Introduction As usual, as it is RISCV, a lot is optional with important details left to implementation So let's see what is possible (definition from Gemini): Recommended : Program Buffer Execution (ProgBuf): Memory is accessed by halting the CPU and executing standard load or store instructions placed into a dedicated buffer. This uses the core's native pipeline, meaning all MMU translations, Physical Memory Protection (PMP), and cache hierarchy rules apply automatically. Optional: System Bus Access (SysBus): The Debug Module acts as an independent master directly on the system interconnect, bypassing the CPU entirely. This allows reading or writing physical memory while the core is actively running, though it does not go through the CPU's MMU or local L1/L2 caches. (NB this is more or less what ARM doe...

Swindle : Downloading code to the CH32VXX faster

 Now that the new bootloader has shown that it can be fast to write to the CH32v3xx flash, time to revisit the swindle way of loading code. (Gemini was really helpful again. But as a smart assistant, no vibe coding here). Starting point: So we started around average speed of 3kB/S (including erase, download and write) Optim 1: use bigger blocks Before, we were configuring the block size/erase size to be 256 bytes (same as the small hardware pages). Reconfiguring the description to be 4kB gave a small speed bump => 5 kB (internally it will call 256 bytes multiple times, it just reduces the overhead). Optim 2: Faster writing to RAM The dominant slowdown is the amount of time needed to write to the CH32V3xx ram (then we call the flashstub to actually write it, that's pretty fast). Just the writing caps the overall speed to 9 kB/s , without even erasing or writing. So the optimisation is to use a fast_write_ram function there that is using abstract commands with auto exec to pipelin...

Swindle Preview 6

New year version  Preview 6 https://github.com/mean00/swindle/releases Ethernet version for the CH32V307 eval board RTT & serial fixes Updated blackmagic engine Breakpoints in Flash for CH32V1/2 

Ethernet Swindle and gcc vs clang

Image
 There will be soon a new flavor of the swindle : The ethernet swindle It's starting to work nicely, utltimately the goal is to use the CH32V208 that is available for ~ 4$ on aliexpress. It's basically a CH32V307 without HS usb and without fpu,  same flash, same ram (more on that later).  LWIP is pretty big and i'm running short on both flash & ram. While looking into it, i discovered a nice option that gcc has and clang does not "-msave-restore" Since the Riscv does not have stmia/ldmia style instruction, it must push and pop all registers one at a time when entering/exiting a function. That is consuming a lot of code space for short functions. The -msave-restore creates function to save/restore , all possible variants and call them instead of manually pushing/popping registers. Let's give it a try, baseline is clang + hw FPU: Clang + HW FPU    255 508   (+0kB) Clang + no FPU       257 632  (+2KB) Clang + FPU+LTO  232...

SW breakpoint for the CH32V203 (and similar)

  The WCH doc clearly  states the QingKev4 b does not have hardware breakpoints. We saw that a bit earlier. The CH32V203 among others is a QingKeV4 b . I've added support for flash software breakpoint for the CH32V[2/3]xx to swindle. It is still a bit experimental. When such software breakpoints are used, under the hood the following happens : - Identify the page where the breakpoint is ( 256 bytes page for the CH32V[2/3]xx - Read the page - Store the 16 bits where the breakpoint is - Replace those 16 bits by a "ebreak" opcode - Erase the page - Write the modified page When removing the breakpoint the same thing happens except we put back the original opcode. It is a bit slow, but usable. The main drawback is that it will speed up flash wearing a lot. The framework is in place, if and when need it will be easy to add such functions to other chips. The main difference with other flashing operations are : - we want to use the smaller size possible. Usually we aim a bit hig...

Swindle : Preview 5 out

 After a long time, Swindle preview 5 is out, small changelog - Updated to latest blackmagic engine - Preliminary support for RP2350 (host and target) - Support for voltage translators - RTT support (with auto setup) - Better cortex  register support (including trustzone ones) - Overall better stability, it should freeze much less often - and of course continued support for CH32V30x (host and target) 

CH32V3, debug in ram with vscode continued

Summary of previous episodes (CH32v3): 1- Reallocate shadow ram to have 128k of RAM 2- In flash, put a basic harmless loop 3- Tweak the linker script to put everything in ram 4- Load the code (to ram), change the PC  to the code in ram 5- You now upload much faster with infinite software breakpoints Vscode You can use the cortexm extension with riscv, it works fine with one caveat : you cannot "attach" You can only "launch" (this is specific to riscv) and that's the root of the problem. The init script looks like this :     {              "name" : "riscv GCC (pico)" , "type" : "gdb" , "request" : "launch" , "cwd" : "${workspaceRoot}" , "target" : "${workspaceRoot}/build/swindle_bootloader_ch32v3x_GCC_DEBUG.elf" , "gdbpath" : "${config:riscv_gdb}" , "breakAfterReset...

swindle (lnBMP) v0.3

 A small release of swindle, a blackmagic derivative with rust in it : Changelog (short): - Better CH32v3xx support (host and target) - Rewrote ADiv logic so that we can ... - Use RP2040 PIO hardware to drive SWD - Update to latest blackmagic and still the M ain features : - Run on GD32F303, CH32V303, RP2040 - Support ARM devices and WCH riscv devices (CH32V2xx and CH32V3xx) - Soft breakpoint to debug code in ram (Arm only for now) - Built in FreeRTOS support through  "mon fos M0|M4|RV"

CH32V203C8xx : no breakpoint ? :(

 A couple of months back i bought some CH32V203 on ebay.  Why ? They were cheap, they are pin to pin compatible with STM32F103Cxxxx, i can put them on bluepill board . They are fast riscv.  Why not. NB: by mistake i bought the ones with 64kB of flash :( But there is a BIG showstopper, there seems to be no hw breakpoints, only sw breakpoints.  If you have a lot of ram (like the RP2040) you can put the code in ram until it works fine and then put it in flash. That's not the case here. Having the debugger read/modify/write all the time to but sw breakpoint in flash is really a pain. In theory, the "flash" of the CH32 is actually flash copied to ram, so if there was a way to use the fake flash ram to put SW breakpoint in it, we would be good. For reference, the CH32V303 has only 4 breakpoints, and no watchpoint (i.e. triggers with the right capabilities) which is already a bit of a pain in the neck. I'll put those aside for the moment.

lnBMP => Swindle

Image
In order to avoid confusion , i renamed lnBMP to  swindle   (swindle has SWD in it) It can run on :  GD32F303  CH32V303/5/7 (just need enough flash /ram)  RP2040 (normal or zero) and it can debug all the usual blackmagic targets + CH32V2XX/CH32V3XX. I dropped support for the bluepill / STM32F103 because it has not enough ram/flash and the CH32/GD32/RP are so cheap it is not even worth the time. The next item on my todo list is to update the blackmagic part and to use the PIO controller inside the RP2040 to do SWD / RVSW (Arm/CH32) Example: a itsy bitsy RP2040 zero debugging a CH32V30X based swindle board

lnBMP : CH32V3xx support

Image
 It is painful, but it is beginning to work : On the picture a RP2040-pico zero running lnBMP and happily debugging a ch32v307 Riscv chip (of course it can still debug Arm chips) Perigoso did a lot of work there, only the communication protocol /implementation was missing. It is still a bit slow though :(

CH32Vxx : WCH_LINKW in riscv mode

Image
Edit: There is a much simpler way. Press the Key Button will connecting the USB-C , it will switch between ARM & RISCV I recently bought the WeAct WCHLINK-W, a small dap style debugger  (both USB & BT)   At first it is configured in Arm/SWD mode and is being listed as  1a86:8012 QinHeng Electronics  by lsusb. On linux, the simpler way to switch it to RiscV mode is to download mountriver community  Then go to Flash->Configuration Click Query on the "Target Mode" line. It should be detected as WCH DapLink Switch it to "WCH Link RV", click apply , wait 2 seconds and done! The id of the device has changed and now lsusb should report 1a86:8010 QinHeng Electronics

lnBMP + CH32V303!

Image
 Finally got the PCB (that was my first one) As expected a couple of mistakes (selected footprints too small etc..) but it works! Since the CH32V303 is running at 140 Mhz, it is faster than the bluepill based one. For reference, i did the same PCB for a GD32F303, and it was more complicated. 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. I've also ran into a false problem. The normal BMP  just reboots when it asserts, so you dont see that happening. The lnBMP halts when it asserts, took me a bit of time to realize that was not due to a problem i introduced.

lnBMP running on a CH32V303

Image
The lnBMP is a project using the blackmagic probe core + a gdb remote protocol parser written in rust, on top of the lnArduino framework. As it is running on lnArduino, i'm making sure it works also on the CH32v3x chips You can see from left to right  : 1- The bluepill board under debug 2-  lnBlackmagic running on a homeboard based on  CH32v303 3- The WCH debugger to debug the CH32V303 I ported a basic tinyusb driver for the ch32v3x so now it works to some extent! 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.

Rust + CH32V307 + ILI9341 : Small demo video

Image
The mandatory youtube-video-or-it-didnt-happen (This is the screen test for my power supply)

CH32V307 : Rust + I2C + Clang

Image
 I2C is still  a bit unstable but here we go : CH32V307+SSD1306 + rust + clang ! This is a pic of the simplerSSD1306 rust driver running on the CH32V307 + rnArduino NB: The code seems to be significantly larger than the exact same thing built for bluepill / Arm cortex m3 though. NB: Seems the rust target riscv32-imafc does not exist as of today. So no FPU with rust!

lnDSO: Pics of HW modification to use a GD32VF103 (RISCV)

Image
 For reference, here are the modifications to do to replace the STM32F103 (or CH32F103 on some cheap clones) by a GD32VF103 There are 2 extra modifications, unrelated to the VF103 :  * Put a schottky in reverse between r36 and ground to clamp the negative voltage. Probably not needed, but i saw -4 v when testing there. * Replace the diode on the bottom right by a P Mosfet in reverse to avoid wasting 0.6 v there (SH1B). 

lnDSO: Success with GD32VF103

Image
It works ! The first ~ working frankenstein DSO150 with a GD32VF103 RISCV core. As usual, the dumber the mistake is, the harder it is to find In  no special order : - Arm : The vector table must be 512 bytes aligned - Riscv : Dont forget to set the capture pin to ADC mode (the arm version does not care for whatever reason) - When switching the pins from LCD to button, initialize them properly All these are *DUMB* mistakes, but each time it took me a week to figure out why it didnt work.

lnDSO : Slow progress

Image
lnDSO is the successor to DSO-arduino STM32, i.e. alternative firmware for the DSO 150 The main differences are : - It is written using lnArduino, so much more consistent in terms of drivers / low level, compatible with STM32F1/GD32F1/GD32F3/GD32VF103 (yes, i like gigadevice chips). - Capture engine is much better, it should not lose any capture - Much simpler code base, much easier to modify The status so far is:  - it is beginning to work really  nicely on the GD32F303  (my default setup) - untested on STM32F103 but should work easily, the GD32F303 is a enhanced version of GD32F103 which is an enhanced version of STM32F103 imho. - kind of working on the VF103 (RiscV), see image below. It does not capture much :( On the VF103, working around the fact that PB3 is used by jtag  is really a pain. On the DSO 150, PB3 is used on the parrallel bus to the screen but also as the rotary encoder press detection.  The screen is finally working fine with the buttons, the r...

DSO150/RiscV: Blaming the innocent

Image
While redoing the DSO150 on top of lnArduino i'm cleaning up a lot of stuff i just used  "as-is" previously. In particular, i rewrote the ILI9341 driver to be fast while still being portable to some extend. NB: It's a 8 bits parallel ILI9341 , not your vanilla SPI connected ILI9341. The new code worked fine on the GD32F303  (Arm) based unit but i ran into problems when used on the risc-v powered board (GD32VF103). Same DSO board, the two mcus have the  same hw components internally, just the core is different . I had strong doubt about the "lazy" write of the riscV chip.  If that happens, it means that when you write something, it is actually written a bit later. That's problematic when you are driving LCD signals. Adding fence/fence.i everywhere seemed to fix the obvious problem. But wait a sec,  adding  plain nops works also. So either delayed write issue or timing issue. Ok, we'll add the fence/nop and look into that later. Ah, the screen goes bla...