world leader in high performance signal processing
Trace: » porting

Porting U-Boot To Your Board

So you have a new custom Blackfin board and you want to get Das U-Boot up and running on it? Here's the document for you. Unfortunately, it isn't the only document you're going to need. You should also make sure to have the HRM for your Blackfin variant, as well as all the datasheets for all the main parts on your board (that you will be configuring in U-Boot). Since it is the job of U-Boot to initialize all the low-level hardware details, you're going to need to know the hardware settings.

For the purposes of this document, we will be creating a new BF537 board code named “cow”. Whether your board is based on a different processor or you've got a cooler name, these details should be easily replaceable.

Here is a quick list of the files/directories in U-Boot that you will need to modify/create:

Top-level Build

Makefile

In the top-level Makefile, simply locate the Blackfin section where the variable BFIN_BOARDS is declared and add your board to it. The Blackfin portions of the makefile use this variable to set up everything else for the selected board.

BFIN_BOARDS += bf537-cow

If you generate any non-standard files in your Board Directory, you will also need to update the clean target to have those files removed. Common files (like objects *.o) are automatically removed for you.

MAKEALL

If you plan on contributing your board back to the Blackfin U-Boot mainline, you should update the MAKEALL script. Locate the LIST_blackfin variable and add your board to the end of it.

LIST_blackfin=" \
    ...
    bf537-cow
"

This script is used to quickly run compile tests for all available Blackfin boards. The Blackfin U-Boot maintainer uses this when making board-independent changes so as to be sure that no boards break (and if they do, he will fix them for you).

MAINTAINERS

If you plan on contributing your board back to the Blackfin U-Boot mainline, you should update the MAINTAINERS list. Locate the Blackfin Systems section and add your contact e-mail and board(s) to the end of it. Feel free to add the Blackfin development mailing list as well.

...
# Blackfin Systems:
...
Some Developer <your.email@company.com>

    BF537-COW        BF537
...

Board Configuration File

This file is the heart of your board setup. It describes all of the features to enable, drivers to include, and settings. Here we'll cover the key defines and give pointers to further documentation.

Once you tackle the Blackfin options below, check out the customizing page for the next steps.

Format

Please make sure your board configuration file has this general format:

/* Some copyright / license info */
 
#ifndef __CONFIG_BF537_COW_H__
#define __CONFIG_BF537_COW_H__
 
/* this must come first */
#include <asm/config-pre.h> 
 
...
 
/* this sets up the default list of enabled commands */
#include <config_cmd_default.h>
 
/* Undo any settings you don't like from the config_cmd_default.h */
 
#endif

Blackfin Settings

There are a few Blackfin specific defines you must setup.

CONFIG_BFIN_CPU

This is a short string that represents the desired Blackfin processor and its silicon version. So if we want to target silicon revision 0.3 of the BF537 for our board:

#define CONFIG_BFIN_CPU bf537-0.3

CONFIG_BFIN_BOOT_MODE

This controls the expected boot method of your board. Generally speaking, the code attempts to be boot-mode agnostic, but this isn't always the case. Make sure this actually matches your BMODE pins. Keep in mind that U-Boot supports more boot modes than your Blackfin variant may, so only select ones that your Blackfin variant actually supports. See the Blackfin Boot ROM Boot Modes section for more information.

When changing boot modes, make sure you run make clean first to ensure all files are properly recompiled.

If we want to create an LDR which can boot over the UART, then we would do something like:

#define CONFIG_BFIN_BOOT_MODE BFIN_BOOT_UART

Here is the complete list of possible values for BFIN_BOOT_MODE:

file: arch/blackfin/include/asm/config-pre.h

scm failed with exit code 1:
file does not exist in git

CONFIG_UART_CONSOLE

Simply define this to the UART number you have setup as your console. So if you are using UART0, just do:

#define CONFIG_UART_CONSOLE 0

Clock Settings

These set of defines are used to control the clock settings for your board. They are directly used to program the PLL and related registers. Only basic validity checks are performed (at the register level). No checks are performed to make sure datasheet compliance.

You should consult the PLL Registers chapter of the HRM for your Blackfin variant.

  • CONFIG_CLKIN_HZ - The clock input frequency
  • CONFIG_CLKIN_HALF - Cut input frequency in half
  • CONFIG_PLL_BYPASS - Bypass the PLL
  • CONFIG_VCO_MULT - Clock input multiplier
  • CONFIG_CCLK_DIV - Core clock divider
  • CONFIG_SCLK_DIV - System clock divider

For quick reference, the clock calculations are:

Core:   (CLKIN / (2 ^ CLKIN_HALF) * VCO_MULT) / CCLK_DIV
System: (CLKIN / (2 ^ CLKIN_HALF) * VCO_MULT) / SCLK_DIV
Direct Settings

If you want to just program a register directly, you can use the CONFIG_<MRR>_VAL define. So if you wish to program the VR_CTL MMR with a specific setting, you can set CONFIG_VR_CTL_VAL in your board configuration.

Asynchronous Memory Bus Settings

There are a few defines that correlate directly to the registers. On all Blackfin's you have to define:

  • CONFIG_EBIU_AMGCTL_VAL - Global Memory Control
  • CONFIG_EBIU_AMBCTL0_VAL - Bank 0 and Bank 1 Control
  • CONFIG_EBIU_AMBCTL1_VAL - Bank 2 and Bank 3 Control

On some newer Blackfin's (as older ones do not have these settings), you will have to define:

  • CONFIG_EBIU_MBSCTL_VAL - Memory Bank Select Control
  • CONFIG_EBIU_MODE_VAL - Memory Mode Control
  • CONFIG_EBIU_FCTL_VAL - Flash Control

For exact meanings of a particular register, consult the HRM for your processor and any devices that you will have hooked up to these banks.

External Memory Settings

For Blackfin's that have SDRAM, you will need to define:

  • CONFIG_EBIU_SDRRC_VAL - SDRAM Refresh Rate Control
  • CONFIG_EBIU_SDBCTL_VAL - SDRAM Bank Control
  • CONFIG_EBIU_SDGCTL_VAL - SDRAM Global Control

For Blackfin's that have DDR, you will need to define:

  • CONFIG_EBIU_DDRCTL0_VAL - DDR Control
  • CONFIG_EBIU_DDRCTL1_VAL - DDR Control
  • CONFIG_EBIU_DDRCTL2_VAL - DDR Control
  • CONFIG_EBIU_DDRCTL3_VAL - (Optional) DDR Control
  • CONFIG_EBIU_RSTCTL_VAL - (Optional) DDR Reset Control

For exact meanings of a particular register, consult the HRM for your processor and the datasheets for the memory module you are using.

Calculating DDR/SDRAM Settings

For assistance in calculating the Blackfin settings based on your memory's timings, please see the SDRAM page.

Board Directory

This is where all of your board-specific files and code lives. There are three files that you are required to have in here. Those are:

Makefile

You can use this common template in any board directory:

# BF537-COW board makefile

include $(TOPDIR)/config.mk

LIB = $(obj)lib$(BOARD).a

COBJS   := $(BOARD).o
SOBJS   := 

SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS    := $(addprefix $(obj),$(COBJS))
SOBJS   := $(addprefix $(obj),$(SOBJS))

$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds
	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)

clean:
	rm -f $(SOBJS) $(OBJS)

distclean:  clean
	rm -f $(LIB) core *.bak $(obj).depend

include $(SRCTREE)/rules.mk

sinclude $(obj).depend

If you have more C files or assembly (.S) files to compile, simply add them to the COBJS or SOBJS variable as appropriate.

Board Build Flags

If you wish to add custom compiler flags for your board, then the config.mk file is the place for it. Simply append the variable in question (like PLATFORM_RELFLAGS or PLATFORM_CPPFLAGS) with whatever flag you want.

Keep in mind that the TEXT_BASE variable is not used by the Blackfin platform, so do not set it.

Most people will use this simply to tweak the flags given to the ldr utility when generating the u-boot.ldr file.

# This is not actually used for Blackfin boards so do not change it
#TEXT_BASE = do-not-use-me

#PLATFORM_RELFLAGS += -some-gcc-flag
#PLATFORM_CPPFLAGS += -DMY_CRAZY_DEFINE

# Setup LDR_FLAGS according to our boot mode (BFIN_BOOT_MODE variable is defined automatically)
LDR_FLAGS-BFIN_BOOT_UART = --port g --gpio 6
LDR_FLAGS += $(LDR_FLAGS-$(BFIN_BOOT_MODE))

Board C File

This is generally where you put the core/required functions that are needed by common U-Boot code. We'll cover the functions you should be sure to actually implement.

checkboard

Used to check random board specific details before initializing drivers. Usually just prints out a banner for your board. Return a value of zero to indicate success or return non-zero to indicate failure (in which case the board should hang or reboot).

int checkboard(void)
{
	printf("Board: BF537 cow board\n");
	printf("       Support: http://cow.town/\n");
	return 0;
}

board_reset

This function is optional. If you need to tweak the hardware some how before performing a soft system reset, then place those details here.

void board_reset(void)
{
	/* do something weird */
}

misc_init_r

This function is where you place miscellaneous board initialization code. This is run after pretty much everything else has been initialized but before the main execution of the console shell. Same as the checkboard function -- return zero for success, non-zero to panic the board. Make sure you define CONFIG_MISC_INIT_R in your board configuration file.

int misc_init_r(void)
{
	/* do random stuff */
}
MAC address management

If your board has ethernet capabilities and your MAC does not have a dedicated EEPROM for storing the MAC address, and you have not hardcoded the MAC address in your board configuration file, you must implement this sort of code in your board's misc_init_r() function. If your MAC does have a dedicated EEPROM, then the U-Boot driver will take care of this function for you.

The purpose of this semi-complicated system is to allow you to store/retrieve the MAC address from wherever you like. For example, the BF537-STAMP utilizes a sector of parallel flash for storing the MAC address in a persistent manner.

For more information, consult the doc/README.enetaddr file.

int misc_init_r(void)
{
...
	uchar enetaddr[6];
	if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
		/* we cram the MAC in the last flash sector */
		memcpy(enetaddr, (void *)0x203F0000, 6);
		eth_setenv_enetaddr("ethaddr", mac_addr);
	}
...
}

board_eth_init

The board_eth_init() function is the board callback function for registering your ethernet devices. Here you call the different network driver init functions and return their result.

file: board/bf537-stamp/bf537-stamp.c

scm failed with exit code 1:
file does not exist in git

More Information

The memory layout guide may help you for customizing where to place U-Boot's code and data.