您的位置:首页 > 其它

使uboot支持S3C6410的SD启动

2013-06-13 16:40 459 查看
2011-05-14 20:18 898人阅读 评论(0) 收藏 举报

ctools磁盘三星语言

这里使用的uboot并非uboot官方发布的uboot代码,而是为三星定制的一个uboot版本s3c-u-boot-1.1.6,其代码作者就包括了三星的程序员与denx的员工。这个版本支持SD启动,不过默认是nand启动,使它支持uboot需要做以下事情:

  1、 虽然支持uboot启动,但是uboot代码里不叫SD启动方式,而是叫movinand启动方式,在incluede/configs/smdk6410.h中就有这个选项,所以在这个文件里关闭nand启动,打开movinand启动就可以了:

  //#define CONFIG_BOOT_NOR

  //#define CONFIG_BOOT_NAND 注释nand启动

  #define CONFIG_BOOT_MOVINAND 打开movinand启动

  //#define CONFIG_BOOT_ONENAND

  //#define CONFIG_BOOT_ONENAND_IROM

  #define CONFIG_NAND

  //#define CONFIG_ONENAND

  #define CONFIG_MOVINAND 打开movinand选项,使uboot支持movinand的操作

   2、如果单纯是做上面的改动,还是不够的,在运行的时候会发现到了一定的时候uboot就死掉了,其实这是因为uboot中假设SMDK6410在使用 SD方式的时候是从CH0启动的,但是手上的这个板子是通过CH1启动,那么在运行被复制到SRAM中的8K代码时候没办法在CH0检测到SD,更没办法 将SD 里的代码复制到SDRAM中。修改办法是在incluede/

  movi.h中HSMMC_CHANNEL修改为1。

  3、然后如果将上述修改后编译出来的u-boot.bin通过IROM_Fusing_tools直接烧写到SD中也是没办法启动的,需要运行以下的命令进行处理:

  cat u-boot.bin >> temp

  cat u-boot.bin >> temp

  split -b 256k temp

  mv xaa u-boot_256k.bin

  split -b 8k u-boot.bin

  mv xaa u-boot_8k.bin

  cat u-boot_256k.bin >> u-boot_mmc.bin

  cat u-boot_8k.bin >> u-boot_mmc.bin

   经过这些处理,实际上是将u-boot.bin内容重复一次后(为了保证达到256K,如果这个bin更小,那么可能需要重复3次、4次,直到超过 256K 为止),将前256K制成u-boot_256k.bin,再将前8K制成u-boot_8k.bin,最后将u-boot_256k.bin +u-boot_8k.bin合并成一个256K+8K大小的文件u-boot_mmc.bin,这个文件前256K就是u-boot_256k.bin 而后8K就是u-boot_8k.bin。把这个u-boot_mmc.bin通过IROM_Fusing_tools烧写到SD卡就可以成功启动系统
了。

  为什么要做这样的处理这个bin文件呢?下面通过分析IROM_Fusing_tools、uboot的源码来揭示其中的由来。

   从网上可以下载到IROM_Fusing_tools的源码,在按下这个软件的start控件后,先是读取这个SD卡的第一个扇区,也就是这个磁盘的 MBR 扇区,判断是不是FAT32格式的磁盘(这也是为什么用来做启动的SD必须格式化为FAT32格式),接着获取总的扇区数目TOTAl_SECOTR,并 将所要烧写的bin文件烧写到磁盘的这个扇区:TOTAL_SECTOR – 2 - SIZE_OF_IMAGE/512。其中TOTAl_SECTOR是这个磁盘总的扇区数目;SIZE_OF_IMAGE/512是这个bin文件将要占
据的扇区数(这里是以512为扇区大小的,因此对于扇区更大的SD卡也就没办法使用了,而现在的大容量SD都可能使用了2K甚至4K的扇区,除非修改这个 程序,并同步地在uboot中修改程序);至于2则是保留的2个扇区,至于为什么要保留这2个扇区,需要分析uboot的源码情况,下面将做进一步的阐 述。

  在SD启动方式下,S3C6410内部的IROM程序BL0首先运行,并将SD中的最后18个扇区开始的16个扇区内容复制到片内 的8K SRAM,也就是SteppingStone,接着跳转到这块SRAM的开始地址开始运行,这8K的代码实际上就是上面u-boot_mmc.bin这个 文件的最后8K,也是u-boot.bin的最开始8K代码,这段代码也叫BL1。从BL0跳转到BL1的时候uboot也就接管了CPU。

  Uboot的入口在start.S这个文件,cpu/s3c64x0/start.S中有这样一段代码:

  #ifdef CONFIG_BOOT_MOVINAND

  ldr sp, _TEXT_PHY_BASE

  bl movi_bl2_copy

  b after_copy

  #endif

  这段代码是实现SD启动的关键。到了这里后就执行movi_bl2_copy,这个函数负责将SD内的uboot完整地复制到SDRAM,这时候完整的uboot也叫BL2,而这个函数实际上是调用了以下函数:

  CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);

  HSMMC_CHANNEL这是SD/MMC通道号,手上板子使用的是CH1,而默认是CH0,所以需要对这个进行修改。

   MOVI_BL2_POS 是需要拷贝的数据位于SD的起始扇区,其计算办法是这样的,先得到这个SD的总扇区数TOTAL,再减去256K的BL2和8K的BL1所占的扇区数,最 后减去0.5K 的eFuse和0.5K的保留区所占的扇区数,而这里还定义SD的扇区为512B。从这里可以看到和IROM_Fusing_tools对SD卡的处理是 完全对应的。这里还有一个问题,总扇区数TOTAL是如何得到的?从程序来看是从(TCM_BASE - 0x4)这个地址读取到的,至于TOTAL是如何被放到这里的就只能从BL0的代码找答案了。

  MOVI_BL2_BLKCNT是需要复制的扇区数目,这里就是定义为256K,这也是为什么必须把u-boot.bin转换成256K的文件。

  BL2_BASE是目的地址,也就是SDRAM中的地址。这里定义为0x57E00000,就是128M 的SDRAM的最后2M,因为到这里为止MMU尚未打开,因此这里使用的是物理地址。

  MOVI_INIT_REQUIRED这个参数的意义是什么暂时没有任何资料说明。

  而CopyMovitoMem这个函数的定义是这样的:

  #define CopyMovitoMem(a,b,c,d,e) (((int(*)(int, uint, ushort, uint *, int))(*((uint *)(TCM_BASE + 0x8))))(a,b,c,d,e))

  这个定义实际上是调用了位于TCM_BASE + 0x8这个地址的函数指针,其中TCM_BASE的值为0x0C004000,至于这个地址放的是什么,也没资料说明。

  当复制完BL2后便会跳转到BL2的start_armboot这个C语言函数中运行了,此后的运行过程就不需要再分析了。


S3C6410开发全纪录(一)《还原SD卡启动的真相》

分类: Embed Linux2011-07-26
12:34 4690人阅读 评论(2) 收藏 举报

cdisknullbufferintegerbyte

前章我们也大致分析了SD卡的启动过程,在具体进行问题的定位及解决的过程中,发现还是有很多不明确的地方,网上的文章也多是人云亦云让我们来一步一步搞清楚S3C6410 SD卡启动的步骤及过程(我这里的开发板为OK6410,256M+1G的配置,SD卡为2G,MMC)
一、开发板跳线,从SD卡启动

[cpp] view
plaincopy

查看《OK6410开发板LINUX2.6用户手册.pdf》 将跳线设置为 11111000 (从左到右为 pin8 到 pin1的设置,别搞反了)

这些设置可以在s3c6410的datasheet中查到,打开《s3c6410_rev12.pdf》125页

Table 3-1. Device operating mode selection at boot-up

从这里可以看到,最后3个位为0,表示从SD/MMC(CH0)启动

[cpp] view
plaincopy

修改UBOOT,让它支持从SD卡读取数据,并将自己自举到内存

当我们设置完CPU的跳线,CPU已经清楚要从哪里去取第一条指,S3C6410到底是怎么工作的呢

之前找到过一篇参考文章 《S3C2450_IROM_ApplicationNote_Rev003.pdf》

这次找到了官方的文档更清楚的说明了这一切《S3C6410_Internal_ROM_Booting.pdf》

在文档中我们看到CPU上电之后的启动过程如下

[cpp] view
plaincopy

① iROM supports initial boot up,initialize system clock,D-TCM,device specific controller and bootin device.

② iROM boot codes can load 4KB of bootloader to stepping stone. The 8KB boot loader is called BL1

③ BL1: BL1 can initialize system clock, UART, and SDRAM for user. After initializing, BL1 will load remaining boot loader which is called BL2 on the SDRAM

④ Finally, jump to start address of BL2. That will make good environment to use system.

[cpp] view
plaincopy

按照这个启动过程,我们必须准备好8K的引导代码在BL1,

用来初始化系统,始终,串口,SDRAM等,并且将完整的BootLoader放在BL2上

2.7 Boot Block Assignment Guide 中有详细的描述

2G以下 SD/MMC 的卡的存储结构

SD/MMC 1Block = 512 Byte

=========================================================================================

| SD/MMC Device |

=========================================================================================

| | Recommendation | Mandatory |

| User File System |=====================================================================

| | Kernel | BL2 | BL1(8K) | Signature(512Byte) | Reserved(512Byte) |

| | | | 16 Block | 1 Block | 1 Block |

=========================================================================================

有了这个大致的印象,我们先放一下,下面我们来修改UBOOT的代码

二、修改UBOOT代码

[cpp] view
plaincopy

s3c6410的uboot源码见最后的参考资料

修改makefile 交叉工具链的绝对路径(嘿嘿,这个交叉工具链当然是俺自己做的交叉工具链了,参考前面篇BLOG)

ifeq ($(ARCH),arm)

CROSS_COMPILE = arm-none-linux-gnueabi-

endif

CROSS_COMPILE = /opt/cross_toolchains/arm/4.6.1/bin/arm-none-linux-gnueabi-

[cpp] view
plaincopy

修改 include/configs/smdk6410.h 打开 #define CONFIG_BOOT_MOVINAND 这个宏,并屏蔽其他的启动选项

在UBOOT的代码中,将IROM的启动模式称之为MOVINAND

这个UBOOT就已经可以从SD卡启动了,S3C6410具体又是怎么工作的呢?

[cpp] view
plaincopy

在 cpu/s3c64xx/start.S 中我们看到如下这段

#ifdef CONFIG_BOOT_MOVINAND

ldr sp, _TEXT_PHY_BASE

bl movi_bl2_copy

b after_copy

#endif

分析 movi_bl2_copy 函数

[cpp] view
plaincopy

cpu/s3c64xx/movi.c 中 void movi_bl2_copy(void) 中定义如下

[cpp] view
plaincopy

#if defined(CONFIG_S3C6400)

CopyMovitoMem(MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, CONFIG_SYS_CLK_FREQ, MOVI_INIT_REQUIRED);

#else

writel(readl(HM_CONTROL4) | (0x3 << 16), HM_CONTROL4);

CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);

#endif

确定MOVI_BL2_POS的值

[cpp] view
plaincopy

./include/movi.h:#define MOVI_BL2_POS (MOVI_LAST_BLKPOS - MOVI_BL1_BLKCNT - MOVI_BL2_BLKCNT - MOVI_ENV_BLKCNT)

./include/movi.h:#define MOVI_LAST_BLKPOS (MOVI_TOTAL_BLKCNT - (eFUSE_SIZE / MOVI_BLKSIZE))

./include/movi.h:#define MOVI_BL1_BLKCNT (SS_SIZE / MOVI_BLKSIZE)

./include/movi.h:#define MOVI_BL2_BLKCNT (((PART_ZIMAGE_OFFSET - PART_UBOOT_OFFSET) / MOVI_BLKSIZE) - MOVI_ENV_BLKCNT)

./include/movi.h:#define MOVI_ENV_BLKCNT (CFG_ENV_SIZE / MOVI_BLKSIZE)

./include/movi.h

#ifdef CONFIG_BOOT_MOVINAND

#define MOVI_TOTAL_BLKCNT *((volatile unsigned int*)(TCM_BASE - 0x4))

#define MOVI_HIGH_CAPACITY *((volatile unsigned int*)(TCM_BASE - 0x8))

#else

#define MOVI_TOTAL_BLKCNT 7864320 // 7864320 // 3995648 // 1003520 /* static movinand total block count: for writing to movinand when nand boot */

#define MOVI_HIGH_CAPACITY 0

#endif

./include/movi.h:#define MOVI_BLKSIZE 512

./include/movi.h

#if defined(CONFIG_S3C6400) || defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)

#define TCM_BASE 0x0C004000

#define BL2_BASE 0x57E00000

#elif defined(CONFIG_S3C2450) || defined(CONFIG_S3C2416)

#define TCM_BASE 0x40004000

#define BL2_BASE 0x33E00000

#else

# error TCM_BASE or BL2_BASE is not defined

#endif

./include/movi.h

#if defined(CONFIG_S3C6400)

#define SS_SIZE (4 * 1024)

#define eFUSE_SIZE (2 * 1024) // 1.5k eFuse, 0.5k reserved

#else

#define SS_SIZE (8 * 1024)

#define eFUSE_SIZE (1 * 1024) // 0.5k eFuse, 0.5k reserved`

#endif

./include/movi.h:#define PART_ZIMAGE_OFFSET 0x40000

./include/movi.h:#define PART_UBOOT_OFFSET 0x0

./include/configs/smdk6410.h:#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */

确定BL2_BASE的值

[cpp] view
plaincopy

./include/movi.h

#if defined(CONFIG_S3C6400) || defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)

#define TCM_BASE 0x0C004000

#define BL2_BASE 0x57E00000

#elif defined(CONFIG_S3C2450) || defined(CONFIG_S3C2416)

#define TCM_BASE 0x40004000

#define BL2_BASE 0x33E00000

#else

# error TCM_BASE or BL2_BASE is not defined

#endif

经过计算我们可以看出,这里决定CopyMovitoMem的功能,是TCM_BASE - 0x4,这个地址的寄存器的值(隐含的也告诉我们UBOOT编译出来之后不得大于256k)

《S3C6410_Internal_ROM_Booting.pdf》中看到

0x0C003FFC globalBlockSizeHide Total block count of the MMC device

这个值,具体的为,256K(根据打印可以得出,没找到具体的说明)

MOVI_BL2_BLKCNT 的值为 ( (0x40000-0)/512 - (0x4000/512) ) = 512 -32 (个扇区)

网上大多数资料写到CopyMovitoMem是将256k的数据搬运到内存中,从这个计算上我们可以看出实际这个结论是错的

在这里只搬运了 256k-16k的数据到内存

在MOVI_BL2_POS的定义中做了相应的处理,以保证位置的正确性

编译uboot,生成u-boot.bin

[cpp] view
plaincopy

make smdk6410_config

make -j4

三、将修改好的UBOOT烧录到SD卡中

生成的uboot-bin是不是直接可以烧录到SD卡中呢?

有现成的工具IROM_Fusing_Tool.exe(开源的,可以找到源代码),但这个工具烧录的是nb0文件

实际上nb0文件的结构是:256k+8k 这样的一个形式,在Linux系统可以通过下面这个脚本来生成nb0文件

[cpp] view
plaincopy

#!/bin/sh

rm -rf temp x* u-boot_256k.bin u-boot_8k.bin u-boot_mmc.nb0

cat u-boot.bin >> temp

cat u-boot.bin >> temp

split -b 256k temp

mv xaa u-boot_256k.bin

split -b 8k u-boot.bin

mv xaa u-boot_8k.bin

cat u-boot_256k.bin > u-boot_mmc.nb0

cat u-boot_8k.bin >> u-boot_mmc.nb0

我想直接将uboot-bin烧录到SD卡中,使用脚本太麻烦,于是我打算自己写一个烧录工具,关键代码如下

需要说明的是,我这里使用的是VC6,WINDOWS XP,VC6对磁盘IO的操作本身支持并不是非常好,有很多扩展的定义,功能都无法使用,这里很多都我手工添加进去的

如果使用的是VC2003及以上版本,会简单一些

[cpp] view
plaincopy

DWORD CSC6410BootLoaderWriterDlg::BlockDataRead(char cPart,DWORD dwBlockIndex,DWORD dwReadCount,BYTE* pBuffer)

{

CString devName;

devName.Format("\\\\.\\%c:",cPart);

HANDLE hDevice = CreateFile(devName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);

DWORD dwFilePointer = SetFilePointer(hDevice,dwBlockIndex*512, 0,FILE_BEGIN);

DWORD dwBytesRead = 0;

BOOL bRead = ReadFile(hDevice,pBuffer,dwReadCount,&dwBytesRead,NULL);

if(bRead == FALSE)

{

DWORD dwError = GetLastError();

}

CloseHandle(hDevice);

return dwBytesRead;

}

[cpp] view
plaincopy

DWORD CSC6410BootLoaderWriterDlg::BlockDataWrite(ULONG nPhysicalDriveNumber,DWORD dwBlockIndex,BYTE* pData,DWORD dwDataLen)

{

if( (dwDataLen % 512) != 0 ) dwDataLen = ( (dwDataLen / 512) + 1 ) * 512;

CString devName;

devName.Format("\\\\.\\PhysicalDrive%d",nPhysicalDriveNumber);

HANDLE hDevice = CreateFile(devName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);

DWORD dwFilePointer = SetFilePointer(hDevice,dwBlockIndex*512, 0,FILE_BEGIN);

DWORD dwBytesWrite = 0;

BOOL bWrite = WriteFile(hDevice,pData,dwDataLen,&dwBytesWrite,NULL);

if(bWrite == FALSE)

{

DWORD dwError = GetLastError();

}

CloseHandle(hDevice);

return dwBytesWrite;

}

看到区别了吗?这里要非常非常注意!

Write函数中devName的构建形式与Read函数中的不一样,这个问题让我调试了很久,如果在Write函数中使用Read函数的构建形式,则会遇到WriteFile工作不正常的现象

具体为:在操作最后若干个扇区时,bWrite 等于 TRUE,dwBytesWrite却为0(为什么?还没能深究下去)

另外,如果要写入的数据长度不是512的整数倍,一定要进行处理,否则会引起GetLastError是87,参数错误

因为所有的FLASH,最小的扇区时512字节,则最少要以512个字节作为一次操作单位

(文件系统帮我们解决了这些问题,我们现在是对磁盘裸的操作,所以不能按照有文件系统的想法来考虑这个问题)

下面是Write函数构造devName时需要用到的函数

[cpp] view
plaincopy

ULONG CSC6410BootLoaderWriterDlg::GetPhysicalDriveNumber(char cPart)

{

typedef struct _DISK_EXTENT {

ULONG DiskNumber;

LARGE_INTEGER StartingOffset;

LARGE_INTEGER ExtentLength;

} DISK_EXTENT, *PDISK_EXTENT;

typedef struct _VOLUME_DISK_EXTENTS {

ULONG NumberOfDiskExtents;

DISK_EXTENT Extents[ANYSIZE_ARRAY];

} VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS;

#define VOLUMEDISKSIZE (sizeof(VOLUME_DISK_EXTENTS))

#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 5636096

CString devName;

devName.Format("\\\\.\\%c:",cPart);

HANDLE hDevice = CreateFile(devName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );

VOLUME_DISK_EXTENTS volumeData;

DWORD dwOut = 0;

DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL, 0, &volumeData, VOLUMEDISKSIZE, &dwOut, NULL );

CloseHandle( hDevice );

return volumeData.Extents[0].DiskNumber;

}

下面这段代码是用来获得,所有插入的U盘(可移动磁盘,注意下面的判断)的盘符

[cpp] view
plaincopy

void CSC6410BootLoaderWriterDlg::OnButtonGetdriverinfo()

{

// TODO: Add your control notification handler code here

// 获取所有的盘符

m_cbList.ResetContent();

DWORD dwStrLen = GetLogicalDriveStrings(0,NULL);

char* pString = new char[dwStrLen+1];

memset(pString,0,dwStrLen+1);

GetLogicalDriveStrings(dwStrLen+1,pString);

char *pNow = pString;

while(TRUE)

{

if(pNow >= (pString+dwStrLen-1)) break;

DWORD dwRet = GetDriveType(pNow);

if(dwRet == DRIVE_REMOVABLE)

{

m_cbList.InsertString(0,pNow);

}

pNow += strlen(pNow);

pNow ++;

}

delete[] pString;

m_cbList.SetCurSel(0);

m_cbList.SetFocus();

WriteLog("U盘检查完成");

}

最后是写入代码,在这里我们会要求SD卡首先会被各式化成FAT32各式,以便我们能去读取FTA32文件分配表中MBR的部分

[cpp] view
plaincopy

void CSC6410BootLoaderWriterDlg::OnButtonOp()

{

// TODO: Add your control notification handler code here

int nCurSel = m_cbList.GetCurSel();

if(nCurSel == -1)

{

MessageBox("探测磁盘信息");

return;

}

CString strBootFilePath;

m_eBootFilePath.GetWindowText(strBootFilePath);

if(strBootFilePath == "")

{

MessageBox("请先选择需要烧录的引导文件");

return;

}

// 获得驱动器盘符

CString strText;

m_cbList.GetLBText(m_cbList.GetCurSel(),strText);

char cPart = strText[0];

// 获得 PhysicalDriveNumber

ULONG nPhysicalDriveNumber = GetPhysicalDriveNumber(cPart);

// 读取 0 扇区 mbr

BYTE szMbr[512];

memset(szMbr,0,sizeof(szMbr));

DWORD dwReturn = BlockDataRead(cPart,0,sizeof(szMbr),szMbr);

if(dwReturn != sizeof(szMbr))

{

MessageBox("Read MBR error.","错误",MB_OK|MB_ICONERROR);

return;

}

{

CString strLog;

strLog.Format("读取MBR成功");

WriteLog(strLog);

}

// 判断是否为 fat32

// FAT16 为 0x36 0x37 0x38 0x39 0x3a 0x3b

char szFs[6];

szFs[0] = szMbr[0x52];

szFs[1] = szMbr[0x53];

szFs[2] = szMbr[0x54];

szFs[3] = szMbr[0x55];

szFs[4] = szMbr[0x56];

szFs[5] = '\0';

if ( strcmp(szFs,"FAT32") != 0)

{

MessageBox("请将SD卡格式化为FAT32文件系统","错误",MB_OK|MB_ICONINFORMATION);

return;

}

// 获得磁盘的扇区总数

//1CH-1FH 4 本分区隐含扇区数

//20H-23H 4 该盘实际使用扇区数(不包括隐含扇区)

DWORD count_block_hidden = 0;

memcpy(&count_block_hidden,&szMbr[0x1c],sizeof(count_block_hidden));

DWORD count_block = 0;

memcpy(&count_block,&szMbr[0x20],sizeof(count_block));

DWORD count_block_total = count_block_hidden + count_block;

// 另一种方法 获得 扇区总数

// #define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX 458912

// struct _DISK_GEOMETRY_EX

// { DISK_GEOMETRY Geometry;

// LARGE_INTEGER DiskSize;

// UCHAR Data[1];

// } DiskEX;

// DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,NULL,0,(LPVOID)&DiskEX,sizeof(DiskEX),(LPDWORD)&bytesReturned,NULL);

// 读取 u-boot.bin 文件

// 最大 256k

#define MOVI_TOTAL_BLKCNT 0x40000

BYTE buffer_utoot[MOVI_TOTAL_BLKCNT];

memset(buffer_utoot,0,sizeof(buffer_utoot));

CFile cf;

cf.Open(strBootFilePath,CFile::modeRead);

DWORD uboot_size = min(MOVI_TOTAL_BLKCNT,cf.GetLength());

cf.Read(buffer_utoot,uboot_size);

cf.Close();

// 将引导程序 uboot-bin 写入相应的位置

DWORD bl2_begin = count_block_total-1-1-16-512;

DWORD bl1_begin = count_block_total-1-1-16;

dwReturn = BlockDataWrite(nPhysicalDriveNumber,bl1_begin,buffer_utoot,8192);

if(dwReturn != 8192)

{

MessageBox("写入引导8k字节失败");

return;

}

{

CString strLog;

strLog.Format("写入引导8k字节成功");

WriteLog(strLog);

}

dwReturn = BlockDataWrite(nPhysicalDriveNumber,bl2_begin,buffer_utoot,uboot_size);

if(dwReturn < uboot_size)

{

MessageBox("写入引导失败");

return;

}

{

CString strLog;

strLog.Format("引导文件写入完成,磁盘总扇区数:%d",count_block_total);

WriteLog(strLog);

}

}

到这里,我们就可以完全分析清楚,并可以自主的制作一个S3C6410的启动SD卡了,附后为一些参考资料,这里没办法贴附件,问题给我留言吧

后面的内容中,我们将进入UBOOT,对UBOOT进行修改,请关注下一节《如何计算内存大小,并在UBOOT中调整内存大小》

四、参考资料

下载 uboot1.1.6 (支持 movinand)

http://www.rayfile.com/zh-cn/files/7ac4e133-0e58-11de-bd70-0014221b798a/

使uboot支持S3C6410的SD启动

/article/8986645.html

《S3C6410_Internal_ROM_Booting.pdf》

《s3c6410_rev12.pdf》

《smdk6410_users_manual_rev1.0.pdf》

《K4X51163PC.pdf》

《OK6410开发板LINUX2.6用户手册.pdf》

《OK6410开发板硬件手册2.1.pdf》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: