Before and after semihosting

Source: Internet
Author: User
Tags types of functions

Compared with the traditional 4/8-bit single-chip microcomputer, arm's performance and processing capabilities are of course far ahead, but correspondingly, arm's system design complexity and difficulty, compared with the traditional design method. This article aims to discuss some basic aspects of system program design, introduce some features of embedded system program development based on ARM, and propose and solve some common problems.

This article is divided into several independent topics that will be published one after another.

(1) Basic concepts of embedded Program Development
(2) system initialization process
(3) how to meet the flexible requirements of Embedded Systems
(4) Design of Exception Handling Mechanism
(5) arm/thumb Interaction
(6) skills for developing efficient programs

1. Embedded Program Development Process

Unlike software development engineering on general computers and workstations, the development process of an embedded program has many characteristics and uncertainties. The most important aspect is the tight coupling between software and hardware.

Figure 1 shows two types of simplified hierarchical structure of embedded systems. Due to the flexibility and diversity of embedded systems, there is a lack of uniform standards between different layers in Figure 1, and almost every independent system is different. In this way, it brings great difficulties to the upper-layer software designers. First, too much consideration of hardware in the software design process makes development and debugging inconvenient. Second, if all software work needs to be done after the hardware platform is ready, naturally, the entire system development cycle is extended. These are problems that should be improved and avoided in terms of methods.

Figure 1 two types of Embedded System Structure Models

To solve this problem, the engineering and design personnel put forward many countermeasures. First, you can design a relatively unified interface function at the application and driver (or API) layer, is completely done. In this way, the software design standardization of the application layer is greatly improved, facilitating the reuse and Transplantation of applications across platforms.

For the driver/hardware abstraction layer, it is very difficult or even impossible to standardize the directly driven hardware. However, in order to simplify program debugging and shorten the development cycle, we can develop programs under a specific EDA tool environment, and then port them to the hardware platform. This not only ensures the correctness of the program logic design, but also makes the software development feasible or even ahead of the hardware development process.

We call it the development of PC software out of the hardware embedded software development stage. We can use Figure 2 to illustrate the development process of an embedded system program.

Figure 2 Development Process of embedded system programs

In the "PC software" development stage, you can use software simulation, that is, instruction set simulation, to verify the user program. In arm's development tools, armulator embedded in ads and ISS in realview development tools all provide this function. In a simulated environment, you can set the model and clock frequency of the ARM processor, and configure the time series parameters of the memory access interface. The program runs in a simulated environment, not only can the program run the process and logic test, it can also collect information such as the number of clock cycles, the number of Memory Access cycles, and the status of pipelines (effective periods, waiting periods, continuous and non-continuous access periods) when the processor is running. These valuable information cannot be obtained in the hardware debugging phase and is very valuable for program performance evaluation.

To simulate a target system more completely and practically, armulator and ISS also provide an open API programming environment. You can use standard C to describe a variety of hardware modules, together with the kernel modules provided by the tool, to form a complete "software" hardware environment. The software developed in this environment can be closer to the final goal.

This advanced EDA tool environment greatly facilitates embedded development by program developers. After the development of a "PC software", a real embedded software can be developed successfully as long as it is transplanted correctly. The porting process is relatively easy to form a set of standardized processes. Three of the most important aspects are:

◆ Hardware support for database functions
◆ Match the storage resource distribution on the target system
◆ Application program environment Initialization

2. library functions in the development tool environment

If the user program calls some library functions related to the target, you need to cut these functions before the application to meet the requirements allowed on the target. Consider the following three types of functions:

◆ Functions used to access static data
◆ Functions used to access the target Storage
◆ Functions implemented using the semihosting (semi-host) Mechanism

In addition to the functions defined in the iso c standard, the C library functions mentioned here also include some additional extended functions and compilation auxiliary functions provided by the compilation tool.

2.1 cut down the functions used to access static data

The static data in the library function is basically defined in the header file. For example, the returned values of the ctype class library function are obtained through the predefined ctype Attribute Table. For example, to change the default judgment of the isalpha () function, you need to modify the definition of the character attribute in the corresponding ctype Attribute Table.

2.2 cut down the function for accessing the target memory

There is a kind of dynamic memory management functions, such as malloc (), which runs independently of the target system. However, the memory space it uses needs to be determined based on the target. Therefore, the malloc () function itself does not need to be reduced or transplanted, but those functions that set the dynamic memory zone (address and space) are directly related to the memory distribution of the target system, need to be transplanted. For example, the stack initialization function _ user_initial_stackheap () is used to set the heap and stack addresses. Obviously, for each specific target platform, this function needs to be correctly transplanted based on the specific target storage resources.

The following is an example of porting the example function _ user_initial_stackheap:

_ Value_in_regs struct _ initial_stackheap _ user_initial_stackheap (
Unsigned r0, unsigned sp, unsigned R2, unsigned SL)
{
Struct _ initial_stackheap config;
Config. heap_base = (unsigned INT) 0x11110000;
// Config. stack_base = sp; // optional
Return config;
}

Note that the above function body does not fully comply with the standard C keywords and syntax specifications, and uses the C language extension feature in the arm Compiler (ads or realview compilation tool. For compiler-specific C language extensions, please refer to the relevant compiler instructions. Here we will briefly introduce the function _ user_initial_stackheap (), which mainly returns the base address of the heap and stack. In the above program, only the heap base address is set (set to 0x11110000 ), that is to say, the user uses the memory address starting from 0x11110000 as the dynamic memory allocation zone (heap zone ). The specific address must be determined by the user based on the target system and application conditions. At least the following conditions must be met:

◆ The address space starting from 0x11110000 is valid and writable (RAM)
◆ The memory space does not conflict with other functional areas (such as code, data, and stack)

Because the full execution effect of the _ user_initial_stackheap () function is to return some numerical values, as long as it complies with the call standard of the interface, it looks more intuitive to directly use the Assembly:

Export _ user_initial_stackheap
_ User_initial_stackheap
LDR r0, 0x11110000
MoV PC, LR

If this function is not transplanted, the default setting will be used during compilation. This setting applies to arm's integrator platforms.

2.3 cut down functions implemented using the half-host mechanism

Most functions in library functions involve input/output stream devices. For example, file operation functions need to access disk I/O, and print functions need to access character output devices. In an embedded debugging environment, all standard C-library functions are effective and have their default behaviors. Many operations that are not supported by the hardware of the target system are completed through debugging tools. For example, for the printf () function, the default output device is the information output window in the debugger.

However, a real system needs to run independently from the debugging tool. Therefore, during the program porting process, you must first understand the running machines of these library functions.

Figure 3 illustrates the structure of C-library functions in ads.

Figure 3 hierarchical calling during function implementation in database C

4 as shown in the example, the printf () function eventually calls the underlying input/output function _ sys_write () to implement the output operation, while _ sys_write () the internal mechanism of the debugging tool is used to output information to the debugger.

Figure 4 printf () debugging process

Obviously, such a function call process cannot be implemented in a real embedded system, because the embedded system that runs independently will not be involved by the debugger. If you still need to retain the printf () function in the final system and have the correct output device (such as LCD) in the system hardware, you need () the called output device is redirected.

Simply considering the output redirection of printf (), there are three ways to achieve this:

◆ Rewrite printf () itself
◆ Rewrite fput ()
◆ Rewrite _ sys_write ()

It should be noted that the more underlying functions are called by other upper-layer functions, the more likely they are to change the implementation of an underlying function, then, all the upper-layer functions that call the function are changed.

Taking the re-implementation of fputc () as an example, the following example shows how to change the fputc () output device to the system serial communication port:

Int fputc (int ch, file * F)
{/* E.g. Write a character to an UART */
Char tempch = CH;
Sendchar (& tempch); // UART driver
Return ch ;}

The sendchar () function in the Code is assumed to be the serial device driver function of the system. As long as the fput () interface of the new function conforms to the standard, after compiling the link, the function implementation overwrites the original default function body, and all calls to the function, all of its behaviors are redirected by newly implemented functions.

3 semihosting Mechanism

As mentioned above, many library functions call a mechanism called semihosting In the debugging environment. Specifically, semihosting refers to an I/O device that allows code to run on an arm target but uses the host that runs the arm debugger; that is, a mechanism for the arm target to pass input/output requests from application code to the host running the debugger. Generally, these input/output devices include the keyboard, screen, and disk I/O.

A half host is implemented by a set of defined SWI operations, as shown in Figure 5. The library function calls the appropriate SWI (software interruption), then debugs the proxy program to handle SWI exceptions, and provides the required communication with the host. In most cases, half-host SWI is called by the code in the library function. However, applications can also directly call half-host SWI. The interface functions of half-host SWI are common. When a half-host operation is performed under a hardware simulator, instruction set simulator, realmonitor, Or Angel, no porting is required.

Figure 5 semihosting implementation process

Use a single SWI number to request a half-host operation. Other SWI numbers can be used by programs or operating systems. The SWI number used for the half host is:

In arm status: 0x123456
In the thumb status: 0xab

SWI number indicates to the debugging agent that the SWI request is a half host request. Identify the specific operation type and use the register R0 as the parameter. The available half-host operation numbers passed by R0 are allocated as follows:

◆ 0x00 ~ 0x31: these numbers are used by arm and correspond to 32 specific execution functions respectively.
◆ 0x32 ~ 0xff: these numbers are reserved by arm for future use as function extensions.
◆ 0x100 ~ 0x1ff: these numbers are reserved for the user application. However, if you write your own SWI operations, we recommend that you directly use the SWI command and SWI number, instead of adding the half host SWI number to these operation type numbers.
◆ 0x200 ~ 0 xffffffff: these numbers are not defined. These numbers are not currently used and are not recommended. The software interrupt number used by the half-host SWI can also be customized by the user. However, if the default Soft Interrupt number is changed, you need:
◆ Change the half-host SWI call of all code (including library code) IN THE SYSTEM
◆ Reconfigure the debugger to capture and respond to half-host requests so that the new SWI number can be used.

4. Application Environment initialization and migration based on the target system resources

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.