Hi guys! It’s Andy Liu. We started to sell the SwiftIO board in July 2020. And we have received hundreds of orders from different countries. You guys are awesome! You are not only customers but angels for us. I want to express the depth of my gratitude to all of you!
Our project may take years to be perfect, and we would like to run it in a steady way so we have more chances to incorporate your feedback and improve continuously. It might evolve slowly, but nothing could kill us.
At present, the SwiftIO board hardware is stable. But the software still needs improvement. We received some issues about the software:
The IDE has problems in different OS environments
The USB drive may not appear after pressing the DOWNLOAD button
Here, I’ll give a brief explanation of the techniques we use in our project. After reading this article, you would know the principle of our project and what to do if you encounter some issues before we solve them.
Again, thanks very much for your support in such an early stage! Hope we could grow together in the long term 😘
As you know, those who are unfamiliar with Swift regard it as an Apple exclusive-use programming language. But we know that’s wrong. Swift is modern, safe, efficient and especially, cross-platform. That’s why I have the confidence to make this language work in the microcontroller world. (Some of you might mention Rust, but I have to admit that Rust is too hard for me to get started😭)
Before we start, you could have a look at the definition of Clang here, it is described as a C language family frontend for LLVM.
Similarly, Swift is a Swift language frontend for LLVM, sounds weird? A little.
Swift leverages all the infrastructures of LLVM, so it doesn't need to implement various architecture backends. But still, a lot of work needs to be done. The official Swift team focuses mainly on x86-64 and ARM Cortex-A architectures. Thanks to the good infrastructure of LLVM, what I did is just combine the existing ARM Cortex-M backend with the Swift compiler source code. It’s so natural that not only I thought of this way. During my exploration, I referred to those resources:
Enthusiasts around the world are trying different ways to explore new possibilities in this brand new field. We share the same curiosity and passion. We believe that Swift would do something magic in the embedded world in the future!
Unlike the swift-project1 and swift-embedded which run completely on bare-metal, we chose Zephyr RTOS to abstract the low-level hardware. In this way, we don’t need to write those on-chip devices’ drivers, like I2C, UART, SPI, etc... And it would be very convenient to port our framework to other microcontrollers. This definitely simplifies our works in the future. The structure of our framework is just as follows:
If your project is built successfully, you would notice there will be a file called
swiftio.bin generated in the
.build directory. You just need to copy it to the root directory of the SD card, eject it, then the SwiftIO board will reset and run your code.
When you click the build button or download button, the IDE will use related tools and libraries in mm-sdk to build the whole project. At present, the build script is written in Python. Later, when Swift package manager could run well in Windows, we are going to rewrite it using Swift. So we can take full advantage of the package management feature of SPM. Now, let me explain in detail the whole process of building. Suppose you create a project named Blink:
When you click the build or download button in the IDE, here are what the IDE will do:
Open a terminal and change the directory to the Blink project
path_to/mm-sdk/tools_mac/scripts/dist/mm/mm build --sdk path_to/mm-sdk --module ~/Document/MadMachine/Library
If you were clicking the download button, there will be two extra steps:
Blink/.build/swiftio.bin to the USB drive
Eject the USB drive
The command in the second step is responsible for the whole building process. Two arguments in the command mean:
--sdk The path to mm-sdk
--module The path to the Library. Since currently there is no available package management feature, we have to put all the dependent libraries into the same folder, and then assign it when invoking this building command.
Let’s talk about how the command works in detail:
The Python script will find and build all the dependencies in the specified library folder. Then the static libraries will be generated according to the dependencies defined in the
Blink.mmp (Actually, it’s a TOML file)
Build your own project to generate a static library
Link all the related static libraries together to generate
objcopy to convert
Append 4 bytes CRC information to
Blink.bin, then we get
You might be wondering how the
swiftio.bin is loaded and executed on the board. In fact, a pre-installed bootloader (or called firmware) has been written into the onboard Flash. This flow chart would reveal the key information about how it works:
Also, I would like to say, we now use copy and run mode, your application would be copied from the SD card and run in the SDRAM. In fact, your project could be built in XIP mode. In this mode, your project is the firmware itself. But you need to write the
.bin file to the onboard Flash. In this condition, you don’t need an SD card at all.
Arduino gave birth to the trend of electronic makers and it gained great success. What’s more, many open source projects based on Arduino were successful as well.
In my opinion, Arduino is the most successful attempt to simplify the API of hardware. It still uses C/C++, however, it abstracts all the on-chip devices and offers easy-to-use API to developers. You can now easily find plenty of Arduino drivers of hardware modules through long-time evolution and accumulation. It makes hardware development as simple and fun as playing with LEGO.
As we can see, Python has become so popular in recent years. Compared to C/C++, it is very easy to earn. As an interpreted language, users could see the results immediately without finishing all the code and compiling it. To realize MicroPython, Damien George created an efficient interpreter using C. This could run in an extremely limited microcontroller environment. In this way, developers are able to use Python in the embedded world.
However, Python needs to be interpreted. This leads to low efficiency when running it. So most complicated projects based on MicroPython implement their core algorithm in C, just provide some simple Python API to the users, such as OpenMV and CircuitPython.
Raspberry Pi, in fact, is totally different from what we talk about here. However, many guys couldn't tell it from microcontrollers. So I would like to explain a little.
Raspberry Pi is actually a well-equipped computer, but small in size. It runs a full Linux operating system, you can connect keyboard, mouse, hard disk and display to it. The only similarity with microcontrollers may be some commonly used on-chip devices, like GPIO, I2C, SPI, which can be controlled by Swift (Linux version) as well.
It is built on complicated hardware and software. Designing a board that can run Linux is much more difficult than a microcontroller board, moreover, the board needs to be adapted to the Linux system which is more complicated.
On the contrary, when our project comes to a stable state, we will provide an easy way to port different boards so that all kinds of boards could join in this ecosystem. I wish more and more hardware boards could use Swift.
For my part, our project is more like a combination of Arduino and MicroPython. Swift is not only modern and easy-to-learn like Python, but also efficient like C/C++. The only weakness now is that the generated bin file has a large size, thus it’s hard to be put into Flash of low-end microcontrollers. But we will continue to explore new ways to reduce its size.
In addition, We would gradually provide more and more Swift libraries and try our best to take full advantage of the Swift language. Imagine that one day, you could program different screens in SwiftUI style. How cool that would be : )
The IDE is based on the Electron framework, you could regard it as a graphical interface of mm-sdk. The design principle is to give beginners an easy-to-start environment to edit and build their own projects. The main purpose of the IDE is to help users to invoke the build script, copy
swiftio.bin to the USB drive and eject the USB drive in the background.
The IDE would copy built-in Examples and Library to the user's
Documents/MadMachine folder when you first run it. But it may encounter permission problems. If it failed to copy those files, you would meet errors when building your project. Check out if there are those two directories in your
This is a known issue in the Swift compiler. Swift does not officially support Windows yet. Since Swift 5.3 would officially support Windows in a very short time, we’ll check this out then.
This problem may be caused by these reasons:
Bad quality USB cable, there are so many bad quality USB cables in the market. Some of them can only charge your device without communication feature : (
Incompatible MicroSD card
Incompatible USB hub or incompatible USB-C to USB-A adapter
To solve problems 1 and 2, we offer a high-quality USB cable and a Kingston microSD card along with our board. But we still got feedback that the USB drive did not appear. In this situation, there is a temporary solution: use a USB card reader to copy the
swiftio.bin. At the same time, we’ll continue to improve the compatibility of the firmware.