达芬奇(Davinci)系列嵌入式处理器是TI公司的具有高速处理能力的新一代嵌入式设备[1],它同时具备了DSP和精简指令级计算机技术的优点。它集成了一个高性能的DSP核心与一个ARM9内核,被广泛应用于嵌入式图片、视频处理中[2]。在Davinci平台下,通常以ARM核为基础构建嵌入式操作系统,但是目前经常采用一片NOR Flash加上一片NAND Flash作为外部存储设备,并且通常都是256 B/页或者512 B/页的小页面NAND Flash,本文旨在只以一片2 KB/页的大页面NAND Flash(Samsung K9K8G08U0A)作为外部存储设备、Davinci TMS320DM6446作为处理器的硬件结构下,阐述构建稳定可靠的系统需要解决的问题。
1 问题概述
EMIF是用来连接Flash、SRAM等多种存储设备的外设端口。TMS320DM6446的EMIF端口支持每路32 MB总共4路可寻址的片选空间,支持8 bit以及16 bit的数据总线宽度,具有可编程的建立、选通以及保持时间,还具备NAND Flash ECC校验数据生成功能等[5],因此可以方便灵活地与外部NAND Flash芯片通信。在本文的硬件系统中,即采用TMS320DM6446的EMIF的CS2空间与Samsung K9K8G08U0A NAND Flash相连。
由于本系统只有一片NAND Flash作为外部的存储设备,因此所有的引导程序、操作系统内核以及根文件系统均需要存储在这上面,系统也就需要从NAND Flash启动。TMS320DM6446具有多种启动方式,具体由哪种方式启动,由系统复位时引脚BTSEL[1:0]电平决定,当BTSEL[1:0]被置为“01”时,TMS320DM6446的ARM核从EMIFA的EM_CS2存储空间开始执行(地址为0x0200 0000),这种情况下EMIF连接的是具有线性地址的非易失存储器,通常是NOR Flash。当BTSEL[1:0]不为“01”时,TMS320DM6446内部的ROM BOOT LOADER(简称RBL)开始运行,RBL再根据BTSEL[1:0]的不同值决定从何处加载用户的引导程序UBL(USER BOOT LOADER)。当BTSEL[1:0]为“00”时,RBL将从连接到EMIF的CS2空间的NAND Flash中加载UBL。由于RBL的加载过程是将UBL拷贝到ARM的内部RAM中,因此对于UBL的大小限制在14 KB以内,但是在嵌入式环境常用的U-BOOT、ViVi等的大小都远超过这个限制,因此需要多级加载,一级引导程序主要做系统的初始化,然后将二级引导程序(在本系统中采用U-BOOT,本文后面提到的UBL均指一级引导程序)从NAND Flash中读取到RAM中,然后启动它,由U-BOOT负责操作系统的引导[4]。于是整个NAND Flash上系统构建的关键问题包括如何移植UBL,以使其能够正常初始化系统,正常加载二级引导程序U-BOOT到RAM中,U-BOOT的移植使其满足大页面NAND Flash的读写要求以及裸机时引导程序的烧写。
2 UBL移植
UBL为TI公司提供的对于Davinci系列处理器通过内部的ROM BOOT LOADER启动时的一级引导程序。其工作流程如图1所示。
UBL的移植主要针对本系统中硬件板的结构修改系统初始化过程以及增加对Samsung K9K8G08U0A NAND Flash的支持,以下分别阐述。
2.1 系统初始化
2.1.1 设置CPU、DDR工作频率
TMS320DM6446具有两路PLL,其中PLL1通过分频供系统的主时钟及大部分外设的时钟,PLL2供DDR2使用。DSP时钟频率为SYSCLK1=27 MHz×(PLL1_PLLM+1),使用固定一分频,本系统中DSP工作在正常频率594 MHz,因此需设置PLL1_PLLM=21,即设置寄存器0x1C4 0910为21。
本系统使用两片K4T1G164QQ-HCE6 DDR2 SDRAM作为系统内存,该芯片为DDR2 667芯片,时钟频率为333 MHz。TMS320DM6446中DDR2使用PLL2的PLLDIV2分频作为时钟频率,计算公式为(27 MHz×(PLL2_PLLM+1))/(PLL2_PLLDIV2→RATIO+1)。因此设置PLL2_PLLM=23,PLL2_PLLDIV2→RATIO=1,PLL2_PLLDIV2的第15位为分频允许位,应置为1,所以PLL2_PLLDIV2为0x8001,即寄存器0x1C4 0D10=23,0x1C4 0D1C=0x8001。
2.1.2 配置EMIF接口
根据Samsung K9K8G08U0A NAND Flash的读、写时序要求,TMS320DM6446的EMIF用于与NAND Flash连接时,配置寄存器各字段值需满足如下要求:
RSETUP≥tCLR(m)/tCYC-1=0
RSTORBE≥max((tREA(m)+tSU)/tCYC,tRP(m)/tcyc)-1=1.5
R_SETUP+R_STROBE≥(tCEA(m)+tSU)/tcyc-1=2
R_HOLD≥(tH-tCHZ(m))/tcyc-1=-4
R_SETUP+R_STROBE+R_HOLD≥tRC(m)/tcyc-3=-0.5
TA≥max((tCHZ(m))/tcyc,(tRHZ(m)-(R_HOLD+1)tcyc)/(tcyc))-1≥2
W_SETUP≥max(tCLS(m)/tcyc,tALS(m)/tcyc,(tCS(m)/tcyc)-1=1
W_STROBE≥tWP(m)/tcyc-1=0.2
W_SETUP+W_STROBE≥tDS(m)/tcyc-1=0.2
W_HOLD≥max((tCLH(m))/(tcyc),(tALH(m))/tcyc,(tCH(m))/(tcyc),(tDH(m))/(tcyc))-1=-0.5
W_SETUP+W_STROBE+W_HOLD≥tWC(m)/(tcyc)-3=-0.5
其中tSU是EMIF数据建立时间,取值5 ns,tH数据保持时间取0,EMFI时钟为系统6分频,所以tcyc=1/(27×(21+1)/6)≈10 ns,根据EMIF连接NAND的取值要求,设置EMIF CS2的配置寄存器值为0x842429c。
2.2 支持Samsung K9K8G08U0A NAND Flash
UBL通过数据结构struct _NAND_DEV_STRUCT_来表示一个型号的NAND Flash,具有devID、numBlocks、pagesPerBlock、bytesPerPage几个字段。通过struct _NAND_
DEV_STRUCT_类型的数组gNandDevInfo[]来记录所有支持的NAND Flash。UBL在从NAND Flash读取数据之前,首先通过读取设备号命令0x90得到NAND Flash的设备号,然后从数组gNandDevInfo[]中查找具有相同设备号的记录,从而得到NAND Flash的详细信息,以确定NAND Flash的读方式。
因此,需要UBL支持特定的NAND Flash,只需要将其信息添加到数组gNandDevInfo[]中即可。本系统中用到的Samsung K9K8G08U0A NAND Flash设备号为0xD3,具有8 192个存储块,每个块具有64个页面,每页具有2 048 B数据存储区域以及64 B的Spare区域,在数组gNandDevInfo[]中添加{0xD3,8192,64,2048+64}即可。
3 U-BOOT移植
本系统中使用的U-BOOT引导程序由TI公司提供的支持Davinci平台以及NAND Flash启动的U-BOOT1.1.3移植而来。