Order Number: AN1809/D Rev. 0, 3/2000 Semiconductor Products Sector Application Note A Minimal PowerPCª Boot Sequence for Executing Compiled C Programs PowerPC Systems Architecture & Performance risc10@email.sps.mot.com This document describes the procedures necessary to successfully initialize a PowerPC processor and begin executing programs compiled using the PowerPC embedded application interface (EABI).
Overview Part I Overview The procedures discussed in this document perform only the minimum amount of work necessary to execute a user program. The sample boot sequence is designed to run from system reset. It does not contain exception handling facilities for other exceptions, although the code is located so that it doesnÕt interfere with exception space. This allows users who wish to provide exception handling to add exception code without modifying this source.
PowerPC Processor Initialization 2.2 Memory Management Unit A boot program will need to set up the MMU if memory management is required. Using the MMU to translate memory addresses allows the programmer to specify protections and access controls for individual regions of memory. For a minimal system with four or fewer memory regions, it is sufÞcient to use block address translation (BAT) to perform a rudimentary mapping.
PowerPC Processor Initialization The procedure for initializing a pair of BAT registers is as follows: 1. 2. 3. 4. 5. 6. Disable the MMU. If modifying a data BAT, execute an isync instruction. Initialize the lower portion of the BAT array entry. Initialize the upper portion of the BAT array entry. Execute an isync instruction. Re-enable the MMU when all setup is complete. Unused BAT registers must be invalidated by clearing the Vs and Vp bits in the upper BAT register before enabling and translating.
PowerPC Processor Initialization Table 4. Block Access Protection Control Vs Vp PP Block Type 0 0 xx No BAT match 0 1 00 UserÑno access 1 0 00 SupervisorÑno access 0 1 x1 UserÑread only 1 0 x1 SupervisorÑread only 0 1 10 UserÑread/write 1 0 10 SupervisorÑread/write 1 1 00 BothÑno access 1 1 x1 BothÑread only 1 1 10 BothÑread/write In addition, the programmer may specify the memory/cache access modes for the mapped region.
PowerPC Processor Initialization When the MMU setup completes, the MMU may be enabled by setting MSR bits 26 and 27, Instruction Address Translation (IR) and Data Address Translation (DR). At this point, address translation is active. 2.3 Caches At power-up, the L2 cache (if available) and L1 instruction and data caches are disabled. These should be turned on to boost program performance.
PowerPC EABI Compliance Part III PowerPC EABI Compliance The PowerPC EABI speciÞes the system interface for compiled programs. The EABI is based on the System V Application Binary Interface and the PowerPC Processor Supplement. For general ABI documentation, refer to these documents, as well as the PowerPC Embedded Application Binary Interface. This document only includes aspects of the EABI that apply directly to preparing to jump into a compiled C program.
Sample Boot Sequence Much of the required EABI register setup is accomplished through a call to __eabi(). The user does not call this function directly. Instead, the compiler inserts the call to __eabi() at the beginning of main() in the user program. Most compile environments provide an __eabi() function that is automatically linked with user programs. Unfortunately, this standard __eabi() is often designed to work with a particular operating system or environment..
Sample Boot Sequence 4.1 ConÞgurable Options The design of the sample boot sequence allows it to be easily conÞgurable. The many options deÞned in the header Þles allow the user to choose how the code should execute. These options are summarized in Table 6. Table 6. User-Configurable Program Options Option DeÞnition Location DeÞnition Default Value USER_ENTRY ppcinit.h SpeciÞes the name of the entry point in the user C program.
Sample Boot Sequence Table 6. User-Configurable Program Options (Continued) Option DeÞnition Location DeÞnition Default Value PRAM_BASE ppcinit.h The start address of the address range corresponding to the physical address of the RAM. 0x0000_0000 VROM_BASE ppcinit.h The start address of the address range corresponding to the virtual address of the ROM. PROM_BASE VRAM_BASE ppcinit.h The start address of the address range corresponding to the virtual address of the RAM.
Sample Boot Sequence Table 7 shows the default BAT register values. Table 7.
Sample Boot Sequence Each of these options can be conÞgured in order to customize the boot sequence for a particular application. The conÞgurable boot sequence contains #deÞne statements that can be combined to easily create BAT entry values. For example, the default entry for the upper instruction BAT 1 speciÞes a 32-Mbyte block size, valid user mode, valid supervisor mode, with a BEPI of 0x0000_0000.
Sample Boot Sequence 4.4 Code Relocation The code relocation depends on variables that are allocated in the Þle ld.script. The text, data, and bss sections of the program may be relocated from ROM to RAM using these variables. The Þrst relocation that takes place is the text relocation. The relocation code looks at the ld.script variables _img_text_start and _Þnal_text_start to determine if the text must be relocated. If the two variables are equal, then no text relocation occurs.
Sample Boot Sequence The transition from .S and .c Þles to .o Þles is accomplished using gcc -c : ppcinit.o: ppcinit.h ppcinit.S $(CC) -c ppcinit.S test.o: test.c $(CC) -c test.c $(CC) must be deÞned as the path to the cross-compiler. (See Part V, ÒSource Files,Ó Section 5.5, ÒMakeÞle.Ó) Note that the assembly source Þle is named ppcinit.S as opposed to ppcinit.s. This causes the preprocessor to run and strip out the C++ style comments.
Sample Boot Sequence The example .text section is located at 0xFFF0_0000 in the compiled image and at 0x0000_0000 after the relocation. The sample boot code places its Þrst executable instruction at an offset of 0x0100 from the start address using the .space assembler directive. This means that this Þrst instruction will be located at the PowerPC system reset vector, 0xFFF0_0100, and it is executed when system reset occurs.
Sample Boot Sequence *(.dynamic); _final_data_end = .; } /* Now save off the start of the data in the image */ _img_data_start = LOADADDR(.data); The _Þnal_data_start and _Þnal_data_end symbols indicate the post-relocation start and end addresses of the data section. In addition, the symbol _img_data_start holds the start address of the data section in the ROM image. This information will be used during the relocation of the data. The linker script treats the bss section much like the data section.
Sample Boot Sequence 4.6 Using the Sample Boot Sequence Using the sample boot sequence requires setting up the conÞgurable parameters to describe a particular hardware conÞguration. The process is described as follows: In ppcinit.h: 1. #deÞne either MPC603e, MPC750, or MPC7400 to match the processor type. One of these must be deÞned for the code to work properly. 2. To use the instruction cache, #deÞne ICACHE_ON to 1. To disable the instruction cache, deÞne it to 0. 3.
Sample Boot Sequence 4.7 Limitations of the Sample Boot Sequence The sample boot sequence is intended to be used in a controlled environment and is designed to be as minimal as possible. As a result, there are some limitations to its design and use as follows: 1. The image should be built to be initially located at either 0xFFF0_0000 or 0x0000_0000. 2. Memory is mapped via the BAT registers. The segment registers and page tables are not used. 3.
Source Files Part V Source Files The following sections contain the complete source code for the Þles ppcinit.S, ppcinit.h, ld.script, and makeÞle. 5.1 ppcinit.S /* // // // // // // // // // // // // // // // // // // // // // // // // */ This file contains generic boot init code designed to be run on PowerPC processor simulations that just need minimal setup.
Source Files // hereÕs the real startup code, located outside the exception vector space system_reset: addis r0,0,0x0000 // from reset, the BATs are in an unknown state on most PPCs. // Invalidate them all to avoid error states mtspr ibat0u,r0 mtspr ibat1u,r0 mtspr ibat2u,r0 mtspr ibat3u,r0 isync mtspr dbat0u,r0 mtspr dbat1u,r0 mtspr dbat2u,r0 mtspr dbat3u,r0 isync // If thereÕs L2 cache we enable later, set it up and invalidate it.
Source Files // turn mfspr rlwinm mtspr #endif off the L2I global invalidate bit r3, l2cr r3,r3,0,11,9 l2cr, r3 // L2CACHE_ENABLE // Note MSR state at power-up: // all exceptions disabled, address translation off, // Exception prefix at 0xfff00000, FP disabled #if MMU_ON // // // // // // // // == 1 If the code specifies that weÕre going to use the MMU, branch to to the setup function that handles setting up the BATs and invalidating TLB entries.
Source Files // get the start address of the main routine of the code we want to run. addis r3,r0,USER_ENTRY@h ori r3,r3,USER_ENTRY@l mtspr srr0,r3 // Set the MSR. // we just move the value into srr1 - it will get copied into // the msr upon the rfi.
Source Files addis ori r1,r0,STACK_LOC@h r1,r1,STACK_LOC@l // STACK_LOC defined in ppcinit.
Source Files //--------------------------------------------------------------------------// Label: relocate_image // // copy this image and the user code into RAM space. // Note that the starting locations of text, data, and bss are // defined in the ld.script. Make sure these definitions, // as well as the definition for STACK_LOC in ppcinit.h, give // ample room for your image.
Source Files cont1: lwzx stwx lwzx cmp bne r5,0,r4 r5,0,r3 r8,0,r3 0,0,r8,r5 error addi addi r4,r4,4 r3,r3,4 cmp ble 0,0,r3,r7 cont1 // This clear_bss code can be removed if youÕre sure you never // depend on unitialized data being 0.
Source Files setup_bats: 26 addis r0,r0,0x0000 addis ori addis ori mtspr mtspr isync r4,r0,IBAT0L_VAL@h r4,r4,IBAT0L_VAL@l r3,r0,IBAT0U_VAL@h r3,r3,IBAT0U_VAL@l ibat0l,r4 ibat0u,r3 addis ori addis ori mtspr mtspr isync r4,r0,DBAT0L_VAL@h r4,r4,DBAT0L_VAL@l r3,r0,DBAT0U_VAL@h r3,r3,DBAT0U_VAL@l dbat0l,r4 dbat0u,r3 addis ori addis ori mtspr mtspr isync r4,r0,IBAT1L_VAL@h r4,r4,IBAT1L_VAL@l r3,r0,IBAT1U_VAL@h r3,r3,IBAT1U_VAL@l ibat1l,r4 ibat1u,r3 addis ori addis ori mtspr mtspr isync r4,r0,DBAT1L_V
Source Files addis ori addis ori mtspr mtspr isync r4,r0,IBAT3L_VAL@h r4,r4,IBAT3L_VAL@l r3,r0,IBAT3U_VAL@h r3,r3,IBAT3U_VAL@l ibat3l,r4 ibat3u,r3 addis ori addis ori mtspr mtspr isync r4,r0,DBAT3L_VAL@h r4,r4,DBAT3L_VAL@l r3,r0,DBAT3U_VAL@h r3,r3,DBAT3U_VAL@l dbat3l,r4 dbat3u,r3 // BATs are now set up, now invalidate tlb entries addis r3,0,0x0000 #ifdef MPC603e addis r5,0,0x2 // set up high bound of 0x00020000 for 603e #endif #if defined(MPC750) || defined(MPC7400) addis r5,0,0x4 // 750/MAX have 2x as
Source Files #ifdef MPC603e rlwinm mtspr #endif blr r6,r5,0,22,20 hid0,r6 //----------------------------------------------------------------------// Function: invalidate_and_enable_L1_icache // // Flash invalidate and enable the L1 icache //----------------------------------------------------------------------invalidate_and_enable_L1_icache: mfspr r5,hid0 ori r5,r5,0x8800 isync mtspr hid0,r5 #ifdef MPC603e rlwinm mtspr #endif blr r6,r5,0,21,19 hid0,r6 //--------------------------------------------------
Source Files //--------------------------------------------------------------------// // Define space for data items needed by this code // //--------------------------------------------------------------------.data /* save time base to use for benchmarking numbers */ TBUSAVE: .double 0 TBLSAVE: .double 0 5.2 ppcinit.h #include "reg_defs.h" /* contains bit defines and register names */ /* Set the entry point into the user code. defined as main.
Source Files * RAM type = burst SRAM * Output Hold = 0.5ns * * These may need to be changed for your board.
Source Files #define DBAT0L_VALIBAT0L_VAL #define DBAT0U_VALIBAT0U_VAL #define #define #define #define IBAT1L_VAL IBAT1U_VAL DBAT1L_VAL DBAT1U_VAL (PRAM_BASE | BAT_READ_WRITE) (VRAM_BASE|BAT_BL_32M|BAT_VALID_SUPERVISOR| BAT_VALID_USER) IBAT1L_VAL IBAT1U_VAL #define #define #define #define IBAT2L_VAL IBAT2U_VAL DBAT2L_VAL DBAT2U_VAL (BAT_NO_ACCESS) (BAT_INVALID) (BAT_NO_ACCESS) (BAT_INVALID) #define #define #define #define IBAT3L_VAL IBAT3U_VAL DBAT3L_VAL DBAT3U_VAL (BAT_NO_ACCESS) (BAT_INVALID) (BAT
Source Files #define dbat3u 542 #define dbat3l 543 #define pvr 287 #define l2cr 1017 /* general BAT defines for bit settings to compose BAT regs */ /* represent all the different block lengths */ /* The BL field is part of the Upper Bat Register */ #define #define #define #define #define #define #define #define #define #define #define #define BAT_BL_128K BAT_BL_256K BAT_BL_512K BAT_BL_1M BAT_BL_2M BAT_BL_4M BAT_BL_8M BAT_BL_16M BAT_BL_32M BAT_BL_64M BAT_BL_128M BAT_BL_256M 0x00000000 0x00000004 0x0000000C
Source Files #define #define #define #define #define #define L2CR_L2I L2CR_TS L2CR_TS_OFF L2CR_L2OH_5 L2CR_L2OH_1 L2CR_L2OH_INV 0x00200000 0x00040000 ~L2CR_TS 0x00000000 0x00010000 0x00020000 /* /* /* /* /* /* bit 10 Global invalidate bit */ bit 13 Test support on */ bit 13 Test support off */ bits 14-15 Output Hold time = 0.5ns*/ bits 14-15 Output Hold time = 1.0ns*/ bits 14-15 Output Hold time = 1.0ns*/ 5.4 ld.
Source Files DATA_START = DEFINED(DATA_START) ? DATA_START : (((ADDR(.text) + SIZEOF(.text)) & 0xFFFFFFE0) + 0x00000020); IMAGE_DATA_START = DEFINED(IMAGE_DATA_START) ? IMAGE_DATA_START : (((LOADADDR(.text) + SIZEOF(.text)) & 0xFFFFFFE0) + 0x00000020); .data DATA_START : AT (IMAGE_DATA_START) { _final_data_start = .; *(.data) *(.data1) *(.sdata) *(.sdata2) *(.got.plt) *(.got) *(.dynamic) *(.fixup); _final_data_end = .; } /* Now save off the start of the data in the image */ _img_data_start = LOADADDR(.
Source Files .debug_pubnames 0 : {*(.debug_pubnames)} .debug_sfnames 0 : {*(.debug_sfnames)} .line 0 : {*(.line)} } 5.5 MakeÞle PREFIX TARGET = /path/to/your/cross-compiler/gnu-solaris = powerpc-eabi CC = $(PREFIX)/bin/$(TARGET)-gcc LD = $(PREFIX)/bin/$(TARGET)-gcc OBJCOPY = $(PREFIX)/bin/$(TARGET)-objcopy OBJDUMP = $(PREFIX)/bin/$(TARGET)-objdump # # Define locations for the text and data code sections. The bss # gets tacked on to the end of the data by the linker script, # don't worry about it.
Source Files LDFLAGS += -Wl,--defsym,DATA_START=$(DATA_START) \ -Wl,--defsym,IMAGE_DATA_START=$(IMAGE_DATA_START) endif # define options for the objdump DUMPFLAGS = --syms --disassemble-all # list C modules to link with the init code here C_SRC = test.c C_OBJS = $(C_SRC:.c=.o) # use variables to refer to init code in case it changes PPCINIT = ppcinit.o PPCINIT_DEP = reg_defs.h ppcinit.h ppcinit.S # # define build targets # all: go.srec clean: rm *.o *.elf *.srec *.dump *.
Source Files A Minimal PowerPCª Boot Sequence for Executing Compiled C Programs 37
Source Files 38 A Minimal PowerPCª Boot Sequence for Executing Compiled C Programs
Source Files A Minimal PowerPCª Boot Sequence for Executing Compiled C Programs 39
DigitalDNA and Mfax are trademarks of Motorola, Inc. The PowerPC name, the PowerPC logotype, and PowerPC 603e are trademarks of International Business Machines Corporation used by Motorola under license from International Business Machines Corporation. Information in this document is provided solely to enable system and software implementers to use PowerPC microprocessors.