1 基本思想
1、 软件版本为u-boot 1.1.6。
2、 尽可能使用VDSP的库函数,而不使用u-boot中的实现,如malloc,memcpy等。
3、 仍然使用A核运行u-boot,B核空闲,但可方便加入代码。
4、 使用vdsp进行存储管理,即用LDF文件和malloc等完成内存管理,将u-boot的代码放在SDRAM最高的1M,Stack与Heap默认使用L1 SRAM。
5、 保留u-boot的目录结构,为每一个有可执行代码的u-boot目录在VDSP下生成一个dlb工程。
6、 不创建新板子,直接在bf561-ezkit的基础上修改。
7、 首先使其具有基本功能,再逐步添加新功能。
2 工程创建
1、 用VDSP生成一个标准的BF561的工程组u-boot,包含u-boot,corea,coreb,sml2,sml3几个工程,此工程的目录为u-boot/vdsp。
2、 将u-boot/include目录添加到工程的包含路径中。
3、 考虑到A核要设置PLL,在B核(mainb.c)中添加代码:
#include <ccblkfn.h>
void main(void)
{
idle();
while(1) idle();
}
4、 在u-boot/include目录下创建config.h,并加上内容:
#ifndef __U_BOOT_CONFIG_H__
#define __U_BOOT_CONFIG_H__
// 与此使用VDSP的库函数
#ifndef ASSEMBLY
#include <ccblkfn.h>
#include <string.h>
#else
#define __ASSEMBLY__ 1
#endif
// 将与库同名的函数更名
#define getenv u_boot_getenv
#define fputs u_boot_fputs
#define printf u_boot_printf
// 与编译器相关的定义
#define __GNUC__ 4
#define __builtin_bfin_ssync ssync
#define BOOL_WAS_DEFINED 1
// 系统定义
#define __bfin__ 1
// U-BOOT的配置文件
#include <configs/bf561-ezkit.h>
#endif //__U_BOOT_CONFIG_H__
5、 在u-boot/include目录下创建version_autogenerated.h,并加上内容:
#define U_BOOT_VERSION "U-Boot 1.1.6-svn (ADI-2007R1)"
6、 将include目录下的asm-blackfin目录改名为asm。
3 修改头文件中的不兼容部分
1、 在maina.c中加上
#include <common.h>
并编译修改出现的Warning和Error。
2、 将asm/system.h中的代码
#define cli()
__cli()
#define sti()
__sti()
#define save_flags(x)
__save_flags(x)
#define restore_flags(x)
__restore_flags(x)
#define save_and_cli(x)
__save_and_cli(x)
修改为:
//#define cli()
__cli()
//#define sti()
__sti()
#define save_flags(x)
do { x = cli(); sti(x); } while(0)
#define restore_flags(x)
do { sti(x); } while(0)
#define save_and_cli(x)
do { x = cli(); } while(0)
3、 在asm/system.h中注释掉__xchg函数。
4、 修改include/configs/bf561-ezkit.h中关于PLL的几个参数。
5、 在bf561-ezkit.h中添加有关BFIN_CPU的定义:
#define ADSP_BF536
0x536
#define ADSP_BF537
0x537
#define ADSP_BF561
0x561
#define BFIN_CPU
ADSP_BF561
6、 注释掉include/common.h中关于sprintf和vsprintf的定义。
7、 修改asm/string.h,注释掉以下行:
//#define __HAVE_ARCH_STRNLEN
1
8、 在asm/string.h中加上一行:
#define __HAVE_ARCH_STRSPN
1
9、
4 暂时去除所有额外的功能
以下所有修改均在include/configs/bf561-ezkit.h中完成。
1、 将
#define CONFIG_COMMANDS ( CONFIG_COMMANDS1 | CONFIG_COMMANDS2 )
修改为:
#define CONFIG_COMMANDS 0
2、 将
#define CONFIG_ICACHE_ON
#define CONFIG_DCACHE_ON
注释掉。
3、 添加
#define CFG_NO_FLASH
1
5 调用u-boot的入口函数
10、 由于u_boot的start.s中初始化了PLL,因些将其中的相关部分提取出来并放在corea.dlb中。
// 本文件从init_sdram.s移植而来
#include <linux/config.h>
#include <config.h>
#include <asm/blackfin.h>
#include <asm/mem_init.h>
// EBIU_SDBCTL Masks
#define EBE
0x00000001 // Enable SDRAM
// external bank 0
#define EBSZ_16
0x00000000 // SDRAM external
// bank size = 16MB
#define EBSZ_32
0x00000002 // SDRAM external
// bank size = 32MB
#define EBSZ_64
0x00000004 // SDRAM external
// bank size = 64MB
#define EBSZ_128
0x00000006 // SDRAM external
// bank size = 128MB
#define EBCAW_8
0x00000000 // SDRAM external bank column
// address width = 8 bits
#define EBCAW_9
0x00000010 // SDRAM external bank column
// address width = 9 bits
#define EBCAW_10
0x00000020 // SDRAM external bank column
// address width = 9 bits
#define EBCAW_11
0x00000030 // SDRAM external bank column
// address width = 9 bits
#define CCLK_DIV1
0x00000000 // CCLK = VCO / 1
#define CCLK_DIV2
0x00000010 // CCLK = VCO / 2
#define CCLK_DIV4
0x00000020 // CCLK = VCO / 4
#define CCLK_DIV8
0x00000030 // CCLK = VCO / 8
#if (CONFIG_CCLK_DIV == 1)
#define CONFIG_CCLK_ACT_DIV
CCLK_DIV1
#endif
#if (CONFIG_CCLK_DIV == 2)
#define CONFIG_CCLK_ACT_DIV
CCLK_DIV2
#endif
#if (CONFIG_CCLK_DIV == 4)
#define CONFIG_CCLK_ACT_DIV
CCLK_DIV4
#endif
#if (CONFIG_CCLK_DIV == 8)
#define CONFIG_CCLK_ACT_DIV
CCLK_DIV8
#endif
void InitSDRam(void)
{
// 此函数从init_sdram中移植而来
unsigned imask, tmp;
/*
* PLL_LOCKCNT - how many SCLK Cycles to delay while PLL becomes stable
*/
*pPLL_LOCKCNT = 0x300;
ssync();
/*
* Put SDRAM in self-refresh, incase anything is running
*/
*pEBIU_SDGCTL = (*pEBIU_SDGCTL) | (1 << 24);
ssync();
/*
* Set PLL_CTL with the value that we calculate in R0
* - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
* - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
* - [7] = output delay (add 200ps of delay to mem signals)
* - [6] = input delay (add 200ps of input delay to mem signals)
* - [5] = PDWN : 1=All Clocks off
* - [3] = STOPCK : 1=Core Clock off
* - [1] = PLL_OFF : 1=Disable Power to PLL
* - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
* all other bits set to zero
*/
imask = cli();
ssync();
*pPLL_CTL = ((CONFIG_VCO_MULT & 63) << 9) | CONFIG_CLKIN_HALF | (CONFIG_PLL_BYPASS << 8);
idle();
sti(imask);
while(!(*pPLL_STAT & (1 << 5))) ssync();
*pPLL_DIV = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
ssync();
/*
* We now are running at speed, time to set the Async mem bank wait states
* This will speed up execution, since we are normally running from FLASH.
*/
*pEBIU_AMBCTL1 = (AMBCTL1VAL >> 16) & 0xffff;
ssync();
*pEBIU_AMBCTL0 = (AMBCTL0VAL >> 16) & 0xffff;
ssync();
*pEBIU_AMGCTL = AMGCTLVAL;
ssync();
/*
* Now, Initialize the SDRAM,
* start with the SDRAM Refresh Rate Control Register
*/
*pEBIU_SDRRC = mem_SDRRC;
ssync();
/*
* SDRAM Memory Bank Control Register - bank specific parameters
*/
*pEBIU_SDBCTL = mem_SDBCTL;
ssync();
/*
* SDRAM Global Control Register - global programmable parameters
* Disable self-refresh
*/
tmp = *pEBIU_SDGCTL;
tmp &= ~(1 << 24);
/*
* Check if SDRAM is already powered up, if it is, enable self-refresh
*/
if(*pEBIU_SDSTAT & (1 << 3))
tmp |= (1 << 23);
*pEBIU_SDGCTL = tmp;
ssync();
/* Write in the new value in the register */
*pEBIU_SDGCTL = mem_SDGCTL;
ssync();
}
11、 在A核的main中调用InitSDRam函数。
12、 在A核的main中调用board_init_f函数。
6 创建lib_blackfin.dlb
1、 在vdsp中创建lib_blackfin.dlb,并加入lib_blackfin/board.c文件。
2、 修改u-boot.ldf,将lib_blackfin.dlb放入L3,具体的位置最后再调整。
3、 由于u-boot的全局状态gd是指向SDRAM中的一个固定地址,我们将之放在Stack中,由VDSP自动分配空间。
4、 修改asm/global_data.h中的定义:
#define DECLARE_GLOBAL_DATA_PTR
register gd_t * volatile gd asm ("P5")
修改为:
#define DECLARE_GLOBAL_DATA_PTR
extern gd_t * gd
5、 在lib_blackfin/board.c中添加gd的定义:
static gd_t global_data;
gd_t * gd = &global_data;
6、 将lib_blackfin/board.c中pr_debug函数的inline去掉,避免编译时的警告。
7、 在board.c中去除对网络参数的查询,将
bd->bi_ip_addr = getenv_IPaddr("ipaddr");
修改为:
#if (CONFIG_COMMANDS & CFG_CMD_NET)
/* IP Address */
bd->bi_ip_addr = getenv_IPaddr("ipaddr");
#endif
8、 加入board/bf561-ezkit/bf561-ezkit.c。
9、 加入lib_blackfin/bf533_linux.c。
7 创建lib_generic.dlb
1、在VDSP中创建lib_generic.dlb工程将加入lib_generic/vsprintf.c。
2、修改u-boot.ldf,将lib_generic.dlb放入L3,具体的位置最后再调整。
3、修改编译时出现的警告和错误。
4、在vsprintf.c的前面加上
#include <config.h>
5、在vsprintf.c中删除printf和vsprintf两个函数的实现。
6、在此工程中加入lib_generic/string.c。
7、在string.c的前面加上:
#include <config.h>
8、将string.c中的strnlen的函数定义
size_t strnlen(const char * s, size_t count)
修改为:
__kernel_size_t strnlen(const char * s, __kernel_size_t count)
9、在linux/string.h中注释掉strspn的定义:
//extern __kernel_size_t strspn(const char *,const char *);
10、 加入ctype.c。
11、 加入crc32.c。
12、 加入display_options.c。
13、 加入zlib.c,并在此文件前加上
#include <config.h>。
14、 加入dlmalloc.c,并在此文件前加上
#include <config.h>
#include <linux/types.h>
15、
8 创建common.dlb
1、 在VDSP中创建common.dlb工程。
2、 修改u-boot.ldf,将common.dlb放入L3,具体的位置最后再调整。
3、 加入cmd_nvedit.c。
4、 加入env_common.c。
5、 加入env_flash.c。
6、 将env_flash.c中的
memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE);
修改为:
#ifndef CFG_NO_FLASH
memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE);
#endif
7、 加入console.c。
8、 加入main.c。
9、 加入lists.c。
10、 加入devices.c。
11、 加入command.c。
12、 加入exports.c。
13、 加入cmd_bootm.c。
9 创建cpu.dlb
1、 在vdsp中创建cpu.dlb,此工程将容纳cpu/bf561目录下的文件。
2、 加入serial.c。
3、 在serial.c前加上定义:
#define SIC_ISR
0xFFC00114 // SIC Interrupt Status
// register 0
#define pSIC_ISR
(volatile unsigned long *)SICA_ISR0
4、 加入interrupts.c。
5、 加入cpu.c,在icache_enable函数前加上定义
unsigned int flags;
将cli();改为flags = cli();
将sti();改为sti(flags);
其它函数中的错误同样改正。
6、 加入flush.s。在工程配置的Assembly中添加定义__ASSEMBLY__。
将
.byte4
0xFFFFFC00; /* 1K */
.byte4
0xFFFFF000; /* 4K */
.byte4
0xFFF00000; /* 1M */
.byte4
0xFFC00000; /* 4M */
改为:
.byte4 = 0xFFFFFC00;
/* 1K */
.byte4 = 0xFFFFF000;
/* 4K */
.byte4 = 0xFFF00000; /* 1M */
.byte4 = 0xFFC00000; /* 4M */
7、 加入traps.c。将
#include <asm/arch/anomaly.h>
改为:
#include <asm/arch-bf561/anomaly.h>
8、 加入ints.c。修改blackfin_init_IRQ函数中的cli和sti,并在此函数之前添加定义:
#define SIC_IMASK
0xFFC0010C // SIC Interrupt Mask
// register 0 - hack to fix
// old tests
9、 加入interrupt.s。
10、 将asm/entry.h中的.macro改为define。
将
( R7 : 0, P5 : 0) = [ SP ++ ]; /
改为:
( R7:0, P5:0) = [ SP ++ ]; /
11、 在interrupt.s中
将
call _trap_c
改为:
call _trap_c; //加上分号
10 为u_boot_cmd分配空间
在u-boot.ldf文件中为u_boot_cmd这个结构体分配存储空间,即在scratchpad这个Section中加上以下语句:
___u_boot_cmd_start = .;
INPUT_SECTIONS(common.dlb(.u_boot_cmd) common.dlb(__u_boot_cmd))
___u_boot_cmd_end = .;
至此就拥有了第一个可以在VDSP下运行的u-boot版本,它支持以下的命令:
ezkit> ?
?
- alias for 'help'
bootm
- boot application image from memory
help
- print online help
printenv- print environment variables
setenv - set environment variables
version - print monitor version