2020-08-08

2020-08-08 Longan Nano GD32VF103 Demo

 


>>>Longan Nano GD32VF103<<<

Longan Nano GD32VF103 Risc-V 108MHz 32b MCU toolchain, libraries and applications

>>>Longan Nano Demo<<<


Display Class: Interfaces with the ST7735 80x160 display using SPI0 and DMA0.
Screen Class: Provides asynchronous methods to print on the display



1Longan nano GD32VF103 Demo

I built Display, Screen and Chrono class drivers for the Longan nano GD32VF103 board.

This Demo application is meant to show off the features of the drivers and jump start the development of the application.

I spent extra effort in testing and documentation to make sure the drivers are as stable as possible since they are going to be the building blocks for all my future applications on this board.


1.1Chrono Class Driver

The Chrono class uses the 64bit 27MHz@108MHz CPU clock timer to provide accurate timings.

Time units are defined in the Longan_nano::Chrono::Unit enum.

The Chrono class has two modes of operation:

  • start/stop elapsed timer: measures DeltaT

  • start/accumulate: integrate a DeltaT on an accumulator

Those two modes of operations can be used to profile uptime, elapsed time, time spent running code and more.


1.2Display Class Driver

The Display class interfaces directly with the LH096T ST7735S 0.96 inches 80x160 oled color screen.

The library uses the .init method to initialize the display has two modes of operations:

  • register_sprite/update for asynchronous non blocking operations.

  • draw_sprite for synchronous blocking operations.

The Display class uses optional DMA acceleration and the SPI0 and a few GPIOs to communicate with the physical screen.

The Display class does not use interrupts. While using interrupts can make the driver transparent to the user by automagically calling the update method, it can interfere with other real time operations. As design philosophy, the driver is meant to be secondary to the application and meant to show information, giving the application control over the amount of resources used by deciding the call speed of the update method. Calling .update() every 100us will result in about 1250 sprites updated per second. If the user makes more print calls than what the display can handle, the display will simply ignore older calls displaying the most recent sprite. At top load a refresh rate of about 1250/100=12.5 frames per seconds can be expected. The refresh rate becomes 1.25 fps at full load if .update() is executed every 1000us instead of 100us.


1.3Screen Class Driver

The scope of the screen class is to support ascii print of fixed size on fixed grid, and is meant for the common use case of showing debug and runtime number of the application.

The Screen class add a sprite based abstraction layer with print to reduce the size of the frame buffer and CPU use. It also provides a large number of overloaded print methods. The Screen class inherit the Display class, allowing to decouple the physical screen from the print implementation and simplify a move to a bigger screen if needed.

The Screen class supports two ascii fonts. 8x10 Courier Now and 8x16 NSimSum that can be toggled by setting the define FONT_HEIGHT and recompiling, the smaller font shows 8x20=160 sprites on screen, while the bigger font shows 5x20=100 sprites on screen and is easier to read.


2DEMOS

There are ten demo, showcasing the use of the print and timing functions to display an HMI.

  1. Clear the screen to a random color every 500ms

  2. Print a random character in a random position of the screen every 1ms

  3. Same as above but with random foreground and background colors

  4. Print a random string in a random position of the screen every 25ms

  5. Same as above but with random foreground and background colors

  6. Print numbers with right and left adjust

  7. CPU execution and uptime with engineering format 4 significant digit and SI suffix

  8. Same as above but with screen builtin pending and error methods

  9. Same as above but with random foreground and background colors

  10. Constant workload demo. Print 10 sprites every 25ms and show CPU use

Illustration 1 - Demo


 
Video 1 - Demo

3Documentation and Style

I made a point to learn more C++ features, with this project I elected to use .hpp files with header and implementation together since inline needs to be declared alongside the header anyway. I also experimented with scoping of typedef and enum to allow the same enum name to be in multiple libraries without conflicts.

I also integrated the Doxygen documentation style comments and generated the automatic documentation, as well as integrating the documentation alongside the code repository in GitHub.

The same style is going to be used for my next classes and drivers.


4Conclusions

I begun this project to learn a Risc-V MCU. The Longan Nano Demo provides an example application for the scheduler, Chrono, Screen and PA8 button, and can be used as a base to develop applications with the Longan Nano GD32VF103.

I am satisfied with the performance, and how the drivers have turned out. The board provides great value, and in my opinion is held back by the poor examples. Hopefully more people will adopt the Longan Nano and help in building libraries and example code to make it easier to develop applications on Risc-V MCUs to come.

The first application of this MCU will be as new motor controller for OrangeBot.


5Source Code

>>>GitHub Repository<<<


5.1Doxygen Documentation

>>>DoxyGen<<<




5.2Source Code

>>>Screen and Display classes<<<








No comments: