Application of ARM Position Independent Programming in Bootloader

Publisher:平章大人Latest update time:2015-03-13 Source: go-gddqKeywords:ARM  Bootloader Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
        ARM processors support position-independent programming, which means that programs loaded into any address space of the memory can run normally. Its design method plays an important role in the development of embedded application systems. This article first introduces the basic concepts and implementation principles of position-independent code, and then explains the programming method and implementation process of position-independent programming based on ARM assembly. Finally, taking embedded Bootloader programming as an example, it introduces the role of position-independent programming in Bootloader programming.

        introduction

  Programming based on position-independent code PIC (PositionIndependent Code) plays an important role in the development of embedded application systems, especially in the development of Bootloader programs and kernel initialization design in the bare metal state; the position-independent programming method can also be used to build high-efficiency dynamic link libraries in specific applications. Therefore, a deep understanding and proficiency in position-independent programming methods will help developers design simple and clear applications. This article first introduces the basic concepts and implementation principles of position-independent code, then explains the programming method and implementation process of position-independent programming based on ARM assembly, and finally takes Bootloader programming as an example to introduce the role of position-independent programming in Bootloader programming.

        1 Position-independent code and programming method

        1.1 Basic concepts and implementation principles

  An application must be compiled, assembled, and linked before it can become an executable file. During linking, all target files must be relocated, symbol reference rules must be established, and running addresses must be assigned to variables, functions, etc. When the program is executed, the system must load the code into the address space specified during linking to ensure that the program correctly references symbols such as variables and functions during execution so that the program can run normally. In a system with an operating system, the relocation process is automatically completed by the operating system.

  When designing the Bootloader program, it must be done in a bare metal environment, and the running address of the Bootloader image file must be set by the programmer. Normally, the Bootloader program is downloaded to the 0x0 address of the ROM for startup, and in most application systems, in order to start quickly, the Bootloader program is first copied to the SDRAM and then run. Generally, the addresses of the two are not the same, and the address relocation process of the program in the SDRAM must be completed by the programmer. In fact, since the Bootloader is the first program to be executed after the system is powered on, the copy of the Bootloader program and all the work before this must be completed by itself, and these instructions are executed in the ROM. In other words, these codes can be executed correctly even if they are not in the runtime address space specified at the time of linking. This is position-independent code, which is a special code that can be executed normally when loaded into any address space.

  Position-independent code is often used in the following situations:

  ◆ The program is dynamically loaded into the memory during operation.
  ◆ The program is loaded into the memory after being combined with different programs in different occasions (such as shared dynamic link libraries)
  . ◆ The mapping between different addresses during operation (such as the Bootloader program).

  Although the -fPIC option can be used to generate position-independent code for C language when compiling with GCC, this does not correct the inherent position-dependency defects in programming. In particular, for assembly language code, the programmer must follow certain programming guidelines to ensure the position independence of the program.

  1.2 Key points of position-independent programming for ARM processors

  The position-independent executable file PIE (PositionIndependent Executable) of the ARM program consists of two parts: position-independent code PIC and position-independent data PID (PositionIndependent Data).

  PID is mainly for the readable and writable data segment (.data segment), which stores global variables with initial values. In order to achieve its position independence, register R9 is usually used as a static base address register to point to the first address of the readable and writable segment, and the offset relative to the base address register is used to address the variables of the segment. This method is often used to generate multiple independent data segments for multiple instances of reentrant programs. In program design, it is generally not necessary to consider the position independence of the readable and writable segment, mainly because the readable and writable data is mainly allocated in SDRAM.

  PIC includes the code and read-only data (.text segment) in the program. To ensure that the program can run correctly in both ROM and SDRAM space (such as the Bootloader program in the bare metal state), position-independent code programming must be used. The following focuses on the key points of PIC programming.

  PIC follows the programming specifications of ATPCS (ARM Thumb Procedure Call Standard) of read-only segment position independence ROPI (Read Only Position Independence):

  (1) Program design specifications

  When referencing symbols in the same ROPI segment or another ROPI segment with a fixed relative position, it must be a PC-based symbol reference, that is, an offset relative to the current PC is used to implement a jump or a constant access.

  ① Position-independent program jump. In the ARM assembler, the relative jump instruction B/BL is used to implement program jump. The target address of the jump in the instruction is represented by an offset based on the current PC, which is independent of the absolute address value assigned to the address label during linking. Therefore, the code can jump to any position to achieve position independence.

  In addition, you can also use the ADR or ADRL pseudo-instructions to read the address label value into the PC to implement program jumps. This is because pseudo-instructions such as ADR or ADRL will be replaced by the compiler to operate on the address value based on the PC, but the address range that can be read in this way is small and varies depending on whether the address value is word-aligned. However, in ARM programs, using instructions such as LDR to directly read the address label value into the PC to implement program jumps is not position-independent. For example:

  LDRPC, =main

  The result of compiling the above LDR assembly pseudo-instruction is:

  LDRPC, [PC, OFFSET_TO_LPOOL]
  LPOOLDCD main

  It can be seen that although LDR loads the contents of a PC-based storage unit LPOOL into the PC, the storage unit stores the absolute address of the main function entry determined at link time, so the actual segment where the main function is located is not position-independent.

  ② Position-independent constant access. In applications, it is often necessary to read and write related registers to complete the necessary hardware initialization. To enhance the readability of the program, the EQU pseudo-instruction is used to assign values ​​to some constants, but position independence must be achieved during the access process. The following introduces the position-independent constant access method using the GPIO initialization of PXA270.

  GPIO_BASEEQU0x40e00000;
  GPIO base register address GPDR0EQU0x00c; offset relative to GPIO base register
  init_GPDR0EQU0xfffbfe00; initial value of register GPDR0
  LDRR1, =GPIO_BASE
  LDRR0, =init_GPDR0
  STRR0, [R1, #GPDR0]

  The compiled result of the above assembly code segment is:

  LDRR1, [PC, OFFSET_TO_GPIO_BASE]
  LDRR0, [PC, OFFSET_TO_init_GPDR0]
  STRR0, [R1, #0xc]
  GPIO_BASEDCD0x40e00000
  GPDR0DCD0x00c
  init_GPDR0DCD0xfffbfe00

  It can be seen that the LDR pseudo-instruction actually uses the offset based on the PC to reference the symbolic constants GPIO_BASE and init_GPDR0, so it is position-independent. From this, we can draw the following conclusion: using the LDR pseudo-instruction to read a constant into other general registers other than the PC can achieve position-independent constant access; but when an address value is read into the PC for program jump, the jump target is position-dependent.

  (2) Programming Specifications 2

  Other references by code in the ROPI segment must be absolute addresses, or writable data based on the static base registers of the read-write position-independent (RWPI) segment.

  Using absolute addresses can only reference symbols in code segments that have been relocated to specific locations. By introducing absolute addresses in position-independent code, the program can jump to a specified location. For example, assuming that stage 1 of the Bootloader copies its own code to the SDRAM address space specified during linking, when it wants to jump to the C program entry of stage 2, it can use the instruction "LDRPC, =main" to jump to the main function entry address of the program in SDRAM to start execution. This is because the program assigns an absolute address to the main function when compiling and linking, and the system implements program jumps by directly assigning the absolute address of the main function to the PC. If the relative jump instruction "Bmain" is used, it will only jump to the main function entry inside the boot ROM. [page]

  2 Application of Position Independent Code in Bootloader Design

  When using GNU tools to develop a bootloader, the program will use a linker script to set the memory map of the image file during linking. A simple linker script structure is as follows:

  OUTPUT_ARCH(arm)
  ENTRY(_start)
  SECTIONS {
    . = BOOTADDR;/*Bootloader start address*/
    __boot_start = .;
    .textALIGN(4): {/*Code segment.text*/
      *(.text)
    }
    .dataALIGN(4): {/*Data segment.data*/
      *(.data)
    }
    .gotALIGN(4): {/*Global offset table.got segment*/
      *(.got)
    }
    __boot_end = .;/*Bootloader image file end address*/
    .bssALIGN(16): {/*Stack segment.bss*/
      __bss_start = .;
      *(.bss)
    __bss_end = .;
    }
  }

  The syntax of the link script is not introduced here. It should be pointed out that the output segment address described in the link script is the virtual address VMA (Virtual Memory Address). The "virtual address" here only refers to the relocation of each output segment to the corresponding storage address space when the image file is executed, and has nothing to do with memory management. Therefore, the above link script actually specifies that the Bootloader image will be relocated to the storage address space starting from BOOTADDR when it is executed, so as to ensure that the symbols are correctly referenced at the relevant locations so that the program can run normally.

  After the ARM processor is reset, it always takes the first instruction from the address 0x0. Therefore, you only need to set BOOTADDR to 0, and then download the compiled executable binary file to the storage space starting from the 0x0 address of the ROM, and the program can be booted normally; however, once the image file is specified to start from the 0x0 address during linking, the Bootloader can only run in the ROM space starting from the 0x0 address, and cannot be copied to the SDRAM space to run for fast booting. Of course, for microprocessors with MMU functions such as PXA270, although the entire Bootloader image can be copied to SDRAM first, and then the MMU function is used to map the SDRAM space to the 0x0 address, and then continue to run in SDRAM; but this will complicate the design and implementation of the Bootloader on the one hand, and on the other hand, in some applications where the MMU function must be shielded (such as booting the armlinux system), the MMU cannot be used for address remapping.

  The above problem can be solved by using ARM's position-independent programming. When linking the program, just set BOOTADDR to the address of the SDRAM space (generally, the highest 1 MB storage space in SDRAM is used as the starting address). In this way, after the ARM processor is powered on and reset, the Bootloader can still start execution from address 0 and copy itself to the SDRAM starting from the specified __boot_start to run. The startup code architecture corresponding to the link script that implements the above function is as follows:

  .section .text
  .globl _start
  _start:
  Breset/*Reset exception*/
  /*Other exception handling code*/
  reset:
  /*Reset handler*/
  copy_boot:/*Copy Bootloader to SDRAM*/
  LDRR0, =0x0LDRR1, =__boot_start
  LDRR2, =__boot_end
  1:LDRMIA R0!, { R3-R10 }
  STRMIA R1!, { R3-R10 }
  CMPR1, R2
  BLT1b
  clear_bss:
  /*Clear .bss segment*/
  BL
  init_Stack/*Initialize stack*/
  LDRPC, = main/*Jump to C program entry of stage 2*/
  .end

  The program entry is _start, which is the reset exception. All other exception vectors are implemented using the relative jump instruction B to ensure position independence. After completing the basic hardware initialization, the Bootloader image is copied to the specified SDRAM space using the parameters of __boot_start and __boot_end passed by the link script, and the .bss segment is cleared. After initializing the stack, the program assigns the absolute address of the main function entry to the PC, and then jumps to the SDRAM to continue running. Before the program jumps to the main function, all the code runs in the ROM, so the position independence of the code must be guaranteed. Therefore, when calling subroutines such as initializing GPIO, storage system, and stack, relative jump instructions are used to complete it.

  Using position-independent design Bootloader program has the following advantages:

  ① Simplify the design and facilitate fast booting of the system. Position-independent code can avoid address mapping during booting and easily jump to SDRAM for fast booting.
  

  ② Realize intelligent reset processing. Since position-independent code can be loaded into any address space for execution, the current address at runtime is not necessarily the same as the address assigned at link time. Using this feature, you can add the following code to the reset handler after making the processor enter SVC mode and disable interrupts, so that different reset processing can be performed according to the current runtime address:

  ADRR0, _start/*Read the instruction address of the _start label near the current PC*/
  LDRR1,=__boot_start/*Read the starting address of the Bootloader in SDRAM*/
  CMPR0,R1
  BEQclear_bss

  The _start label address read by the ADR instruction in the above code is determined by the execution address of the instruction. If it is started from the Bootloader in SDRAM, the above comparison results are equal, and the program directly jumps to the clear_bss label address for execution, which can avoid the reinitialization of the storage system and the copy process of the Bootloader; if it is powered on or hardware reset, the program is started from ROM, and the above comparison results are not equal, and the program will perform a comprehensive reset processing operation including system initialization and Bootloader copying.

  ③ Easy to debug. Bootloader debugging is usually a tedious process. Using position-independent code, the image file can be loaded into SDRAM for debugging, which can truly reflect the situation of the program booting the system from ROM and avoid frequent burning of program memory.

  3 Conclusion

  The position-independent programming introduced in this article is implemented through symbol reference specifications based on PC or base registers. This method is widely used in actual system development, and can be used for boot program design, general application program development or embedded shared library development. Introducing position-independent code in the design of Bootloader can make the program structure simpler and clearer, avoid address remapping and quickly boot the system from SDRAM; referencing the position-independent design method makes the reset processing function of Bootloader more flexible, and also makes the program debugging in SDRAM and ROM have the same effect.

  references

  [1] Du Chunlei. ARM Architecture and Programming [M]. Beijing: Tsinghua University Press, 2003.
  [2] Chen Wenzhi. Principles and Practices of Embedded System Development [M]. Beijing: Tsinghua University Press, 2005.
  [3] ARM Limited. ARM Architecture Reference Manual. 2nd ed,2000.
  [4] ARM Limited. ADS Developer Guide. Release 1.2,200111.
  [5] ARM Limited. ADS Assembler Guide. Release 1.2,200111.
  [6] Red Hat Inc. Using ld, the GNU linker. Version 2.14.

Keywords:ARM  Bootloader Reference address:Application of ARM Position Independent Programming in Bootloader

Previous article:Research on 32-bit high-end embedded microprocessor and embedded operating system kernel based on ARM9
Next article:Implementation of S3C2410 interrupt program

Recommended ReadingLatest update time:2024-11-16 21:59

ARM11-S3C6410 UART
I think the serial port program is probably the simplest ARM program. However, let me make a note of it.     The specific settings are as follows:    #define ULCON0     (*((volatile unsigned long *)0x7F005000)) #define UCON0      (*((volatile unsigned long *)0x7F005004)) #define UFCON0     (*((volat
[Microcontroller]
ARM11-S3C6410 UART
Research on power of solar power generation control system based on ARM
introduction At present, the domestic solar automatic trackers in my country mainly include: differential pressure solar tracker, controlled release solar tracker, clock solar tracker, and comparative control solar tracker. Pure mechanical trackers and clock electromechanical trackers have low accuracy. This sy
[Microcontroller]
Research on power of solar power generation control system based on ARM
Development of a New Embedded ECG Monitor Based on ARM7
1. Introduction        Cardiovascular disease is currently the most harmful disease to humans, and the electrocardiogram is the main means and basis for the examination, diagnosis and prevention of this type of disease. Because the traditional PC-based ECG monitor is expensive, bulky, not easy to move and mainly conce
[Microcontroller]
Development of a New Embedded ECG Monitor Based on ARM7
Microchip Launches New Arm®-Based PIC® Microcontroller Family
Microchip Launches New Arm®-Based PIC® Microcontroller Family, Easier Way to Add Bluetooth® Low Energy Connectivity The PIC32CX-BZ2 MCU family offers built-in Bluetooth Low Energy (BLE) and other wireless capabilities, outstanding analog performance and comprehensive design support
[Microcontroller]
Microchip Launches New Arm®-Based PIC® Microcontroller Family
Hexadecimal conversion to decimal display program based on arm7 chip lpc2138
#include LPC213X.H   void delay(int x) { while(--x); }   void DsipInit() { PINSEL0= 0; PINSEL1|= 0x0 6; IO0DIR |= 0xffff 7; IO0CLR = 0xffff 7;      } void Display(unsigned int val) { int k, m; IO0CLR = 0xffff 7; k=((val&(0x0f0)) 4)*16+((val&(0xf00)) 8)*16*16+(val&(0x00f));//Convert hexadecimal to de
[Microcontroller]
Hexadecimal conversion to decimal display program based on arm7 chip lpc2138
Design of CAN bus analyzer based on ARM microcontroller and smart phone
In view of the need for CAN bus communication quality, testing and verification, as well as the complexity of traditional CAN analyzers and the insufficiency of having to use a PC as a display terminal, a design of a CAN bus analyzer based on an ARM microcontroller and a smart phone is demonstrated. The analyzer uses
[Test Measurement]
Design of CAN bus analyzer based on ARM microcontroller and smart phone
Surprise! Arm China Executive Chairman and CEO Wu Xiong'ang was dismissed
        On June 10, according to the 21st Century Business Herald, Arm China Executive Chairman and CEO Wu Xiong'ang was dismissed.   "The past week has been in a tense state, and it involves legal procedures such as the replacement of the legal person. It has not been announced to the public yet." It is reported tha
[Embedded]
Surprise! Arm China Executive Chairman and CEO Wu Xiong'ang was dismissed
Registration is now open for Arm Tech Symposia
The industry-renowned Arm® Tech Symposia annual technology conference will kick off at the Ritz-Carlton Hotel in Pudong, Shanghai on November 19, 2024, and will move to the Renaissance Shenzhen Bay Hotel on November 21. As Arm's most important annual technology event, this year's Arm Tech Symposia, with the
[Network Communication]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号