Abstract: This paper describes in detail the implementation method of a graphical interface display system based on the uClinux embedded operating system, and specifically discusses the writing of the framebuffer driver under uClinux.
Keywords: uClinux, Microwindow, Framebuffer driver
1. Introduction
In the emerging field of embedded systems within the IT industry, Linux, with its stability, efficiency, customizability, scalability, and broad hardware support, combined with its free and open-source nature, is playing an increasingly important role as an embedded operating system. More and more embedded systems, including PDAs, set-top boxes, and WAP phones, require a full-featured web browser. This includes support for HTML, JavaScript, and even Java Virtual Machines. All of this necessitates a high-performance, highly reliable GUI. These systems generally do not want to be built on top of a large, cumbersome, and resource-intensive operating system and GUI, such as Windows or X Window. However, even with the advent of Linux, the GUI remains an issue, primarily due to the excessive size and bloat of X Window. uClinux is an embedded Linux operating system specifically designed for processors without a memory management unit. Its embedded Microwindow provides excellent support for graphical interfaces in embedded systems.
2. System Composition and Structure
The uClinux-based embedded graphical interface display system consists of two main parts: software and hardware. The software comprises uClinux, the Framebuffer driver, and Microwindow. The hardware system consists of a Motorola embedded CPU 5272, an EPSON 13506 LCD controller, and a TRULY MCT-G320240DNCW LCD screen. The structure is shown in Figure 1.
Figure 1. Composition structure of the embedded graphical interface display system based on uClinux
Hardware design environment: The development board is a Motorola 5272C3, and the uClinux kernel version is 2.4.17.
3. Architecture of Microwindow
MicroWindow is a lightweight GUI characterized by its small size, low resource consumption, and high reliability. It is a customizable and compact graphical user interface support system ideal for industrial control real-time systems and embedded systems. MicroWindow employs a layered architecture. The bottom layer consists of a set of abstract interfaces for the screen, mouse/touchscreen, and keyboard, independent of any special hardware. The middle layer is a portable graphics engine. The top layer comprises various APIs for graphical applications to use. Currently, there are two APIs: ECMA APIW and NANO-X APIS. These APIs are largely compatible with Win32 and X Window systems, making application portability very easy.
Figure 2. Architecture of Microwindow
In uClinux, the lowest-level SCREEN abstract interface of Microwindows is built on the Linux framebuffer device. The framebuffer device is an abstraction of the graphics display hardware device; it represents the frame buffer of the video hardware. This article will focus on how to design the framebuffer device driver for a specific hardware environment under uClinux.
4. Design of the Framebuffer device driver
In Linux, devices are divided into three main categories: character devices, block devices, and network device interfaces. So, which category does the Framebuffer device belong to? This can be confusing at the beginning of the design process. Actually, to the user, the framebuffer device is no different from other devices in the /dev directory. It is a character device, using major device number 29, with minor device numbers used to distinguish between framebuffer devices.
For example:
0=/dev/fb0 First frame buffer
1=/dev/fb1 Second frame buffer
…
31=/dev/fb31 32nd frame buffer
0-31 are the secondary device numbers.
The framebuffer driver primarily relies on four data structures. These structures are defined in the include/linux/fb.h file: fb_info, fb_var_screeninfo, fb_fix_screeninfo, and fb_monospecs. The latter three structures can be accessed in user space, while the fb_info structure can only be accessed in kernel space.
The `fb_fix_screeninfo` structure defines certain fixed characteristics of the video board hardware. These characteristics are defined during hardware initialization and cannot be modified afterward. The most important members in this structure are `smem_len` and `line_length`. The former indicates the size of the video memory, and the latter provides a byte count for each display line, making it easy to move the video memory pointer to the next display line.
The structure `fb_var_screeninfo` defines some variable characteristics of the video hardware. These characteristics can be dynamically changed by the application during program execution. Due to space limitations, only the main members of this structure will be explained here; for detailed explanations, please refer to `fb.h`. The member variables `xres` and `yres` define the actual resolution displayed on the screen. `xres_virtual` and `yres_virtual` are virtual resolutions, defining the video memory resolution. For example, if the screen's vertical resolution is 400, and the virtual resolution is 800, this means that 800 display lines are stored in video memory, but only 400 lines can be displayed at a time. Which 400 lines are displayed? This requires another member variable, `yoffset`. When `yoffset=0`, the 400 lines are displayed starting from line 0 of video memory; if `yoffset=30`, the 400 lines are displayed starting from line 31 of video memory.
Of these four structures, the most important is `fb_info`, which can only be accessed in kernel space. Internally, it defines `struct fb_ops`, whose members consist of a series of Framebuffer operation functions.
The fb_monospecs structure is only used in kernel 2.5.x and is not used in the current kernel.
As mentioned earlier, from the user's perspective, framebuffer devices are no different from general character devices. Therefore, there are two options for writing device drivers for video hardware: one is to abstract the video hardware as a general character device, writing the driver similarly to a general character device driver; the second is to write a framebuffer device driver. The first method is not standardized and has limited functionality, so it is not recommended. The following section will use an analogy with character driver development to introduce how to write a framebuffer driver.
Character drivers register their devices with the kernel using the function `register_chrdev`. `register_chrdev` requires three parameters: the first is the major device number; the second is the driver name corresponding to that major device number; and the third is a pointer to the function that actually performs the operation, pointing to a `struct file_operation`. The main task in writing a character driver is writing the various sub-functions and filling in the fields of `file_operation`. When a user process uses system calls to operate on the device file, the system finds the corresponding device driver using the major device number of the device file. Then, it reads the corresponding operation function pointer from this data structure and transfers control to that function. This is how Linux drivers work.
Framebuffer device drivers work similarly, registering a framebuffer device by calling `register_framebuffer`. It takes only one argument, the previously mentioned `struct fb_info`, which internally defines the structure member `fb_ops`. Writing a framebuffer driver primarily involves writing the member functions of `fb_ops`. Unlike character drivers, framebuffer drivers do not implement ioctl calls. The initialization function for the framebuffer driver is registered in `linux/drivers/video/fbmem.c`. All ioctl calls for framebuffer drivers are uniformly implemented by `fbmem.c`, which provides ioctl calls based on the currently active framebuffer device.
5. Hardware Circuit Design
The 5272 is a mid-to-low-end embedded CPU in Motorola's Coldfire series. Low-end doesn't mean inefficient; at a clock speed of 66MHz, it achieves 63 MIPS, close to the MIPS of the MPC860. Furthermore, it boasts a rich array of peripheral interfaces and has the highest integration density among the Coldfire series.
The 5272 bus is a 32-bit synchronous data and address bus, supporting both synchronous and asynchronous termination. During a bus transmission cycle between the 5272 and peripheral devices, a wait clock cycle can be inserted using the TA signal to achieve asynchronous termination of the bus transmission. The 5272 bus interface uses four signals, BS0 to BS3, to indicate the current bus cycle's data bus width. The 5272's I/O space is memory-mapped, so it does not have a dedicated I/O address space. Because the 5272 lacks an MMU unit, its memory space uses direct physical addressing.
The LCD screen controller is the EPSON 13506. This is an LCD/CRT/TV graphics controller with a wide range of CPU interfaces. It has a 16-bit wide EDO memory interface, with a maximum memory capacity of 2Mbytes. At 16bpp, the maximum resolution is 640×480. It supports virtual display, meaning the displayed image size can be larger than the actual screen size.
The diagram below shows the interface circuit between the Coldfire 5272 CPU and the EPSON13506.
Figure 3. Schematic diagram of the interface circuit between 5272 and 13506
The EPSON13506 CPU interface data bus width is 16 bits. The 5272 uses Big Indian byte order, meaning that when the bus width is 16 bits, the high 16 bits of the data bus are valid. The EPSON13506 M/R# pin controls whether the current read/write operation is on the video memory or the 13506 I/O registers, controlled by the 5272 address line A21. Thus, in the 5272 CS6 address space, a 1 in address bit 21 indicates the video memory address, while a 0 indicates the 13506 I/O register address. The 5272 address bus A0 is not connected to the EPSON13506 AB0 pin because in the EPSON13506 CPU interface mode Generic1, the EPSON13506 AB0 pin must be high. This prevents byte addressing. To achieve byte addressing, a CPLD can be used to perform logical operations to select the appropriate pin, thus enabling byte addressing.
The key challenge in the entire circuit design lies in a deep understanding of the EPSON13506 CPU interface type. The connection between the video memory and the LCD screen is relatively simple and will not be elaborated here.
6. Conclusion
More and more embedded systems are now requiring graphical user interfaces, especially in industrial control fields. This system has been successfully applied to chromatography workstations. Its user-friendly interface greatly reduces the difficulty of instrument operation, simplifies the operation process, and improves production efficiency.
References:
[1]Allessandro Rubin,Linux Device Drivers O'Reilly&Associates, Inc, 1998
[2] Chen Lijun, Linux Operating System Kernel Analysis [M]. Beijing: Posts & Telecom Press, 2000.