29,99 €
With the availability of free and open source C/C++ compilers today, you might wonder why someone would be interested in assembler language. What is so compelling about the RISC-V Instruction Set Architecture (ISA)? How does RISC-V differ from existing architectures? And most importantly, how do we gain experience with the RISC-V without a major investment? Is there affordable hardware available? The availability of the Espressif ESP32-C3 chip provides a way to get hands-on experience with RISC-V. The open sourced QEMU emulator adds a 64-bit experience in RISC-V under Linux. These are just two ways for the student and enthusiast alike to explore RISC-V in this book. The projects in this book are boiled down to the barest essentials to keep the assembly language concepts clear and simple. In this manner you will have "aha!" moments rather than puzzling about something difficult. The focus in this book is about learning how to write RISC-V assembly language code without getting bogged down. As you work your way through this tutorial, you'll build up small demonstration programs to be run and tested. Often the result is some simple printed messages to prove a concept. Once you've mastered these basic concepts, you will be well equipped to apply assembly language in larger projects.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 351
Veröffentlichungsjahr: 2022
RISC-V Assembly Language Programming Using ESP32-C3 and QEMU
●
Warren Gay
●This is an Elektor Publication. Elektor is the media brand of Elektor International Media B.V.PO Box 11, NL-6114-ZG Susteren, The NetherlandsPhone: +31 46 4389444
●All rights reserved. No part of this book may be reproduced in any material form, including photocopying, or storing in any medium by electronic means and whether or not transiently or incidentally to some other use of this publication, without the written permission of the copyright holder except in accordance with the provisions of the Copyright Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licencing Agency Ltd., 90 Tottenham Court Road, London, England W1P 9HE. Applications for the copyright holder's permission to reproduce any part of the publication should be addressed to the publishers.
●Declaration
The Author and Publisher have used their best efforts in ensuring the correctness of the information contained in this book. They do not assume, and hereby disclaim, any liability to any party for any loss or damage caused by errors or omissions in this book, whether such errors or omissions result from negligence, accident, or any other cause.
All the programs given in the book are Copyright of the Author and Elektor International Media. These programs may only be used for educational purposes. Written permission from the Author or Elektor must be obtained before any of these programs can be used for commercial purposes.
●British Library Cataloguing in Publication DataA catalogue record for this book is available from the British Library
●ISBN 978-3-89576-525-4 Print ISBN 978-3-89576-526-1 eBook
●© Copyright 2022: Elektor International Media B.V.Editor: Alina NeacsuPrepress Production: D-Vision, Julian van den BergElektor is part of EIM, the world's leading source of essential technical information and electronics products for pro engineers, electronics designers, and the companies seeking to engage them. Each day, our international team develops and delivers high-quality content - via a variety of media channels (including magazines, video, digital media, and social media) in several languages - relating to electronics design and DIY electronics. www.elektormagazine.com
Contents
Chapter 1 • Introduction
1.1. The Joy of the Machine
1.2. Assembler Language
1.3. Why RISC-V?
1.4. Base Instruction Sets Covered
1.5. Projects in this Book
1.6. What do you need?
1.6.1. ESP32-C3 Hardware
1.7. Assumptions About the Reader
1.8. Summary
Chapter 2 • ESP32-C3 Installation
2.1. ESP32-C3 Device
2.2. Manual Installation (Linux and MacOS)
2.3. Windows Install
2.4. Summary
Chapter 3 • Installation and Setup of QEMU
3.1. Linux/MacOS Platforms:
3.2. Windows
3.3. Installing QEMU on MacOS
3.4. Install QEMU on Devuan Linux
3.5. QEMU Package Search
3.5.1. Building QEMU on Linux
3.5.2. Basic Build Steps
3.5.3. Linux/MacOS Setup of Fedora Linux
3.5.4. Linux/MacOS Boot Fedora Linux
3.5.5. Linux/MacOS Boot Test
3.6. Installing QEMU on Windows
3.7. Summary
Chapter 4 • Architecture
4.1. Program Counter Register
4.2. Endianness
4.3. General Purpose Registers
4.4. Introducing Subsets
4.5. Register Specifics
4.5.1. No Flag Bits
4.5.2. Register x0 / Zero
4.5.3. Register x1 / ra
4.5.4. Register x2 / sp
4.5.5. Register x3 / gp
4.5.6. Register x4 / tp
4.5.7. Registers x5-x7 / t0-t2
4.5.8. Register x8 / s0 / fp
4.5.9. Register x9 / s1
4.5.10. Registers x10-x11 / a0-a1
4.5.11. Registers x12-x17 / a2-a7
4.5.12. Registers x17-x27 / s2-s11
4.5.13. Registers x28-x31 / t3-t6
4.5.14. Register Summary
4.6. Instruction Set Base Subsets/Extensions
4.7. ESP32-C3 Hardware:
4.8. QEMU RISC-V 64 Bit Emulator
4.9. RISC-V Privilege Levels
4.10. RISC-V is Huge
4.11. Summary
Chapter 5 • Getting Started
5.1. Memory Models & Data Types
5.1.1. RV32 Model
5.1.2. RV64 Model
5.2. The Impact of XLEN
5.3. First Exercise
5.3.1. The Main Program
5.3.2. Assembler Routine add3
5.3.3. Assembly Language Format
5.3.4. Pseudo Opcode .global
5.3.5. Pseudo Opcode .text
5.3.6. The add Opcode
5.3.7. Calling add3
5.3.8. RV64I Consideration
5.3.9. Running the Demonstration
5.4. First Exercise on ESP32-C3
5.5. Assembler Listings
5.5.1. ESP32-C3 Assembler Listing
5.5.2. Influencing Assembly Code
5.4.3. Objdump
5.6. Summary
Chapter 6 • Load and Store Memory
6.1. A Word About Word Sizes
6.2. Load Instructions
6.3. Load Program Example
6.4. The .data Section
6.5. Unsigned Values
6.6. Memory Alignment
6.7. Experiment
6.8. Immediate Values
6.9. The li Pseudo-Op
6.10. The addi Opcode
6.11. Pseudo-Op mv
6.12. Loads under RV64I
6.1.3 The .section Pseudo-Op
6.14. Storing Data
6.15. Review
6.16. RISC-V Assembler Modifiers
6.17. Summary
Chapter 7 • Calling Convention
7.1. Register Usage
7.2. Call Procedure
7.2.1. Opcode jal
7.2.2. Pseudo Opcode jr
7.2.3. Pseudo Opcode ret
7.2.4. General Call Procedure
7.2.5. Call to 32-bit Absolute Address
7.2.6. Revised Call Procedure
7.2.7. Concrete Call Example
7.2.8. Simple Call Experiment
7.2.9. Running in gdb
7.3. Argument Passing in Registers
7.4. The Stack
7.4.1. Prologue
7.4.2. Epilogue
7.4.3. Floating Point Arguments
7.4.4. A Big Call Experiment
7.5. Calling printf()
7.6. Summary
Chapter 8 • Flow Control
8.1. Branching Instructions
8.1.1. Unconditional Transfers
8.1.2. Conditional Branches
8.2. Shift Opcodes
8.3. ESP32-C3 Project
8.3.1. Function c_ones()
8.3.2. Main Test Program
8.3.3. Assembler Function ones()
8.4. Compare and Set
8.5. Odd Parity Example
8.6. RV64I Odd Parity
8.7. Position Independent Code
8.8. Summary
Chapter 9 • Basic Opcodes
9.1. Arithmetic Opcodes
9.1.1. add, addi and sub
9.1.2. lui
9.1.3. auipc
9.1.4. RV64 Arithmetic
9.2. Logical Opcodes
9.3. ESP32-C3 Rotate Left
9.4. RV64 Rotate Left
9.5. ESP32-C3 Rotate Right
9.6. Pseudo Opcodes
9.7. Unsigned Multi-precision Arithmetic
9.8. Signed Multi-precision Arithmetic
9.8.1. Signed Overflow
9.9. Summary
Chapter 10 • Multiply / Divide
10.1. Multiplication Operations
10.2. Division Operations
10.3. Opcode mul/mulu
10.4. Opcode mulhs/mulhu
10.5. Optimized Multiply
10.6. Unsigned Factorial
10.7. Opcode div/divu
10.8. Optimized Divide
10.9 Division By Zero
10.10 Divide Overflow
10.11 Safe Division
10.12. Greatest Common Divisor
10.13. Combinations
10.14. Summary
Chapter 11 • Addressing, Subscripting and Strings
11.1. Testing for Null Pointers
11.2. Sizeof Type for Pointers
11.3. Matrix Memory Layout
11.3.1. Subscript Calculation
11.4. Identity Matrix Example
11.5. String Functions
11.5.1. Function strlen()
11.5.2. Function strncpy32()
11.5.3. String to Integer Conversion
11.5.4. What if there is no Multiply?
11.5.5. Integer to String Conversion
11.6. Indexed Branching
11.7. Summary
Chapter 12 • Floating Point
12.1. Floating Point Registers
12.2. GNU Calling Convention
12.3. Floating-Point Control and Status Register (fcsr)
12.3.1. Rounding Modes fcsr.frm
12.3.2. Accrued Exception Flags fcsr.fflags
12.4. NaN Generation and Propagation
12.5. Opcodes and Data Formats
12.6. Load and Store
12.7. Floating Computation
12.8. Conversion Operations
12.8.1. Floating-Point Zero
12.8.2. Conversion Failures
12.9. Floating-Point Signs
12.10. Floating-Point Move
12.11. Floating-Point Compare
12.12. Classify Operation
12.13. Fahrenheit to Celsius Revisited
12.14. Summary
Chapter 13 • Portability
13.1. C/C++ Pre-Processor
13.2. Testing for RISC-V Architecture
13.3. Testing For Integer Multiplication
13.4. RV32 vs RV64
13.5. Assembler Macros
13.6. Summary
Chapter 14 • Determining Support
14.1. Privilege Levels
14.1.1. Machine Level
14.1.2. Supervisor Level
14.1.3. User Level
14.2. Control and Status Registers
14.2.1. Machine ISA Register
14.3. Opcodes
14.4. ESP32-C3
14.5. Reporting MISA
14.6. RV64 Platform
14.7. Counters
14.7.1 Project rdcycle
14.7.2. ESP32-C3 rdcycle Support
14.8. Summary
Chapter 15 • JTAG Debugging
15.1. Espressif JTAG
15.2. Device Requirements
15.3. Software Components
15.4. JTAG With No Serial Window
15.4.1. Starting OpenOCD
15.4.2. Problems with OpenOCD
15.4.3. Terminating OpenOCD
15.4.4. Start gdb
15.5. Operating gdb
15.5.1. Abbreviations
15.5.2 GDB Walkthrough
15.5.3. Quitting gdb
15.6. JTAG With a Serial Window
15.6. Miscellaneous
15.7. Summary
Chapter 16 • Inline Assembly
16.1. Keyword Asm
16.2. Basic asm Form
16.2.1. Keyword volatile
16.2.2. Multiple Instructions
16.2.3. Behind the Scenes
16.3. Extended Asm
16.3.1. Assembler Template
16.3.2. Output Operands
16.3.2.1. Constraint
16.3.3. Input Operands
16.3.3.1. Clobbers
16.4. Bit Multiply
16.5. Example asm goto
16.6. Register Constraints
16.7. Summary
Chapter 1 • Introduction
Introducing.... RISC-V!
With the availability of free and open-source C/C++ compilers today, you might wonder why someone would be interested in assembler language. What is so compelling about the RISC-V Instruction Set Architecture (ISA)? How does RISC-V differ from existing architectures? And most importantly, how do we gain experience with the RISC-V without a major investment? Is there affordable hobbyist hardware available?
The availability of the Espressif ESP32-C3 chip provides a student with one affordable way to get hands-on experience with RISC-V. The open-sourced QEMU emulator adds a 64-bit experience in RISC-V under Linux. These are just two ways for the student and enthusiast alike to explore RISC-V in this book.
1.1. The Joy of the Machine
In the earliest days of computing, there was great enthusiasm in working out the mechanical steps required to perform some computation or algorithm. The programmer was aware of every machine cycle, status bit and register available to him as resources to be exploited. In those early times debugging was often performed on a console decorated with lamps, buttons and switches. There was always great satisfaction in getting it right and making it run even faster than before.
I fear that today, we've lost some of that passion for exploiting the machine. Our CPU tower might possess only a power-on button and LED. But if we're lucky, it might provide a disk activity LED as well. Embedded systems are better, sporting multiple LEDs that can be utilized. Whether desktop or embedded device, we still program in high-level languages like C/C++. While there is still joy in that, the thrill of the hunt may be lacking for those thirsting for more. Getting that algorithm to execute even faster or more efficiently is not just a badge of honor, but a matter of pride.
One deterrent to assembly language has been the extremely cluttered instruction sets of today's architectures. The Intel and AMD instructions sets, for example, have been horribly extended in the name of compatibility. RISC-V allows the enthusiast to sweep all that clutter aside and start over with a clean slate. This makes things so much easier because there is less to be learned.
Getting back to assembler language will bring back that thrill of the hunt that you may be pining for. At the assembly level, the programmer directs every step of the machine. You decide how the registers are allocated and apply every binary trick in your toolbox to make that process slick. While we don't have hardware debug consoles anymore, we do have powerful debugging tools like the GNU gdb debugger. There's never been a better time to do assembly language than today.
1.2. Assembler Language
It might seem counterproductive to program in assembly language. While C/C++ languages will continue to be used for productive development, there frequently remain opportunities for optimizing code at the machine level. In these areas, you will be empowered to exploit the machine in otherwise difficult ways.
One attractive area is writing custom floating-point algorithms in assembly language. For each calculation, you can carefully evaluate which rounding method to use and check for special exception cases at strategic places in the code. In C/C++, the tendency is to simply code the formula.
Even if you decide that you have no need to write assembly language code, being able to read it can be extremely helpful when debugging. Compilers, often at higher optimization levels, can generate incorrect code (this happens more often than you think). Being able to verify that the generated code is correct can save you from a great deal of guessing when debugging. With a working knowledge, you can step through the code one instruction at a time in a debugger and pinpoint the problem. Once the problem is revealed, you can then decide on a work-around for the compiler or replace the errant code directly with some assembler language code.
In microcomputer solutions, performance is often paramount. Assembler language programming provides more options for meeting those performance goals. Finally, it is possible that one day RISC-V may become one of the few standard instruction sets in general use.
1.3. Why RISC-V?
Probably its most attractive feature is that it is designed to be free and open so that it is not hindered by restrictive licensing. This permits any manufacturer to create a RISC-V product without purchasing an expensive or restrictive license.
The RISC-V instruction set is also designed to be clean, unlike many existing architectures. Today's Intel ISA is a bewildering mess of adapted and extended instructions. To be fair, this was done to maintain code compatibility, but what a bewildering mess it has become. Now that security is more important than ever, there is a pressing need for a simpler design.
Reduced Instruction Set Computer (RISC) architecture had its beginnings in research projects conducted by John L. Hennessy at Stanford University between 1981 and 1984. MIPS (Microprocessor without Interlocked Pipeline Stages) was developed with the IBM 801 and the Berkeley RISC projects. The Berkeley RISC project was led by David Patterson who coined the term RISC. The thrust of these efforts was to develop a design that was simpler and potentially faster than the CISC (Complex Instruction Set Computers) of that time.
Today, simplicity benefits the chip manufacturer in lowering the cost of chip development and verification. Simplicity means fewer transistors, which leads to lower power requirements. A simple instruction set also reduces the complexity that the software developers must face. Finally, the RISC-V ISA has provision to include vendor extensions, without requiring any special approval. This can lead to surprising innovations.
1.4. Base Instruction Sets Covered
RISC-V is now a large body of work. In chapter 4, Architecture, I'll discuss base instruction sets and extensions to RISC-V. The focus of this book, however, will be on the RV32 and RV64 subsets of RISC-V. This permits an ample study of the ESP32-C3 device (RV32) as well as Fedora Linux under QEMU (RV64). These two environments should provide the reader with a well-rounded tutorial.
1.5. Projects in this Book
In many books applying MCU (Microprocessor Computing Units) concepts, the project builds are the focus. In them, the emphasis is placed on using GPIO (General Purpose Input/Output), I2C, SPI and other built-in peripherals to build something fun.
This book has a different focus, but it is still fun! The projects in this book are boiled down to the barest essentials to keep the assembly language concepts clear and simple. In this manner, you will have "aha!" moments rather than puzzling about something difficult. The focus of this book is on learning how to writeRISC-V assembly language code without getting bogged down. As you work your way through this tutorial, you'll build up small demonstration programs to be run and tested. Often the result is some simple printed messages to prove a concept. Once you've mastered these basic concepts, you will be well equipped to apply assembly language in larger projects.
1.6. What do you need?
This book uses the Espressif ESP32-C3 dev kit device for hardware. You will also emulate RISC-V in 64-bit mode using the QEMU emulator on your desktop computer. The emulator requires that you have at least 20 GB of free disk space available. For both of the ESP-IDF (ESP Integrated Development Framework) and QEMU instances, an internet connection for downloading is assumed.
A suitably modern desktop computer is required to program the ESP32-C3 and to run the QEMU emulator, running Fedora Linux. If you lack 20 GB of free disk space, then that can be remedied by plugging in a USB hard drive to add some disk space.
1.6.1. ESP32-C3 Hardware
When purchasing hardware for use with this book, be sure to acquire the correct device type. The original ESP32 devices used the Xtensa processor and are not RISC-V devices. At the time of writing there are several types of ESP32:
ESP32 (Xtensa dual-core and single-core 32-bit LX6 microprocessor)ESP32-S2 (Single-core Xtensa LX7 CPU)ESP32-S3 (Dual-core Xtensa LX7 CPU)ESP32-C3 Single-core 32-bit RISC-V (WiFi 2.4 Ghz IEEE 802.11b/g/n)ESP32-C6 Single-core 32-bit RISC-VThis book was developed specifically with the Espressif ESP32-C3 device (emphasis on the "C3").
When purchasing, don't make the mistake of just buying just a chip. Be sure to purchase a "devkit" that consists of a PCB with the GPIO breakouts, USB interface and the ESP32-C3 chip soldered onto it. You might also find it listed as "ESP-C3", but be careful. Make sure this refers to the ESP32-C3, and not some other ESP32 variants (using the Xtensa CPU). You'll also need an appropriate USB cable to flash and communicate with the devkit. The projects in this book can run off of the power from the USB cable.
Figure 1.1 illustrates an early ESP32-C3 dev board purchased from AliExpress. This version 1 dev board cannot support JTAG. Notice that these use a USB to serial interface chip (CH340C), which can be seen in the photo. If you aren't concerned about JTAG support, then these are otherwise suitable to use.
Figure 1.1: An early version 1 dev board. Note the USB to serial chip just right of the micro USB connector.
As time went on, Espressif came out with ESP32-C3 devices with JTAG support (version 3 or later). Since these connect directly from the ESP32-C3 chip to the USB port, they don't use a serial to USB converter chip. This makes it easy to identify the boards that support JTAG. With a direct connection to the USB bus, the ESP32-C3 can perform JTAG functions over the USB bus, as well as the usual serial communications. These are the preferred ESP32-C3 devkits to obtain. Figure 1.2 illustrates a JTAG-capable ESP32-C3 dev board sitting on a breadboard.
Figure 1.2: A revision 3 ESP32-C3 dev board supporting JTAG access.
1.7. Assumptions About the Reader
The reader is assumed to have a basic understanding of what a CPU is, what registers are and the rudiments of computer memory. Assembler language and debugging require knowledge of number systems, specifically binary and hexadecimal. The reader should also be familiar with endianness. Knowing how big-endian ordering differs from little-endian will be helpful.
The reader is expected to be familiar with basic file system navigation: changing directories, creating directories and copying files. In some cases, the editing of a script file may be necessary. The Windows user should also be familiar with the Linux file system in this regard when using QEMU (emulating Fedora Linux).
Knowledge of the C language is assumed. Code examples will consist of a C language main program calling an assembly language function.
The QEMU examples use a RISC-V version of downloadable Fedora Linux. Consequently, some familiarity with the Linux command line is an asset even for Windows users. The ESP32-C3 examples will use your native desktop environment for ESP development, whether Linux, MacOS or Windows. In all cases, simple commands are issued to build and run the test programs.
Finally, the reader is expected to do some software downloading and installation. Unfortunately, there is a fair amount of this initially, but the good news is that it is all free and open software. Once installed, the reader can then focus on the RISC-V concepts presented in this book.
1.8. Summary
The next pair of chapters deal with installing your ESP-IDF (ESP Integrated Development Framework) and the QEMU emulation software. This bit of work is necessary to let the good times roll. So gather your disk space and enable your internet access and begin!
Bibliography
[1] The_RISC-V_Reader_An_Open_Architecture_Atlas_by_David_Patterson_Andrew_Waterman.pdf
Chapter 2 • ESP32-C3 Installation
ESP32-C3 celebrates RISC-V
This chapter illustrates the steps necessary to get you up and running using the ESP32-C3 device. The first part of this chapter focuses on Linux and MacOS software installations. This is what Espressif calls "Manual Installation". Espressif also supports IDE installations for Eclipse or VSCode if you prefer. See their online documentation for that.
Windows users will want to skip to the later part of this chapter starting with the section heading "Windows Install". This will guide you through the use of the downloaded Espressif windows installer.
For either installation, you will need to plan for ample disk space and be connected to your internet. The ESP-IDF on the Mac (for device ESP32-C3 only) requires about 1.5 GB of disk. But the compilers and other tools will also require additional disk space as they are installed. I recommend that you allocate a minimum of 10 GB of free disk space before you proceed. The downloads are rather large and will take some time to complete. Choose a time to install where you are not rushed.
2.1. ESP32-C3 Device
Espressif markets and sells several devices under the ESP32 moniker, so make sure you purchase the correct device in order to enjoy RISC-V adventures. If your part says ESP32 but not C3, it is not the RISC-V version of the CPU.These devices are also sold as bare modules. So be sure to get a "dev kit" form of the product. One product that I am using is a ESP32-C3-DevKitM-1 clone. By the time you read this there may be newer versions of the ESP32-C3-DevKit and those are likely your best option.
Dev kits may include a USB to serial chip (USB-UART bridge) like the CP2102. My devices used the CHG340 chip. Either bridge chip is ok, since we are only interested in the RISC-V CPU in this book. Now you can purchase dev kits with JTAG support. These devices with revision 3 or later use the USB facilities directly. Figure 2.1 illustrates two early examples of revision 1 dev boards. The CH340C USB to serial converter chip is very conspicuous.
Figure 2.1: Two ESP32-C3 devices with revision 1 PCBs (using USB to serial converters).
2.2. Manual Installation (Linux and MacOS)
Locate the Espressif "Get Started" web page. If the website doesn't change too much, you should be able to arrive there directly using the following url:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html
Otherwise search for "ESP-IDF Programming Guide" with your browser.
Once you arrive at that page, don't forget to choose the product type ESP32-C3 in the upper left. Espressif supports multiple device types, and we are primarily interested in the ESP32-C3 with RISC-V support. It should look something like Figure 2.2.
Figure 2.2: Set the device selection as ESP32-C3.
Scroll down the page until you see the link "Linux and MacOS". Click on the link to open a new page of instructions.
Linux and MacOS
On this page you will be guided through the following basic steps:
Install Prerequisites.Get ESP-IDF.Setup the tools.Set up the environment variables.First Steps for ESP-IDF.Note: If the instructions differ at all from this text, do follow the instructions found on the website instead. Espressif may have made changes to the installation procedure by the time you read this.
Install Prerequisites
The prerequisites will vary somewhat with the Linux distribution you're using. Check the Espressif website for the latest updates by distro.
Ubuntu and Debian
For these distributions, the following packages should be installed (some may already be installed):
$ sudo apt install git wget flex bison gperf python3 python3-pip \
python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev \
dfu-util libusb-1.0-0
You might wish to split these up into smaller steps, like the following:
$ sudo apt install git wget
$ sudo apt flex bison
$ sudo apt gperf python3
$ sudo apt python3-pip python3-setuptools
$ sudo apt cmake ninja-build
$ sudo apt ccache libffi-dev
$ sudo apt libssl-dev dfu-util libusb-1.0-0
CentOS 7 & 8
CentOS uses the yum installer, and the dependencies are listed as follows:
$ sudo yum -y update && sudo yum install git wget flex bison gperf \
python3 python3-pip python3-setuptools cmake ninja-build ccache \
dfu-util libusbx
Arch
Espressif has documented the following dependencies for the Arch distro:
$ sudo pacman -S --needed gcc git make flex bison gperf python-pip \
cmake ninja ccache dfu-util libusb
Espressif notes that CMake version 3.5 or newer is required. If you're running an older distribution, you may need to update your system packages. For other Linux distributions not listed here, use the above as a hint to the package names that you may need to add or update.
MacOS
MacOS users usually install HomeBrew (recommended) or the MacPorts open-source projects to add functionality to their Mac. If you've not done that yet, you need to do that now. Refer to the following sites for more information about this:
https://brew.sh/ (HomeBrew)
https://www.macports.org/install.php (MacPorts)
Whether you use HomeBrew or MacPorts, you must install pip:
$ sudo easy_install pip
Next, CMake and Ninja are installed. For HomeBrew install:
$ brew install cmake ninja dfu-util
For MacPorts users, use:
$ sudo port install cmake ninja dfu-util
Espressif recommends that you also install ccache for faster build times. For HomeBrew, use:
$ brew install ccache
For MacPorts use:
$ sudo port install ccache
Note: Espressif indicates that if during the installation you encounter an error like the following:
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrunThen you will need to install the Apple XCode command line tools in order to continue. Install these with:
$ xcode-select --install
MacOS Python 3
Check the version of python you have installed with:
$ python --version
If it is a version older than 3, or is not present, then check the following (notice that the command name is python3 this time):
$ python3 --version
If that fails, then you need to install it. For HomeBrew:
$ brew install python3
For MacPorts:
$ sudo port install python38
Get ESP-IDF
At this point, you need to decide where to place your ESP-IDF software (not as root). I'm going to assume in this book, that the directory will be named ~/espc3, where the tilda (~) represents your home directory. You can choose a different directory name, by simply substituting ~/espc3 for the name you prefer.
First, create the subdirectory to house your files in (starting from your home directory):
$ mkdir -p ~/espc3
and then change to it:
$ cd ~/espc3
Now access the files from GitHub by performing:
$ git clone --recursive https://github.com/espressif/esp-idf.git
This git operation downloads several files and will take some time to complete. It is also a good opportunity to take a break for your favourite beverage.
When the git operation completes, you will have the Espressif software downloaded into the subdirectory ~/espc3/esp-idf.
Setup the Tools
Now we need to install some tools used by the ESP-IDF framework, like the compiler and Python packages.
$ cd ~/espc3/esp-idf
$ ./install.sh esp32c3
Performing this step will result in more files being downloaded and installed. This step progresses much faster than the GitHub clone operation but can still require some time. Perhaps your beverage needs a refill?
At the end of this installation, you might encounter a message like:
WARNING: You are using pip version 21.2.1; however, version 22.0.3 is available.
You should consider upgrading via the
'~/.espressif/python_env/idf5.0_py3.9_env/bin/python -m pip install --upgrade pip' command.
This is optional, but I chose to do it.
At the end of the installation, your session should have completed with the message:
All done! You can now run:
$ . ./export.sh
At this point, you should run this script and watch for any error messages. Some errors you might see may include:
ERROR: tool xtensa-esp32-elf has no installed versions. Please run '/Users/joe/espc3/esp-idf/install.sh' to install it.
ERROR: tool xtensa-esp32s2-elf has no installed versions. Please run '/Users/joe/espc3/esp-idf/install.sh' to install it.
ERROR: tool xtensa-esp32s3-elf has no installed versions. Please run '/Users/joe/espc3/esp-idf/install.sh' to install it.
In other words, these messages complain about missing support for:
• xtensa-esp32-elf
• xtensa-esp32s2-elf
• xtensa-esp32s3-elf
If you're only concerned about our ESP32-C3 device, which was not listed in error, you can ignore these messages. If you also want to support these other devices (regular ESP32, ESP32-S2 and ESP32-S3), you can follow the Espressif advice and run the installation scripts suggested.
Setup Environment Variables
To run the Espressif tools to build your projects some environment changes must be applied each time you login. In a fresh terminal session, you would need to do the following. Make sure that you type a space between the dot and the rest of the pathname:
$ . ~/espc3/esp-idf/export.sh
Assuming that no critical error messages are reported, this sets up your terminal session to build your ESP projects. Some users may wish to create a shorter way to do this. Espressif recommends creating an alias like get_idf as follows:
$ alias get_idf='. $HOME/espc3/esp-idf/export.sh'
Once that alias is defined, you can just type:
$ get_idf
to establish your build environment. Depending upon the shell you use for your terminal session, you might want to set the get_idf alias up in your ~/.profile or ~/.bashrc file, so that it is automatically defined each time you login.
Once that export.sh script has run, your environment will have the variable IDF_PATH set. In this chapter, it would have the value "~/espc3/esp-idf". This allows you to use the shell value $IDF_PATH in commands and scripts if you like.
First Steps for ESP-IDF
The installation procedure has covered a lot of ground so let's test it. Change to the example subdirectory shown:
$ cd $IDF_PATH/examples/get-started/hello_world
(or)
$ cd ~/espc3/esp-idf/examples/get-started/hello_world
Configure the Target Device
In order to build for the ESP32-C3 device, we need to tell the build framework about it:
$ idf.py set-target esp32c3
Build Example hello_world
This step adjusts the environment so that it knows that it is compiling for our RISC-V device (ESP32-C3). Now test the build process:
$ idf.py build
The first time this runs for a given project, it will compile a lot, but don't be concerned. Subsequent builds will not take so long. When it succeeds, the process should end with a message:
Project build complete. To flash, run this command:
....snip....
or run 'idf.py -p (PORT) flash'
Flash the Device
Before we can flash your RISC-V (ESP32-C3), we need to find out what port it appears on when you plug its cable into a USB port. But before you plug in your device's USB cable, list the cu devices under /dev as follows:
$ ls /dev/cu*
/dev/cu.Bluetooth-Incoming-Port /dev/cu.usbserial-0001
This will list some that are already present. Don't be concerned if no devices show up. Now plug in your RISC-V device's USB cable and list the files again:
$ ls /dev/cu*
/dev/cu.Bluetooth-Incoming-Port /dev/cu.usbserial-0001 /dev/cu.usbserial-1430
n this example, the device /dev/cu.usbserial-1430 was added. This is the device name we need for flashing our device. Define it in the shell variable named PORT, so that you won't have to type it each time:
$ PORT=/dev/cu.usbserial-1430
$ export PORT
To flash the example program to your device, try it now (the example output has been abbreviated somewhat):
$ idf.py flash
Executing action: flash
Serial port /dev/cu.usbserial-1430
Connecting....
Detecting chip type... ESP32-C3
Running ninja in directory /Users/joe/espc3/esp-idf/examples/get-started/hello_world/build
Executing "ninja flash"...
...
Chip is ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: 7c:df:a1:b4:44:94
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00004fff...
Flash will be erased from 0x00010000 to 0x00034fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Compressed 19984 bytes to 12116...
Writing at 0x00000000... (100 %)
Wrote 19984 bytes (12116 compressed) at 0x00000000 in 0.7 seconds (effective 221.1 kbit/s)...
Hash of data verified.
Compressed 151072 bytes to 81515...
Writing at 0x00010000... (20 %)
Writing at 0x00019a2e... (40 %)
Writing at 0x00020360... (60 %)
Writing at 0x00027602... (80 %)
Writing at 0x0002dada... (100 %)
Wrote 151072 bytes (81515 compressed) at 0x00010000 in 2.7 seconds (effective 443.9 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 103...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 262.5 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Done
If your session appeared similar to this, then congratulations are in order. You have flashed your first RISC-V program to the device.
Running hello_world
To see the hello_world program run, we monitor it as follows:
$ idf.py monitor
$ idf.py monitor
Executing action: monitor
Serial port /dev/cu.usbserial-1430
Connecting....
Detecting chip type... ESP32-C3
Running idf_monitor in directory /Users/joe/espc3/esp-idf/examples/get-started/hello_world
...
--- idf_monitor on /dev/cu.usbserial-1430 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x1750
load:0x403ce000,len:0x930
load:0x403d0000,len:0x2d3c
entry 0x403ce000
I (30) boot: ESP-IDF v5.0-dev-1730-g229ed08484 2nd stage bootloader
I (30) boot: compile time 19:50:12
I (30) boot: chip revision: 3
I (33) boot.esp32c3: SPI Speed : 80MHz
I (38) boot.esp32c3: SPI Mode : DIO
I (43) boot.esp32c3: SPI Flash Size : 2MB
I (48) boot: Enabling RNG early entropy source...
I (53) boot: Partition Table:
I (57) boot: ## Label Usage Type ST Offset Length
I (64) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (71) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (79) boot: 2 factory factory app 00 00 00010000 00100000
I (86) boot: End of partition table
...
I (145) boot: Loaded app from partition at offset 0x10000
I (148) boot: Disabling RNG early entropy source...
I (165) cpu_start: Pro cpu up.
I (173) cpu_start: Pro cpu start user code
I (173) cpu_start: cpu freq: 160000000 Hz
I (173) cpu_start: Application information:
I (176) cpu_start: Project name: hello_world
I (182) cpu_start: App version: v5.0-dev-1730-g229ed08484
I (188) cpu_start: Compile time: Mar 1 2022 19:50:05
I (194) cpu_start: ELF file SHA256: d4ad172e8078f033...
I (200) cpu_start: ESP-IDF: v5.0-dev-1730-g229ed08484
I (207) heap_init: Initializing. RAM available for dynamic allocation:
I (214) heap_init: At 3FC8C540 len 00033AC0 (206 KiB): DRAM
I (220) heap_init: At 3FCC0000 len 0001F060 (124 KiB): STACK/DRAM
I (227) heap_init: At 50000020 len 00001FE0 (7 KiB): RTCRAM
I (234) spi_flash: detected chip: generic
I (238) spi_flash: flash io: dio
I (242) sleep: Configure to isolate all GPIO pins in sleep state
I (249) sleep: Enable automatic switching of GPIO sleep configuration
I (256) cpu_start: Starting scheduler.
Hello world!
This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision 3, 2MB external flash
Minimum free heap size: 328924 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
After the device boots up, you will see the message "Starting scheduler". The next message shown is the "Hello world!" that we were waiting for. Then the program counts down and will reboot again until you terminate it. To stop monitoring, type Control-] (control plus the right square bracket) and you should be returned to your shell. Congratulations, you ran your first RISC-V program!
2.3. Windows Install
While it is possible to install the Windows Subsystem for Linux (WSL and WSL2) on Windows 10 and later, you may not be able to get the Linux USB access to work with the ESP32-C3 device. For this reason, I'll document the native Windows install procedure as provided by Espressif. Espressif provides the install documentation here:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/windows-setup.html
Limitations
Espressif lists the following limitations:
The installation path of ESP-IDF and ESP-IDF Tools must not be longer than 90 characters.From their web page:
[Installation paths that are too long] might result in a failed build. The installation path of Python or ESP-IDF must not contain white spaces or parentheses. The installation path of Python or ESP-IDF should not contain special characters (non-ASCII) unless the operating system is configured with "Unicode UTF-8" support.
System Administrator can enable the support via Control Panel. Change date, time, or number formats - Administrative tab - Change system locale - check the option "Beta: Use Unicode UTF-8 for worldwide language support" - Ok and reboot the computer.
ESP-IDF Tools Installer
Look for and click on the link "Windows Installer Download" provided on their website". Make certain that you have selected ESP32-C3 from the top left drop down of the ESP-IDF Programming Guide web page. At the time of writing, this downloads from:
https://dl.espressif.com/dl/esp-idf/?idf=4.4
They provide several different installers, which at the time of writing include:
Universal Online Installer 2.13 for Windows 10, 11, size 4 MBEspressif-IDE 2.4.2 with ESP-IDF v4.4 for Windows 10, 11, size 1 GBESP-IDF v4.4 Offline Installer for Windows 10, 11, size 600 MBESP-IDF v4.3.2 Offline Installer for Windows 10, 11, size 570 MBESP-IDF v4.2.2 Offline Installer for Windows 10, 11, size 376 MBESP-IDF v4.1.2 Offline Installer for Windows 10, 11, size 353 MBIn this guide, I've chosen the Universal Online Installer. Once the installer has been downloaded and launched, you'll be prompted to "Select Setup Language", which will be "English" by default.
Next is the "License Agreement", where you want to click "I accept the agreement" and then click the "Next" button.
The installer does a "Pre-installation system check". If there were any warnings, click the "Apply Fixes" button. Likely it will complain that you need Administrator access, which the "Apply Fixes" button will correct. Once all is good, click on the "Next" button.
The next dialog "Download or use ESP-IDF" asks you to choose one of:
Download ESP-IDF.Use an existing ESP-IDF directory.Choose "Download ESP-IDF" and click the "Next" button.
In the "Version of ESP-IDF" dialog, choose the version of the software to download. At the time of writing, the most current version was v4.4 (release version). It is probably best to choose the latest version available. Click the "Next" button.
In the "Select Destination Location" dialog, you are asked where you want the software to be installed. By default, the text "C:\Espressif" is used. If you need it on another drive or a different directory, this is where you can choose it. Click the "Next" button.
In the "Select Components" dialog, you are presented with a tree of checkboxes. The one area that you might want to deliberate is the "Chip Targets", where it lists the following choices:
ESP32 (optional)ESP32-C3 (make sure this remains checked for RISC-V)ESP32-S Series:ESP32-S2 (optional)ESP32-S3 (optional)If you need to save disk space, then unselect the optional items listed above. Make certain however that ESP32-C3 remains checked. Click the "Next" button.
At this point, the "Ready to Install" dialog box appears with a summary of your choices so far. If the summary appears okay, then click the "Install" button.
If any prompt presents a "Do you want to allow this app to make changes to your device?" question, then answer with a click on the "Yes" button.
You will also get prompts from "Windows Security" to the effect "Would you like to install this device software?". Click on the "Install" button.
The software will then download and install for a considerable amount of time. Later on, the "Installing ESP-IDF tools" dialog will appear towards the end. If you're feeling a craving for coffee or tea, this would be a great time to make it. The download and installation may take about 45 minutes depending upon your system and internet.
After the above is completed, you are presented with a "Completing the ESP-IDF Tools Setup Wizard" dialog. I suggest you leave all the options checked and click the "Finish" button. Click on "Yes" if you are prompted with "Do you want to allow this app to make changes to your device?".
Once all that has been completed, you should have two more start menu options:
ESP-IDF 4.4 CMDESP-IDF 4.4 PowerShellas shown in Figure 2.3 (yours may differ slightly).
Figure 2.3: The created ESP-IDF startup links in the start menu.
Now it is time to test your installed ESP-IDF on a provided example program.
Windows First Steps on ESP-IDF
Using the ESP-IDF PowerShell (or CMD), let's use a test project to test the software with. When you start your shell, it will place you into a directory that depends upon your install choices. The prompt that I got was:
PS C:\Espressif\frameworks\esp-idf-v4.4>
In the text that follows, I will just show "PS C:>" as the prompt. Now change to the hello_world subdirectory:
PS C:> cd examples
PS C:> cd get-started
PS C:> cd hello_world
Choose your target device type by executing the following command:
PS C:> idf.py set-target esp32c3
his configures the build for this project to compile for your RISC-V device. Once that completes, you can build your hello_world software:
PS C:> idf.py build
The first time you build your project a lot of compiling of dependencies will occur. On successive builds however, the process only rebuilds what is needed and is much faster. If all went well, the command should complete with the message:
Project build complete. To flash, run this command:
...
or run 'idf.py -p (PORT) flash'
ow we must discover the name of your USB device when the ESP32-C3 is plugged in. Open the Device Manager and expand the "Ports (COM & LPT)" after plugging in your ESP32-C3 device. See Figure 2.4 for an example:
Figure 2.4: Locating the COM port for the ESP32-C3 plugged into the serial port.
In this example, we see that Windows has registered the ESP32-C3 as the device name COM3. Your device may use a different name depending on the device hardware. My device used a CH340 USB serial interface chip, and so the "CH340" shows up in the name.
Once you know the device name, you can flash it:
PS C:> idf.py -p COM3 flash
If all went well, you will see that it recognizes the device and uploads the compiled software to it. In order to see hello_world run, we monitor it with:
PS C:> idf.py -p COM3 monitor
Several message lines will appear, but eventually you will see some output similar to the following:
--- idf_monitor on com3 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x16bc
load:0x403ce000,len:0x930
load:0x403d0000,len:0x2d40
entry 0x403ce000
I (30) boot: ESP-IDF v4.4 2nd stage bootloader
I (30) boot: compile time 15:55:20
I (30) boot: chip revision: 3
I (32) boot.esp32c3: SPI Speed : 80MHz
I (36) boot.esp32c3: SPI Mode : DIO
I (41) boot.esp32c3: SPI Flash Size : 2MB
I (46) boot: Enabling RNG early entropy source...
...
I (228) spi_flash: detected chip: generic
I (232) spi_flash: flash io: dio
I (236) sleep: Configure to isolate all GPIO pins in sleep state
I (243) sleep: Enable automatic switching of GPIO sleep configuration
I (250) cpu_start: Starting scheduler.
Hello world!
This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision 3, 2MB external flash
Minimum free heap size: 329676 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
Restarting in 6 seconds...
After booting up, it will eventually reboot and display "Hello world!" as often as you allow it to continue. To exit monitor mode, type Control-] (control key plus the right square bracket). Congratulations, you have successfully compiled, flashed and ran your first RISC-V program!
2.4. Summary
This may have been a tedious chapter for getting your Espressif software ready. The good news is that the difficult part is over and that your ESP32-C3 is now at your beckon call.
Chapter 3 • Installation and Setup of QEMU
QEMU speaks RISC-V!
In this chapter, instructions are provided for installing QEMU for the RISC-V emulator. Running the QEMU emulator allows us to explore the 64-bit RISC-V machine without having actual hardware for it. Additionally, it provides us debugger access to the machine in a friendly Linux environment.
When there is no QEMU binary install package available for your Linux desktop, it can be compiled from source code. The procedure for that is provided in this chapter. Otherwise, Windows and MacOS users can download and use prebuilt binary installs instead. Windows users should skip down to the section "Installing QEMU on Windows" near the end of this chapter.
Book Source Code
All users should check out the source code available for this book somewhere convenient. How and where you can download it will vary according to whether you are using Windows or not.
3.1. Linux/MacOS Platforms:
Throughout this book, I'll assume that the directory used for the checked-out code is under ~/riscv/repo. Be sure to use the -b master option to checkout the correct branch.
$ git clone https://github.com/ve3wwg/risc-v.git -b master ~/riscv/repo
Copy the file:
$ cp ~/riscv/repo/boot.sh ~/riscv/boot.sh
This provides a copy of the checked-out