at91bootstrap: Create a Custom Board Configuration
Introduction
This training topic is for advanced developers who wish to create a custom board configuration (almost from scratch) for the at91bootstap bootloader.
Prerequisites
For an introduction to at91bootstrap, see the at91bootstrap: A Second Stage Bootloader for Microchip MPUs page.
Create a Custom Board Configuration
Step 1: Create a directory for your custom board.
The at91bootstrap bootloader contains the contrib/board/ directory for contributed boards. Within the directory are vendor names. Create a directory with your <vendor> name. Within the <vendor> directory you can create a directory with your individual custom projects’ <board> name(s). You may want to use the board’s unique name (e.g., <board>) or you may want to preface the target device part number ahead of the board’s name (e.g., <sam9x60_board>).
/project_1/
|-- at91bootstrap/
|-- contrib/
|-- board/
|-- <vendor>/
|-- <board>/
Step 2: Populate the directory with the following files:
There are multiple files that are required in the custom project directory. It is best to copy these files from the default Microchip evaluation kit that closely matches your custom project design and edit them to suit your custom project board.
The key items that you will need to know before you begin are:
- System Clock source (external, internal)
- Static RAM
- Non-Volatile Memory (NVM) Boot Memory: SD Memory Card, e.MMC, NOR Flash (QSPI), NAND Flash memory
- Which program you will jump to (U-Boot, Linux®, BusyBox, RTOS, MPLAB® Harmony 3 application, Bare Metal Program)
In the following sub-steps, we explain how to set up each file.
a. <board>_<nvm_boot_memory>_<uboot_or_linux>_defconfig
b. <board>.c
c. <board>.h
d. board.mk
e. Config.in.board
f. Config.in.linux_arg
g. Config.in.<board>
h. Config.in.boardname
a: Create a default configuration file:
The default configuration file allows the autotools programs to generate a .config file that defines the features make will build into the image.
Loading U-Boot (boot.bin)
Below are three examples for the SAM9X60 that will load U-Boot (boot.bin) from external NVM memory to internal SRAM.
The first example will load U-Boot from SD Memory Card:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_SDCARD=y
4 CONFIG_DEBUG=y
5 CONFIG_THUMB=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: Boots from SD Memory Card.
Line 4: Enables debug/log messages to be displayed on the console.
Line 5: Supports thumb instruction set. This is set only for ARM9 devices and not for Arm® Cortex® A5, which supports Thumb-2 instructions.
The second example will load U-Boot from NAND Flash memory:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_NANDFLASH=y
4 # CONFIG_PMECC_AUTO_DETECT is not set
5 CONFIG_PMECC_CORRECT_BITS_8=y
6 CONFIG_IMG_SIZE="0x000c0000"
7 CONFIG_DEBUG=y
8 CONFIG_THUMB=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: Boots from NAND Flash memory.
Line 4: For an ONFI compliant NAND, the ECC correction is automatically activated. Refer to the SAMA5D2 Series datasheet sections 16.4.7.1 and 16.4.7.2 or SAM9X60 datasheet sections 11.4.7.1 and 11.4.7.2.
Line 5: Specifies the PMECC error correction bits. Used when CONFIG_PMECC_AUTO_DETECT is not set.
Line 6: Size of the U-Boot (boot.bin) image (in HEX) to be loaded by at91bootstrap.
Line 7: Enables debug/log messages to be displayed on the console.
Line 8: Supports thumb instruction set. This is set only for ARM9 devices and not for Arm Cortex A5 which supports Thumb-2 instructions.
The third example will load U-Boot from NOR Flash (QSPI) memory:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_SPI_CLK=50000000
4 CONFIG_IMG_ADDRESS="0x00040000"
5 CONFIG_IMG_SIZE="0x000c0000"
6 CONFIG_DEBUG=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: SPI Clock frequency.
Line 4: Memory location in NOR Flash memory where U-Boot (boot.bin) is stored. The at91bootstrap copies boot.bin from this address location to an address location specified in external RAM.
Line 5: Size of the boot.bin image (in HEX) to be loaded by at91bootstrap.
Line 6: Enables debug/log messages to be displayed on the console.
Loading Linux
Below are three examples for the SAM9X60 that will load a Linux image from external NVM memory to external RAM.
The first example will load Linux image from SD Memory Card:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_SDCARD=y
4 CONFIG_LOAD_LINUX=y
5 CONFIG_IMAGE_NAME="zImage"
6 CONFIG_DEBUG=y
7 CONFIG_THUMB=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: Boots from SD Memory Card.
Line 4: Boots Linux directly.
Line 5: Name of the Linux image file.
Line 6: Enables debug/log messages to be displayed on the console.
Line 7: Supports thumb instruction set. This is set only for ARM9 devices and not for Arm Cortex A5 which supports Thumb-2 instructions.
The second example will load Linux image from NAND Flash memory:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_NANDFLASH=y
4 CONFIG_LOAD_LINUX=y
5 CONFIG_IMAGE_NAME="zImage"
6 # CONFIG_PMECC_AUTO_DETECT is not set
7 CONFIG_PMECC_CORRECT_BITS_8=y
8 CONFIG_IMG_SIZE="0x000c0000"
9 CONFIG_DEBUG=y
10 CONFIG_THUMB=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: Boots from NAND Flash memory.
Line 4: Boots Linux directly.
Line 5: Name of the Linux image file.
Line 6: For an ONFI compliant NAND, the ECC correction is automatically activated. Refer to the SAMA5D2 Series datasheet sections 16.4.7.1 and 16.4.7.2 or SAM9X60 datasheet sections 11.4.7.1 and 11.4.7.2.
Line 7: Specifies the PMECC error correction bits. Used when CONFIG_PMECC_AUTO_DETECT is not set.
Line 8: Size of the Linux image (in HEX) to be loaded.
Line 9: Enables debug/log messages to be displayed on the console.
Line 10: Supports thumb instruction set. This is set only for ARM9 devices and not for Arm Cortex A5 which supports Thumb-2 instructions.
The third example will load Linux image from NOR Flash (QSPI) memory:
1 CONFIG_SAM9X60_<board>=y
2 CONFIG_RAM_256MB=y
3 CONFIG_SPI_CLK=50000000
4 CONFIG_OVERRIDE_CMDLINE=y
5 CONFIG_IMG_ADDRESS="0x00200000"
6 CONFIG_OF_OFFSET="0x00180000"
7 CONFIG_LOAD_LINUX=y
8 CONFIG_JUMP_ADDR="0x26F00000"
9 CONFIG_DEBUG=y
Line 1: Defines the board name. Used in the main makefile. Also used as a macro for board-specific initialization.
Line 2: Memory size of external RAM.
Line 3: SPI Clock frequency.
Line 4: If CONFIG_OVERRIDE_CMDLINE is selected, then you can override the kernel argument set by CONFIG_LINUX_KERNEL_ARG_STRING as shown in the figure below.
Line 5: Memory location in NOR Flash memory where the Linux image is stored.
Line 6: Memory location in NOR Flash memory where the Device Tree is stored.
Line 7: Boots Linux directly.
Line 8: The memory location in the external RAM where the Linux Image should be copied to.
Line 9: Enables debug/log messages to be displayed on the console.
Naming Convention
The suggested naming convention for your custom project default configuration is to concatenate the board name (<board>) with the NVM memory that at91bootstrap will load from SD Memory Card, NOR Flash, NAND Flash, etc. and the program that will be loaded, U-Boot, Linux, BusyBox, etc.
<board>_<nvm_boot_memory>_<uboot_or_linux>_defconfig
Legend:
- qspi – NOR Flash Memory
- sd – SD Memory Card
- if no number is given, boot from port 0
- if number is given, boot from indicated port (for example, 1 = port 1)
- nf – NAND Flash Memory
- df – Serial/DataFlash Memory
Legend:
- uboot – Third-Stage Bootloader
- linux_image_dt – Linux kernel and Device Tree
b: Create a <board>.c file:
The <board>.c file performs all the hardware initialization of the custom project board.
Function hw_init() is a mandatory function. It performs all of the peripheral and hardware initialization. Examine the <board>.c file that closely matches your custom project board design. In general, the following peripheral and hardware initializations must be performed:
- Clock initialization:
- The PLLA is initialized and the MCK is switched to PLLA output.
- Peripheral Clocks that are in use are initialized within the respective peripheral initialization routines.
- External DRAM initialization:
- The most important function is external DRAM initialization (you will see them inside the #ifdef CONFIG_DDR2).
- If you are using a similar SRAM from the evaluation kits, you can examine and reuse the DDR RAM configuration and initialization functions.
- If a different DRAM is used, refer to the DRAM datasheet to gather information needed to alter the configuration and initialization functions.
- The ddramc_init() function is implemented for external DRAM initialization called by hw_init(). The ddramc_init() function calls the ddramc_reg_config() function to populate the RAM configuration and timings followed by the ddram_initialization.
- Pin initialization:
- Pin initializations are initialized.
- External NVM initialization:
- The external NVM that contains the third-stage bootloader or program to be loaded by at91bootstrap is initialized.
- Other initializations:
- The bus matrix system, timer, debug console, LEDs, or anything specific to the custom project board is initialized.
c: Create a <board>.h file:
The <board>.h file provides definitions for the clock (Main and peripheral) and setting for all of the NVM memory on your custom project board.
Ensure the clock related to NVM memory settings is set to the values required. The clock settings depend on the choice for the clock source, i.e.:
- An external source of 8 to 24 MHz crystal oscillator
- External Clock Source
- Both external and internal clock 12 MHz RC
- Internal slow clock and 12 MHz RC
This will determine the clock definition for BOARD_MAINOSC.
Other required definitions are:
- Bus frequency
- Main clock frequency
- PLLA prescaler settings (multiplier and divider)
- Console UART baud
The NVM-related definitions depend on what type of memory you choose.
For an SD Memory Card, the following definitions are required:
- CONFIG_SYS_BASE_SDHC: The address location where the peripheral is memory mapped.
- CONFIG_SYS_ID_SDHC: The peripheral ID.
For a NAND Flash memory, the following definitions are required:
- CONFIG_SYS_NAND_BASE: The address location where the External Bus Interface with NCS3 (chip select 3) is memory mapped.
- CONFIG_SYS_NAND_MASK_ALE: The Address Latch Enable line (A21 of the Static Memory Controller).
- CONFIG_SYS_NAND_MASK_CLE: The Command Latch Enable line (A22 of the Static Memory Controller).
- CONFIG_SYS_NAND_ENABLE_PIN: NAND Flash memory Chip Select pin
- CONFIG_SYS_NAND_OE_PIN: Output Enable pin
- CONFIG_SYS_NAND_WE_PIN: Write Enable pin
- CONFIG_SYS_NAND_ALE_PIN: Address Latch Enable pin (A21 of the Static Memory Controller)
- CONFIG_SYS_NAND_CLE_PIN: Command Latch Enable pin (A22 of the Static Memory Controller)
For DataFlash Memory, the following definitions are required:
- CONFIG_SYS_SPI_CLOCK: SPI Clock Frequency (typically defined in the defconfig file for the board)
- CONFIG_SYS_SPI_MODE: SPI mode
- CONFIG_SYS_BASE_SPI: The address location where the peripheral is memory mapped
- CONFIG_SYS_SPI_PCS: SPI Chip Select pin
d: Create a board.mk file:
Edit the board.mk file with the compiler and assembler flags.
e: Create a Config.in.board file:
Edit the Config.in.board file with the configuration choices used by menuconfig.
f: If you are loading a Linux Image directly, create a Config.in.linux_arg file:
If you want at91bootstrap to load the Linux image directly, without loading a third-stage bootloader such as U-Boot, you will need to edit the Config.in.linux_arg file with the boot arguments that will be passed to the Linux kernel.
You will also need to update the Config.in.kernel file in the at91bootstrap root directory.
g: Create a Config.in.boardname file:
This file defines CONFIG_BOARDNAME used by menuconfig to display the list of contributed boards a user can choose from. This file is sourced by the contrib/board/Config.in.boardname which is in turn sourced by board/Config.in, sourced by the main Config.in.
Step 3: Update files in contrib/board directory.
Update the following files in the contrib/board folder with the files you created:
Config.in.board file:
source “contrib/board/<vendor_name>/<board_name>/Config.in.board”
Config.in.boardname file:
source “contrib/board/<vendor_name>/<board_name>/Config.in.boardname
Config.in.linux_arg file:
source “contrib/board/<vendor_name>/<board_name>/Config.in.linux_arg”
Building Your Custom Project at91bootstrap
Once you have created your custom project directory and populated it with the required files, you can now build your customized at91bootstrap.
Step 1: Change directory into the at91bootstrap directory:
$ cd ~/project_1/at91bootstrap
Step 2: Clean and configure make
$ make mrproper
$ make <board>_defconfig
Step 3: You may customize the default configuration setting using menuconfig:
$ make menuconfig
You may exit menuconfig by repeatedly typing ESC-ESC.
Step 4: Build at91bootstrap:
$ make
The results of the build will be a binary image that can be written to the external memory device selected during configuration.
$ cd ~/project_1/at91bootstrap/binaries
Summary
In this training, you learned some advanced methods of creating a custom board configuration for at91bootstrap.