uLisp support for CH32 EVT Boards?


#1

Hello,

I hope you are doing well.

Recently, I was reading about the 10-cent CH32V003 RISC-V MCU and just wondered if it would be possible to consider adding support in a future uLisp version.

This seems to be the “official” Arduino core.

Best regards,


#2

Yes, I’ve been thinking about the CH32 processors for a while.

The CH32V003 probably isn’t suitable because it only has 16K of flash and 2K of RAM, less even than an Arduino Uno (which has 32K of flash). Also, RISC-V code tends to take up more flash than AVR or ARM code.

However, there are some other processors from WCH that do look promising:

  • The CH32X035F8P6 has 62K of flash and 20K of RAM.
  • The CH32X033F8P6 also has 62K of flash and 20K of RAM.

As far as I can see, only the first of these has support from the official Arduino core. Does anyone have experience of using it?


#3

Hello,

Thanks a lot for your feedback. I was checking what appears to be the official store. Are you referring to this?

It doesn’t look beginner-friendly; somehow it’s using a double-pin arrangement. It would be great if there was something like the ESP32 or Pico form factor!

image

Here official MCU specs.

Best regards,


#4

Hello,

Just to add to the previous comments, here is another form factor, though from a “non-official” store.

However, I suspect that the Arduino core will support “official” boards only.

Best regards,


#5

I hadn’t got as far as thinking about what board to use, but I’m pretty sure the Arduino core for that processor will work on any board; the pins may just be in a different order.


#6

Hi,

Ok, I will try a simple Arduino example.

I just bought both boards; hopefully, they will arrive in a few weeks!

Best Regards


#7

Yes, getting Blink working is always the first step!


#8

Hello,

Just a quick update: I got the CH32X035F8U6-EVT-R0, but it looks like the board is still not supported by the Arduino core.

I just opened an issue.

Best Regards,


#9

Dear friends, good day!
I couldn’t resist and decided to “go all out…”. I managed to drag uLisp to C++ project for CH32V307VCT6 microcontroler bypassing Arduino platform. It worked fine, but there is not much free flash memory left. I’m not sure that graphics will fit there.
However, I managed to connect and configure an external SRAM 512K (the scheme is available). Thanks to this, the number of cells became 65535. But this code is disabled by the macro “#define BOARD_HAS_ExternalRAM” so that you can use the devices which are available on aliexress. The sources and scheme are available for everyone at the link


#10

Dear friends, good afternoon!
I finally managed to add graphics. But I had to omit the function descriptions in the extension.
Currently, the extension includes touchscreen scanning functions, but without calibration, in their raw form. File and directory management functions allow you to rename, delete, and create directories and files.

(rename-file path new_name)
(delete-file path)
(ensure-directories-exist path)

The streaming mechanism in this version allows file copying in Lisp. (Open two streams simultaneously)

(defun copy-file (source dest)
 (if (and (stringp source) (stringp dest))
  (with-sd-card (wrstr dest 2)
   (with-sd-card (rdstr source 0)
     (let ((c 0))
      (loop
         (setq c (read-byte rdstr))
          (if (equal c nil) (return))
          (write-byte c wrstr)
       ))) t)
  nil
 ))

I had difficulty detecting the end of the file. An addition to the SDread function were nessessary. Perhaps this is the cost of leaving Arduino.

int SDread () {
  if (LastChar) {
    char temp = LastChar;
    LastChar = 0;
    return temp;
  }
  char c ;
  fres = f_read(&SDgfile, &c, 1, &uint_result);
  if(fres != FR_OK) return -1 ;
  if(uint_result <= 0) return -1 ;
  return 0x0ff & c ;
}

The extension also contains graphical functions for loading up to 50 fonts from prepared binary files. They are loaded into external SRAM, half of which is allocated to the lisp-workspace.

(load-font index FileName)

(set-font index)

Sets the font with number “index” as current font.

Addition functions for info about current font:

(getfontheight)
(getfontwidth)
(getfontinfo)

There’s a Qt-based program on my GitHub that converts system fonts to *.h format, which I then convert into binary files.

Two functions which allows to fill arbitrary user-drawn convex poligons :

(fill-init)
(... draw figure by lines, triangles, rectangles, circles... )
(fill-poly color)

Save a rectangular region to SD and read it back to the screen

(save-rect x y w h FileName)
(load-rect x y File Name)

Several examples of different fonts

And here is my uLisp-computer with external SRAM:

But for for present moment graphics only work with displays ILI9488.

These codes are for anyone who might find them useful.
Sincerely, Anatoly.


#11

Great work! Here’s the spec of the CH32V307VCT6:

Did you use an existing evaluation board from AliExpress, and if so, which one do you recommend?

Is it easy to get hold of MounRiver Studio? I assume it’s Windows only (not macOS)?

Have you tried the uLisp RISC-V assembler; does it work OK?


#12

Dear David, good day!
MounRiverStudio is also available for Linux and Mac.
https://www.mounriver.com/download

I program this chip using the wch-LinkE adapter, as it’s the most fully featured. It’s available on AliExpress.
https://aliexpress.ru/wholesale?SearchText=wch-LinkE&g=y&page=1&searchInfo=A6Xy5EbOuRNHD9XaZ1XowO6MaUXUaxfNydEY9uvD%2BZGWNnIOJw7iL0z79poo2biSJXo2ZqfZe4yloSdfGF0DqE4LhDQFTTChmDNAtBwiUmCQm2glxhOitI26rRaKIethFrHz2tOLwYOp9K5rWl02Ej6p8D%2Bx6%2F%2Bl23KES9rkBqJmzlNvIH6NRyyktw%3D%3D
But it is possible to write a bootloader there for programming via UART.

Devices that are attractive and have a full set of pins from the 100-pin ch32v307vct6 package:
https://aliexpress.ru/item/1005005819702456.html?sku_id=12000034463950530&spm=a2g2w.productlist.search_results.1.1a696749NYJYqA
or
the unit:
https://aliexpress.ru/item/1005006504033913.html?sku_id=12000037540537954&spm=a2g2w.productlist.search_results.5.1a696749NYJYqA
Github with information


There is an SD slot and additional SPI flash.

I’m not sure if it’s possible to connect external SRAM to them, or if the ethernet will interfere with it, but you can probably connect psRAM.
So I made my own board in Kicad, which has already been ordered. But I will need to assemble and test it. The Gerber files are on my GitHub.

I haven’t tried uLisp assembler yet. I thought it was better suited for more powerful processors. But if there’s a chance it’s compatible, i’d definitely like to give it a try.

Sincerely, Anatoly.


#13

Equivalent links to the two boards @AnatolySch recommends, on the main AliExpress site:

https://www.aliexpress.com/item/1005005819702456.html

https://www.aliexpress.com/item/1005006504033913.html


#14

A simple test you can do to see if machine code works:

Evaluate:

(defcode mul13 (x) #x45b5 #x0533 #x02b5 #x8082)

This creates a machine-code routine called mul13, with one parameter, consisting of three instructions which multiplies its single integer argument by 13.

Test it with:

(mul13 10)

If this returns 130 the machine code is working. As a next step you could load the RISC-V assembler and try the examples:

RISC-V assembler examples


#15

One thing I don’t quite understand. You wrote:

If you’re not using the Arduino platform, how are you replacing the calls to the Arduino core that uLisp makes? I’m thinking of the functions like Serial.begin(), millis(), delay(), pinMode(), digitalWrite(), etc?

Have you written your own versions of them; essentially, a minimal Arduino core?


#16

David, thanks, I’ll definitely try uLisp assembler !

For Serial.begin() , millis() , delay() , pinMode() , digitalWrite() i wrote my own codes.

A serial port is used pre-initialized by my code, with interrupt and ring buffer 1kb.

To control the pins, I use descriptors that contain the port number, pin number, and available ADC/DAC channels. (board_pins.h, board_pins.cpp)

typedef struct {
  uint8_t	iPort ;
  uint8_t	iBit;
  uint8_t	iADCChannel;
  uint8_t	iDACChannel;
} pindesc_t;

and an array of numbers storing the current state of each pin.

For the millis and delay functions, I use a system timer, with ready-made code with minimal modifications. MounRiver generates rich peripheral libraries of C source code when creating a new project.

Timers are currently not implemented. This will be possible if the Flash memory size is sufficient.

The SPI stream works, but I don’t yet know the best way to control the chip select signal. I could reserve a pin for it. But I could also manually (digital write) control any pin before and after running the stream. Then I could work with multiple devices.


#17

I started check the assembler. Since I was using the uLisp source code for esp32, i had to look at functions from the riscv platform. The defcode command now works.

32768> (defcode mul13 (x) #x45b5 #x0533 #x02b5 #x8082)
mul13

32752> (mul13 10)
130
32752>

Now I will look at other examples and the compiler.


#18

Dear David, good afternoon!
My experiments with Assembler are going well. I tried the uLisp compiler. It complains about :integer variables

27797>(pprint (comp '(* 13 17)))
Error: undefined: :integer

Maybe I missed something. I tried to define it

27797> (defvar :integer 0)

This led to the following

27788> (pprint (comp '(* 13 17)))                                                                                                                  
(0
  ($li 'a0 13)
  ($addi 'sp 'sp -4)
  ($sw 'a0 0 '(sp))
  ($li 'a0 17)
  ($lw 'a1 0 '(sp))
  ($addi 'sp 'sp 4)
  ($mul 'a0 'a1 'a0))

But the Fibonacci function compiles strangely.

27788> (defun fib (n)                                                                                                                              
  (if (< n 3) 1                                                                                                                                    
    (+ (fib (- n 1)) (fib (- n 2)))))
fib

27829> (comp 'fib)
(nil ($mv (quote a0) (quote nil)))

I made a mistake somewhere probably.


#19

I’ll check it; perhaps something has changed.

Which version of uLisp are you using?

And I assume you’re using this version of the compiler: Lisp compiler for RISC-V.


#20

I used version 4.7 for ESP from November 3, 2024. But I don’t remember the link I downloaded the assembler from. Most likely, it was through the link to the examples RISC-V Assembler - Version 4 - 18th October 2024.
I tried to find the definition of :integer in all the ulisp…ino sources and in the assembler and compiler sources.