We bring a cheap single-payer system to order with our own hands
In the last article, you and I considered what a single-board computer, which costs only 1,000 rubles, is capable of. As we found out, the prospects of this device are very good, but in fact, Orange Pi sells almost bare metal, which needs to be modified by yourself. Yes, there is Ubuntu / Fedora, yes, there is a comb with I2C / SPI – but out of the box it all works crookedly, or does not work at all. Even the promised SPI/I2C buses are practically not available out of the box. There is not much material on the network about finalizing this single-player, so I decided to bring it to life myself and share it with you – including the finished binary images! I wonder what a modified single-payer can do for the price of a case of beer? 🙂
What we will work on
In the last article, you and I decided on the potential prospects of such a device. For the price of 3x ESP32, the manufacturer offers us two full-fledged computing ARM cores, 256 megabytes of RAM, 512 megabytes of built-in NAND memory, a power controller with the possibility of operation from lithium-ion batteries and a 3G modem. But there was a spoonful of tar in the barrel of honey: no one was going to support it all, and Orange Pi almost immediately killed the support for the device, limiting itself to a Debian/Ubuntun port for the device.
Moreover, the manufacturer did not even describe how to work with the device’s GPIOs and buses – which effectively turned it from a single board into a normal TV set-top box, only without a normal video output. I was extremely surprised why the community did not want to work on such a cheap board – most people just saw the whole situation and went to leave a negative review without even trying to understand. After all, for an experienced linuxoid-embedder, there is work here for a day or two!
In addition, the GSM stack does not work in Linux. Yes, absolutely. The manufacturer did not even cooperate with MediaTek to try to implement work with the modem at the system level. After all, in fact, all work with the modem takes place only at the level of AT commands. So what was the problem?
I will have to deal with all this! We clone the repository with the kernel sources and run to collect!
We collect the core. I2C and SPI
Instead of the typical Buildroot, Orange Pi uses its own simple build system based on shell scripts: as a toolchain, it uses the ready-made linaro. In part, this is due to the very chips on which their devices work – MediaTek, for example, does not use the Mainline core and in the assembly process has a bunch of steps to prepare the final image. Even menuconfig does not work there, and all changes have to be made in the previously generated configuration.
We clone the repository with the assembly system and run the script:
git clone https://github.com/orangepi-xunlong/OrangePi_Build
cd OrangePi_Build
./Build_OrangePi.sh
We select our board – 3G IoT and wait until the assembly system actually downloads everything necessary for assembly – the kernel source code, external folders (drivers, bootloader and MediaTek linux port). Please note, OrangePi has even tied the assembly system to a specific version of the system: only Ubuntu 18.04, but in fact the kernel will be assembled without problems almost anywhere. After everything has been downloaded, go to the folder with the build script and run the build script:
cd ../OrangePi3G_iot/
./build.sh
And no, we do not run it – the script complains that it cannot deliver some packages. No problem – we install bsdtar and python minimal manually and go to edit the script code. It is located in scripts/general.sh: we remove outdated package names from there.
After that, the kernel should compile successfully. Pay attention to the version of your board – the ones sold now are exactly A. If you try to throw them a kernel for B, they will go to kernel panic due to the lack of eMMC.
If mkbootimg complains about libstdc++6, then install its x86 version from the repositories.
The finished core will lie in output/kernel/boot.img, which can be flashed to the device. With one small nuance, it is designed for loading from the internal memory, which is critically small for the Linux distribution! We don’t have the boot_sd.img that comes with the original distribution. An attempt to disassemble the image with the standard AndImgTool was unsuccessful – the ramdisk is embedded directly in the zImage image, and not separately, as is usually the case with Android images.
After digging into the assembly scripts, I still did not understand the logic of creating boot_sd, I did not find anything related to sd even by grep all over the folder. Well, then let’s try a workaround: compile the necessary drivers as modules (ko) that are loaded. We go to our config located in linux/arch/arm/configs/3giot_defconfig and change CONFIG_I2C_CHARDEV and CONFIG_SPI_SPIDEV to m. Explanation: y will cause the build system to compile the driver statically with the kernel, while m will extract it as a separate ko module, which can then be loaded via insmod.
We assemble the kernel again, this time the compilation takes no more than a minute. The files we need will appear in linux/drivers/spi/spidev.ko and linux/drivers/i2c/i2c-d-ev.ko. We transfer them to the host PC, and then to the device itself using SSH:
Download the kernel modules:
insmod i2c-dev.ko
And yes! As many as two i2c buses appeared in the system (/dev/i2c-0, /dev/i2c-1). We install i2c-tools and go to check with i2cdetect: the first bus is completely free for our projects, and the second one has a peripheral hanging at some addresses (FM radio as an option):
I2C now works for sure! But what about SPI?
insmod spidev.ko
Device or resource busy.
Unfortunately! spidev cannot be loaded dynamically, only statically linked with the kernel, which we cannot do yet. However, there is a technical possibility to make SPI work: for example, write your own driver that translates commands from the user to the SPI API, which works at the kernel level.
GPIO
In the last article, I briefly explained how to work with gpio from user-space at the terminal level. However, most developers will potentially use the native API for GPIO — well, don’t they seriously want to parse the status output to the console? So I decided to write a tiny library to work with GPIOs, as simple as DigitalWrite/DigitalRead!
Let’s first understand how to work with the GPIO driver. To do this, we open the original sources of the kernel and look carefully at what the driver offers us: in our case, these are IOCTL calls, and they are also simple and understandable. It’s just great! I wrote a single-header library in 10 minutes: no error checking, but workable.
void gpioInit();
void gpioSetDir(int num, byte dir);
byte gpioGetDir(int num);
void gpioWrite(int num, byte value);
byte gpioGetState(int num);
byte gpioRead(int num);
void gpioSetPullState(int num, byte enabled, byte up);
Example of use (141 – extreme pin on the comb):
#define GPIO_IMPL
#include "gpio.h"
#include <stdio.h>
void testPin(int pin)
{
printf("Pin state %i is %i\n", pin, gpioGetState(pin));
gpioSetDir(pin, 1);
gpioWrite(pin, 0);
printf("Pin state %i is %i\n", pin, gpioGetState(pin));
gpioWrite(pin, 1);
printf("Pin state %i is %i\n", pin, gpioGetState(pin));
}
int main(int argc, char** argv)
{
gpioInit();
testPin(141);
}
Modem
I’ll say right away: I haven’t been able to start the modem yet, but I’m actively working on it. In this part of the article, I will outline my findings and assumptions about modems on MediaTek chips.
MediaTek devices have one driver for communication with GPS, A-GPS and modem – ccci, judging by the cross chip communication interface. It is the ccci that creates the devices with which the input from the microphone and the output to the speakers come, and it also creates the control interfaces to communicate with the various modules of this SoC.
When starting the kernel, ccci creates many devices – ccci_ioctl, ccci_ipc, ccci_fs and the most necessary for us – ttyC0/ttyC1/ttyC2 – Depending on the number of SIM cards in the system. In addition to ccci, the system has some 6620_launcher – a binary that downloads Wi-Fi firmware and gsm0710muxd – a special service that allows you to talk and sit on the Internet at the same time in GPRS networks.
MTK smartphones have a factory mode – the so-called test mode, which is run at factories. You have probably seen Chinese menus that look like recovery – this is what factory mode is. From this mode, you can call 911 and activate the modem without running Android and RIL. How does it work? Let’s go read the kernel sources!
In the factory mode, the program reactivates the modem after each test. For this, there are test mode functions for working with AT commands and for modem initialization. First, it opens the /dev/ttyC0 terminal — that’s where communication with the modem takes place using AT commands:
After that, the program brings the modem out of sleep mode using the command “AT+ESLP=0”, initializes the SIM card using the command “AT+ESIMS” and sets the operating mode using “AT+EFUN=1” and “AT+CREG=1”. After that, the modem starts searching for a network and is available for normal communication using AT commands. However, after writing a test software to communicate with a modem under Debian, I received Device not found errors. Why? I don’t know yet. However, I continue to study this issue!
Conclusion
You can download the files I have prepared
disc
. There are compiled kernel modules, a library for working with GPIO and some test programs as examples.
Fortunately, we were able to get the gadget working on our own. It is very surprising that such a large and respected manufacturer of Orange Pi decided to banally “score” in support of its own device. And I personally believe that those readers who once bought a similar device and killed it, putting up with the lack of guides, should not throw them into a long box.
A little enthusiasm, experience and a vision of the future project – and everything will work out 🙂