Android’s kernel for beagleboard-xm

Rowboat port enable TI device on android’s linux kernel at http://gitorious.org/rowboat

1, Build

   1: make CROSS_COMPILE=arm-eabi- distclean

   2: make CROSS_COMPILE=arm-eabi- omap3_beagle_android_defconfig

   3: make CROSS_COMPILE=arm-eabi- uImage

The generated uImage is in arch/arm/boot.

2, Modifications

2.1 arm\mach-omap2\board-omap3beagle.c

This file is major BSP for beagleboard. It defines __mach_desc_OMAP3_BEAGLE for architecture features as follows

MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
    /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
    .phys_io    = 0x48000000,
    .io_pg_offst    = ((0xfa000000) >> 18) & 0xfffc,
    .boot_params    = 0x80000100,
    .map_io     = omap3_beagle_map_io,
    .init_irq   = omap3_beagle_init_irq,
    .init_machine   = omap3_beagle_init,
    .timer      = &omap_timer,
MACHINE_END

This structure is put into .arch.info.init section referenced in link script file at arm\kernel\vmlinux.lds.S

    .init : {           /* Init code and data       */
        _stext = .;
        _sinittext = .;
            HEAD_TEXT
            INIT_TEXT
        _einittext = .;
        __proc_info_begin = .;
            *(.proc.info.init)
        __proc_info_end = .;
        __arch_info_begin = .;
            *(.arch.info.init)
        __arch_info_end = .;
        __tagtable_begin = .;
            *(.taglist.init)
        __tagtable_end = .;

The machine description structure is as follows:

struct machine_desc {
    /*
     * Note! The first four elements are used
     * by assembler code in head.S, head-common.S
     */
    unsigned int        nr;     /* architecture number  */
    unsigned int        phys_io;    /* start of physical io */
    unsigned int        io_pg_offst;    /* byte offset for io 
                         * page tabe entry  */

    const char      *name;      /* architecture name    */
    unsigned long       boot_params;    /* tagged list      */

    unsigned int        video_start;    /* start of video RAM   */
    unsigned int        video_end;  /* end of video RAM */

    unsigned int        reserve_lp0 :1; /* never has lp0    */
    unsigned int        reserve_lp1 :1; /* never has lp1    */
    unsigned int        reserve_lp2 :1; /* never has lp2    */
    unsigned int        soft_reboot :1; /* soft reboot      */
    void            (*fixup)(struct machine_desc *,
                     struct tag *, char **,
                     struct meminfo *);
    void            (*map_io)(void);/* IO mapping function  */
    void            (*init_irq)(void);
    struct sys_timer    *timer;     /* system tick timer    */
    void            (*init_machine)(void);
};

 

3, Reference

[1] http://processors.wiki.ti.com/index.php?title=TI-Android-FroYo-DevKit-V2_UserGuide

[2] http://gitorious.org/rowboat

Android on my beagleboard-xm

Ha, I get android boot on my beagleboard-xm and output to 24 ich screen in 1920 * 1080.

Seems the startup frame buffer is not correct:

It does a big android….too large screen…..

Seems it cost about 5 minutes booting from welcome screen to android desktop. I think it is caused by too slow for booting from MMC directly, I need try put rootfs in usb disk but it requires enable usb hub early.

android_calc

android_setting_menu

beagleboard-xm research(2)–u-boot

1, Build

From http://code.google.com/p/beagleboard/wiki/BeagleSourceCode, download u-boot 1.3.3 for beagleboard

If you uses latest ARM gcc from codesourcery, you maybe get following error

arm-none-linux-gnueabi-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float  -D__KERNEL__ -DTEXT_BASE=0x80e80000 -I/home/ken/bb/u-boot/u-boot-beagle/include -fno-builtin -ffreestanding -nostdinc -isystem /opt/sourcery_g++/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv7a  -Wall -Wstrict-prototypes -c -o hello_world.o hello_world.c
hello_world.c:1: error: bad value (armv7a) for -march= switch

This issue is caused by latest GCC changing for ARMV7-A architecture, that should uses -march=armv7-a but not -march=armv7a.

To fix it, in u-boot\cpu\omap3\config.mk, change following line:

PLATFORM_CPPFLAGS += -march=armv7a

To:

PLATFORM_CPPFLAGS += -march=armv7-a

Although success to build uboot.bin image, but beagleboard-xm fail to boot it:

a) the serial baudrate is changed from 115200 to 57600

b) system hang after find no NAND memory.

But the u-boot image built from git mainline git://git.denx.de/u-boot.git with omap3 patch can work correctly, please reference http://www.elinux.org/BeagleBoard

   1: git clone git://git.denx.de/u-boot.git u-boot-main

   2: cd u-boot-main

   3: git checkout --track -b omap3 origin/master

Build

   1: make CROSS_COMPILE=arm-none-linux-gnueabi- mrproper

   2: make CROSS_COMPILE=arm-none-linux-gnueabi- omap3_beagle_config

   3: make CROSS_COMPILE=arm-none-linux-gnueabi- 

As mentioned by previous discussion, u-boot.bin is loaded into the first of internal SDRAM at address 0x80008000. So in uboot\board\ti\beagle\config.mk:

   1: #

   2: # Physical Address:

   3: # 8000'0000 (bank0)

   4: # A000/0000 (bank1)

   5: # Linux-Kernel is expected to be at 8000'8000, entry 8000'8000

   6: # (mem base + reserved)

   7:  

   8: # For use with external or internal boots.

   9: CONFIG_SYS_TEXT_BASE = 0x80008000

CONFIG_SYS_TEXT_BASE as macro passed into build options as:

arm-none-linux-gnueabi-gcc   -D__ASSEMBLY__ -g  -Os   -fno-common -ffixed-r8 -msoft-float   -D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0x80008000 -I/home/ken/bb/u-boot/u-boot-mailine/include -fno-builtin -ffreestanding -nostdinc -isystem /opt/sourcery_g++/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include -pipe  -DCONFIG_ARM -D__ARM__ -marm  -mabi=aapcs-linux -mno-thumb-interwork -march=armv5   -o start.o start.S –c

(BTW: there is some interesting compiler options used: –ffreestanding, –isystem, –mabi=aapcs-linux)

It is worth to mention that uboot will keep some information into a global_data in top of stack, the structure is defined in uboot\arch\arm\include\asm\global_data.h:

   1: typedef    struct    global_data {

   2:     bd_t        *bd;

   3:     unsigned long    flags;

   4:     unsigned long    baudrate;

   5:     unsigned long    have_console;    /* serial_init() was called */

   6:     unsigned long    env_addr;    /* Address  of Environment struct */

   7:     unsigned long    env_valid;    /* Checksum of Environment valid? */

   8:     unsigned long    fb_base;    /* base address of frame buffer */

   9: #ifdef CONFIG_VFD

  10:     unsigned char    vfd_type;    /* display type */

  11: #endif

  12: #ifdef CONFIG_FSL_ESDHC

  13:     unsigned long    sdhc_clk;

  14: #endif

  15: #ifdef CONFIG_AT91FAMILY

  16:     /* "static data" needed by at91's clock.c */

  17:     unsigned long    cpu_clk_rate_hz;

  18:     unsigned long    main_clk_rate_hz;

  19:     unsigned long    mck_rate_hz;

  20:     unsigned long    plla_rate_hz;

  21:     unsigned long    pllb_rate_hz;

  22:     unsigned long    at91_pllb_usb_init;

  23: #endif

  24: #ifdef CONFIG_ARM

  25:     /* "static data" needed by most of timer.c on ARM platforms */

  26:     unsigned long    timer_rate_hz;

  27:     unsigned long    tbl;

  28:     unsigned long    tbu;

  29:     unsigned long long    timer_reset_value;

  30:     unsigned long    lastinc;

  31: #endif

  32:     unsigned long    relocaddr;    /* Start address of U-Boot in RAM */

  33:     phys_size_t    ram_size;    /* RAM size */

  34:     unsigned long    mon_len;    /* monitor len */

  35:     unsigned long    irq_sp;        /* irq stack pointer */

  36:     unsigned long    start_addr_sp;    /* start_addr_stackpointer */

  37:     unsigned long    reloc_off;

  38: #if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))

  39:     unsigned long    tlb_addr;

  40: #endif

  41:     void        **jt;        /* jump table */

  42:     char        env_buf[32];    /* buffer for getenv() before reloc. */

  43: } gd_t;

The structure size maybe different according to configure macros, so at beginning of build, a script is used to calculate current size of global data:

   1: arm-none-linux-gnueabi-gcc -DDO_DEPS_ONLY \

   2:         -g  -Os   -fno-common -ffixed-r8 -msoft-float   -D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0x80008000 -I/home/ken/bb/u-boot/u-boot-mailine/include -fno-builtin -ffreestanding -nostdinc -isystem /opt/sourcery_g++/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include -pipe  -DCONFIG_ARM -D__ARM__ -marm  -mabi=aapcs-linux -mno-thumb-interwork -march=armv5 -Wall -Wstrict-prototypes -fno-stack-protector   \

   3:         -o lib/asm-offsets.s lib/asm-offsets.c -c -S

   4: Generating include/generated/generic-asm-offsets.h

   5: tools/scripts/make-asm-offsets lib/asm-offsets.s include/generated/generic-asm-offsets.h

In EFI, there is similar design that put PeiCore’s private data at top of stack as global data.

2, Memory Map

0x9fff0000  ~  TLB table

0x9ff7f000 ~ 0x9fff0000 : Reserved for U-boot (449K)

0x9ff1f000 ~ 0x9ff7f000: for malloc(384k)

0x9ff1efe0 ~ 0x9ff1f000: board info (32 bytes)

0x9ff1ef68 ~ 0x9ff1efe0: global data (120 bytes)

0x9ff1ef68: New stack point

0x80008000                              reset vector

0x8007020 ~0x80008028      interrupt vectors

0x8000100 : Linux boot parameters

SDRAM #1

0x4020FF80 ~ 0x40210000  global_data

0x4020F800 ~0x4020FF80   stack

 

2, Workflow

  1. uboot\arch\cpu\armv7\start.S
    • Like x-load, start.S provide the first assemble loader for u-boot
    • The first instruction is reset vector and the interrupt/exception handle are closed to it. As system.map file:
80008000 T _start

80008020 t _undefined_instruction

80008024 t _software_interrupt

80008028 t _prefetch_abort

8000802c t _data_abort

80008030 t _not_used

80008034 t _irq

80008038 t _fiq

    • Switch CPU to SVC32 mode.
   1: mrs    r0, cpsr

   2: bic    r0, r0, #0x1f

   3: orr    r0, r0, #0xd3

   4: msr    cpsr,r0

    • Copy interrupt vectors to ROM indirect address: 0x4020F800
    • Because beagleboard-xm does not have NAND/OneNand device, so need copy DPLL initialize code into ROM indirect address after interrupt vectors
    • Init CPU in assemble like x-load:
      • Setup important registers: mmu, cache
      • Setup memory timing.
    • Setup stack for C code at 0x4020FF80 (uboot\include\configs\omap3_beagle.h):
   1: #define CONFIG_SYS_INIT_RAM_ADDR    0x4020f800

   2: #define CONFIG_SYS_INIT_RAM_SIZE    0x800

   3: #define CONFIG_SYS_INIT_SP_ADDR        (CONFIG_SYS_INIT_RAM_ADDR + \

   4:                      CONFIG_SYS_INIT_RAM_SIZE - \

   5:                      GENERATED_GBL_DATA_SIZE)

 

As above mentioned, before top of stack, global_data will be stored, the size of global_data is determined/generated at build time (include\generated\generic-asm-offices.h)

   1: #define GENERATED_GBL_DATA_SIZE (128) /* (sizeof(struct global_data) + 15) & ~15 */

    • Call C function board_init_f (uboot\arch\arm\lib\board.c):
      • Assign/Init global data structure at 0x4020F800
      • Disable memory I/O cache for compiler optization, just like MemoryFence() used in edk2 MdePkg:
   1: __asm__ __volatile__("": : :"memory");

Because many hardware intialization or I/O accessing will use write/read same MMIO address, the compiler maybe optimizate these code out or re-arrange read/write sequence, so it will break. Above instruction like asm volatitle used.

      • call all function defined in init_sequence array:
        • timer_init (arch/arm/cpu/armv7/omap-common/timer.c)
          • here used GPTIMER2 (there are 12 GP time in OMAP3), which base adress is 0x49032000
        • Initialize environment, because no NAND, so the environment is relocated to RAM as in arch\arm\include\asm\global_data.h
   1: #define    GD_FLG_RELOC        0x00001    /* Code was relocated to RAM        */

            By default, some configuration value comes from global variable default_environment in common\env_common.c such as baudrate.

        • serial initliazation

beagleboard-xm use NS16650 serial at COM3 0x49020000, datasheet at http://www.national.com/ds/PC/PC16550D.pdf

        • Init stage1 console for print
        • Print CPU/board information
        • Init I2C device.
        • Init SDRAM device, caculate the bank’s size.
      • Reserve RAM memory for u-boot at top of RAM1 started from 0x80000000
      • Relocate code for new location at 0x9ff7f000/stack at 0x9ff1ef60 (arch\arm\cpu\armv7\start.S, relocate_code())
      • Jump to board_init_r() in new location in RAM, (The sequence is very like PeiCore relocation in EFI)
      • In beaglboard’s board_init_r() (board\ti\beagle\beagle.c):
        • Init GPMC
        • set board id for linux as 1546
        • set boot parameter address at 0x80000100
        • Init MMC driver
        • Init stdio drivers such as serial, nulldev
        • Init jumptable?
        • Evalute board version, for beagleboard-xm board, set VAUX2 to 1.8v for EHCI PHY. And print DIE ID at 0x4830A200
        • Init IRQ/FIQ stack which size are all 4K
        • Change CPSR to enable interrupt
        • Enter main_loop() function to read boot/user script …

beagleboard-xm research(1) — Initialization & x-load

1, General boot process and device

The initialization process for OMAP Dm37x beagleboard:

  • Preinitialization
  • Power/clock/reset ramp sequence
  • Boot ROM
  • Boot Loader
  • OS/application

Six external pins(sys_boot[5:0]) are used to select interfaces or devices for booting. The interfaces are GPMC, MMC1, MMC2, USB and UART.

The ROM code has two booting functions: peripheral booting and memory booting:

  • In peripheral booting, the ROM code pools a selected communication interface such as UART or USB, downloads the executable code over the interface, and execute it in internal SRAM. Downloaded software from an external host can be used to program flash memories connected to the device.
  • In memory booting, the ROM code finds bootstrap in permanent memories such as flash memory or memory cards and executes it. The process is normally performed after cold or warm device reset.

Overall boot sequence is as follows:

Following is 32K SRAM memory map of GP device, which is used only during the booting process.

Beagleboard-xm is OMAP3, so use 64K SRAM which range is 40200000-4020FFFF.

2, Boot from MMC/SD card

In general, beagleboard-xm uses memory booting from MMC/SD card, because this board does not have NAND device. There are some limitations as follows:

  • Supports MMC/SD cards compliant with the Multimedia Card System Specification v4.2 from the MMCA Technical Committee and the SD I/O Card Specification v2.0 from the SD Association. Includes high-capacity (size >2GB) cards: HC-SD and HC MMC
  • 3-V power supply, 3-V I/O and 1.8-V I/O voltages on port 1
  • Supports eMMC/eSD (1.8-V I/O voltage and 3.0-V Core voltage) on port 2. The external transceiver mode on port 2 is not supported.
  • Initial 1-bit MMC mode, 4-bit SD mode
  • Clock frequency:
                –   Identification mode: 400 kHz
                –   Data transfer mode: 20 MHz
  • Only one card connected to the bus 
  • Raw mode, image data read directly from card sectors 
  • FAT12/16/32 support, with or without a master boot record (MBR). 
  • For a FAT (12/16/32)-formatted memory card, the booting file must not exceed 128 KB.
  • For a raw-mode memory card, the booting image must not exceed 128 KB.  

The image used by the booting procedure is taken from a booting file named MLO. This file must be in the root directory on an active primary partition of type FAT12/16 or FAT32.

An MMC/SD card can be configured as floppy-like or hard-drive-like:

  • When acting like a floppy, the content of the card is a single FAT12/16/32 file system without an MBR holding a partition table.
  • When acting like a hard drive, an MBR is present in the first sector of the card. This MBR holds a table of partitions, one of which must be FAT12/16/32, primary, and active.

3, MLO image format

For a GP device, the image is simple and must contain a small header having the size of the software to load and the destination address of where to store it when a booting device is other than XIP. The XIP device image is even simpler and starts with executable code.



4, x-load

4.1 Why uses x-load

As above mentioned, the SRAM in beagleboard-xm is very tiny as 64K, the u-boot image size is almost 196K, so beagleboard-xm can not use u-boot as MLO. The x-load is used here, which can be considered as u-boot loader, and it’s size is around 24K.

4.2 How to build x-load

  • Get mainline x-load source code from

git clone git://gitorious.org/x-load-omap3/mainline.git

make CROSS_COMPILE=arm-none-linux-gnueabi- omap3530beagle_config

make CROSS_COMPILE=arm-none-linux-gnueabi-
       Although beagleboard-xm use DM3735 process, there is updated config file in x-load mainline’s tree. So it is ok for reuse omap3530beagle_config file.

  • Generate MLO file

After building, x-load.bin is generated as raw executable binary. As above mentioned about non-XIP image format, the size and address should be added at image’s first 16 bytes. So use signGP scipt to do it. The source code of signGP is http://beagleboard.googlecode.com/files/signGP.c

4.3 x-load’s research

4.3.1 memory map

In beagleboard-xm, ROM code will load x-load binary into SRAM (0x4020000 ~ 0x4020FFFF) 64K range. The range is allocated as follows:

Runtime stack: 0x4020000 ~ 0x40207FFF

MLO                : 0x4020800 ~ 0x4020FFFF

please reference board\omap3530beagle\config.mk for TEXT_BASE setting:

   1: # For XIP in 64K of SRAM or debug (GP device has it all availabe)

   2: # SRAM 40200000-4020FFFF base

   3: # initial stack at 0x4020fffc used in s_init (below xloader).

   4: # The run time stack is (above xloader, 2k below)

   5: # If any globals exist there needs to be room for them also

   6: TEXT_BASE = 0x40200800

Please reference cpu\omap3\start.S for stack pointer setting:

   1: /* Set up the stack                            */

   2: stack_setup:

   3:     ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */

   4:     sub    sp, r0, #128        /* leave 32 words for abort-stack   */

   5:     and    sp, sp, #~7        /* 8 byte alinged for (ldr/str)d    */

Because the x-load is non-XIP code, so TEXT_BASE is passed to compiler:

arm-none-linux-gnueabi-gcc -Wa,-gstabs -D__ASSEMBLY__ -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8  -D__KERNEL__ -DTEXT_BASE=0x40200800 -I/home/ken/bb/x-load/mainline/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/lib/gcc/i486-linux-gnu/4.4.3/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv7-a  -c -o cpu/omap3/start.o /home/ken/bb/x-load/mainline/cpu/omap3/start.S

 

4.3.2 startup process

  1. The boot is started from cpu\omap3\start.S and the first instruction is reset vector.
  2. set cpu mode to Supervisor (SVC) 32 bit mode.
  3. Copy vectors to indirect address 0x4020F800 (SRAM_OFFSET0 + SRAM_OFFSET1 + SRAM_OFFSET2)
  4. relocates clock code into SRAM where its safer to execute
  5. Initialize CPU
    1. Invalidate instruction, L2 cache, and invalidate TLBs, disable MMU
    2. Initialize SRAM stack at 0x4020FFFC, so can use C code now.
    3. In C code s_init do some early initialization such watchdog,  configure SDRAM.
  6. Relocate code section
  7. Set runtime stack
  8. Clear bss section for uninitialization value.
  9. Jump to C code start_armboot().
    1. Initialize the serial device
    2. print version information like
      Texas Instruments X-Loader 1.4.4ss
    3. Initialize I2C which base address is 0x48070000 in L4 core.
    4. reading GPIO173, 172, 171 to determin the version of beagleboard then print it, for beagleboard-xm board, the value should be 0, 0, 0
    5. Initialize MMC card and load u-boot.bin from MMC card into pop SDRAM 0x80008000
      1. If no MMC found, try to boot from onenand or nand, but beagleboard-xm does not has these devices
      2. try to boot from serial ……
    6. Jump to 0x80008000, over for x-load.

4.3.3 x-load vs EFI’s SEC phase

So we can see the x-load is very like SEC phase in UEFI specification, in Intel’s tiano implementation, the SEC phase mainly:

  • Enter protect mode
  • Prepare early C stack in CAR, the CAR is instruction cache in process for temporary stack/heap, just like Omap’s internal SRAM for boot phase. Unlike SRAM, the CAR will be disabled/destroyed after SEC phase.
  • Initialize CPU such as MTRR for flash range.
  • Initialize early ACPI timer for performance collection.
  • Find the PeiCore from flash and shadow into CAR for PEI phase.

5, Reference
=======
1) DM37x Multimedia Device Silicon Revision 1.x

我的beagleboard-xm到货拉

好久没玩过OMAP了,绕来绕去这几年最终又从Intel的架构绕回来了ARM,世界变化真快啊