Friday, 21 August 2020

ESP32 + Joy-IT touch screen

 Intro

As I have said a number of times before Elektor is a great place to find introductory projects.  The January/February 2020 edition contains an article on attaching a Joy-IT touch screen to an ESP32.  The example provides a very neat interface to the Elektor Weather Station project and shows what it is capable of.  The system makes use of littlevGL an application by Gabor Kiss-Valose which does all the graphics and touch screen heavy lifting.  It works on linux and other platforms as well as ESP32 and appears to be coming a popular/standard product.  To make life simple I purchased the Joy-IT touch screen from Elektor and also, after a false start, purchased an ESP32 devkitC from eBay.

Installation

The Arduino IDE is used for this project.  After connecting and testing board connectivity with a blink program (set LED to GPIO 2) I needed to set up the ESP32_eSPI software and littlevgl and configure them.  There are 10 wires used in the interface, including power and SPI, so it isn't too complicated.  The Elektor article comes with the required libraries and configuration files as a download.  This made it easy to setup, I copied libraries and configuration files across as appropriate.  In addition to TFT and LVGL libraries, other libraries are included for MQTT, json and CRC32.

Testing

There is a basic TFT test in the TFT_eSPI examples so I compiled/uploaded and it displayed pretty colours and text.


I then took the Elektor Weather Station Example, set the "demo" flag and compiled it.  Very impressively out comes the Weather Station screen, complete with touch screen capability and demo data .


Conclusion


This is great as it provides examples of tabs, gauges, meters, labels and touch screen input.  It should be easy to modify for my own purposes.  As an extra it gives me a way in to using MQTT and JSON data on Arduino/ESP32.  It is an excellent introduction to a wonderful product which can be quite challenging.  The littlevgl software and Joy-IT screen can also be used on an RPI.  At first sight the ESP32 usage, utilising wifi to obtain data updates seems best.  Then the ESP32/screen only need to be switched on when in use and don't need to be near an RPI.


Friday, 7 August 2020

Bare Metal RPI: Dealing with files

 Intro

It is over a month since my last entry on bare metal programming.  At the time I was struggling to work out how to implement file access.  My programs could use terminal input/output and libraries, we had made a start on coding replacement for OS calls in syscalls.c.  This allows us to write programs which don't have storage requirements but this tends to limit application to mathematical type calculations, or perhaps text based games.

Searching through github for RPi bare metal sdcard i/o programs yields a few possibilities.  Chan has written FatFs, a filesystem module for small embedded systems, including ARM. John Cronin has written an RPI second stage bootloader which contains FatFs.  It uses file access to load  a program from disk, rather than having to set up a kernel.img file for each test.  I found it a little difficult to understand how to apply this.  Finally I settled on Marco Maccaferri's rpi bare metal repository.   Not only does he implement fileio but also has frame buffer and USB functions.  I decided to concentrate on Maccasoft initially.

Maccasoft investigation

 Maccasoft separates FatFs into a directory and implements RPI specific functions in a file emmc.c.  In fact he has done a grand job in setting up a kernel folder containing sub-folders for USB, FatFs and drivers for frame buffer, HDMI console, png images, Simple DirectMedia graphics, audio, GPIO and compression.  This is really what we are aiming for, a bare metal kernel, not dependent on linux, which allows us to write programs using a variety of drivers.

I started by testing the "template" application Maccasoft provided.  I ran make on the kernel folder, then make on the template folder and copied the resulting kernel.img to SDcard.  I connected an HDMI screen and a USB keyboard and booted.  Very impressively I get a low-res screen showing messages, the ability to type in and the ability to move the cursor around the screen. 

Optimistically I then ran make on the "abbaye des morts" game.  I had to change "uint" variables to "unsigned int" but  compilation was successful and I copied the image to SD card.  The game is excellent, a properly playable platform game with graphics and sound.  Marco has come up with a very good product.
 

Maccasoft File Access

At this stage I had made no further progress on file i/o as maccasoft doesn't seem to use fles although the template app does mount the SD card.  I looked at John Cronin's github and I was able to get it to read and write files in the root directory.

I then realised that Maccasoft has a reasonably complete syscalls.c with open/close/read/write functions implemented so I should be able to use standard fopen/fclose/fread/fwrite functions to use the SD card.

This proved to be the case we can open/close/read/write files in the root directory using standard C functions.  This is a big step forward for us.

Bootloader integration

David Welch's bootloader is indispensible for loading and testing new versions of programs.  It expects application programs to be loaded at 0x8000 and is itself loaded at 0x200000.  Maccasoft link script does load at 0x8000 and uses the space above for heap.  When we try to load a Maccasoft kernel.img using the bootloader it works fine.  This is great, we now have file access and a bootloader.

UART stdin/stdout

Maccasoft sets up a framebuffer to allow writing to an HDMI screen and configures USB for a keyboard input.  In fact I much prefer using a putty console for stdio.  I take my previous termio program and add uart_get and uart_put to main.c.  This is straightforward.  Now I add a function uart_init() and put all uart functions in uart.c so that I have added them to the kernel.  This also works fine.

Looking at syscalls.c we notice that the file pointers 0,1 and 2 which refer to stdin, stdout, stderr respectively are excluded from processing in _write and _read.  I add code to _write so that uart_putc or uart_puts is called if fp=1.  Now putchar, puts and printf all use UART output by default and I have a properly working stdout device.  This is great progress.

I have so far struggled to work out the details to make _read work for both character and string input so stdin is not fully working, but I wont worry about this for the moment as I can use uart_gets and ssprintf for stdin functions.

Summary

We have made great progress using Maccasoft's work.  We have working file access, standard output and (almost) standard input.  We have a working boot loader and a separate "kernel" to implement standard functions and drivers.  This gives us the capability to write a variety of standalone applications.  Maccasoft also provides us with a frame buffer, USB devices, audio, image processing and GPIO controls if we want them.

In fact I did try out USB drivers a bit further.  RPI mouse, USB stick and Ethernet interfaces are all correctly detected.  However Marco hasn't needed to progress them further. You could read a file sector or an ethernet frame but would have to write the higher levels yourself.  There is some discussion on the RPI forum. Rene Stange wrote the USPI RPI bare metal drivers and has gone further in his Circle  C++ bare metal OS project.