Labels

Monday, 28 March 2022

RISC-V Programs

I  bought my Nezha back in June 2021.  Of course the reason for buying it was the RISC-V (RV) instruction set, so to make it worthwhile I needed to write some assembly programs.  I learned assembly mainly from Anthony J Dos Reis's book which I started last October.  I wrote a few I/O routines then, and have been slow to follow up but I have gradually made progress.

Part of the problem is that C is an easier language for "low-level" program and the use of Assembly is somewhat artificial.  One solution is to use assembly to look at our programming environment provided by Linux, we can more easily look at registers and memory in Assembly.  Another solution is to look closely at how the C and assembly environments work together, which I shall cover in a subsequent post.

I am unsure how much to use clib subroutines in my program.  They provide me with all the functionality of the C standard functions.  At best it saves me time writing lots of low-level subroutines, at worst it means that I might as well be writing C.

Display registers and addresses

My first program (memdisp1) simply displayed the contents of some particular registers and label addresses within the program itself.  I used clib printf to display register values but found that it only prints 32-bit values.  This meant that addresses were incomplete, I could shift right to get the remaining hex digits.  It turns out that there are 6 more bits to be read.



From the output we can see that the program entry point (main) is at 2A,DA2E,66D4 and the stack pointer is at 3F,FFDA,E490.  A 32-bit address gives a potential range of 4GB and 6 extra bits multiply that by 64 to 256GB, although of course we dont have that much memory.  In practice linux will assign an appropriate set of memory pages to the process.  It is more important for us to know where in the stack our data is and what offset in the program our instructions are.

Display register values properly


As printf doesn't do a good job of printing my 64-bit registers (there may be a compilation setting I am missing which limits results to 32-bit) I wrote an assembly program (memdisp2) to print a register value by selecting the rightmost 4 bits and printing the corresponding hex digit.  The program loops round shift right 4 bits each time until all the digits have been printed.
As there are no C lib calls in this program we don't need the overhead of C initialisation and the program is a lot smaller1408B compared tih 8584B



Display a range of memory


We now have the tools to print out a decent memory dump within our program.  The code to display a 64 bit register goes in a routine disp64.  We put the code to display a range of addresses in another subroutine disprange, so that it can be used generally.  Memdisp4 simply calls disprange to display some values.


The result looks pretty good to me.  We could also use the debugger (GDB) to get this type of information but it is handy to be able to dump it within our program. The program is loaded at a different location each time it is run and to understand more about the linking and loading process I would be delving further into Linux rather than RV assembler.


RISC-V : Learning Assembly


Study Texts

I read a book RISC-V Assembly Language by Anthony J Dos Reis to learn RISC-V (RV).  The book assumes you don't have any prior experience with assembly language and some parts are rather slow and obvious to me.  However it pays to read through in detail as there is a lot of important information included.
One downside of the book is that the examples use an assembler "rv" written by the author, which runs on Windows.  Of necessity, time is devoted to the way it works.  As I am using a real RV computer I would prefer focussing on the real environment.  I agree that Reis's "rv" assembler makes it much easier for most people to get started, as I am rather unusual / fortunate in having a real linux RV system.

 I also used the definitive RISC-V Reader, written by the architects, David Paterson and Andrew Waterman.  This highlights the rational elegance of the language and compares it with older CISC (Intel) and RISC (ARM) architectures.  The language can be summarised in a very few pages - although this doesn't help a lot in learning it.

Machine Code

The Reis book focuses on RV32I 32-bit base instruction set.  There are cutdown versions for 16 bit as well as 64-bit and 128-bit varieties. My computer is 64-bit  but runs the 32-bit instruction set mostly.  There are a few extra instructions for 64-bit systems but they are just natural extensions.  For example the LW instruction loads a 32-bit word into a 32 or 64 bit register and LD loads a 64-bit word into a 64-bit register.  One of the strengths of RV is you should be able to program a wide variety of devices with, mostly, the same instruction set.

There are various standard fields in a machine code instruction.  Care has been taken to put the fields in the same place within all instructions wherever possible, in fact there are only 6 different formats.  This makes the hardware simpler and assists pipelining.



All instructions are 32 bits in length with the opcode in the right-hand 7 bits.  This helps quick identification of  an instructions purpose when looking at machine code.
There are 32 registers which are divided into groups for different purposes such as temporary, saved, function arguments.  Stack pointer, return address and global pointer registers have specific uses.
In total there are only about 60 instructions covering the expected operations such as load, store, branch, add, shift and logical operations.

Assembly Language

Using a small instruction set makes learning the basic operations of loading, storing, adding, shifting, looping and branching very simple.
As RV machines don't have a status word some things need to be processed somewhat differently.  The result of comparison operations is put into a register; the programmer needs to test for overflow conditions themselves.

A sample program is shown below:


The subroutine mechanism requires you to save the return address on the stack when you enter a subroutine (assuming you want to be able to call other subroutines) and in practice the stack can be used for most of the storage required in the program.
There is a convention that "callee" registers, s0-s11 need to be saved within your subroutine if you modify them.  Temporary registers and argument registers are assumed to be overwritten across a subroutine call, so if the calling program needs them it is responsible for saving them.
This is a nice mechanism to minimise unnecessary save / restore overhead for subroutines.

Pseudo Instructions

Pseudo instructions pad out the instruction set.  For example there is a BLT (branch if less than) but no  BGT (branch if greater than) instructions.  You can code BGT t0, t1, done-label and the assembler translates to BLT t1, t0, done-label.  A NOP (no operation) pseudo-instruction is translated to addi x0, x0,0 (add nothing to the read-only x0 register).

Load immediate (LI) and load address (LA) are particularly helpful allowing us to load 32 bit data and addresses.  LI basically uses two instructions: LUI (load unsigned immediate) loads the lower 12 bits and ADDI (add immediate) to add in the upper 20 bits.  There are some wrinkles which the assembler deals with for you.  Similarly LA uses LUI and AUIPC (Add Upper Immediate to PC) and sorts out the complexities for you.

Multiplication and divison

The RV32I instruction set doesn't include multiplication and division instructions but RV32M does.  So if your processor can do multiply and divide you can use the standard instructions, if not you need to implement suitable subroutines such as the shift-add algorithm provided in the study text.

Conclusion

I have just about covered the RV language.  The RISC-V Reader is even shorter than the Reis text book and provides a lot of comparisons with ARM and Intel architecture to justify RV design.  RV seems to have a bright future now that suitable hardware is being developed and sold.  Although not yet competitive with established players it seems likely that it will grow rapidly over the next few years.

Thursday, 10 February 2022

TinaLinux on Nezha

 Generally I am happy with Debian as the OS on a microprocessor.  I am most familiar with it since it is installed on RPi and I use it regularly.

Allwinner have developed TinaLinux for thei embedded systems.  It is based on OpenWrt which was initially targetted as a Linux implementation for routers.  TinaLinux compressed images are upto 100MB in size compared with about 1GB for a Debian image including GUI.

Some Sipeed D1-Nezha boards apparenly had TinaLinux in flash memory when they were delivered but mine didn't and I wanted to find out more.  There wasn't a Tina image available for the Nezha, although there is one for the LicheeRV, and I successfully booted the LicheeRV Tina SD card on Nezha.

Allwinner provide an SDK for creating Tina builds - you can specify in great detail which Linux features and comands you want to include and use the Linux "make" command to compile the software and build the image.  Images can be burned to SD card or copied to Nand flash memory.  When you boot from an image you can test that the features and commands work as expected.

Setup SDK

There are various pre-requisites and requirements for the environment hosting Tina SDK.  In particular, you are advised to to use an old (v14 from 2014) version of Ubuntu.  Luckily a Virtualbox VM is available from Allwinner which has been setup with appropriate software.  I downloaded it (1.6GB) and started it up in the VirtualBox environment.  The VM supports shared folders and has a network connection so I am easily able to transfer files to / from the VM and download software from the internet.

The next step is to download the Tina SDK from Allwinner.  A user registration is required together with a public key from the recipient machine to obtain access to the download.  I created keys with  ssh-keygen on my Ubuntu VM and uploaded the public key to the Allwinner site.  Following their instructions I used the repo command to download the SDK from github.  The download took well over two hours and resulted in 11GB of software in the tina-d1-open folder.

Build an Image

Rather than doing any configuration I decided to build an image based on the configuration provided.  It took some time to compile everything, but after 8 hours I saw a message saying the build was successful.  I was then able to pack the image, copy it to Windows and use PhoenixCard to burn it to SD card.  Amazingly the SD card booted into linux (the first part of the boot is shown below) and I was able to sign on to TinaLinux on the serial console and have a look around.


Test the system


The first problem I had was that the filesystem has no spare space, and in fact it is read-only - which is appropriate for a nand flash load but doesnt help me.
It took me a while to work out where the system partition table is defined within the Tina SDK but once I had made it somewhat bigger and rebuilt the system I had some space available.  Of course the make utility only recompiles changes and the rebuild was complete in 10 minutes.  I couldn't find a place in the SDK to make the root filesystem read-write so I remounted the disk at first startup.

Now that we have a system we can configure I tried to get a network.  The ifconfig and udhcpc utility will start up ethernet but wifi would't work for me.  With ethernet working I rebuilt the system to include sshd-server and after booting I was able to start sshd and ssh into the system from a remote terminal.

For the moment I don't want to do too much configuration.  I contented myself with adding a small web server (uhttpd) and fdisk providing the ability to modify partitions.

Each time the system is rebuilt any tailoring is lost.  Luckily my Nezha has a USB stick plugged in and it is useable from Tina so I created a script on the stick which I can run on boot.  This mounts rootfs read-write, starts sshd and permits root to have ssh access locally.

In conclusion I am very pleased that I have been able to build a TinaLinux system and test it on the Nezha.






Saturday, 29 January 2022

Sipeed LicheeRV Panel

Intro

The Sipeed LicheeRV 86 Panel is a very exciting product.  It is based on the same LicheeRV D1 board and dock but it includes a 4" touch screen and ethernet connection.  At $72 it is somewhat more expensive than the basic boards but it is much closer to being a self-contained working system.  It works on 5V USB or 12V supply.  The panel comes with a case which protects the board which is attached to its rear side.  In fact it could easily provide the basis for a home automation control.  It is only about the size of a light switch and could easily be wall mounted near a door way to activate room functions.  The only extra needed is a 12V power supply (similar to the one used by low voltage LEDs).


There is plenty of documentation available on the Sipeed BBS and the linux-sunxi community web-site has started to add descriptions.

Installation - Tina


I first installed the Tina WAFT (WebAssembly Framework for Things) image using good instructions which Sipeed provided, translated to English with Google Translate.  A USB cable connected to the USB-C UART port at one end and the PC at the other to provide power and a serial console.  The system boots in about 5 seconds into Maix Linux.  Tina / MaixLinux is a very small IoT (Internet of Things) linux which uses Busybox to provide basic command line tools. The image is only 115MB in size so it is great for small systems. I quickly tried looking at using WAFT but the demo didn't seem to work.  In addition, the panel screen didn't work initially (rapid scrolling of the image) so I moved on Debian.



Installation - Debian


The debain image is somewhat larger.  Initially I chose LicheeRV_Debian_86_480p.7z. It was easy enough to download from mega.nz although it was 1.1G compressed and expands into a 4GB image.
As usual I used PhoenixCard software to burn the image and inserted in the SD card on the back of the panel.  The system boots up without many errors and you can sign on via the serial console (putty) as sipeed or root.

The Panel has an ethernet connection using a rather unusual connector onto the back of the panel which is shown below.  The cable provided has an RJ45 and a barrel connector on one end and circuit board connectors for ethernet (on the left) and power (on the right).  If you want you can use the 12V power connector instead of using USB power input.  With the ethernet connected we can easily signin to the system using ssdh

When the system was booted up the 4 inch screen showed a signon screen scrolling vertically and was unuseable.  I tried all the different images, both Tina and Debian but the screen problem remained.  Eventually I tried over-writing the "fex" partition on the SD card (partition 1) with the fex file for a 720p display.  On booting the system works perfectly.  So the problem was that the downloaded images were for a 480p screen, which is the one which is described in the advert.  However I have a 720p screen which needs a different fex file.  I reported this on the LicheeRV/Nezha Telegram thread and a note will be added to the linux-sunxi community webpage to explain this.
I plugged a screen and keyboard into the HOST USB port and I was then able to signin to Debian.  The screen is 720p x 720p so although it is very small it is very detailed and if you look closely enough it is quite useable.  As a first test I ran HTOP to display system usage.
I wanted to display an image and there weren't any I could find on the system.  I needed to install wget using the apt package manager and could then download an image from my website and display it on the panel.  It looks very clear.

Initially I couldn't get the wireless interface to work on either Debian or Tina.  Once I realised that I am using the 8723ds wireless chip (not the xr829) I retrieved the correct images and wifi networking works fine.

I now have available a lovely RISC-V panel with ethernet / wifi with a small high quality screen. 





  





Thursday, 27 January 2022

Sipeed LicheeRV Dock

 A couple of weeks after I saw the Sipeed LicheeRV advertised and bought one, the LicheeRV Dock became available.  A docking station for the LicheeRV costs about £4.  I ordered a LicheeRV + Dock on 29th December and it was delivered 13th January.  The docking station provides a HDMI connection, a USB port, 40 pin connector and wifi (Realtek 8723DS), so there are many more things you can do with it.

 


Its specification is very similar to the Nezha which came out 6 months ago but it is about 1/3 the price.  This was expected, the Nezha gave people an early look at RISC-V.  The LicheeRV is more of a product.

Documentation for the LicheeRV is now available on the sipeed BBS and it is quite extensive.  Although it is initially in Chinese,  Google Translate does a perfectly acceptable job translating it into English for me.



There are also a number of images available to make installation easier.  Firstly I tried the Debian image and, once I had plugged a screen in on the HDMI port and a keyboard/mouse on the USB port I was ready to go.


It was easy to boot into Debian and use the GUI.  Once I worked out the wifi is RTL8723DS and chosen the right image I could configure the wifi and SSH into the system easily enough.

Similarly Tina is easy to setup.  I downloaded and burned the image for tina hdmi 8723 and booted up.  I was then able to configure wifi details and connect to the network.

The screen is used as a monitor rather than a terminal I think.  When booting it show a 480x480 screen shot in chinese with a date 2021.12.8.  I can display a color bar test but the frame viewer doesn't work for me (yet?).


So for about £20 I have a working RV system with network, HDMI and a choice of Operating Systems.




Tuesday, 25 January 2022

LFS : Linux from Scratch

 Why

Linux installation is straightforward.  For an RPi you just download an image in Windows, burn it on to an SD card, insert the card in RPi with screen, keyboard attached and turn the power on.  Adding network capability is similarly easy, in Raspbian you specify the package name to the apt command and the necessary steps are completed to install dependencies and the requested software.

From other activities I know that setting up partitions and choosing a kernel are also important.  Building a kernel is a matter of ensuring you have all the necessary files and running one long compile job.

The missing part of the picture is the ability to set up all the basic software in files and folders so that the system works.  It turns out that, as expected, there is a lot of work involved.  Thanks to the LFS (Linux from Scratch) project and the PiLFS ( RPi LFS) guide I have been able to successfully build my own minimal system, sign on, add packages etc.    

It is a challenging objective and the LFS team have done an amazing job in making each of the 100 or so tasks understandable so that you can create the Linux system you want.  Even with this  I would have struggled to build my own system.  PiLFS provides a guide to how to implement LFS on a Pi system together with a host configuration containing working build software and two large scripts to automate many of the tasks.  I feel that LFS is awesome and I'm grateful to PiLFS for making it practical to build with my patchy Linux knowledge.

Host System

You need a set of software running on the host system to be able to build linux, the list includes kernel, c compiler, make and various utilities:

bash  binutils  bison  bzip2  coreutils  diffutils  findutils  gawk  GCC  glibc  grep  gzip  Linux-kernel
m4  make  patch  perl  python  sed  tar  texinfo  xz

This isn't a long list bearing in mind the scale of the work we are undertaking.  I use a RPi4 as my host system.  PiLFS provide a RPi image so we can be sure we start with the correct pre-requisites.  We boot RPi with the image and we can start building. 

The first task is to make a new partition as a target for the software which is built.  Following PiLFS suggestion create a new partition (20GB) on the SD card.  All the software will be installed in the root file system; on completion we boot software from the new partition.

Download software and create LFS user

A number of tarballs are downloaded containing sources for software to be installed on our new system.  They are installed in the /sources folder on the new system.  There are also some patch files which will need to be applied.  Software is downloaded from the linux from scratch website which ensures that packages are all at compatible levels.

A userid LFS is setup to carry out compilation tasks for the new system.  Good practice says that root should only be used when necessary, LFS is able to carry out most of the work.

Create Toolchain and utility tools

The first thing we need to do as user lfs is build a toolchain for the new system.  Binutils is created first, it provides a linker and assembler.  Next we compile GCC onto the new system - of course we are using GCC on the host system to do the compilation.  Our task is made easier because both our host and target systems are RPis so GCC is going to work.  A proper cross-compiler would be (even) more challenging.

The remaining toolchain software we need is linux-headers, glibc and libstdc (for c++).  These five builds are quite complex and PiLFS provides a script which automates the process for us.

The script also compiles utilities which will be required on the new system m4, ncurses, bash, coreutils, diffutil, file, findutils, gawk, grep gzip, make, patch, sed, tar, xz. 

Entering Chroot

The chroot command allows us to use the new filesystem we have created with the existing kernel. The chroot environment doesn't have access to the host software.  Before entering chroot we have to setup the virtual filesystem that the kernel uses to manage / communicate with software running in the environment. 

Within chroot, as root user, we create some essential files (/etc/hosts. pwsswd, group) and compile some more tools (gettext, bison, perl, python, texinfo, util-linux).

Building new system software

We are finally ready to do the proper build of all the software on the new system.  There are 73 steps to carry out and PiLFS has simplified the process by putting all the builds into a script for us.
Many hours later the build is finished.

Finale

One of the last tasks is to setup a filesystem table (/etc/fstab) for the target system.  It looks very similar to the host except that the root partition is changed to the one we have just been building.

In our simplified environment we are going to use the same kernel as before - there is no particular advantage in building a new one and we can do it as a separate exercise whenever.  In addition we have been working for many hours to get this far and I want to see if it works... 


it does :):):)

Amazingly we have our own working linux system.  Anything that works has been done by us and anything that doesn't is yet to be installed.  It is very satisfying.  Thanks to the LFS project I know (or can find out by checking the doc) what all the components are, how they are built and what they do.  In particular LFS has an excellent summary of the relevant configuration options used to create the software.

Next Steps

There are a few extras we need to add for a basic working system:
openssh - needed to login from a terminal session, in particular to be able to copy / paste commands.
wget - needed to download packages to extend our system
ntp - RPi has no clock so we need to obtain the time at each system startup.

We can also install other software installs facilitated by LFS or attempt our own installations from github etc.

In conclusion this is a wonderful exercise to help me understand what I am using on a Linux system.







Sunday, 16 January 2022

Sipeed LicheeRV

 Back in June 2021, I was fortunate enough to spot that the Sipeed Nezha RISC-V development SBC was on sale.  It is the first Linux RISC-V SBC system for less than $100 and marks the beginning of a new era in home / hobbyist computers.  It is based on the Raspberry Pi form factor and runs Debian Linux.  I have greatly enjoyed getting to know it and particularly using it to write some simple RISC-V assembly programs which I can compile directly using the GCC compiler.

On 24th November I saw on the Sipeed twitter feed that the Lichee RV is for sale.  It uses the same processor as the Nezha but has very few peripherals on board and no GPIO pins.  An SPI connector is used for an LCD screen and there is an SD card holder.  Instead it has an m2 connector which can connect to external devices such as Ethernet, wifi, bluetooth.  It costs $13 as opposed to the Nezha $99 crowdfunder price and doesn't have a limit on the number available.

 I purchased the version with a screen (total $17) on Ali Express and waited in anticipation for it to be delivered.  It arrived in the UK on 4th December and was delivered 16th December so I was one of the first to receive them outside China, certainly an early arrival in Europe.

Initially I wasn't sure what to do with it, my Nezha SD card didn't seem to do anything.  On 24th December O-GL in France and Daniel Maslowski in Germany on Telegram provided me with the information needed.  There is an international download folder on mega.nz and a  set of tutorials on the sipeed forum.


On 4th January I was  lucky enough to look a the Mega.nz site and see that a zip file for an Ubuntu 20.04 build including the LCD had just been uploaded.  It was slightly more complicated to download than the usual images, I had to locate files manually in the correct part of the SD card.  However this meant that the download was 167MB instead of 1.07GB so it was worth the extra work.  Initially the build did nothing but on 5th January someone on Telegram posted a correction to the instructions and the result was that I could get a working Ubuntu Linux with tiny LCD console.


Of course there wasn't a lot I could do with just a screen but I was quickly able to solder on the four pins in the bottom left corner of the board so that I could connect an FTDI cable, allowing me to sign on to a serial console session.
So I now have a working Linux system on a tiny 6cm x 4cm board - a bit similar to the RPi Zero.

I was also able to download Debian and Tina images and create SD cards.  The Sipeed tutorial provides console commands to switch the on board LED on/off using GPIO commands and Iwas able to check that this works.  The basic board doesn't have any networking capability so I had to await my LicheeRV dock before progressing much further.







Saturday, 15 January 2022

Christmas Lights Improvements last year

 For the past few years I have set up music controlled colourful Xmas lights using Lightshow Pi software (LSPi) running on a Raspberry Pi RPi.  LSPi software hasn't changed in the past three years but it still works and support is still available from enthusiastic users, particularly SoftwareArtist.  I started my updates for Xmas early in December 2021 which helped me produce something useful in time for Xmas day.

Last year I ran the music (MPD) and LSPi on the same server.  My RPi server used for this application had a disastrous SD card failure during the year so I needed to reinstall software on my shiny new RPi4 application server (PI41) this December.  Luckily LSPi configuration was backed up and my notes on installation was up to date.  Currently the MPD music player is active on my web server (PI40) along with the web pages to select and play music.  

LSPi Installation is well documented on reddit.  I followed  the instructions, which have been updated for RPi4.  I encountered one error in building "rpi-audio-levels" which the helpful SoftwareArtist on reddit provided a solution for.  Once I updated RPi firmware, LSPi installation worked fine and I was able to test that LSPi on PI40 was controlling GPIO output properly.

The LSPi configuration required for my setup is quite simple.  Music is streamed in from MPD on PI40 and RGB output provided on three GPIO pins.  The sample LSPi configuration file has detailed explanatory comments for all the options but my cutdown file only requires a few.
The most important command is "stream_command_string" which causes LSPi to listen to the music being played on PI40 by MPD.  Clearly MPD needs to be setup with a streaming output on port 8000 to achieve this in mpd.conf






I found by trial and error the pin_modes, pwm_range and attenuate_pct settings to give a pleasing range of colours on the output.  We need to set preshow_configuration to null to avoid a few seconds delay before the lightshow starts.  I was grateful that this solution avoids the syncing problems I have previously experienced with the lights being a secnd or two behind the music.  The current solution is quite impressive, RPi is calculating Fast Fourier Transforms (FFTs) in real time to determine music frequencies and using these to calculate pwm duty cycles.

The second improvement I made this year was to "finalise" my MOSFET setup.  I use MOSFETs to increase the RPI GPIO voltage to 12V and provide the current that MOSFETs need to drive the 5050 LED strip. Previously a breadboard solution provided this facility.  My track record in transferring working breadboard configurations to perfboard has been abysmal so although the circuit is quite straightforward I was very careful to draw out a design, check it, cut wires to length and find the necessary components before I started.  I colour-coded the RGB wires and on completion made sure the wires were tidy then put labels on the connections.  





I am rather proud of the results, it works a treat and I will probably keep the lights setup all year round.

Tuesday, 26 October 2021

Nezha : Using syscalls for IO

 It was back in July I first posted about my Nezha RISC-V SBC.  At the time I was pleased to have a solid, reliable Debian build and excited with the ability to write native RV assembly programs and run them  at the command line without the usual inconvenience of cross-compilation and loading.

I purchased Anthony Reis' (AR) beginners guide to RV assembly which provides a gentle learning curve for me.  It starts with a chapter on machine language which is interesting as it describes the format of some types of instructions ().  I am hoping not to do too much low level debugging but this info provides an insight into the RV design, in which instructions are standardised to facilitate their implementation on a variety of hardware platforms.

One of the problems with an instructional RV book is that people have a range of environments in which they write programs.  Many would use a QEMU RV VM, some would have a smaller RV machine to load executables onto and a lucky few like me have an RV linux SBCfor native compilation. As AR starts on the assembly language tutorials he provides his own program which functions as an RV-32 assembler and simulation environment.  This provides input output to the screen using his own bespoke functions.  For example two instructions sin and sout are provided to input / output a string to / from a program.  A lot of assembly programming deals with peripherals so this isn't very helpful (although it is the correct approach for a general purpose tutorial / textbook).

The first thing I need to do is to work out how to implement the same functionality in my linux / gcc environment so that I don't need to use AR's assembler / io functions.  Previously I was able to use Stephen Smith's hello world example which uses a linux system call (ecall) to output a string.  Instead of using ecall it is possible to to the call statement, so that you can use the C function name rather than a numeric syscall number.  RV registers a0, a1, a2, ... registers are used for the parameters.  I was very pleased with my first attempt, shown below, which calls printf to display a string containing an integer parameter.  I needed to link it with a linker option "-no-pie" to include the necessary library modules for terminal output.


Once we have this mechanism it is easy to provide simple macros with the same name and parameter as those used in Anthony Reis book.  Now my first program example, which adds two numbers together looks just like the one in the book.





Sunday, 17 October 2021

DIY Frequency Counter

 

I am concerned with my 6502 reliability now that I have increased the clock speed to 1MHz and I want the ability to slow the clock down (again).  I could revert to my arduino Nano clock but this is quite a bit slower.  Instead I decided to use a decade counter so that I can slow the clock by a factor of 10, 100, 1000 etc.  Chips are ridiculously chep and I can easily add one next to the clock on the breadboard.
It occurred to me that I need to measure my clock speed to be sure the counter is having the expected effect.  It would also be very useful to check the nano clock generated frequenct if I am using it.

Ebay shows some cheap kits alongside expensive "professional" equipment.  I only need a rough idea so a kit is perfect.  It comprises TTH (through the hole) components, 5 x seven segment displays for output and a PIC16 microcontroller for measurement.

The only instruction provided is a link to a youtube video.  It turns out to be very helpful.  Kev, the guy who provides it, makes a board whilst talking, it takes about 5 minutes.  It is reassuring and charming that he is quite amateurish.  There are a couple of important points he makes, firstly how to solder the extra capacitor to improve low frequency measurement and secondly a reference / link to operating instructions he has found.

The board is very nice to solder with well-spaced components and generous solder pads.  I built it and it works.  It accurately tested a 20MHz oscillator as having a frequency 20.064 MHz.  Next I measured the clock speed on my W65C02SXB board, which I understood was running at 8MHz.  The measurement was 1.8MHz, looking at the clock chip on the board I noticed that this is correct - so the tester has already proved itself useful.

In conclusion, I am very pleased with this circuit, it is always nice to solder useful things.  I am now ready to face my next 6502 test.








W65C02SXB : WDC to the rescue

 

I am a little nervous about my 6502 system.  I moved beyound the "use wires to connect hardware on breadboard" stage so time ago and I am more intereseted in software development now.  In fact I am aiming to run C and BASIC programs on my system next.  Underneath the hardware is working but subject to the vagaries of bad connections or deficiencies in programming due to my incomplete understanding.  The recent increase in clock speed (or some undiscovered unknown issue) has led to the system becoming frustrating to work with and almost unuseable.

Whilst considering buying a circuit board to formalise my hardware (for example from dbuchwald) I came across a development board from WDC  which perfectly matches my requirement. It was released in 2014, apparently as an educational board and is still available. WDC have been the main player keeping 6502 hardware ecosystem alive for many years now so a board from them is likely to be good.

The W65C02SXB  has a 65C02, ROM, RAM, VIA and ACIA just like mine.  Obviously it has the advantage that all connections are in place and should be reliable.
The clock runs at 8MHz s the board should be significantly faster than my existing breadboard version.
The second enhancement is that all necessary pins, including data bus address bus and 65C02 control pins are available on headers so are easily accessible for attaching devices / peripherals.

I ordered one immediately from Mouser in the UK and it was delivered by Fedex five days later after an epic journey from Grand Prairie, Texas.



There is a getting started project provided by WDC which demonstrates how to assemble (WDC02AS), link (WDCLN) and run a program to flash the onboard X LEDs.  The program is loaded and run using the debugger (WDCDB) which shows you the assembler source, memory variables / registers and allows you to single step or run through a program.  This is magnificent and provides a whole new world, hopefully making it much easier to develop code.

A second project  providing very detailed instructions is available from Instructables to flash an external LED attached to a VIA pin.  The executable image is loaded via TIDE (Terbium IDE) into memory and can then be run using the debugger.

These WDC tools make software development a very different experience from my DIY environment and hopefully speed up the process.  All I need to do is attach appropriate hardware to the board connectors and start development.  It looks like WDC and instructables hoped for other projects to be based on the board but I haven't seen many, there are a few references on 6502.org which I can follow up.

Monday, 20 September 2021

6502 : Xmodem Fights Back



 Previous I have been pleased to be able to (1) download a file to RAM and (2) use xmodem to transfer a program and then run it. I was very pleased with both results and felt that I had cracked xmodem.  The good feeling didn't last long.

Download speed

I wanted to get started on testing my C programs and they use the terminal working at 19.2k baud whereas my download testing has been conducted at 9600 baud.   The C program displayed some garbled characters when the speed was reduced to 9.6k and in general my programs work at 19.2k so I need to standardise my transfers on 19.2k.

Increase clock speed

Unfortunately, when I changed to 19.2k my xmodem downloads appeared to complete but would not run as they were losing characters.  My thoughts turned to flow control or increasing the clock speed.  RTS/CTS flow control didn't seem to work last time I tried it and I don't really need my Nano slow testing capability so adding the 1MHz clock chip is the way to go.  

Changing over to the clock chip simply requires connecting 5V, GND and the clock output to 6502.  After doing this nothing was displayed on the terminal screen with a simple program which outputs a message.  I find I need to put a 255 cycle delay loop between each character output to the terminal.  I tried RTS/CTS flow control but it made no difference.

A short while later I discovered, on the 6502 site forum that the 65C51 has a design error which means that flow control doesn't work


 The easiest workaround is the method I chose; to insert a delay.

Spurious Interrupts

With the transmission speed fixed, I returned to testing xmodem downloads.  Unfortunately matters became worse.  The 6502 appeared to randomly restart itself during or after downloads.  I guessed that the system was getting interrupts, causing it to jump to the reset vector.  So far I have only covered Ben's interrupt tutorials and haven't set anything up.  The 6502 has an NMI pin (connected to 5V) and an IRQ pin connected to the 6522 VIA CA1 pin.    I set up small code snippets which displayed a message on the terminal when one of the interrupts occurred and configured the NMI and IRQ vectors accordingly.

As expected the IRQ vector was used each time a spurious interrupt occurred.  This happened even when the IRQ pin was held high.  The 6502 provides a BRK instruction (opcode $00) which also causes an interrupt to the IRQ vector.  When an interrupt occurs, the interrupt return address and process status register byte are written to the stack.  Initially my code to test BRK would not return to continue the program when an RTI (return from interrupt) instruction was encountered.  I found in an article that compilers need to treat BRK as a 2 byte opcode to jump back to the correct address but they only reserve 1 byte ($00) which means the program returns to the wrong address.  I corrected this by adding NOP after BRK and RTI then works fine.


I spent some time writing interrupt code which saves the type of interrupt, return address and interrupt count to page zero variables so that I can print out interrupt details.  A separate subroutine can print this information out to the LCD on request.   For debugging spurious interrupts we only need capture a single interrupt so the interrupt processor has an option to print details within the interrupt and not return to the program.

With the capability to determine spurious interrupt details in place we are now more prepared to continue debugging xmodem.




Monday, 30 August 2021

6502 : Xmodem

 My 6502 system is working well but I still find the program upload process irritating.  I am probably being a diva about this as the old school method to remove, program, replace the EEPROM chip was very painful.   My programs are quite small but it takes time to compile them, transfer them to an Arduino sketch then run the sketch to copy the program to EEPROM.  For a 1KB program, which is quite large for my assembler programs but reasonable for C it can take a minute to process.

I have been thinking of trying to implement XMODEM for a while, it seems sensible to use the serial port session which will allow a transfer at 19200 baud, taking a few seconds for program download into RAM (not EEPROM).  6502.org provides a copy of Daryl Rictor's xmodem code so a couple of weeks ago I tried it out.  The code is intended for a 65C02 + ACIA 6551, the same as mine, and it is only a couple of hundred lines long so I thought I have a good chance of success.  I was a little nieve but that is the best way to start a long journey.

It was easy to download the program and tweak it to compile/load successfully.  However, on starting Xmodem nothing happened.  Not knowing the code or the protocol or having a tool to look at serial port traffic meant that debugging and experimentation were unsuccessful.

I found the modem protocol is quite simple so I wrote a C program under Windows WSL to download a test packet meaning that at least I had reasonable input.  I still couldn't get the example code working so I wrote my own version called xm.  After a while this worked fine, I could compile a program, start xm running and run my serial program to send the machine code. I excluded most of the modem error checking, particularly block number and CRC checks as we are transmitting at quite slow speeds down a 15cm cable.  The only downside is that I have to exit Putty to start the serial program downloading as they share the COM port; on completion I have to restart Putty.  This can be accomplished by means of a batch file loop but still it doesn't seem right.

In an effort to streamline this process I considered writing my own terminal emulator, from which I could easily start the transfer program.  Again I chose C under WSL as my development environment.  Configuring and using serial ports with C isn't terribly easy, some low level commands are required to setup the UART; as usual a good tutorial made this easy.  After that READ and WRITE statements can be used to fill/send buffers through the port.  Under Linux and WSL there isn't a function kbhit() to tell you if the user has pressed a key so I had to implement that myself based on Morgan Mcguire.  Although I could easily capture and display information from the 6502 and deal with keyboard input properly I couldn't get the two to work together seamlessly and I didn't complete this attempt.

On a whim I googled to see whether there are any software only (free) packages which can monitor the serial port.  It turns out there are a few, and Serial Port Monitor seemed a good choice.  The free version is old and not Windows 10 friendly so I used a demo of the paid version.  It is a shame it costs $100 so it is't something I would buy for a one-off problem.  The software is clever enough (using admin privilege) to share the serial port with Putty and after a few minutes learning I could see the serial port traffic.

Using Serial Port Monitor I could see that xmodem was sending a good packet to the 6502 but it was being NAKed by the 6502 and repeatedly resent.  My debugging focussed again on the sample code but I still couldn't get it working.  In particular, not all bytes were read in the ACIA port properly.  I tried all sorts of things to make it work, including slowing the transmission to 9600 or 4800, swapping my Arduino Nano controllable clock for the 1Mhz chip,  using RTS / CTS flow control with extra wires on the USBTTL connection, putting delays on the 6502 send characters which were being garbled.

Eventually I decided to write my own 6502 program, jmodem.  With my new understanding of modem and the structure of the sample code it was a simple job to write my own using subroutines I have previously written.  The only new feature is to read characters until no more come.  Xmodem sends a 128 byte buffer with 3 header characters, terminated by two CRC bytes.      It then stops and waits for ACK or NAK.  If any characters are lost there will be less than 133 characters in total.  Once I had this subroutine working with Putty terminal input remaining coding was easy.  The program initially accepted just one block, checked the number of bytes and transferred it to a fixed memory address.  It was then easy to loop round until an EOT byte was received.


Success is sweet.  I can now load programs into RAM quickly when I want to without exiting Putty using a standard technique.  Completed programs or subroutines can still be saved in ROM using the Arduino Mega but we no longer need it for normal development or system usage.





Thursday, 19 August 2021

Printing reports from Google in Landscape

I have a simple but very useful mariadb/mysql database for my art slideshow app and I use the excellent utility HeidiSQL to maintain it.  Mariadb doesn't have reporting capabilities which is a problem for me as I occasionally need to print lists of pictures.  It is, of course, possible to create and display queries and I can save these to a linux file.  However they need some formatting and importing them to Word, setting up the layout, checking it looks ok is a pain.  Exporting csv data and reading into Excel is a comon way of processing records, but I am not keen on writing Excel macros to do this.  I am sure there are lots of reporting packages I could use but that would be overkill.

I do have the capability to output a selection of records to a browser thanks to Tania Rascia's excellent tutorial.  I use the web query to update descriptions in the database associated with pictures so I thought it would be worthwhile to see whether I am able to print reports.  Usually printing from a web browser provides what you want but is messy due to screen formats being inappropriate but I thought some tailoring would be possible.

In fact it turns out to be a simple and effective solution.  Clearly we want to use CSS to reformat our web page for printing.  Using the @media CSS rule you can specify separate definitions for screen and print.  My first experiment was to display screen text as blue and printed text as green.
To test output just choose print in the browser and you see the print version of the report in print preview


After that we can write print specific CSS to ensure the report is in landscape mode and that instructions and unnecessary screen text are hidden.  I can also set up a print button on my screen.


A very satisfying solution to my problem.






Wednesday, 11 August 2021

Windows 10 Pro

Why

One of the good things about using RPis is that we can SSH into them remotely so it is easy to use multiple systems for different purposes with a single screen (or two) and keyboard.

I am planning to purchase a new PC but I am not looking forward to it  because of all the tasks involved in switching over from the old one.  It would be much simpler and satisfying to run old and new in parallel.  I could set up the new PC and transfer over important and frequently used applications and data.  There are lots of apps, data, configurations on the old one which I probably don't need and I could leave them in place initially.

Unfortunately running two Windows PCs with separate screens and keyboards is a pain.  They take up a lot of space and aren't convenient to use.  I could use KVM style screen / keyboard switch but good ones are expensive and I find them messy.

I could use TeamViewer, splash top  or VNC to access the old PC from the new one.  In the past I have found them a bit clunky but that is probably my lack of familiarity.  However I decided to try Microsoft Windows Remote Desktop which I would hope is well integrated.

How

To use RDP I need my existing Win10 PC to be running Win10 Pro.  Win10 Pro doesn't have many useful features but RDP and bit locker disk encryption are good.  

Buying direct from Microsoft is quite expensive but a quick Google showed me that there are plenty of third-party suppliers who can provide a product key for about £20.  These sites can be dodgy so I picked one called unitysoft, which has an office address and support available.  On purchase I received a product key and some straightforward instructions.

All you really have to do is change the product key in Settings > System >  About.
The computer then spends a couple of minutes reconfiguring existing software so you have Windows 10 Pro.  You can check this in Settings > System > About 😀😊😊

To access the PC remotely just download the Microsoft Remote Desktop app onto Macbook, iPad etc and connect to the system with your current userid and password.  If you are logged on locally you will be logged off.

So

This is wonderful, just what I always wanted.  I can install my new PC, transfer over what I want to it and leave the old box in the corner connected to network but without screen / keyboard.  If there is something I need over the next few months (and there will be) I can turn on the old PC and sort it out.

In the example below you see my lovely Macbook M1 with a Windows Remote Desktop.  Normally I would run it as a full screen, but this shows the Apple background and apps as well as the Windows desktop.  At the moment I am debugging a 6502 program with my board attached to the PC using a COM port.  I can sit in comfort with no cables or hardware attached attached to my Macbook and happily use Windows functions. Bliss.



Monday, 9 August 2021

6502: Download programs to RAM

 My current mechanism for loading programs onto 6502 is to use the Arduino Mega to download machine code to ROM.  Although this is a vast improvement on using an Eeprom programmer it is quite slow, particularly for C programs which tend to be larger.

It would be preferable to use the 6502 serial interface to download a compiled program to RAM where it cn be executed.  This is analagous to loading a program from disk into memory and running it.  I still expect to save completed programs and subroutines in ROM, but this scheme should make the development cycle easier.

Both Extraputty and TeraTerm provide xmodem transfers.  Daryl Rictor has provided a sample xmodem implementation for 6502 so I have the basic ingredients available to me.

My objective is to take a machine code / hex program from the PC, transmit via USB serial port to the ACIA 6551 then read it in to RAM where it can be executed.

Initial tests did not go well. I dont have the ability to log the character string that Extraputty / xmodem is sending or an understanding of the protocol or much idea of how the receive program works.  The trial and error method is somewhat doomed.

The xmodem protocol is intended to be simple to implement, a major factor in its long term popularity. 

 
Data is downloaded in 128-byte packets.
Each packet has a 3 byte header: <soh=0x01> <block number> <inverted block number>
There is also a 2 byte trailer containing a CRC code.
This makes a total of 133 bytes

The receiver sends a character 'C' to the sender to start transmission.
Sender responds with a packet (133 bytes) which the receiver acknowledges with <ACK>.
The receiver carries out block number and CRC checks, if they fail the receiver sends <NAK> instead of <ACK> and the sender retransmits.
This is repeated until all packets are sent, at which point the sender sends <EOT=0x04>

To simplify testing I wrote a C program on my PC which sens a single xmodem format packet to the 6502.  I was pleased to find that Windows/WSL allows me to use a PC COMnn port as /dev/ttySnn providing the program has sudo privileges.  It is a bit fiddly to configure the settings but straightforward if you have a good tutorial .  The completed program looks more complicated than it is. 

Unfortunately, even with a known test program I couldn't make xmodem work. My 6551 works fine but my system or ExtraPutty may be incompatible in some way with Daryl's xmodem example.

I then decided to write my own xmodem receiver.  I simply have to read in some data packets, in a known format, into RAM using my existing subroutine library and I have Daryl's example for hints and guidance.  As we are using a short local connection I can skip the error checking - if an error occurs I would just reload the program.

This approach is much more successful.  I can take an executable program, created using cc65 on the PC and transfer it to 6502 RAM.  After checking using the monitor that my first program was transferred successfully to RAM address $1000 I tried to run it but (of course!) it failed.  The program had originally been compiled to run at $8000.  Once I changed the .org statement to rectify this it ran fine.  I would include an  image but the test program just displays a '#' character and allows character input.

This is an excellent result.  Although there are currently a number of rough edges to smooth over we have a working solution.  It allows us to reduce reliance on the Arduino Mega and the expectation is that it will accelerate downloads and speed up my development cycle (which involves frequent program changes).

Wednesday, 21 July 2021

Nezha : creating an image

Debian 0.3 Image

I received a working Debian Image with my Nezha, which is great but its only provenance was that it came with the board and was built on 1st June, just before the boards were shipped.  On 10th June Wu Caesar, the main man, provided an "official" release Debian 0.3 which was built on 3rd June.

I struggled to burn it to an SD card as it wasn't in a standard image format.  The Telegram forum was vital to resolve this.  The readme.txt said that you need a utility "PhoenixSuit"  used by Allwinner to burn the image.  However, try as I might, I couldn't get PhoenixSuit 3.1.0 to work.  A Telegram post on 1st July provided a link to RVboards downloads; the RVboards SBC is identical to the Nezha.  The download site contained PhoenixCard 4.2.5 which is a much newer version of the image burning software.  I successfully burned Debian 0.3 images to both 64GB and 16GB SDcards.  After using PhoenixCard you can't reformat SD cards using Windows but it may be possible to fix with the PhoenixCard "restore" option.

The image has networking configured and boots into an LXDE GUI on the HDMI port.  Although slower than other Linux SBCs it was great to see it is a proper product.  GCC is ready for use so we are off to a great start.  In the following minor setup tasks I was most pleased that configuration activities were totally normal.

Debian 0.3 configuration

I want to run the system headless, so I set up a static address.  Systemd networking is used so there was a slightly different procedure, setting up a file /etc/systemd/network/lan0.network containing the static address details.  Once the static address is in place I can use SSH access and copy over an ssh-id file for autologin.

At first I wasn't sure if / how the console is configured as we dont have a boot config.txt file.  The board comes with a USBTTL cable and I found details for connections in the advert for the rvboard on AliExpress!  Once the serial cable is connected and started at 19200 baud we see the console startup which has much useful detail in it.

I could now change the run level using systemctl from graphical.target to multi-user.target.  Startup and shutdown are now significantly faster.

Debian 0.5 image

On 2nd July Pierce Andjelkovic kindly provided a Debian 0.5 image on Telegram.  Again I had a tortuous trial and error experience installing it. The instructions are in Chinese but Google translate does a great job in decoding the chinese character sequences.

The image is copied to an SD card using dd then adjusted using gdisk to delete the 6th and last partition.  I struggled to get gdisk to delete the partition on my 16GB disk and eventually found I could do it using my Nezha board, running Debian 0.3.  I also found that simply burning the image to a 32GB SD card is a lot easier, it doesn't need the partition to be deleted.

The same configuration tasks were completed for static IP (although I needed to edit the traditional /etc/network/interfaces) and runlevel.

Debian 0.5 software

I could use apt-get to upgrade software successfully and installed lighttpd as a simple webserver without difficulty.  This is great, we can assume that the usual debian functions work normally.

I wanted to use a samba client to access shares on other systems but cifs is apparently not included so I could not mount devices on other systems.  However I could install samba and configure local shares so that other systems can copy files on/off.

Having GCC native compilation available is wonderful so I quickly tested the hello world C program.  More importantly and exciting is that I can do native compilation of risc-v assembly programs.  Not knowing what risc-v instructions are or how to program isn't a problem.  With Google as my friend I was able to successfully compile and run a risc-v hello world program, amazing 😁

To learn assembly I purchased a book RISC-V Assembly Language by Anthony Dos Reis which was mentioned on Telegram forum.  It appears to provive a nice simple introduction so I am looking forward to it.