What Can QEMU Do in Embedded Programming?

What Can QEMU Do in Embedded Programming?

What Can QEMU Do in Embedded Programming?

  • 1. Introduction

  • 2. Bare-metal or RTOS Programming in Embedded Systems

  • 3. Research on Network Programming Using QEMU

  • 4. Embedded Graphics Development

  • 5. Development of Embedded Linux

  • 6. Conclusion

1. Introduction

In the process of embedded development, a lot of time is spent interacting with hardware devices, controlling their specific behaviors through programs. This often follows the development model inherited from microcontrollers. In the current complex embedded systems, many require the use of design patterns for development, such as file systems, networks, graphics, algorithms, etc. If software simulators can be used for development, it can greatly reduce the time spent on board debugging and alleviate the hassle of hardware connections, allowing for software code analysis at home.

What Can QEMU Do in Embedded Programming?

In actual project development, QEMU is also very useful. For example, when performing network programming, socket programming is often used directly, with the upper layer interfaces conforming to POSIX standards. This allows for a simple separation of upper layer application development and lower layer driver work, enabling a reasonable division of work details. When designing embedded GUI programming, various interfaces can also be designed through the framebuffer. Additionally, if one wants to learn a new embedded programming language or gain a deeper understanding of processor architecture, bare-metal programming that runs directly on QEMU can facilitate exploration.

What Can QEMU Do in Embedded Programming?

Below are some practical applications of QEMU that will be described in detail.

2. Bare-metal or RTOS Programming in Embedded Systems

QEMU performs instruction translation, allowing for corresponding bare-metal development and learning based on actual needs, such as language learning, embedded C programming, embedded RUST programming, and other projects. Some useful learning projects on GitHub also support QEMU, enabling programming in RUST on ARM, even without good hardware conditions, allowing for learning RUST in embedded programming.

For ARM programming, QEMU can simulate many architectures. By learning and mastering these architectures, one can accelerate their understanding of architecture programming.

./qemu-system-arm -M virt -cpu ?
Available CPUs:
  arm1026
  arm1136
  arm1136-r2
  arm1176
  arm11mpcore
  arm926
  arm946
  cortex-a15
  cortex-a7
  cortex-a8
  cortex-a9
  cortex-m0
  cortex-m3
  cortex-m33
  cortex-m4
  cortex-m55
  cortex-m7
  cortex-r5
  cortex-r5f
  max
  pxa250
  pxa255
  pxa260
  pxa261
  pxa262
  pxa270-a0
  pxa270-a1
  pxa270
  pxa270-b0
  pxa270-b1
  pxa270-c0
  pxa270-c5
  sa1100
  sa1110
  ti925t

However, embedded development often involves hardware interaction. QEMU also provides different categories of hardware, such as flash, network cards, SD cards, interrupts, serial ports, etc., which play a crucial role in learning different architectures.

For example, when learning Cortex-M3 or AArch64 programming, using QEMU to run one’s own bare-metal code allows for convenient experimentation.

During RTOS development, QEMU is often used as a debugging tool for development and verification work related to Loongson, Raspberry Pi, and RISC-V. In RTOS, context switching is critical, involving the saving and restoring of register information, as well as interrupt handling, which helps in understanding the low-level programming methods of the architecture.

Previously, I also did QEMU programming on AArch64, starting with QEMU and gradually porting it to Raspberry Pi, as the peripherals are consistent, and the code does not need to change. The firmware that runs on QEMU can also be placed directly on the Raspberry Pi’s SD card and run normally.

What Can QEMU Do in Embedded Programming?

The above image shows the running effect of the firmware compiled in QEMU’s rt-thread/bsp/raspberry-pi/raspi3-64, which basically completes support for stack frames, interrupts, MMU in the AArch64 architecture, as well as support for peripherals like SD card, graphics, serial port, and mailbox. This firmware can also be placed directly on the Raspberry Pi hardware’s SD card and run with the same effect as in QEMU.

In addition, I have also done some extended development on QEMU support, such as research on GD32’s RV-Star in the RISC-V ecosystem based on the Institute of Software, Chinese Academy of Sciences, and adapted various processor series from Nuclei. This is more useful for software-level verification, such as running the Nuclei SDK or supporting the RISC-V V extension’s NMSIS.

qemu-system-riscv64 -M nuclei_n,download=ilm -cpu nuclei-nx600fdp -nodefaults -nographic -serial stdio -kernel CMSIS/nmsis_release/NMSIS/DSP/Examples/RISCV/riscv_matrix_example/dsp_example.elf

This allows for related DSP verification work. Since nmsis is a port of the ARM-based cmsis to RISC-V, it implements many accelerated computation demos, such as matrix operations, convolution, image processing, etc. These instructions can also yield correct results in Nuclei QEMU.

What Can QEMU Do in Embedded Programming?

With support for RISC-V P and V extensions, its behavior is indistinguishable from actual hardware boards. Performing algorithm optimization and research in QEMU is also worth trying. Although QEMU simulates real computational results using software, from the perspective of instruction set optimization, once the functional logic is correctly implemented, it is efficient to port it to the board for performance testing.

In supporting bare-metal programming and RTOS programming, the Nuclei SDK has also done some work to better observe and analyze the specific behavior of software.

qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/rtthread/msh/msh.elf
Nuclei SDK Build Time: May 31 2021, 11:48:18
Download Mode: ILM
CPU Frequency 168290222 Hz

 \ | /
- RT -     Thread Operating System
 / | \     3.1.3 build May 31 2021
 2006 - 2019 Copyright by rt-thread team
Hello RT-Thread!
msh >
msh >ps
thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
tshell     6  ready   0x000000d8 0x00001000    10%   0x0000000a 000
tidle      7  ready   0x00000078 0x00000200    23%   0x00000020 000
main       2  suspend 0x000000b8 0x00000400    17%   0x00000013 000
msh >

It can also support other RTOS, such as uCOS-II and FreeRTOS.

The running effect of uCOS-II is as follows:

qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/ucosii/demo/demo.elf
Nuclei SDK Build Time: May 31 2021, 11:49:45
Download Mode: ILM
CPU Frequency 182521692 Hz
Start ucosii...
create start task success
start all task...
task3 is running... 1
task2 is running... 1
task1 is running... 1
task3 is running... 2
task2 is running... 2
task3 is running... 3
task2 is running... 3
task1 is running... 2
task3 is running... 4
task2 is running... 4
task3 is running... 5
task2 is running... 5

The running effect of FreeRTOS is as follows:

qemu-system-riscv32 -M nuclei_n,download=ilm -cpu nuclei-n201 -nodefaults -nographic -serial stdio -kernel application/freertos/demo/demo.elf
Nuclei SDK Build Time: May 31 2021, 11:49:45
Download Mode: ILM
CPU Frequency 232205516 Hz
Before StartScheduler
Enter to task_1
task1 is running 0.....
Enter to task_2
task2 is running 0.....
timers Callback 0
timers Callback 1
task1 is running 1.....
task2 is running 1.....
timers Callback 2
timers Callback 3
task1 is running 2.....
task2 is running 2.....

Using QEMU for low-level research will be very efficient. Additionally, utilizing debugging tools like GDB can easily pinpoint where issues arise.

3. Research on Network Programming Using QEMU

Since QEMU’s network can directly connect to the host’s network, research in this area can involve network protocol stacks, upper-layer application programming, etc. For example, studying the implementation of the lwIP protocol stack.

I have written a driver for the e1000 network card device on QEMU, specifically for the QEMU RISC-V 64 virt version.

https://github.com/bigmagic123/rt-thread/tree/riscv_virt_network

For the RT-Thread QEMU RISC-V virt64 version, the following settings can be made.

What Can QEMU Do in Embedded Programming?

The underlying driver is e1000, which provides data transmission and reception for QEMU, as well as network packet reception interrupt services.

With the lwIP driver program adapted on RT-Thread, upper-layer network programming applications can be easily implemented.

For example, using the RT-Thread IoT software package.

What Can QEMU Do in Embedded Programming?

Enabling some examples.

What Can QEMU Do in Embedded Programming?

Finally, testing the web communication situation.

What Can QEMU Do in Embedded Programming?

Of course, the above example is just a very simple demonstration of network programming. The socket programming part is actually universal, whether on ARM architecture, MIPS architecture, or RISC-V architecture. The benefit of using QEMU is that one can adopt a single architecture platform for protocol stack or upper-layer development, which can then be seamlessly ported to their actual board, making overall business debugging very convenient.

For the QEMU RISC-V 64 virt platform, the entire system, from the underlying virtio or e1000 network card device providing data transmission, interrupt message mechanisms, is supported by RT-Thread through the lwIP protocol stack, making the entire network link reasonable and development convenient.

In the development of IoT modules, using QEMU, one can also directly drive the e1000 network card on bare-metal without RT-Thread, and by reading and writing to registers, port other network protocol stacks to achieve data transmission and reception. The upper-layer network programming can easily interface with cloud servers like Alibaba Cloud and Tencent Cloud, while debugging with QEMU’s GDB debugging functionality is also very powerful, allowing for memory dumps for RAM parse analysis.

4. Embedded Graphics Development

Since embedded programming often involves graphics programming, when connecting to an LCD screen, the display driver exposes a framebuffer to the upper layer applications. By reading and writing to the framebuffer and flushing, the LCD image can be updated.

In terms of image programming, QEMU also provides a display window. This display window can bring a lot of convenience to GUI-related development work.

For embedded image programming, you can refer to:

rt-thread\bsp\raspberry-pi\raspi3-64

Related BSPs only need to complete the display program.

One can find a BMP image, sized 800×480.

What Can QEMU Do in Embedded Programming?

Using the Image2Lcd tool to convert the image into an array.

What Can QEMU Do in Embedded Programming?

Finally, compile the array program into the code and place the array in the framebuffer.

What Can QEMU Do in Embedded Programming?

Once everything is ready, development for the display can begin.

#define LCD_BUF_SIZE  (800 * 480)
extern unsigned char gImage_1[];

void lcd_test()
{
    struct rt_device *lcd;
    struct rt_device_graphic_info *test_lcd_info;

    test_lcd_info = rt_malloc(sizeof( struct rt_device_graphic_info));
    // Find the LCD    lcd = (struct rt_device *)rt_device_find("lcd");
    rt_kprintf("lcd get info:\n");
    rt_device_control(lcd, RTGRAPHIC_CTRL_GET_INFO, test_lcd_info);
    rt_kprintf("lcd width is %d\n", test_lcd_info->width);
    rt_kprintf("lcd height is %d\n", test_lcd_info->height);
    rt_kprintf("lcd bpp is %d\n", test_lcd_info->bits_per_pixel);

    rt_memcpy(test_lcd_info->framebuffer, &gImage_1[0], LCD_BUF_SIZE*4);
    // Refresh the image
    rt_device_control(lcd, RTGRAPHIC_CTRL_RECT_UPDATE, NULL);
    rt_thread_delay(20);
}

If touch operations are required, QEMU also provides basic support; relevant low-level drivers can be ported for development work, making it very efficient and convenient.

5. Development of Embedded Linux

When working on Linux development, if one delves into the development of a specific device, it is inevitable to continuously compile and download the Linux kernel, which is a time-consuming task. If only application program development is involved, one may not feel much difference, but once it comes to analyzing the Linux kernel, frequent downloads can waste a lot of time.

Using QEMU can effectively solve this problem. By using QEMU for kernel-level trimming and modular verification work, it can be ported to make it more general, not only effective for this project but also accumulating a lot of experience.

What Can QEMU Do in Embedded Programming?

Analyzing the Linux loader, the Linux driver framework, memory management, multi-core management, etc., can all be conveniently debugged.

Before the actual hardware device is stable, QEMU is a very useful tool for evaluating software projects.

6. Conclusion

In many software development tasks, using QEMU can indeed save time and improve the efficiency of software debugging and analysis.

Simulating hardware operation behaviors with software is fundamentally not much different from actual hardware operations, as the behavior of the lowest-level instruction set has been well implemented in QEMU. In terms of hardware simulation, QEMU can also roughly simulate the behavior of the processor after operating registers. A lot of experiments and research have been conducted during the process of supporting and learning QEMU.

Understanding the use of QEMU will lead to a deeper understanding of embedded software principles. From a broader perspective, virtualization behavior is inherently a good solution for designing an embedded software solution, demonstrating low-level software, or saving download debugging time. For developing functional layers of embedded upper-level business system software, QEMU is a tool worth researching and using.

What Can QEMU Do in Embedded Programming?

What Can QEMU Do in Embedded Programming?

1. Sign up! Build secure embedded systems — from FreeRTOS to SAFERTOS online course

2. The 6th issue of “Microcontrollers and Embedded System Applications” electronic journal is freshly out!

3. Huawei’s official notice: HarmonyOS no longer belongs to Huawei!

4. Clever use of the MCU’s general-purpose registers that do not reset on SystemReset!

5. Why do so many people want to use RTOS with limited resources in microcontrollers?

6. Remembering the university days obsessed with technology on Children’s Day!

What Can QEMU Do in Embedded Programming?

Disclaimer: This article is a network reprint, and the copyright belongs to the original author. If there are any copyright issues, please contact us, and we will confirm the copyright based on the copyright certificate you provide and pay the manuscript fee or delete the content.

Leave a Comment