Explorig the CH32V203 - FreeRTOS and NEOpixels.

by CanHobby in Circuits > Arduino

0 Views, 0 Favorites, 0 Comments

Explorig the CH32V203 - FreeRTOS and NEOpixels.

CH_Expl.png

Deeper exploration of the WCH CH32V203 highlighting various peripherals.

Hardware

F5BVSM9M66HJVNV.png

In this exploration episode we will be looking at a bigger brother of the tiny RISC-V MCU we discussed in our previous project. The CH32V203 is bigger, badder and faster. It features the same peripherals as the 003 but in greater quantity as well as enough memory to support freeRTOS. Our first hardware focus will be on using SPI to drive multiple NEOpixel strips. Our software exploration will use freeRTOS to produce various animations on the strips.

As with most of my explorations I release an incomplete teaser such as this present missive and keep adding to it - so check back often for recent updates.

The board I used to develop this project is pictured above and was purchased from AliExpress. It features the WCH32V203-C8T6 which has 64K Flash and 20K SRAM.

To attach the first NEOpixel strip we need to provide a source of 5V for the strip. I normally use a breadboard mountable USB power supply if I'm only debugging with a small NEO strip. I had no problem connecting the strip DataIn line directly to the MCU board. Strip #1 connects to the MOSI pin of SPI1 which is PA7.





Chinese clones available at CanHobby and eBay.

Programming

F5XN8DUM66HJVOW.png

Clock Frequency - We can run at full throttle (144 MHz) and still accommodate one of my main goals which is to run multiple NEOpixel strips from this board. Using the SPI is the obvious choice but these strips need a fairly specific base frequency of approximately 2.5 MHz. This can be determined from the nominal "ON" pulse width of 400 nS. 1 over 400 nSec gives us 2.5 MHz. Fortunately this number has a wide tolerance. The CH32V203 has an internal oscillator with a base frequency of 8MHz which can be stepped up to 144 MHz maximum. Considering that there is a hidden / 2 factor in the SPI clock, and the fact we are only concerned about the single pulse width rather than the whole cycle time.

144 MHz prescaled by 64 x ( / 4 ) = 434nS

We will be using 2 main functions to light up the strip. We start by initializing SPI1 by calling Init_SPIs( SPI1_msk );

We can see the details by looking at my source code in Init_SPIs.c attached below. This function needs to be called in main() before the freeRTOS tasks. We also find the Clear() function which is handy to brute force clear the full strip just after power on or reset. We would be wise to remember that these strips act as serial memories. If we upload a new version of our program that does not work we may see no change on the strip due to it's retaing the output from the previoous version of our program.

In the absence of C++ (which is just too unwieldy to enable in Moun River) I have a struct called strip which we need to populate for each strip and it's up to 5 associated segments.

Once we have this done we are ready to let freeRTOS unleash a task to continously display the NEOstrip buffer which would normally contain at least 1 segmnt. We do this by putting Compress5( &Neo1 ); in the endless loop of the task. Compress5 basically takes an array of 24 bit RGN values and encods them into NEOpixel pulses, compressing 5 encoded bits into a 16 bit SPI data register.

Binary Semaphore: Both the display task and the animation task need to operate on the same memory structures. We need to use a Semaphore to make sure each display refresh and animation operate atomically to prevent flickering of the final NEOpixel display. We can see mor details of this by examing the different task routines contained in the main.c code.