do {
Add / modify source code
} until (compiles);
Debug;
...
}
Jerry's process, as summarized here, is the simple truth. When you have selected a baseline from which to port, you must add, delete, and modify source code until it compiles, and then debug it until it is running without error! There is no magic formula. Porting any bootloader to a new board requires knowledge of many areas of hardware and software. Some of these disciplines, such as setting up SDRAM controllers, are rather specialized and complex. Virtually all of this work involves a detailed knowledge of the underlying hardware. The net result: Be prepared to spend many entertaining hours poring over your processor's hardware reference manual, along with the data sheets of numerous other components that reside on your board.
7.4.2. U-Boot Makefile Configuration Target
Now that we have a code base to start from, we must make some modifications to the top-level U-Boot makefile to add the configuration steps for our new board. Upon examining this makefile, we find a section for configuring the U-Boot source tree for the various supported boards. We now add support for our new one so we can build it. Because we derived our board from the ESD AR405, we will use that rule as the template for building our own. If you follow along in the U-Boot source code, you will see that these rules are placed in the makefile in alphabetical order of their configuration name. We shall be good open-source citizens and follow that lead. We call our configuration target EP405_config, again in concert with the U-Boot conventions.
EBONY_config: unconfig
@./mkconfig $(@:_config=) ppc ppc4xx ebony
+EP405_config: unconfig
+ @./mkconfig $(@:_config=) ppc ppc4xx ep405
+
ERIC_config: unconfig
@./mkconfig $(@:_config=) ppc ppc4xx eric
Our new configuration rule has been inserted as shown in the three lines preceded with the + character (unified diff format).
Upon completing the steps just described, we have a U-Boot source tree that represents a
7.4.3. EP405 Processor Initialization
The first task that your new U-Boot port must do correctly is to initialize the processor and the memory (DRAM) subsystems. After reset, the 405GP processor core is designed to fetch instructions starting from 0xFFFF_FFFC. The core attempts to execute the instructions found here. Because this is the top of the memory range, the instruction found here must be an unconditional branch instruction.
This processor core is also hard-coded to configure the upper 2MB memory region so that it is accessible without programming the external bus controller, to which Flash memory is usually attached. This forces the requirement to branch to a location within this address space because the processor is incapable of addressing memory anywhere else until our bootloader code initializes additional memory regions. We must branch to somewhere at or above 0xFFE0_0000. How did we know all this? Because we read the 405GP user's manual!
The behavior of the 405GP processor core, as described in the previous paragraph, places requirements on the hardware designer to ensure that, on power-up, nonvolatile memory (Flash) is mapped to the required upper 2MB memory region. Certain attributes of this initial memory region assume default values on reset. For example, this upper 2MB region will be configured for 256 wait states, three cycles of address-to-chip select delay, three cycles of chip select to output enable delay, and seven cycles of hold time. [58] This allows maximum freedom for the hardware designer to select appropriate devices or methods of getting instruction code to the processor directly after reset.
We've already seen how the reset vector is installed to the top of Flash in Listing 7-2. When configured for the 405GP, our first lines of code will be found in the file .../cpu/ppc4xx/start.S. The U-Boot developers intended this code to be
We don't need to understand PowerPC assembly language in any depth to understand the logical flow in start.S. Many frequently asked questions (FAQs) have been posted to the U-Boot mailing list about modifying low- level assembly code. In nearly all cases, it is not necessary to modify this code if you are porting to one of the many supported processors. It is mature code, with many successful ports running on it. You need to modify the board-specific code (at a bare minimum) for your port. If you find yourself troubleshooting or modifying the early startup assembler code for a processor that has been around for a while, you are most likely heading down the wrong road.
Listing 7-6 reproduces a portion of start.S for the 4
Listing 7-6. U-Boot 4xx startup code
...
#if defined(CONFIG_405GP) || defined(CONFIG_405CR) ||
defined(CONFIG_405) || defined(CONFIG_405EP)
/*--------------------------------- */
/* Clear and set up some registers. */
/*--------------------------------- */
addi r4,r0,0x0000
mtspr sgr,r4
mtspr dcwr,r4
mtesr r4 /* clear Exception Syndrome Reg */
mttcr r4 /* clear Timer Control Reg */
mtxer r4 /* clear Fixed-Point Exception Reg */
mtevpr r4 /* clear Exception Vector Prefix Reg */
addi r4,r0,0x1000 /* set ME bit (Machine Exceptions) */
oris r4,r4,0x0002 /* set CE bit (Critical Exceptions) */
mtmsr r4 /* change MSR */
addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */
/* dbsr is cleared by setting bits to 1) */
mtdbsr r4 /* clear/reset the dbsr */
/*---------------------------------- */
/* Invalidate I and D caches. Enable I cache for defined memory regions */
/* to speed things up. Leave the D cache disabled for now. It will be */
/* enabled/left disabled later based on user selected menu options. */
/* Be aware that the I cache may be disabled later based on the menu */