Resumen de los principales puntos en la sección 8
Sección 9 : Elaborando Criterios
9.6 Proceso de pesaje y sus resultados
Intel's IXP425 processor is the core of several reference designs including the IXDP425 and the Coyote boards. The porting work for these platforms is similar. This porting guide will focus on the Coyote platform. The example board is named Cute, which is based on the Coyote platform and is equipped with Ethernet LAN and Ethernet WAN.
7.3.1 Distribution
The distribution of Coyote is defined as described before in the pkg/build directory in files config_opt.c, hw_config.c and dist_config.c. In our example using the Cute board, you would need to make the following changes:
1. config_opt.c – Extend the array openrg_hw_options with another entry for the new board, similar to the COYOTE entry, which should be:
{ "CUTE", "Cute" },
In addition, add a new entry to the openrg_distribution_options array, similar to the COYOTE entry, which should be:
{ "CUTE", NULL },
Finally, add a new entry to the config_option_base array, which defines the new architecture of the machine you will be adding to the kernel. According to the example above, you would need to add the following:
{ "CONFIG_ARCH_IXP425_CUTE", NULL },
2. hw_config.c – Add a new section that defines the specific hardware available on your board. You could copy the COYOTE section and modify it to reflect your board. The section below shows an example of how the Cute board, which has only Ethernet LAN and WAN, is defined:
if (IS_HW("CUTE")) {
token_set_y("CONFIG_IXP425_COMMON_RG");
token_set_y("CONFIG_ARCH_IXP425_CUTE"); /* CUTE machine */
token_set("CONFIG_RG_FLASH_LAYOUT_SIZE", "16"); /* 16MB flash */
token_set("CONFIG_IXP425_SDRAM_SIZE", "32"); /* 32MB SDRAM */
token_set("CONFIG_IXP425_NUMBER_OF_MEM_CHIPS", "2"); /* in 2 chips */
token_set("CONFIG_RG_CONSOLE_DEVICE", "ttyS1");
token_set("CONFIG_IXDP425_KGDB_UART", "1");
if (token_get("CONFIG_HW_ETH_WAN")) {
token_set_m("CONFIG_IXP425_ETH");
dev_add("ixp1", DEV_IF_IXP425_ETH, DEV_IF_NET_EXT);
}
if (token_get("CONFIG_HW_ETH_LAN")) {
token_set_m("CONFIG_IXP425_ETH");
dev_add("ixp0", DEV_IF_IXP425_ETH, DEV_IF_NET_INT);
}
token_set("FIRM", "Cute_company");
token_set("BOARD", "CUTE");
/* Flash chip */
token_set("CONFIG_IXP425_FLASH_E28F128J3", "m");
}
3. dist_config.c – Add a new section for each configuration of the software modules that you would like to build on that hardware. For example, you might want to build several products with different feature sets on the same hardware platform (remember to add each distribution name to the config_opt.c file). The following shows the definitions that will turn the Cute board into a simple Ethernet-Ethernet router with a firewall.
if (IS_DIST("CUTE")) {
hw = "CUTE";
token_set_y("MODULE_RG_FOUNDATION");
token_set_y("MODULE_RG_UPNP");
token_set_y("MODULE_RG_PPP");
token_set_y("MODULE_RG_FIREWALL_AND_SECURITY");
token_set_y("MODULE_RG_ADVANCED_MANAGEMENT");
token_set_y("MODULE_RG_ADVANCED_ROUTING");
/* HW Configuration Section */
token_set_y("CONFIG_HW_ETH_WAN");
token_set_y("CONFIG_HW_ETH_LAN");
goto Exit;
}
The definition of the distribution includes the software modules that are included in it, and the hardware features of the board that are required. In this case, the distribution includes the foundation module, zero-configuration module, PPP module, firewall and security module, advanced management, and advanced routing module. The configured hardware devices are the Ethernet WAN and LAN network devices (which are the only hardware available on this board).
7.3.2 Platform
The IXP425 processor is based on the ARM architecture and each new platform using it should be introduced to the Linux kernel. All the source files referred to in this section are relative to the Linux kernel root directory, which is under the os/linux-<version> directory, for example, os/linux-2.4. The first step is to assign your board with a unique machine number.
The machine numbers are defined in arch/arm/tools/mach-types, and you should add an entry describing your hardware platform to this file. The entry should be added at the end of the file.
For example, the Coyote entry in this file is:
coyote ARCH_IXP425_COYOTE COYOTE 357
These names are used in various places to define the machine. The first and third columns are the platform name, where the first is in lower case and the third is in upper case. The second column should be ARCH_IXP425_<platform> and the last column should be a unique number. In our example, the platform name is "Cute" and we would add a line which could look as follows:
cute ARCH_IXP425_CUTE CUTE 370
The next step, is to set the machine type to register R1. The file you would need to change is arch/arm/kernel/head-armv.S and the lines related to the Coyote platform are:
#elif defined(CONFIG_ARCH_IXP425_COYOTE) ldr r1, =MACH_TYPE_COYOTE
#elif ...
#else
When working on the Cute board, you would add the following lines to this file right before the
#else line:
#elif defined(CONFIG_ARCH_IXP425_CUTE) ldr r1, =MACH_TYPE_CUTE
Next, you need to define the architecture's name and initialization routines. You should do this in the arch/arm/mach-ixp425/arch.c file as shown in the Coyote example below:
#ifdef CONFIG_ARCH_IXP425_COYOTE
MACHINE_START(COYOTE, "Intel IXP425 Coyote") MAINTAINER("Intel - IABU")
/* Memory Base, Phy IO, Virtual IO */
BOOT_MEM(PHYS_OFFSET, IXP425_PERIPHERAL_BASE_PHYS, IXP425_PERIPHERAL_BASE_VIRT)
MAPIO(ixp425_map_io) INITIRQ(ixp425_init_irq) MACHINE_END
#endif
For the Cute example board we would add the following lines at the end of the file (simply replace every "COYOTE" with "CUTE" and every "Coyote" with "Cute"):
#ifdef CONFIG_ARCH_IXP425_CUTE
MACHINE_START(CUTE, "Intel IXP425 Cute") MAINTAINER("Intel - IABU")
/* Memory Base, Phy IO, Virtual IO */
BOOT_MEM(PHYS_OFFSET, IXP425_PERIPHERAL_BASE_PHYS, IXP425_PERIPHERAL_BASE_VIRT)
MAPIO(ixp425_map_io) INITIRQ(ixp425_init_irq)
MACHINE_END
#endif
7.3.3 Boot Sequence
7.3.3.1 Image Structure
The OpenRG image for IXP425-based platforms is constructed by the Makefile in directory os/linux-2.4/arch/arm/boot. There are several options that you might need to adjust in order to build the image that will suit your platform. The following is an excerpt from the Makefile, which describes the parameters that might be influenced by your platform available memory:
ifeq ($(CONFIG_ARCH_IXP425),y) ZRELADDR = 0x00008000 ZTEXTADDR = 0x00A00000 ZBSSADDR = ALIGN(4)
export INITRD = $(TOPDIR)/arch/arm/boot/ramdisk.gz
ifdef CONFIG_RG_BOOTSTRAP
export BOOTSTRAP = $(TOPDIR)/arch/arm/mach-ixp425/bootstrap.o endif
ifdef CONFIG_IXP425_POST
export POST = $(TOPDIR)/arch/arm/boot/post/post_crt.o \ $(TOPDIR)/arch/arm/boot/post/post_mmu.o \ $(TOPDIR)/arch/arm/boot/post/romInit.o \ $(TOPDIR)/arch/arm/boot/post/romuart.o \ $(TOPDIR)/arch/arm/boot/post/romstr.o endif
INITRD_PHYS = 0x00A00000 PARAMS_PHYS = 0x00002000 endif
In order to build an image that could bootstrap the platform, you need to turn on the
CONFIG_RG_BOOTSTRAP option in the distribution process. The RGLoader distribution is supplied with this configuration option already turned on. In case your platform is not going to include a separate boot loader (which means you will only be able to store a single image), you should add this configuration option to your distribution. The line you should add to dist_config.c is:
token_set_y("CONFIG_RG_BOOTSTRAP");
This configuration option will add the arch/arm/mach-ixp425/bootstrap.S file to the image created in the above Makefile. The code in this file is executed only on system bootstrap and is responsible to reinitialize the CPU, SDRAM and expansion bus. The init.S file, located in arch/arm/boot/compressed, copies compressed/vmlinux and ramdisk.gz from the Flash to the memory. It is also responsible for activating the setup_initrd function, which initializes the RAMDISK. The structure of the final image that is burnt to the flash memory is depicted in Figure 7.2.
Figure 7.2 OpenRG Image Structure in Flash
7.3.3.2 Kernel Memory Layout
The following Makefile variables can be modified to control the RAM memory addresses that will be used to start up the system:
1. ZRELADDR is the address to which the final vmlinux kernel image will be decompressed by head.S. This address must be in the form 0xXXXX8000, i.e. the address must end with 0x8000. This offset is used in the linker instructions file compressed/vmlinux.lds to define the load address:
load_addr = LOAD_ADDR = $ZRELADDR
2. ZTEXTADDR defines the start address of the vmlinuZ image (named piggy.gz on ARM-based platforms), i.e. the address to which head.S is loaded. It is used in compressed/
Makefile and in the linker instructions file compressed/vmlinux.lds to define the _start address:
_start = TEXT_START = $ZTEXTADDR
3. ZBSSADDR defines the address of the decompressor heap. It must be defined if the decompressor runs from Flash. It defines the BSS start address in the linker instructions file:
BSS_START = $ZBSSADDR
In order to change the kernel memory layout you would need to use the following calculations.
Let us define X, Y and Z as follows:
1. X The physical address of the beginning of the SDRAM. This will be mapped to the beginning of the linear mapping.
2. Y The virtual address of the beginning of the linear mapping.
3. Z The physical address of the SDRAM to which the RAMDISK must be copied.
Z = X + 0x2000000
The following files should be modified:
1. arch/arm/Makefile defines the kernel virtual link address and should be set to Y
+0x8000. For example, on IXP425, Y is 0xC000000 and the TEXTADDR should be set to 0xC0008000.
TEXTADDR = 0xC0008000
2. arch/arm/boot/Makefile defines the physical address to which the kernel should be loaded, and the physical address to which the compressor should be loaded. The first should be X+0x8000. The second should be defined so that no memory will be overrun.
For example:
ZRELADDR=0x14008000 ZTEXTADDR=0x14080000 INITRD_PHYS=0x16000000
3. arch/arm/mach/arch.c initializes the RAMDISK by calling the setup_initrd function with the address and size of the RAMDISK.
setup_initrd( __phys_to_virt(0x16000000), 8*1024*1024 );
4. include/asm/arch/memory.h defines the kernel RAM virtual address beginning and the physical address in RAM to which it is mapped. For example:
PAGE_OFFSET = 0xC0000000 PHYS_OFFSET = 0x14000000
7.3.3.3 Debug Boot Sequence
When trying to debug the boot sequence, the following could be useful addresses at which to place breakpoints:
1. The decompressor jumps to the kernel at call_kernel , which could be found in file arch/arm/boot/compressed/head.S.
2. The CPU paging is switched on at __ret, which could be found in file arch/arm/kernel/
head-armv.S.
7.3.3.4 Debugging with UART
Another useful technique is to print characters to the console, in order to indicate the boot sequence progress and determine where it had failed. Printing output to the console is simple, as all you need is to write the character to the UART register. Below is a code excerpt that sends one character to the console:
mov r1, #0xc8000003 mov r0, #XX
strb r0, [r1]
7.3.4 Memory
The board's memory configuration includes the SDRAM and Flash configurations.
7.3.4.1 SDRAM Configuration
The configuration of the SDRAM is done using the OpenRG configuration options. The board hardware configuration is defined in pkg/build/hw_config.c and should include the following configuration options to define the memory:
1. CONFIG_IXP425_SDRAM_SIZE should be set to the total size of the memory in MB.
2. CONFIG_IXP425_NUMBER_OF_MEM_CHIPS should be set to the number of chips that are used on the board.
For example, the Coyote board distribution would include the following configuration options, in order to define its 32MB of SDRAM, supplied on 2 memory chips:
token_set("CONFIG_IXP425_SDRAM_SIZE", "32");
token_set("CONFIG_IXP425_NUMBER_OF_MEM_CHIPS", "2");
The values defined in the above mentioned configuration options are used in the include/
asm-arm/arch-ixp425/ixp425.h file, which is part of the kernel, in order to select the correct memory configuration. The available memory configuration defined in ixp425.h is:
#define IXP425_SDRAM_CFG_32MEG_2Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_32Meg_2Chip)
#define IXP425_SDRAM_CFG_64MEG_2Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_64Meg_2Chip)
#define IXP425_SDRAM_CFG_64MEG_4Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_64Meg_4Chip)
#define IXP425_SDRAM_CFG_128MEG_2Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_128Meg_2Chip)
#define IXP425_SDRAM_CFG_128MEG_4Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_128Meg_4Chip)
#define IXP425_SDRAM_CFG_256MEG_4Chip (IXP425_SDRAM_CAS_3CLKS | IXP425_SDRAM_256Meg_4Chip)
7.3.4.2 Flash Configuration
The Flash memory is used to store the OpenRG system components, including the boot loader and its configuration, and the OpenRG image or images along with their configuration files and factory settings. The Flash memory configuration includes defining the correct type of memory chips used on the board and the Flash layout. The Flash memory driver uses the Linux MTD driver. This driver supports Flash memory chips that work according to the CFI API. The Flash driver supports the following memory chips: E28F128J3, E28F640J3 and E28F320J3.
Selecting the type of memory chip used on your board is done in the hw_config.c file. You need to define the proper configuration option CONFIG_IXP425_FLASH_<TYPE> where
<TYPE> is the memory chip type. For example, in the Cute board example, if the board uses the E28F128J3 chip, which is 16MB, define the following in the hw_config.c file:
/* Flash chip */
token_set("CONFIG_IXP425_FLASH_E28F128J3", "m");
In case your board uses a different memory chip, you would have to modify the Flash memory driver to support this memory chip. The driver is provided in vendor/intel/
ixp425/modules/ixp425_flash.c. The Flash layout defines the sections used to store these images and configuration files. Each section entry defines its start address, size and type. The definition of the Flash layout is in the vendor/intel/ixp425/flash_layout.c file, which should be modified to meet your needs. The distribution configuration option CONFIG_RG_FLASH_LAYOUT_SIZE should be set to 8, 16 or 32, in order to indicate the Flash size in MB. The Coyote board has a 16MB Flash, which contains the boot loader and two OpenRG images, along with factory setting and two OpenRG configuration sections. The detailed Flash layout for 16MB Flash is in the vendor/intel/ixp425/flash_layout_16mb.c file.
Also available, are Flash layouts for 32MB in the flash_layout_32mb.c file, and for 8MB in the flash_layout.c file.
7.3.5 Low-level I/O
Low-level I/O configuration includes the GPIO lines and the PCI bus.
7.3.5.1 GPIO Lines
GPIO lines are handled by a set of functions, which are part of the kernel platform specific code, defined in arch/arm/mach-ixp425/gpio.c. These functions are used to configure and access the various GPIO lines and are invoked upon a GPIO interrupt. No modifications are needed to these functions.
7.3.5.2 PCI Bus
The PCI bus requires a set of functions that initialize the GPIO lines and IRQs of your board.
The Coyote platform defines these functions in the arch/arm/mach-ixp425/coyote-pci.c file, as depicted here:
ixp425_pci_init(sysdata);
}
static int __init coyote_map_irq(struct pci_dev *dev, u8 slot, u8 pin) {
int irq = -1;
...
return irq;
}
struct hw_pci coyote_pci __initdata = { init: coyote_pci_init, swizzle: common_swizzle, map_irq: coyote_map_irq, };
You could use the Coyote code as the base for the code you need to write for your board. In the Cute board example, you would need to create a cute-pci.c file, which will handle your board's hardware initialization and mapping of PCI slots to IRQs. In order to inform the kernel of the PCI handlers' location, you would need to modify the arch/arm/kernel/bios32.c file, which sets the PCI vector according to the machine type. For example, the Coyote board uses the following lines to set the PCI vector:
...
In the Cute board example, assuming you have created the cute-pci.c file as defined above with a cute_pci vector, add the following lines immediately after the lines used by the Coyote:
extern struct hw_pci cute_pci;
The machine_is_cute() function is automatically generated by the definition of the new machine type. Make the kernel recognize the right PCI to use on the board by modifying the Makefile under the arch/arm/mach-ixp425 directory. Again, you may find the Coyote line, similar to the following:
obj-$(CONFIG_ARCH_IXP425_COYOTE) += coyote-pci.o
Then, add a line for the Cute board, which would be:
obj-$(CONFIG_ARCH_IXP425_CUTE) += cute-pci.o