您的位置:首页 > 其它

WinCE5.0 SMDK2410 BSP在GEC2410开发板上的移植(3)-基于Nor Flash的Eboot

2009-07-18 13:35 483 查看
之前的两篇文章介绍了基于Nand Flash的Eboot,通过使用Nboot来引导Eboot的方式。其实GEC2410开发板配有1片2M Bytes的Nor Flash(SST39VF1601),程序可以直接运行在Nor Flash上,就不需要Nboot来引导了。当然最终Eboot还是运行在RAM中,Eboot会自我复制到RAM中运行。

原来使用自带的sjf410烧写非常慢,后来找到了H-JTAG和对应2410的烧写配置,然后烧写就非常方便了。因此以后Eboot就放到Nor Flash,OS Image放到Nand Flash中。
SMDK2410 BSP用的Nor Flash是AMD的am29lv800,与GEC2410不同,因此需要增加Nor Flash的驱动。

一、开发环境
编译器: Platform Builder 5.0
目标板: GEC2410 S3C2410A,NAND Flash:64M K9F1208,NOR Flash:2M SST39VF1601 SDRAM 64M,CS8900

二、开始移植
(1)去除不相关代码
注释掉AM29LV800_Init((UINT32)AMD_FLASH_START)
注释掉原来通过Nand Flash读写Eboot配置的函数

去除AM29LV800.c

(2)增加SST39VF1601驱动
之前使用板子自带的ADS下SST39VF1601的驱动,但是始终无法正常读写。后来使用SMARTARM2200带的SST39VF1601驱动进行修改,最终获得成功
其实主要几个函数如下,具体可参考之后我发的整个BSP的源代码
[1]几个宏的定义
#define  SST39VF1601_SECTOR_SIZE   4*1024
#define  SST39VF1601_BLOCK_SIZE    64*1024
#define  GET_ADDR(addr)	(volatile UINT16 *)(SST39VF1601_FLASH_START | (addr<<1))
#define  SST_ID         0x00BF
#define  SST_39VF3201   0x234B

[2]SST39VF1601_CheckID
DWORD SST39VF1601_CheckID( void )
{
volatile WORD *ip;
WORD SST_id1, SST_id2;

/*  Issue the Software Product ID code to 39VF160   */
ip  = GET_ADDR(0x5555);
*ip = 0x00AA;
ip  = GET_ADDR(0x2AAA);
*ip = 0x0055;
ip  = GET_ADDR(0x5555);
*ip = 0x0090;

/* Read the product ID from 39VF160 */
ip  = GET_ADDR(0x0000);
SST_id1 = *ip & 0x00FF;
ip  = GET_ADDR(0x0001);
SST_id2 = *ip;

/* Issue the Soffware Product ID Exit code thus returning the 39VF160 */
/* to the read operating mode */
ip  = GET_ADDR(0x5555);
*ip = 0x00AA;
ip  = GET_ADDR(0x2AAA);
*ip = 0x0055;
ip  = GET_ADDR(0x5555);
*ip = 0x00F0;

//	RETAILMSG(1, (TEXT("SST_id1=0x%x SST_id2=0x%x/r/n"), SST_id1, SST_id2));

/* Check ID */
if ((SST_id1 == SST_ID) && (SST_id2 ==SST_39VF3201))
return (TRUE);
else
return (FALSE);
}

[3]SST39VF1601_SectorErase
UINT8 SST39VF1601_SectorErase(UINT32 Index)
{
volatile UINT16 *ip;
UINT16 temp1,temp2;

ip = GET_ADDR(0x5555);
*ip = 0x00aa;
ip = GET_ADDR(0x2aaa);
*ip = 0x0055;
ip = GET_ADDR(0x5555);
*ip = 0x0080;
ip = GET_ADDR(0x5555);
*ip = 0x00aa;
ip = GET_ADDR(0x2aaa);
*ip = 0x0055;
ip = (UINT16*)GetSectorAddress(Index);

*ip = 0x0030;

while (1)
{
temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{
if (temp1 != 0xffff)
{
return FALSE;
}
else
{
return TRUE;
}
}
}
return TRUE;
}

[4]SST39VF1601_WriteWord
UINT8 SST39VF1601_WriteWord(UINT32 Addr, UINT16 Data)
{
volatile UINT16 *ip;
UINT16 temp1,temp2;

ip = GET_ADDR(0x5555);
*ip = 0x00aa;
ip = GET_ADDR(0x2aaa);
*ip = 0x0055;
ip = GET_ADDR(0x5555);
*ip = 0x00a0;

ip = ((volatile UINT16 *)(Addr));
*ip = Data;
while (1)
{
temp1 = *ip;
temp2 = *ip;
if (temp1 == temp2)
{
if (temp1 != Data)
{
return FALSE;
}
else
{
return TRUE;
}
}
}
return TRUE;
}

以下3个函数是供Read(Write)BootConfig来调用的,与原来的结构一致
[5]SST39VF1601_ReadFlash
BOOL SST39VF1601_ReadFlash(UINT32 dwOffset, PBYTE pData, UINT32 dwLength)
{
PBYTE pReadPtr = (PBYTE)(SST39VF1601_FLASH_START + dwOffset);

memcpy(pData, pReadPtr, dwLength);

return(TRUE);
}

[6]SST39VF1601_EraseFlash
BOOL SST39VF1601_EraseFlash(UINT32 dwOffset, UINT32 dwLength)
{
UINT8 NumSects = 0;
UINT32 dwEraseLength = 0;
UINT16 StartSector = GetSectorNumber(dwOffset);

while(dwEraseLength < dwLength)
{
dwEraseLength += SST39VF1601_SECTOR_SIZE;
++NumSects;
}

if (!NumSects)
{
NumSects = 1;
dwEraseLength = SST39VF1601_SECTOR_SIZE;
}

RETAILMSG(1, (TEXT("SST39VF1601_EraseFlash: Requested 0x%x bytes, Erasing 0x%x sectors (0x%x bytes) (offset 0x%x bytes).../r/n"), dwLength, NumSects, dwEraseLength, dwOffset));

while(NumSects--)
{

if (!SST39VF1601_SectorErase(StartSector + NumSects))
{
RETAILMSG(1, (TEXT("ERROR: SST39VF1601_EraseFlash: EraseSector failed on sector 0x%x!/r/n"), NumSects));
return(FALSE);
}
}

return(TRUE);
}

[7]SST39VF1601_WriteFlash
BOOL SST39VF1601_WriteFlash(UINT32 dwOffset, PBYTE pData, UINT32 dwLength)
{
UINT32 dwByteOffset;

RETAILMSG(1, (TEXT("SST39VF1601_WriteFlash: Writing 0x%x bytes to flash (offset 0x%x bytes).../r/n"), dwLength, dwOffset));

for (dwByteOffset = 0 ; dwByteOffset < dwLength ; dwByteOffset += sizeof(USHORT))
{
if(!SST39VF1601_WriteWord ((SST39VF1601_FLASH_START + dwOffset + dwByteOffset), *(PUSHORT)(pData + dwByteOffset)))
{
RETAILMSG(1, (TEXT("Write to flash failed at offset 0x%x/r/n"),dwOffset + dwByteOffset));

}

}

return(TRUE);
}

[8]只需用以上3个函数代替原来main.c中WriteBootConfig和ReadBootConfig中对应的Flash函数即可
SST39VF1601_ReadFlash(EBOOT_CONFIG_OFFSET, (PBYTE)pBootCfg, sizeof(BOOT_CFG))和
[9]还有两个用到的函数GetSectorNumberGetSectorAddress也是为了兼容原来的结构实现的,针对Sector进行了计算
static UINT32 GetSectorNumber(UINT32 dwOffset)
{
UINT32 ret;
ret = dwOffset/(SST39VF1601_SECTOR_SIZE);
return ret;
}

static UINT32 GetSectorAddress(UINT8 SectorNumber)
{
UINT32 dwSectorAddr = 0;

dwSectorAddr = SectorNumber * SST39VF1601_SECTOR_SIZE;

return(SST39VF1601_FLASH_START + dwSectorAddr);
}

三、烧写完成运行

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐