U-Boot Introduction and Porting It to S3C2440

Introduction to Bootloaders

A bootloader is a critical piece of software that serves as the first executable code run when an embedded device is powered on. It bridges the gap between hardware initialization and operating system loading, performing essential tasks to prepare the system for full functionality.

U-Boot: Universal Bootloader

Overview

U-Boot (Universal Bootloader) is an open-source bootloader widely used in embedded systems, particularly for ARM-based devices. Developed by DENX Software Engineering, it provides a robust and flexible solution for embedded system boot processes.

Core Features of U-Boot

  1. Comprehensive Hardware Initialization

    • Configures essential system components
    • Sets up memory controllers
    • Initializes critical system peripherals
  2. Versatile Boot Sources

    • Supports multiple boot media:
      • NAND Flash
      • NOR Flash
      • SD/MMC cards
      • Ethernet (network boot)
      • USB
      • Serial interfaces
  3. Interactive Command-Line Interface

    • Provides a console for:
      • System diagnostures
      • Memory and register manipulation
      • Boot configuration
      • Network operations
  4. Advanced Scripting Capabilities

    • Supports complex boot scripts
    • Enables conditional boot logic
    • Allows flexible system configuration
  5. Hardware Abstraction

    • Provides a consistent interface across different architectures
    • Supports multiple CPU families
    • Handles platform-specific initialization requirements

Porting U-Boot to S3C2440

Platform Characteristics and Startup Mechanism

The S3C2440 is an ARM920T-based System-on-Chip (SoC) developed by Samsung, commonly used in embedded systems and mobile devices. Understanding its startup process is crucial for effective bootloader development.

S3C2440 Boot Sequence and Startup Mechanism

Boot Mode Selection

The S3C2440 supports multiple boot modes, determined by the state of the following pins during system reset:

  • BOOT[2:0] pins (nBOOT0, nBOOT1, nBOOT2)
  • These pins are sampled at the rising edge of the reset signal

Boot Mode Options:

  1. Internal Boot ROM Mode

    • Default boot mode
    • Executed when no external boot media is detected
    • Provides a built-in first-stage bootloader
  2. NAND Flash Boot Mode

    • Primary boot method for most embedded systems
    • Reads the first 8KB from NAND Flash
    • Loads initial bootloader code into internal SRAM
  3. NOR Flash Boot Mode

    • Alternate boot method
    • Directly executes code from NOR Flash
    • Suitable for systems with NOR Flash storage

Startup Detailed Process

  1. Reset Vector

    • On power-up or reset, the processor starts execution at a fixed memory address
    • For S3C2440, this is typically 0x00000000 (Internal Boot ROM)
  2. Initial ROM Bootloader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ; Simplified representation of ROM bootloader logic
    _rom_bootloader:
    ; Disable interrupts
    MRS r0, CPSR
    ORR r0, r0, #0xC0 // Disable IRQ and FIQ
    MSR CPSR_c, r0

    ; Configure system clock
    BL configure_system_clock

    ; Initialize memory interface
    BL init_memory_controller

    ; Detect and prepare boot source
    BL detect_boot_source
  3. Memory Copy Mechanism
    Copying U-Boot from storage to RAM involves several critical steps:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /* U-Boot memory copy routine for S3C2440 */
    void copy_uboot_to_ram(void)
    {
    /* Source: Typically starts at the beginning of NAND/NOR Flash */
    unsigned char *src = (unsigned char *)BOOT_FLASH_BASE;

    /* Destination: Internal RAM */
    unsigned char *dest = (unsigned char *)UBOOT_RAM_BASE;

    /* Size of U-Boot image */
    unsigned int size = UBOOT_IMAGE_SIZE;

    /* Disable interrupts during copy */
    disable_interrupts();

    /* Copy U-Boot image to RAM */
    while (size > 0) {
    *dest++ = *src++;
    size--;
    }

    /* Verify copy integrity */
    if (verify_memory_copy(src, dest, UBOOT_IMAGE_SIZE) != SUCCESS) {
    /* Handle copy error */
    system_error_handler();
    }

    /* Enable MMU and caches */
    enable_mmu_and_caches();
    }

Critical Initialization Registers

Key registers to configure during startup:

  1. SYSCFG (System Configuration Register)

    • Controls boot mode selection
    • Configures memory interface
      1
      2
      3
      4
      5
      6
      7
      8
      #define SYSCFG_REG 0x56000000
      void configure_syscfg(void)
      {
      /* Set up system configuration */
      SYSCFG_REG = (BOOT_MODE_NAND |
      MEMORY_CONFIG_SDRAM |
      CLOCK_CONFIGURATION);
      }
  2. CLKCON (Clock Control Register)

    • Manages system and peripheral clocks
      1
      2
      3
      4
      5
      6
      7
      #define CLKCON_REG 0x4C000000
      void configure_system_clock(void)
      {
      /* Configure main PLL */
      CLKCON_REG = (MPLL_CONFIGURATION |
      SYSTEM_CLOCK_ENABLE);
      }

Memory Controller Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void init_memory_controller(void)
{
/* BWSCON: Bus Width and Wait State Configuration */
BWSCON = 0x22000000;

/* BANKCON: Memory Bank Configuration */
BANKCON1 = SDRAM_BANK_CONFIG;

/* REFRESH: DRAM Refresh Control */
REFRESH = DRAM_REFRESH_SETTINGS;

/* Initialize SDRAM */
init_sdram();
}

Jumping to U-Boot in RAM

1
2
3
4
5
6
7
8
9
10
11
12
void execute_uboot(void)
{
/* Disable interrupts */
disable_interrupts();

/* Flush caches */
flush_cache();

/* Jump to U-Boot entry point in RAM */
void (*uboot_entry)(void) = (void (*)(void))UBOOT_RAM_BASE;
uboot_entry();
}

Key Considerations During Startup

  1. Minimal Initial Footprint

    • First-stage bootloader must be extremely compact
    • Typically less than 8KB in size
  2. Error Handling

    • Implement robust error detection
    • Provide fallback mechanisms
    • Use LED or serial output for diagnostic information
  3. Performance Optimization

    • Minimize initialization time
    • Use fastest possible memory copy methods
    • Leverage hardware-specific acceleration features

Porting Considerations

1. Initial System Setup

Key steps for system initialization:

  • Disable interrupts
  • Configure system clock
  • Set up memory controller
  • Initialize memory interface

2. Critical Registers for S3C2440

Essential registers to configure during porting:

  • MPLLCON: Main PLL Configuration
  • CLKCON: Clock Control
  • BANKCON1-6: Memory Bank Configuration
  • REFRESH: DRAM Refresh Control

3. Startup Sequence in ARM Assembly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
_start:
/* Disable interrupts */
MRS r0, CPSR
ORR r0, r0, #0xC0 // Disable IRQ and FIQ
MSR CPSR_c, r0

/* Set up stack pointer */
LDR sp, =_stack_top

/* Initialize memory controller */
BL memctl_init

/* Copy data to RAM */
BL copy_code_to_ram

/* Jump to main bootloader */
BL main_bootloader

4. Flash Memory Porting

NAND Flash Initialization Steps:

  1. Configure NAND Flash controller
  2. Implement NAND read/write functions
  3. Set up bad block management
  4. Create flash map and partition table

Memory Initialization Example:

1
2
3
4
5
6
7
8
void memctl_init(void)
{
/* Configure SDRAM Controller */
BWSCON = /* Bus width and wait state configuration */;
BANKCON1 = /* Bank 1 configuration */;
REFRESH = /* DRAM refresh timing */;
BANKSIZE = /* Memory bank size */;
}

Porting Process

  1. Board Configuration

    • Create board-specific header files
    • Define memory map
    • Specify clock frequencies
  2. Low-Level Initialization

    • Implement CPU-specific startup code
    • Configure clocks
    • Set up memory interfaces
  3. Device Drivers

    • Develop drivers for:
      • UART
      • Ethernet
      • Storage interfaces
  4. Testing and Validation

    • Use serial console for debugging
    • Verify boot sequence
    • Test various boot scenarios

JTAG Debugging for S3C2440

JTAG Overview

JTAG (Joint Test Action Group) is a critical debugging interface for embedded systems, providing low-level access to microcontrollers and System-on-Chip devices like the S3C2440.

Hardware Setup

Required Equipment

  1. JTAG Debugger

    • Recommended models:
      • OpenOCD-compatible debuggers
      • Segger J-Link
      • ARM UltraLync
  2. Connection Interface

    • 20-pin or 14-pin JTAG connector
    • Precise pin mapping for S3C2440

JTAG Connector Pinout

1
2
3
4
5
6
7
PIN 1:  VTref     PIN 2:  VTHOST
PIN 3: TRST PIN 4: GND
PIN 5: TDI PIN 6: GND
PIN 7: TMS PIN 8: GND
PIN 9: TCK PIN 10: GND
PIN 11: RTCK PIN 12: GND
PIN 13: TDO PIN 14: GND

OpenOCD Configuration

1
2
3
4
5
6
7
8
9
10
11
12
# s3c2440.cfg
source [find target/samsung_s3c2440.cfg]

target create s3c2440.cpu arm920t -endian little \
-work-area-phys 0x30000000 -work-area-size 0x4000 \
-restart-timeout 1000

reset_config trst_and_srst separate \
trst_pulls_srst \
srst_pulls_trst

flash bank s3c2440_nand nand 0x0 0x8000000 0 1 s3c2440.cpu

Debugging Capabilities

  1. Memory Inspection

    • Read/write system memory
    • Examine register contents
    • Analyze memory-mapped peripherals
  2. Real-time Debugging

    • Set breakpoints
    • Step through code execution
    • Modify register values during runtime

Debugging Workflow

Typical Debugging Commands

1
2
3
4
5
6
7
# Halt processor at reset vector
> halt
> reg pc
> x/10i $pc // Examine instruction stream

# Check memory controller registers
> mdw 0x48000000 10 // Display memory config registers

Challenges and Best Practices

Common Challenges

  1. Incorrect JTAG Clock Speeds
  2. Reset Sequence Problems
  3. Power Supply Considerations

Best Practices

  1. Use latest OpenOCD version
  2. Keep JTAG cable as short as possible
  3. Implement proper shielding
  4. Use dedicated debugging power supply
  5. Regularly calibrate JTAG interface

Software

  • OpenOCD
  • GDB (GNU Debugger)
  • Eclipse CDT with ARM plugins

Hardware

  • Logic Analyzer
  • Oscilloscope
  • Multimeter

Conclusion

Successfully porting U-Boot to the S3C2440 and effectively debugging the system requires a comprehensive understanding of ARM architecture, careful hardware initialization, and advanced debugging techniques. By following a systematic approach and leveraging powerful tools like JTAG, developers can create robust embedded systems solutions.

Key Takeaways

  • Understand the intricacies of the S3C2440 platform
  • Master U-Boot configuration and porting techniques
  • Utilize JTAG for in-depth system debugging
  • Follow best practices in embedded system development