购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.3 U-Boot的移植

U-Boot的作用是引导操作系统,因此U-Boot的移植相对Linux操作系统的移植相对简单,无须考虑太多驱动程序,主要涉及到CPU初始化、SDRAM控制器初始化、Flash驱动程序、串口和网络接口驱动程序。完全从头开始移植一个U-Boot程序工作量是很大的,好在半导体公司一般都提供评估板的板级支持包(Board Support Package,BSP),在其基础上移植可以减少很多工作量。

由于目标板是基于BF536处理器的,而BF536处理器和BF537是兼容的,仅在片内内存配置方面有所不同,所以可以在ADI公司BF537 stamp主板的配置基础上来修改以适应目标板。U-Boot程序中和BF536处理器相关的部分如表4.3所示。

表4.3 U-Boot中BF536处理器相关的目录

4.3.1 板级配置文件

板级配置文件存放在“/includes/configs”目录下,对于stamp板而言就是bf537-stamp.h,在其基础上修改以适应BF536目标板。bf537-stamp.h文件内容如下:

/*

* U-boot - Configuration file for BF537 STAMP board

*/

#ifndef __CONFIG_BF537_H__

#define __CONFIG_BF537_H__

#define CFG_LONGHELP 1

#define CONFIG_CMDLINE_EDITING 1

#define CONFIG_BAUDRATE 115200 //定义BF536启动后串口波特率

//PC端的串口设置要与此一致

/* Set default serial console for bf537 */

#define CONFIG_UART_CONSOLE 0 //控制台被定向到串口0

#define CONFIG_BF537 1

#define CONFIG_BOOTDELAY 3 //U-Boot启动后的延时,以秒为单位

/* define CONFIG_BF537_STAMP_LEDCMD to enable LED command*/

/*#define CONFIG_BF537_STAMP_LEDCMD 1*/

/*

* Boot Mode Set

* Blackfin can support several boot modes

*/

#define BF537_BYPASS_BOOT 0x0011 /* 启动模式0 */

#define BF537_PARA_BOOT 0x0012 /* 启动模式1 */

#define BF537_SPI_MASTER_BOOT 0x0014 /* 启动模式3 */

#define BF537_SPI_SLAVE_BOOT 0x0015 /* 启动模式4 */

#define BF537_TWI_MASTER_BOOT 0x0016 /* 启动模式5 */

#define BF537_TWI_SLAVE_BOOT 0x0017 /* 启动模式6 */

#define BF537_UART_BOOT 0x0018 /* 启动模式7 */

/* Define the boot mode */

#define BFIN_BOOT_MODE BF537_BYPASS_BOOT //定义当前的启动模式,旁路片内ROM

//#define BFIN_BOOT_MODE BF537_SPI_MASTER_BOOT

//#define BFIN_BOOT_MODE BF537_UART_BOOT

#define CONFIG_PANIC_HANG 1

#define ADSP_BF534 0x34

#define ADSP_BF536 0x36

#define ADSP_BF537 0x37

#define BFIN_CPU ADSP_BF536 //选择BF536处理器

/* This sets the default state of the cache on U-Boot's boot */

#define CONFIG_ICACHE_ON //使能指令缓存

#define CONFIG_DCACHE_ON //使能数据缓存

/* Define if want to do post memory test */

#undef CONFIG_POST_TEST

/* Define where the uboot will be loaded by on-chip boot rom */

#define APP_ENTRY 0x00001000 //U-Boot的执行地址,指向SDRAM空间

#define CONFIG_RTC_BF533 1

#define CONFIG_BOOT_RETRY_TIME -1

/* CONFIG_CLKIN_HZ is any value in Hz */

#define CONFIG_CLKIN_HZ 25000000 //定义主板外部晶振频率

/* CONFIG_CLKIN_HALF controls what is passed to PLL 0=CLKIN */

/* 1=CLKIN/2 */

#define CONFIG_CLKIN_HALF 0 //外部时钟频率直径输入到PLL

/* CONFIG_PLL_BYPASS controls if the PLL is used 0=don't bypass */

/* 1=bypass PLL */

#define CONFIG_PLL_BYPASS 0 //不旁路PLL

/* CONFIG_VCO_MULT controls what the multiplier of the PLL is. */

/* Values can range from 1-64 */

#define CONFIG_VCO_MULT 16 //VCO频率=16 * 25 = 400 MHz

/* CONFIG_CCLK_DIV controls what the core clock divider is */

/* Values can be 1, 2, 4, or 8 ONLY */

#define CONFIG_CCLK_DIV 1 //内核时钟=VCO频率/CONFIG_CCLK_DIV

/* CONFIG_SCLK_DIV controls what the peripheral clock divider is */

/* Values can range from 1-15 */

#define CONFIG_SCLK_DIV 4 //系统总线频率=VCO/CONFIG_SCLK_DIV

/* CONFIG_SPI_BAUD controls the SPI peripheral clock divider */

/* Values can range from 2-65535 */

/* SCK Frequency = SCLK / (2 * CONFIG_SPI_BAUD) */

#define CONFIG_SPI_BAUD 2

#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#define CONFIG_SPI_BAUD_INITBLOCK 4

#endif

#if ( CONFIG_CLKIN_HALF == 0 )

#define CONFIG_VCO_HZ ( CONFIG_CLKIN_HZ * CONFIG_VCO_MULT )

#else

#define CONFIG_VCO_HZ (( CONFIG_CLKIN_HZ * CONFIG_VCO_MULT ) / 2 )

#endif

#if (CONFIG_PLL_BYPASS == 0)

#define CONFIG_CCLK_HZ ( CONFIG_VCO_HZ / CONFIG_CCLK_DIV )

#define CONFIG_SCLK_HZ ( CONFIG_VCO_HZ / CONFIG_SCLK_DIV )

#else

#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ

#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ

#endif

#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#if (CONFIG_SCLK_HZ / (2*CONFIG_SPI_BAUD) > 20000000)

#define CONFIG_SPI_FLASH_FAST_READ 1 /* Needed if SPI_CLK > 20 MHz */

#else

#undef CONFIG_SPI_FLASH_FAST_READ

#endif

#endif

#define CONFIG_MEM_SIZE 32 //定义主板SDRAM的容量,以MB为单位

#define CONFIG_MEM_ADD_WDTH 9 //定义SDRAM的列地址宽度

#define CONFIG_MEM_MT48LC16M16A2TG_75 1 //4MB*16*4Bank的SDRAM,频率为133 MHz

//U-Boot以此为依据初始化SDRAM控制器

#define CONFIG_LOADS_ECHO 1

#define CFG_AUTOLOAD "no"

/*

* Network Settings

*/

/* network support */

#if (BFIN_CPU != ADSP_BF534)

#define CONFIG_IPADDR 192.168.1.76 //默认IP地址

#define CONFIG_NETMASK 255.255.255.0 //默认子网掩码

#define CONFIG_GATEWAYIP 192.168.1.1 //默认网关IP地址

#define CONFIG_SERVERIP 192.168.1.126//默认服务器IP地址

#define CONFIG_HOSTNAME BF537

#endif

#define CONFIG_ROOTPATH /romfs

/* Uncomment next line to use fixed MAC address */

//#define CONFIG_ETHADDR 02:80:ad:20:31:e8

/* This is the routine that copies the MAC in Flash to the 'ethaddr'setting */

#define CONFIG_BOOTCOMMAND"run ramboot" //启动后执行的命令

#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT) && defined

(CONFIG_POST_TEST)

/* 上电自检 */

#define CONFIG_POST ( CFG_POST_MEMORY | \

CFG_POST_UART | \

CFG_POST_FLASH | \

CFG_POST_ETHER | \

CFG_POST_LED | \

CFG_POST_BUTTON)

#else

#undef CONFIG_POST

#endif

#ifdef CONFIG_POST

#define CFG_CMD_POST_DIAG CFG_CMD_DIAG

#define FLASH_START_POST_BLOCK 11 /* Should > = 11 */

#define FLASH_END_POST_BLOCK 71 /* Should < = 71 */

#else

#define CFG_CMD_POST_DIAG 0

#endif

/* CF-CARD IDE-HDD Support */

#if defined(CONFIG_BFIN_CF_IDE) || defined(CONFIG_BFIN_HDD_IDE) ||defined(CONFIG_BFIN_TRUE_IDE)

# define CONFIG_BFIN_IDE 1

# define ADD_IDE_CMD CFG_CMD_IDE

#else

# define ADD_IDE_CMD 0

#endif

/*#define CONFIG_BF537_NAND */ /* Add nand flash support */

#ifdef CONFIG_BF537_NAND

# define ADD_NAND_CMD CFG_CMD_NAND

#else

# define ADD_NAND_CMD 0

#endif

#define CONFIG_NETCONSOLE 1

#define CONFIG_NET_MULTI 1

#if (BFIN_CPU == ADSP_BF534)

#define CONFIG_BFIN_CMD (CONFIG_CMD_DFL &~CFG_CMD_NET)

#else

#define CONFIG_BFIN_CMD (CONFIG_CMD_DFL | CFG_CMD_PING)

#endif

#if ((BFIN_BOOT_MODE == BF537_BYPASS_BOOT) || (BFIN_BOOT_MODE ==BF537_UART_BOOT))

#define CONFIG_COMMANDS (CONFIG_BFIN_CMD| \

CFG_CMD_ELF | \

CFG_CMD_I2C | \

CFG_CMD_CACHE | \

CFG_CMD_JFFS2 | \

CFG_CMD_EEPROM | \

CFG_CMD_DHCP | \

ADD_IDE_CMD | \

ADD_NAND_CMD | \

CFG_CMD_POST_DIAG | \

CFG_CMD_DATE)

#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#define CONFIG_COMMANDS (CONFIG_BFIN_CMD| \

CFG_CMD_ELF | \

CFG_CMD_I2C | \

CFG_CMD_CACHE | \

CFG_CMD_JFFS2 | \

CFG_CMD_EEPROM | \

ADD_IDE_CMD | \

CFG_CMD_DATE)

#endif

//引导Linux内核启动时传递给内核的参数

#define CONFIG_BOOTARGS "root=/dev/mtdblock0 rw console=ttyBF0,115200"

#define CONFIG_LOADADDR 0x1000000 //内核的执行地址

#if((BFIN_BOOT_MODE==BF537_BYPASS_BOOT)||(BFIN_BOOT_MODE ==BF537_UART_BOOT))

#if(BFIN_CPU != ADSP_BF534)

#define CONFIG_EXTRA_ENV_SETTINGS \

"ramargs=setenv bootargs root=/dev/mtdblock0 rw

console=ttyBF0,115200\0"\ "nfsargs=setenv bootargs root=/dev/nfs rw " \

"nfsroot=$(serverip):$(rootpath) console=ttyBF0,115200\0" \

"addip=setenv bootargs $(bootargs) " \

"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \

":$(hostname):eth0:off\0" \

"ramboot=tftpboot $(loadaddr) linux;" \

"run ramargs;run addip;bootelf\0" \

"nfsboot=tftpboot $(loadaddr) linux;" \

"run nfsargs;run addip;bootelf\0" \

"flashboot=bootm 0x20100000\0" \

"update=tftpboot $(loadaddr) u-boot.bin;" \

"protect off 0x20000000 0x2007FFFF;" \

"erase 0x20000000 0x2007FFFF;cp.b 0x1000000 0x20000000

$(filesize)\0" \

""

#else

#define CONFIG_EXTRA_ENV_SETTINGS \

"ramargs=setenv bootargs root=/dev/mtdblock0 rw

console=ttyBF0,115200\0" \

"flashboot=bootm 0x20100000\0"\

""

#endif

#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#if (BFIN_CPU != ADSP_BF534)

#define CONFIG_EXTRA_ENV_SETTINGS \

"ramargs=setenv bootargs root=/dev/mtdblock0 rw

console=ttyBF0,115200\0"\"nfsargs=setenv bootargs root=/dev/ nfs rw " \

"nfsroot=$(serverip):$(rootpath) console=ttyBF0,115200\0" \

"addip=setenv bootargs $(bootargs) "\

"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \

":$(hostname):eth0:off\0" \

"ramboot=tftpboot $(loadaddr) linux;" \

"run ramargs;run addip;bootelf\0" \

"nfsboot=tftpboot $(loadaddr) linux;" \

"run nfsargs;run addip;bootelf\0" \

"flashboot=bootm 0x20100000\0" \

"update=tftpboot $(loadaddr) u-boot.ldr;" \

"eeprom write $(loadaddr) 0x0 $(filesize);\0" \

""

#else

#define CONFIG_EXTRA_ENV_SETTINGS \

"ramargs=setenv bootargs root=/dev/mtdblock0 rw

console=ttyBF0,115200\0"\

"flashboot=bootm 0x20100000\0" \

""

#endif

#endif

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */

#include <cmd_confdefs.h>

#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#if (BFIN_CPU == ADSP_BF534)

#define CFG_PROMPT"serial_bf534> " /* Monitor Command Prompt */

#elif (BFIN_CPU == ADSP_BF536)

#define CFG_PROMPT"serial_bf536> " /* Monitor Command Prompt */

#else

#define CFG_PROMPT"serial_bf537> " /* Monitor Command Prompt */

#endif

#else

#if (BFIN_CPU == ADSP_BF534)

#define CFG_PROMPT"bf534> " /* Monitor Command Prompt */

#elif (BFIN_CPU == ADSP_BF536)

#define CFG_PROMPT"bf536> " /* U-Boot命令行显示的提示符 */

#else

#define CFG_PROMPT"bf537> " /* Monitor Command Prompt */

#endif

#endif

#if (CONFIG_COMMANDS & CFG_CMD_KGDB)

#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */

#else

#define CFG_CBSIZE 256 /* Console I/O Buffer Size */

#endif

#define CFG_MAX_RAM_SIZE (CONFIG_MEM_SIZE * 1024*1024) //最多SDRAM空间

#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)/* Print Buffer Size */

#define CFG_MAXARGS 16 /* max number of command args */

#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ #define CFG_MEMTEST_START 0x0 /* SDRAM的测试起始地址 */

#define CFG_MEMTEST_END ( (CONFIG_MEM_SIZE - 1) * 1024*1024)

#define CFG_LOAD_ADDR CONFIG_LOADADDR /* default load address */

#define CFG_HZ 1000 /* decrementer freq: 10 ms ticks */

#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }

#define CFG_SDRAM_BASE 0x00000000 //SDRAM起始地址,由片选决定

#define CFG_FLASH_BASE 0x20000000 //Flash起始地址,由片选决定

#define CFG_MONITOR_LEN (256 << 10) //最高位的256 KB被Monitor使用

#define CFG_MONITOR_BASE (CFG_MAX_RAM_SIZE - CFG_MONITOR_LEN)

#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 KB for malloc() */

//其次的128 KB为malloc使用

#define CFG_MALLOC_BASE (CFG_MONITOR_BASE - CFG_MALLOC_LEN)

#define CFG_GBL_DATA_SIZE 0x4000

//其次全局数据地址

#define CFG_GBL_DATA_ADDR (CFG_MALLOC_BASE - CFG_GBL_DATA_SIZE) //其次系统堆栈地址

#define CONFIG_STACKBASE(CFG_GBL_DATA_ADDR - 4)

#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for

Linux */

#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */

#define CFG_MAX_FLASH_SECT 64 /* max number of sectors on one chip */

#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT) || (BFIN_BOOT_MODE ==

BF537_UART_BOOT) /* for bf537-stamp, uart boot mode still store env in flash */

#define CFG_ENV_IS_IN_FLASH 1 //环境变量是否存储在Flash中

#define CFG_ENV_ADDR 0x20004000 //环境变量的存储地址

#define CFG_ENV_OFFSET (CFG_ENV_ADDR - CFG_FLASH_BASE)

#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)

#define CFG_ENV_IS_IN_EEPROM 1

#define CFG_ENV_OFFSET 0x4000

#define CFG_ENV_HEADER (CFG_ENV_OFFSET + 0x16e) /* 0x12A is the length of LDR file header */

#endif

#define CFG_ENV_SIZE 0x2000

#define CFG_ENV_SECT_SIZE 0x10000 /* Total Size of Environment Sector */

//#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)

#define ENV_IS_EMBEDDED

//#endif

/* JFFS Partition offset set */ #define CFG_JFFS2_FIRST_BANK 0

#define CFG_JFFS2_NUM_BANKS 1

/* 512kB reserved for u-boot */

#define CFG_JFFS2_FIRST_SECTOR 15

#define CONFIG_SPI

/*

* Stack sizes

*/

#define CONFIG_STACKSIZE (128*1024) /* regular stack */

#define POLL_MODE 1

#define FLASH_TOT_SECT 32

#define FLASH_SIZE 0x400000 //共4 MB的Flash空间

#define CFG_FLASH_SIZE 0x400000

/*

* Board NAND Infomation

*/

#define CFG_NAND_ADDR 0x20212000

#define CFG_NAND_BASE CFG_NAND_ADDR

#define CFG_MAX_NAND_DEVICE 1

#define SECTORSIZE 512

#define ADDR_COLUMN 1

#define ADDR_PAGE 2

#define ADDR_COLUMN_PAGE 3

#define NAND_ChipID_UNKNOWN 0x00

#define NAND_MAX_FLOORS 1

#define NAND_MAX_CHIPS 1

#define BFIN_NAND_READY PF3

#define NAND_WAIT_READY(nand) \

do { \

int timeout = 0; \

while(!(*pPORTFIO & PF3)) \

if (timeout++ > 100000) \

break; \

} while (0)

#define BFIN_NAND_CLE (1<<2) /* A2 -> Command Enable */

#define BFIN_NAND_ALE (1<<1) /* A1 -> Address Enable */

#define WRITE_NAND_COMMAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | BFIN_NAND_CLE) = (__u8)(d); } while(0)

#define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | BFIN_NAND_ALE) = (__u8)(d); } while(0)

#define WRITE_NAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)d; } while(0)

#define READ_NAND(adr) ((volatile unsigned char)(*(volatile __u8

*)(unsigned long)adr))

/*

* Initialize PSD4256 registers for using I2C

*/

#define CONFIG_MISC_INIT_R

#define CFG_BOOTM_LEN 0x2000000 /* Large Image Length,set to 64 Meg */

/*

* I2C settings

* By default PF1 is used as SDA and PF0 as SCL on the Stamp board */

/*#define CONFIG_SOFT_I2C 1*/ /* I2C bit-banged */

#define CONFIG_HARD_I2C 1 /* I2C TWI */

#if defined CONFIG_HARD_I2C

#define CONFIG_TWICLK_KHZ 50

#endif

#if defined CONFIG_SOFT_I2C

/*

* Software (bit-bang) I2C driver configuration */

#define PF_SCL PF0

#define PF_SDA PF1

#define I2C_INIT (*pFIO_DIR |= PF_SCL); asm("ssync;")

#define I2C_ACTIVE (*pFIO_DIR |= PF_SDA); *pFIO_INEN &=

~PF_SDA; asm("ssync;")

#define I2C_TRISTATE (*pFIO_DIR &= ~PF_SDA); *pFIO_INEN|= PF_SDA; asm("ssync;")

#define I2C_READ((volatile)(*pFIO_FLAG_D & PF_SDA) != 0);

asm("ssync;")

#define I2C_SDA(bit) if(bit) { \

*pFIO_FLAG_S = PF_SDA; \

asm("ssync;"); \

} \

else { \

*pFIO_FLAG_C = PF_SDA; \

asm("ssync;"); \

}

#define I2C_SCL(bit) if(bit) { \

*pFIO_FLAG_S = PF_SCL; \

asm("ssync;"); \

} \

else { \

*pFIO_FLAG_C = PF_SCL; \

asm("ssync;"); \

}

#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */

#endif

#define CFG_I2C_SPEED 50000

#define CFG_I2C_SLAVE 0xFE

//EBIU控制器定义

#define AMGCTLVAL 0xFF

#define AMBCTL0VAL 0x7BB07BB0

#define AMBCTL1VAL 0xFFC27BB0

#define CONFIG_VDSP 1

#ifdef CONFIG_VDSP

#define ET_EXEC_VDSP 0x8

#define SHT_STRTAB_VDSP 0x1

#define ELFSHDRSIZE_VDSP 0x2C

#define VDSP_ENTRY_ADDR 0xFFA00000

#endif

#if defined(CONFIG_BFIN_IDE)

#define CONFIG_DOS_PARTITION 1 /*

* IDE/ATA stuff

*/

#undef CONFIG_IDE_8xx_DIRECT/* no pcmcia interface

required */

#undef CONFIG_IDE_LED /* no led for ide supported */

#undef CONFIG_IDE_RESET/* no reset for ide supported */

#define CFG_IDE_MAXBUS 1/* max. 1 IDE busses */

#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */

#undef AMBCTL1VAL

#define AMBCTL1VAL 0xFFC3FFC3

#define CONFIG_CF_ATASEL_DIS 0x20311800

#define CONFIG_CF_ATASEL_ENA 0x20311802

#if defined(CONFIG_BFIN_TRUE_IDE)

// Note that these settings aren't for the most part used in include/ata.h

// when all of the ATA registers are setup

#define CFG_ATA_BASE_ADDR 0x2031C000

#define CFG_ATA_IDE0_OFFSET 0x0000

#define CFG_ATA_DATA_OFFSET 0x0020 /* Offset for data I/O */

#define CFG_ATA_REG_OFFSET 0x0020 /* Offset for normal

register accesses */

#define CFG_ATA_ALT_OFFSET 0x001C /* Offset for alternate registers */

#define CFG_ATA_STRIDE 2 /* CF.A0 --> Blackfin.Ax */

#endif /* CONFIG_BFIN_TRUE_IDE */

#if defined(CONFIG_BFIN_CF_IDE) /* USE CompactFlash Storage Card in the common memory space */

#define CFG_ATA_BASE_ADDR 0x20211800

#define CFG_ATA_IDE0_OFFSET 0x0000

#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O */

#define CFG_ATA_REG_OFFSET 0x0000 /* Offset for normal

register accesses */

#define CFG_ATA_ALT_OFFSET 0x000E /* Offset for alternate registers */

#define CFG_ATA_STRIDE 1 /* CF.A0 --> Blackfin.Ax */

#endif /* CONFIG_BFIN_CF_IDE */

#if defined(CONFIG_BFIN_HDD_IDE) /* USE TRUE IDE */

#define CFG_ATA_BASE_ADDR 0x20314000

#define CFG_ATA_IDE0_OFFSET 0x0000

#define CFG_ATA_DATA_OFFSET 0x0020 /* Offset for data I/O */

#define CFG_ATA_REG_OFFSET 0x0020 /* Offset for normal

register accesses */

#define CFG_ATA_ALT_OFFSET 0x001C /* Offset for alternate registers */

#define CFG_ATA_STRIDE 2 /* CF.A0 --> Blackfin.A1 */ #undef CONFIG_SCLK_DIV

#define CONFIG_SCLK_DIV 8

#endif /* CONFIG_BFIN_HDD_IDE */

#endif /*CONFIG_BFIN_IDE*/

#endif

可以看到配置文件的主要内容是时钟参数的配置、启动模式的配置、串口参数的配置、Flash配置、SDRAM配置、网络参数配置等,还有一些内容涉及到CF卡、IDE硬盘、I 2 C接口等,不是U-Boot的必须内容,为精简U-Boot的体积可以去掉这些配置。

4.3.2 PLL设置

时钟系统是处理器的脉搏,处理器按照时钟的节拍对数据流进行加工。Blackfin处理器时钟系统的核心是锁相环(Phase Locked Loop,PLL),外部时钟信号进入锁相环,经过倍频后得到压控振荡器频率,然后由这个频率经过分频得到内核时钟CCLK和系统时钟SCLK。内核时钟是Blackfin内核的运行频率,片内SRAM空间的读写操作也是运行在内核频率。系统时钟SCLK为外设存取总线(Peripheral Access Bus,PAB)、DMA总线(DMA Access Bus,DAB)、外部存取总线(External Access Bus,EAB)和外部总线接口单元(External Bus Interface Unit,EBIU)提供时钟。PLL系统结构如图4.1所示。

图4.1 PLL时钟系统结构框图

各种时钟频率的计算公式如下:

VCOCLK =(CLKIN × MSEL[5:0])/(DF + 1),if MSEL[5:0] != 0

VCOCLK =(CLKIN × 64)/(DF + 1),if MSEL[5:0] == 0

VCOCLK = CLKIN,if BYPASS = 1

CCLK = VCOCLK/(2的CSEL[1:0]次方)

SCLK = VCOCLK/SSEL[3:0],SSEL[3:0] != 0

时钟频率的生成是由一组寄存器控制的,主要是控制寄存器PLL_CTRL和PLL分频寄存器PLL_DIV。

PLL_DIV寄存器如图4.2所示。

图4.2 PLL_DIV寄存器

PLL_DIV寄存器定义内核时钟和系统时钟的分频倍数。

PLL_CTRL寄存器如图4.3所示。

图4.3 PLL_CTRL寄存器

PLL_CTRL寄存器控制PLL的行为模式,关系到时钟频率的设置包括DF、BYPASS和MSEL[5:0]。具体作用效果可以参考前面的时钟计算公式。

明白PLL时钟系统的工作原理后,再针对目标板进行设置就很轻松了。BF536处理器要求的外部输入时钟CLKIN的频率范围是10~50 MHz,目标板的晶振是25 MHz,如果要得到400 MHz的主频和100 MHz的系统频率,需要的参数如下:

DF = 0

BYPASS = 0

MSEL[5:0] = 16

CSEL[1:0] = 0

SSEL[3:0] = 4

所以在bf537-stamp.h文件中定义如下:

#define CONFIG_CLKIN_HZ 25000000 //定义主板外部晶振频率#define CONFIG_CLKIN_HALF 0 //DF = 0

#define CONFIG_PLL_BYPASS 0 //BYPASS = 0

#define CONFIG_VCO_MULT 16 //MSEL[5:0] = 16

#define CONFIG_CCLK_DIV 1 //CSEL[1:0] = 0

#define CONFIG_SCLK_DIV 4 //SSEL[3:0] = 4

bf537-stamp.h文件中仅仅是定义这些值,真正地写进寄存器是在/cpu/bf537/init_sdram.S文件中。

注意:BF536处理器PLL寄存器默认设置是10倍倍频,所以在选择外部时钟时要注意不能超过BF536的最高频率的1/10。

4.3.3 串口设置

串口在嵌入式系统调试中至关重要,尽早地打通串口对调试信息的输出是非常有利的。U-Boot在/cpu/bf537/serial.c文件中定义串口初始化以及串口收/发函数,初始化函数serial_init()在/lib_blackfin/board.c文件中的函数board_init_f()中被调用。在初始化串口之前调用函数init_baudrate()设置串口波特率。串口波特率的宏定义在配置文件中定义。U-Boot默认的波特率是57600 bps,可以在bf537-stamp.h文件中修改该定义为希望的波特率115200 bps,如下:

#define CONFIG_BAUDRATE 115200

4.3.4 SDRAM设置

BF536处理器的SDRAM控制器最大可支持128 MB的SDRAM,总线宽度可以配置为4位、8位或者16位,下面以32 MB SDRAM HY57V561620为例说明SDRAM的配置。HY57V561620是Hynix公司出品的4×4×16位的SDRAM,总线宽度为16位,包括4个Bank。BF536处理器与HY57V561620的连接包括数据总线D[0:15]、地址总线A[1:19]、SDRAM刷新专用信号SA10、时钟信号SCLK、时钟使能信号SCKE、行锁存信号SRAS、列锁存信号SCAS、写使能信号SWE、片选信号SMS和总线屏蔽信号ABE[1:0]。BF536处理器SDRAM起始地址为0x00000000,因此目标板SDRAM地址范围为0x00000000~0x01ffffff,共32 MB。BF536处理器与HY57V561620的连接电路图如图4.4所示。

图4.4 BF536处理器与HY57V561620的连接图

BF536处理器的SDRAM控制器包括4个寄存器:EBIU_SDRRC、EBIU_SDBCTL、EBIU_SDGCTL、EBIU_SDSTAT,其中前3个寄存器的设置决定SDRAM的工作方式,最后1个寄存器反映控制器的状态。

SDRAM刷新率控制寄存器EBIU_SDRRC如图4.5所示。

图4.5 SDRAM刷新率控制寄存器EBIU_SDRRC

EBIU_SDRRC寄存器包括1个12位的刷新率RDIV[11:0],依照以下公式计算该值:

RDIV = ((fSCLK × tREF) / NRA) – (tRAS + tRP)

其中,fSCLK = 系统总线频率;tREF = SDRAM行刷新时间;NRA = 刷新周期,对于HY57V561620来说,NRA=8192;tRAS = 从存储体激活到预充电之间的时间,以时钟周期为单位;tRP = 存储体从预充电到再次被激活之间的最小时间,以时钟周期为单位。

如果系统总线频率为100 MHz,对于HY57V561620来说,

RDIV = ((100×10^6×64×10^-3) / 8192 – (6 + 3) = 0x304

SDRAM存储体控制寄存器EBIU_SDBCTL如图4.6所示。

图4.6 SDRAM存储体控制寄存器EBIU_SDBCTL

表4.4 EBIU_SDBCTL寄存器定义

对于HY57V561620而言,列地址宽度为9位,容量为32 MB。

SDRAM全局控制寄存器EBIU_SDGCTL

EBIU_SDGCTL寄存器决定SDRAM操作的时序,需要配合SDRAM手册进行调整,不同的参数会影响SDRAM的性能,甚至影响是否能够正常工作。

U-Boot对SDRAM的设置体现在三个文件中,首先在配置文件中定义SDRAM容量大小、列地址宽度和型号,其次在mem_init.h中根据前面的定义自动生成EBIU_SDRRC、EBIU_SDBCTL、EBIU_SDGCTL三个寄存器的值,最后在init_sdram.S文件中初始化SDRAM控制器,把上面生成的值写入寄存器。

图4.7 SDRAM全局控制寄存器EBIU_SDGCTL

/include/configs/bf537-stamp.h中的定义:

#define CONFIG_MEM_SIZE 32 //定义主板SDRAM的容量,以MB为单位

#define CONFIG_MEM_ADD_WDTH 9 //定义SDRAM的列地址宽度

//4MB×16×4Bank的SDRAM,频率为133 MHz,与HY57V561620兼容

#define CONFIG_MEM_MT48LC16M16A2TG_75 1

/include/asm-blackfin/mem_init.h中系统时钟为100 MHz时HY57V561620对应的定义:

#define SDRAM_tRP TRP_2

#define SDRAM_tRP_num 2

#define SDRAM_tRAS TRAS_5

#define SDRAM_tRAS_num 5 #define SDRAM_tRCD TRCD_2

#define SDRAM_tWR TWR_2

#define SDRAM_Tref 64

#define SDRAM_NRA 8192

#define SDRAM_CL CL_3

#define SDRAM_SIZE EBSZ_32

#define SDRAM_WIDTH EBCAW_9

#define mem_SDBCTL SDRAM_WIDTH | SDRAM_SIZE | EBE

#define mem_SDRRC ((( CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)

#define mem_SDGCTL ( SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP |SDRAM_tRCD | SDRAM_tWR | PSS )

/cpu/bf537/init_sdram.S中的设置:

p0.l = lo(EBIU_SDRRC);

p0.h = hi(EBIU_SDRRC);

r0 = mem_SDRRC; //把mem_init.h文件生成的mem_SDRRC,w[p0] = r0.l;//写入EBIU_SDRRC寄存器

ssync;

p0.l = (EBIU_SDBCTL & 0xFFFF);

p0.h = (EBIU_SDBCTL >> 16);

r0 = mem_SDBCTL; //把mem_init.h文件生成的mem_SDBCTL,w[p0] = r0.l; //写入EBIU_SDBCTL寄存器

ssync;

P2.H = hi(EBIU_SDGCTL);

P2.L = lo(EBIU_SDGCTL);

R0 = [P2];

BITCLR (R0, 24); //禁止自我刷新p0.h = hi(EBIU_SDSTAT);

p0.l = lo(EBIU_SDSTAT);

r2.l = w[p0];

cc = bittst(r2,3); //判断SDRAM是否已经启动,如果没有则启动,

否则跳过

if !cc jump skip;

NOP;

BITSET (R0, 23);

skip:

[P2] = R0;

SSYNC;

R0.L = lo(mem_SDGCTL);

R0.H = hi(mem_SDGCTL);

[P2] = R0; //把mem_init.h中生成的值写入寄存器中

EBIU_SDGCTL

SSYNC;

nop;

至此,SDRAM控制器初始化完成,如果采用不同型号和配置的SDRAM存储器,可参考以上步骤修改相关参数。

4.3.5 Flash的移植

BF536处理器的异步存储控制器(Asynchronous Memory Controller,AMC)最多支持4个片选信号,每个片选信号可以寻址1 MB的地址空间。4个片选分别是AMS0、AMS1、AMS2和AMS3,其中AMS0支持上电启动。Flash存储器用来存储用户程序,目标板上的Flash存储器选用SST公司的SST39VF3201,该芯片与BF536处理器的连接包括A[1:19]地址总线、D[0:15]共16位数据总线、写使能信号AWE、允许输出信号AOE、片选信号AMS0和复位信号RESET。BF536处理器与Flash芯片的连接电路图如图4.8所示。

图4.8 BF536处理器与SST39VF3201芯片之间的连接电路

用户在U-Boot命令行环境下可以下载并烧写程序、设置环境变量等工作,因此U-Boot涉及到Flash的部分除了异步存储控制器的设置外,还需要编写Flash的擦除、编程等接口程序。

1.异步存储控制器初始化

BF536的异步存储控制器不但可以无缝接口Flash设备,还可以连接所有支持以存储器方式访问的设备,如各种外设控制器、SRAM、FPGA等,不同设备需要的不同时序由寄存器参数来调整。异步存储控制器包括4个片选信号AMS[3:0],称之为段。每个段独立寻址,具有独立的时序,最多可以寻址1 MB的地址空间,其中AMS0支持上电启动,4个片选信号的寻址空间如表4.5所示。

表4.5 BF536 AMC寻址空间

AMC的工作模式由3个寄存器决定:全局控制寄存器EBIU_AMGCTL、段控制寄存器EBIU_AMBCTL0和EBIU_AMBCTL1。

EBIU_AMGCTL寄存器如图4.9所示,定义如表4.6所示。

图4.9 EBIU_AMGCTL寄存器

表4.6 EBIU_AMGCTL寄存器定义

(续表)

EBIU_AMBCTL0寄存器如图4.10所示,定义如表4.7所示。

图4.10 EBIU_AMBCTL0寄存器

表4.7 EBIU_AMBCTL0寄存器定义

(续表)

EBIU_AMBCTL1寄存器如图4.11所示,定义如表4.8所示。

图4.11 EBIU_AMBCTL1寄存器

图4.11 EBIU_AMBCTL1寄存器(续)

表4.8 EBIU_AMBCTL1寄存器定义

(续表)

EBIU_AMGCTL寄存器控制全局属性,包括是否使能片选、DMA与CPU的优先级等,EBIU_AMBCTL0和EBIU_AMBCTL1分别控制4个片选段的动作属性,主要是各种操作的时序,不同的时序对读写操作的影响很大,根据所使用的Flash或者其他外设的要求调整时序以达到最佳性能,能够提供系统的吞吐率。BF536处理器在上电时使用默认值初始化寄存器,默认值一般是最大时延,以满足最慢的Flash的启动要求,系统启动后需要重新设置这些寄存器以追求最佳性能。

U-Boot中对Flash的要求体现在以下3个方面:

(1)/include/configs/bf537-stamp.h中的定义。

#define AMGCTLVAL 0xFF

#define AMBCTL0VAL 0xBBC3BBC3

#define AMBCTL1VAL 0x99B39983

(2)/cpu/bf537/start.S中的初始化。

p2.h = (EBIU_AMBCTL1 >> 16);

p2.l = (EBIU_AMBCTL1 & 0xFFFF);

r0.h = (AMBCTL1VAL >> 16);

r0.l = (AMBCTL1VAL & 0xFFFF);

[p2] = r0; //设置EBIU_AMBCTL1寄存器

ssync;

p2.h = (EBIU_AMBCTL0 >> 16);

p2.l = (EBIU_AMBCTL0 & 0xFFFF);

r0.h = (AMBCTL0VAL >> 16);

r0.l = (AMBCTL0VAL & 0xFFFF);

[p2] = r0; //设置EBIU_AMBCTL0寄存器

ssync;

p2.h = (EBIU_AMGCTL >> 16);

p2.l = (EBIU_AMGCTL & 0xffff);

r0 = AMGCTLVAL;

w[p2] = r0; //设置EBIU_AMGCTL寄存器

ssync;

(3)/board/bf536-stamp/flash.c中具体的Flash操作接口函数。

falsh.c文件中定义了Flash操作的接口函数,包括通用函数和底层接口函数,底层接口函数包括get_codes()、write_flash()、read_flash()、poll_toggle_bit()、erase_flash()、erase_block_flash()等函数。用户需要根据SST39VF3201的芯片手册自己实现这些函数,下面以最基本的读写操作来说明接口函数的实现。

#define CFG_FLASH_BASE 0x20000000 //Flash存储器的起始地址

//定义相对偏移量到绝对地址的映射关系

#define sysAddress(offset) ((volatile unsigned short *)(CFG_FLASH_BASE + (offset << 1)))

/***************************************************************************

* Flash写操作接口write_flash()

* 作用:把一个word数据写入指定地址中

* 输入:long nOffset——相对于0x20000000的地址偏移量

* uint16 nValue——要写入的数据,16 bit

* 输出:写成功返回SUCCESS,否则返回 FLASH_FAIL

***************************************************************************/

int write_flash(long nOffset, uint16 nValue)

{

*sysAddress(0x5555) = 0x00AA; // write data 0x00AA to device addr 0x5555

*sysAddress(0x2AAA) = 0x0055; // write data 0x0055 to device addr 0x2AAA

*sysAddress(0x5555) = 0x00A0; // write data 0x00A0 to device addr 0x5555

*sysAddress(nOffset/2) = nValue; // transfer the Uint16 to destination

if(poll_toggle_bit(nOffset) < 0)

return FLASH_FAIL;

return FLASH_SUCCESS;

}

/***************************************************************************

* Flash读操作接口read_flash()

* 作用:把指定地址处的数据读取到给定变量中

* 输入:long nOffset——相对于0x20000000的地址偏移量

* 输出:uint16 *pnValue——要返回的数据,16 bit

***************************************************************************/

int read_flash(long nOffset, uint16 *pnValue)

{

uint16 nValue = 0x0;

nValue = *(sysAddress(nOffset/2));

*pnValue = nValue;

return TRUE;

} FCUY62CemN36Jy8fk3dluayU7h13UxCE24PPz8MTiZFULM2DQwBVwGwJDJXbk7RN

点击中间区域
呼出菜单
上一章
目录
下一章
×