我有一个exFTA 120G的sd卡,把它塞到读卡器里能当U盘用么?。

怎样把SD卡的东西转到另一个sD卡上_百度知道
怎样把SD卡的东西转到另一个sD卡上
怎样把SD卡的东西转到另一个sD卡上
我有更好的答案
把SD卡插到读卡器然上,然后将SD卡插到电脑上,将卡的内容复制到电脑上,
然后将卡取出,再将另一个SD插到读卡器上再把刚存到电脑上的内容再存到另一个卡上!不用电脑要费些力!
采纳率:79%
先用电脑拷贝到电脑上,sd卡插在读卡器上就类似U盘的作用,然后换另外的sd卡复制过来就行了。
先把sb卡上的东西转存到手机上,然后卸下再转到另一张内存卡上。
这个需要用读卡器在电脑上拷贝。
其他1条回答
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。您尚未登录:请
有没有一种设备可以直接复制sd卡到移动硬盘?
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
posted by wap, platform: Chrome
主要是旅游用,我现在用gopro基本上一天就要录满64G的卡,多买几张卡的话又有点奢侈
有没有类似移动终端的东西可以直接复制sd卡的内容到移动硬盘呢?
不过我要求拷贝速度也要快一点的,因为我之前有一个atom的windows7手机用来复制文件,但是碍于cpu性能,复制速度极其缓慢,所以这次需要一个专用的设备
有推荐的嘛?谢谢了
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&
帖子14107&精华&积分32621&激骚810 度&爱车捷安特山地车&主机笔记本一个&相机手机摄像头自带&手机&注册时间&
posted by wap, platform: 华为
七八年前见过这样的设备,内置硬盘和读卡器,插进去储存卡自动把里面的照片复制到硬盘,好像叫数码伴侣吧
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
posted by wap, platform: Chrome引用:原帖由 @燕山隐士&&于
15:09 发表
posted by wap, platform: 华为
七八年前见过这样的设备,内置硬盘和读卡器,插进去储存卡自动把里面的照片复制到硬盘,好像叫数码伴侣吧 是的,不过我这个sd卡容量大直接用以前的设备似乎拷贝速度太慢了
我之前也考虑过用android手机,但是它的usb host貌似不支持两个usb,而且我atom拷贝的都很慢,用手机感觉会更差
专门为了这个用途去买个win8的板子感觉也不太合适,出去玩也不愿意带笔记本。。。
想来想去还是需要这种设备,就是不知道有没有新出的速度快点的
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&
ps2xboxngc
帖子4926&精华&积分382194&激骚1376 度&爱车&主机&相机&手机&注册时间&
把SD卡插安桌手机里,然后USB外接移动硬盘,直接对拷就行了吧
把所有积分与内裤都压在湖人身上,不要带我回到2006年
帖子7973&精华&积分14594&激骚703 度&爱车明锐1.6AT&主机3DS&相机450D,黑卡III&手机&注册时间&
我的解决方案是,我买了个RT……
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
引用:原帖由 ps2xboxngc 于
15:38 发表
把SD卡插安桌手机里,然后USB外接移动硬盘,直接对拷就行了吧 我只有3儿子,没sd插槽
而且我之前的win7手机也能拷贝,就是usb总线被限制了,每秒速度极慢,大概5M的速度,拷满64g真的很要命。。。引用:原帖由 hellblack 于
15:39 发表
我的解决方案是,我买了个RT……
别打我 哎,我要是买个板子还不如多卖几个卡啊,但是感觉太多余了。。
我查了一圈也没找到合适的设备。。我这需求是不是太奇特了啊?
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&
帖子13184&精华&积分29757&激骚243 度&爱车&主机&相机&手机&注册时间&
个人建议,多买几张SD卡最方便。
帖子7973&精华&积分14594&激骚703 度&爱车明锐1.6AT&主机3DS&相机450D,黑卡III&手机&注册时间&
引用:原帖由 anakin 于
15:43 发表
我只有3儿子,没sd插槽
而且我之前的win7手机也能拷贝,就是usb总线被限制了,每秒速度极慢,大概5M的速度,拷满64g真的很要命。。。
哎,我要是买个板子还不如多卖几个卡啊,但是感觉太多余了。。
... 多备几张卡吧
或者咬咬牙上个T100之类的ATOM win8板
帖子28203&精华&积分27941&激骚1021 度&爱车&主机&相机&手机&来自火星&注册时间&
不特别追求高性能的话64G的卡又不贵~
只要人人都撒了一点谎...世界将变成美好的天堂...
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
posted by wap, platform: Chrome
谢谢各位了
我查了下t100的日本售价,哎,还是买卡好了。。这次不行就多买几张卡加上我那win7手机慢慢考对付一下了
我等明年出新版atom版直接入一个
谁说微软必须死啊,win8.1的板子这时候简直就是无法取代的。。。
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&
帖子7973&精华&积分14594&激骚703 度&爱车明锐1.6AT&主机3DS&相机450D,黑卡III&手机&注册时间&
引用:原帖由 anakin 于
16:33 发表
posted by wap, platform: Chrome
谢谢各位了
我查了下t100的日本售价,哎,还是买卡好了。。这次不行就多买几张卡加上我那win7手机慢慢考对付一下了
我等明年出新版atom版直接入一个
谁说微软必须死啊,win8. ... WIN8本可以满足简单编辑,或者线控单反之类的奇葩需求
对于我这种拍照业余又喜欢炫耀的人来说是神器:D
帖子6302&精华&积分19871&激骚606 度&爱车自行车&主机PSP,PS2,PS3,DSL&相机GF1&手机&注册时间&
以前是经常听说过数码伴侣什么的,就是给人去旅游的时候拍完照片就从卡里传过去的,倒是没怎么听说过评测
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
posted by wap, platform: iPhone
数码伴侣感觉没板子放心,要不是专业的我也不敢买,万一复制的时候出个三长两短。。
win8的板子很心水但是现在便宜的没fullhd,内存也小了点,还没完全符合我要求。。我只能等下一代了
我手头那win7手机倒是体积完美便携性牛逼,可惜usb性能太差差到我用过一次就再也不想碰了。。。
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&
摧残快门爱好者
帖子8008&精华&积分36569&激骚1232 度&爱车&主机&相机&手机&注册时间&
posted by wap, platform: Chrome
128g sd卡没压力啊
Love & Peace !
胶片机主力数码机备机
Reala Ace彩色负片最高峰没有之一 ...
帖子6231&精华&积分22595&激骚678 度&爱车&主机PS3,XBOX360,PC&相机太多了。。&手机&注册时间&
posted by wap, platform: iPhone引用:原帖由 @shacg&&于
16:55 发表
posted by wap, platform: Chrome
128g sd卡没压力啊 gopro用的是microsd,128g的不便宜啊,而且可能有兼容性问题
我用gopro都拍40m码流的2.7k分辨率的高清视频,这级别吃容量刷刷的,去年我一天就拍满一个64g和一个32g卡。。
美帝太好玩了,打算年年去了。。。
UID22380&帖子6231&精华&积分22595&交易积分0 &阅读权限40&在线时间9300 小时&注册时间&最后登录&博客访问: 43904
博文数量: 39
博客积分: 0
博客等级: 民兵
技术积分: 18
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
原文地址: 作者:
前章我们也大致分析了SD卡的启动过程,在具体进行问题的定位及解决的过程中,发现还是有很多不明确的地方,网上的文章也多是人云亦云让我们来一步一步搞清楚S3C6410 SD卡启动的步骤及过程(我这里的开发板为OKM+1G的配置,SD卡为2G,MMC)
一、开发板跳线,从SD卡启动
查看《OK6410开发板LINUX2.6用户手册.pdf》&将跳线设置为&&(从左到右为&pin8&到&pin1的设置,别搞反了)&&
这些设置可以在s3c6410的datasheet中查到,打开《s3c6410_rev12.pdf》125页&&
Table&3-1.&Device&operating&mode&selection&at&boot-up&&&
从这里可以看到,最后3个位为0,表示从SD/MMC(CH0)启动&&查看《OK6410开发板LINUX2.6用户手册.pdf》 将跳线设置为
(从左到右为 pin8 到 pin1的设置,别搞反了)
这些设置可以在s3c6410的datasheet中查到,打开《s3c6410_rev12.pdf》125页
Table 3-1. Device operating mode selection at boot-up
从这里可以看到,最后3个位为0,表示从SD/MMC(CH0)启动
修改UBOOT,让它支持从SD卡读取数据,并将自己自举到内存&&
当我们设置完CPU的跳线,CPU已经清楚要从哪里去取第一条指,S3C6410到底是怎么工作的呢&&
之前找到过一篇参考文章&《S3C2450_IROM_ApplicationNote_Rev003.pdf》&&
这次找到了官方的文档更清楚的说明了这一切《S3C6410_Internal_ROM_Booting.pdf》&&
在文档中我们看到CPU上电之后的启动过程如下&&修改UBOOT,让它支持从SD卡读取数据,并将自己自举到内存
当我们设置完CPU的跳线,CPU已经清楚要从哪里去取第一条指,S3C6410到底是怎么工作的呢
之前找到过一篇参考文章 《S3C2450_IROM_ApplicationNote_Rev003.pdf》
这次找到了官方的文档更清楚的说明了这一切《S3C6410_Internal_ROM_Booting.pdf》
在文档中我们看到CPU上电之后的启动过程如下
①&&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.&&&①
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.
按照这个启动过程,我们必须准备好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的代码&&按照这个启动过程,我们必须准备好8K的引导代码在BL1,
用来初始化系统,始终,串口,SDRAM等,并且将完整的BootLoader放在BL2上
2.7 Boot Block Assignment Guide 中有详细的描述
2G以下 SD/MMC 的卡的存储结构
SD/MMC 1Block = 512 Byte
=========================================================================================
SD/MMC Device
=========================================================================================
| Recommendation |
| User File System |=====================================================================
| Kernel |
| Signature(512Byte) | Reserved(512Byte) |
| 16 Block |
=========================================================================================
有了这个大致的印象,我们先放一下,下面我们来修改UBOOT的代码
二、修改UBOOT代码
s3c6410的uboot源码见最后的参考资料&&
修改makefile&交叉工具链的绝对路径(嘿嘿,这个交叉工具链当然是俺自己做的交叉工具链了,参考前面篇BLOG)&&
ifeq&($(ARCH),arm)&&
CROSS_COMPILE&=&arm-none-linux-gnueabi-&&
CROSS_COMPILE&=&/opt/cross_toolchains/arm/4.6.1/bin/arm-none-linux-gnueabi-&&s3c6410的uboot源码见最后的参考资料
修改makefile 交叉工具链的绝对路径(嘿嘿,这个交叉工具链当然是俺自己做的交叉工具链了,参考前面篇BLOG)
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-none-linux-gnueabi-
CROSS_COMPILE = /opt/cross_toolchains/arm/4.6.1/bin/arm-none-linux-gnueabi-
修改&include/configs/smdk6410.h&打开&#define&CONFIG_BOOT_MOVINAND&这个宏,并屏蔽其他的启动选项&&
在UBOOT的代码中,将IROM的启动模式称之为MOVINAND&&修改 include/configs/smdk6410.h 打开 #define CONFIG_BOOT_MOVINAND 这个宏,并屏蔽其他的启动选项
在UBOOT的代码中,将IROM的启动模式称之为MOVINAND
这个UBOOT就已经可以从SD卡启动了,S3C6410具体又是怎么工作的呢?
在&cpu/s3c64xx/start.S&中我们看到如下这段&&
#ifdef&CONFIG_BOOT_MOVINAND &&
&&&&&&&&ldr&&&&&sp,&_TEXT_PHY_BASE&&
&&&&&&&&bl&&&&&&movi_bl2_copy&&
&&&&&&&&b&&&&&&&after_copy&&
#endif&&在 cpu/s3c64xx/start.S 中我们看到如下这段
#ifdef CONFIG_BOOT_MOVINAND
sp, _TEXT_PHY_BASE
movi_bl2_copy
after_copy
分析 movi_bl2_copy 函数
cpu/s3c64xx/movi.c&中&void&movi_bl2_copy(void)&中定义如下&&cpu/s3c64xx/movi.c 中 void movi_bl2_copy(void) 中定义如下
#if&defined(CONFIG_S3C6400) &&
&&&&&&&&CopyMovitoMem(MOVI_BL2_POS,&MOVI_BL2_BLKCNT,&(uint&*)BL2_BASE,&CONFIG_SYS_CLK_FREQ,&MOVI_INIT_REQUIRED);&&
&&&&&&&&writel(readl(HM_CONTROL4)&|&(0x3&<<&16),&HM_CONTROL4);&&
&&&&&&&&CopyMovitoMem(HSMMC_CHANNEL,&MOVI_BL2_POS,&MOVI_BL2_BLKCNT,&(uint&*)BL2_BASE,&MOVI_INIT_REQUIRED);&&
#endif&&#if defined(CONFIG_S3C6400)
CopyMovitoMem(MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, CONFIG_SYS_CLK_FREQ, MOVI_INIT_REQUIRED);
writel(readl(HM_CONTROL4) | (0x3 << 16), HM_CONTROL4);
CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);
确定MOVI_BL2_POS的值
./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)) &&
#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 &&
./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&&&&&&&&&&&&&&&&0x &&
#define&BL2_BASE&&&&&&&&&&&&&&&&0x33E00000 &&
#&error&TCM_BASE&or&BL2_BASE&is&not&defined &&
./include/movi.h&&
#if&defined(CONFIG_S3C6400) &&
#define&SS_SIZE&&&&&&&&&&&&&&&&&(4&*&1024) &&
#define&eFUSE_SIZE&&&&&&&&&&&&&&(2&*&1024)&&&&&&//&1.5k&eFuse,&0.5k&reserved &&
#define&SS_SIZE&&&&&&&&&&&&&&&&&(8&*&1024) &&
#define&eFUSE_SIZE&&&&&&&&&&&&&&(1&*&1024)&&&&&&//&0.5k&eFuse,&0.5k&reserved` &&
./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&&&&./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))
#define MOVI_TOTAL_BLKCNT
7864320 // 7864320 // 3995648 // 1003520 /* static movinand total block count: for writing to movinand when nand boot */
#define MOVI_HIGH_CAPACITY
./include/movi.h:#define MOVI_BLKSIZE
./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
#define BL2_BASE
0x33E00000
# error TCM_BASE or BL2_BASE is not defined
./include/movi.h
#if defined(CONFIG_S3C6400)
#define SS_SIZE
(4 * 1024)
#define eFUSE_SIZE
(2 * 1024)
// 1.5k eFuse, 0.5k reserved
#define SS_SIZE
(8 * 1024)
#define eFUSE_SIZE
(1 * 1024)
// 0.5k eFuse, 0.5k reserved`
./include/movi.h:#define PART_ZIMAGE_OFFSET
./include/movi.h:#define PART_UBOOT_OFFSET
./include/configs/smdk6410.h:#define CFG_ENV_SIZE
/* Total Size of Environment Sector */
确定BL2_BASE的值
./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&&&&&&&&&&&&&&&&0x &&
#define&BL2_BASE&&&&&&&&&&&&&&&&0x33E00000 &&
#&error&TCM_BASE&or&BL2_BASE&is&not&defined &&
#endif&&./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
#define BL2_BASE
0x33E00000
# error TCM_BASE or BL2_BASE is not defined
经过计算我们可以看出,这里决定CopyMovitoMem的功能,是TCM_BASE - 0x4,这个地址的寄存器的值(隐含的也告诉我们UBOOT编译出来之后不得大于256k)
《S3C6410_Internal_ROM_Booting.pdf》中看到
0x0C003FFC globalBlockSizeHide Total block count of the MMC device
这个值,具体的为,256K(根据打印可以得出,没找到具体的说明)
MOVI_BL2_BLKCNT 的值为 ( (0x2 - (0x) ) = 512 -32 (个扇区)
网上大多数资料写到CopyMovitoMem是将256k的数据搬运到内存中,从这个计算上我们可以看出实际这个结论是错的
在这里只搬运了 256k-16k的数据到内存
在MOVI_BL2_POS的定义中做了相应的处理,以保证位置的正确性
编译uboot,生成u-boot.bin
make&smdk6410_config&&
make&-j4&&make smdk6410_config
三、将修改好的UBOOT烧录到SD卡中
生成的uboot-bin是不是直接可以烧录到SD卡中呢?
有现成的工具IROM_Fusing_Tool.exe(开源的,可以找到源代码),但这个工具烧录的是nb0文件
实际上nb0文件的结构是:256k+8k 这样的一个形式,在Linux系统可以通过下面这个脚本来生成nb0文件
#!/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&&#!/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及以上版本,会简单一些
DWORD&CSC6410BootLoaderWriterDlg::BlockDataRead(char&cPart,DWORD&dwBlockIndex,DWORD&dwReadCount,BYTE*&pBuffer)&&
&&&&CString&devN&&
&&&&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&dwBytesR&&
}&&&DWORD CSC6410BootLoaderWriterDlg::BlockDataRead(char cPart,DWORD dwBlockIndex,DWORD dwReadCount,BYTE* pBuffer)
CString devN
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 dwBytesR
DWORD&CSC6410BootLoaderWriterDlg::BlockDataWrite(ULONG&nPhysicalDriveNumber,DWORD&dwBlockIndex,BYTE*&pData,DWORD&dwDataLen)&&
&&&&if(&(dwDataLen&%&512)&!=&0&)&dwDataLen&=&(&(dwDataLen&/&512)&+&1&)&*&512;&&
&&&&CString&devN&&
&&&&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&dwBytesW&&
}&&DWORD CSC6410BootLoaderWriterDlg::BlockDataWrite(ULONG nPhysicalDriveNumber,DWORD dwBlockIndex,BYTE* pData,DWORD dwDataLen)
if( (dwDataLen % 512) != 0 ) dwDataLen = ( (dwDataLen / 512) + 1 ) * 512;
CString devN
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 dwBytesW
看到区别了吗?这里要非常非常注意!
Write函数中devName的构建形式与Read函数中的不一样,这个问题让我调试了很久,如果在Write函数中使用Read函数的构建形式,则会遇到WriteFile工作不正常的现象
具体为:在操作最后若干个扇区时,bWrite 等于 TRUE,dwBytesWrite却为0(为什么?还没能深究下去)
另外,如果要写入的数据长度不是512的整数倍,一定要进行处理,否则会引起GetLastError是87,参数错误
因为所有的FLASH,最小的扇区时512字节,则最少要以512个字节作为一次操作单位
(文件系统帮我们解决了这些问题,我们现在是对磁盘裸的操作,所以不能按照有文件系统的想法来考虑这个问题)
下面是Write函数构造devName时需要用到的函数
ULONG&CSC6410BootLoaderWriterDlg::GetPhysicalDriveNumber(char&cPart)&&
&&&&typedef&struct&_DISK_EXTENT&{&&
&&&&&&ULONG&&&&&&&&&DiskN&&
&&&&&&LARGE_INTEGER&StartingO&&
&&&&&&LARGE_INTEGER&ExtentL&&
&&&&}&DISK_EXTENT,&*PDISK_EXTENT;&&
&&&&typedef&struct&_VOLUME_DISK_EXTENTS&{&&
&&&&&&ULONG&&&&&&&NumberOfDiskE&&
&&&&&&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&devN&&
&&&&devName.Format("\\\\.\\%c:",cPart);&&
&&&&HANDLE&hDevice&=&CreateFile(devName,&GENERIC_READ,&FILE_SHARE_READ&|&FILE_SHARE_WRITE,&NULL,&OPEN_EXISTING,&0,&NULL&);&&
&&&&VOLUME_DISK_EXTENTS&volumeD&&
&&&&DWORD&dwOut&=&0;&&
&&&&DeviceIoControl(&hDevice,&IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL,&0,&&volumeData,&VOLUMEDISKSIZE,&&dwOut,&NULL&);&&
&&&&CloseHandle(&hDevice&);&&&
&&&&return&volumeData.Extents[0].DiskN&&
}&&ULONG CSC6410BootLoaderWriterDlg::GetPhysicalDriveNumber(char cPart)
typedef struct _DISK_EXTENT {
LARGE_INTEGER StartingO
LARGE_INTEGER ExtentL
} DISK_EXTENT, *PDISK_EXTENT;
typedef struct _VOLUME_DISK_EXTENTS {
NumberOfDiskE
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 devN
devName.Format("\\\\.\\%c:",cPart);
HANDLE hDevice = CreateFile(devName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
VOLUME_DISK_EXTENTS volumeD
DWORD dwOut = 0;
DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL, 0, &volumeData, VOLUMEDISKSIZE, &dwOut, NULL );
CloseHandle( hDevice );
return volumeData.Extents[0].DiskN
下面这段代码是用来获得,所有插入的U盘(可移动磁盘,注意下面的判断)的盘符
void&CSC6410BootLoaderWriterDlg::OnButtonGetdriverinfo()&&&
&&&&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&=&pS&&
&&&&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[]&pS&&
&&&&m_cbList.SetCurSel(0);&&
&&&&m_cbList.SetFocus();&&
&&&&WriteLog("U盘检查完成");&&
}&&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 = pS
while(TRUE)
if(pNow >= (pString+dwStrLen-1))
DWORD dwRet = GetDriveType(pNow);
if(dwRet == DRIVE_REMOVABLE)
m_cbList.InsertString(0,pNow);
pNow += strlen(pNow);
delete[] pS
m_cbList.SetCurSel(0);
m_cbList.SetFocus();
WriteLog("U盘检查完成");
最后是写入代码,在这里我们会要求SD卡首先会被各式化成FAT32各式,以便我们能去读取FTA32文件分配表中MBR的部分
void&CSC6410BootLoaderWriterDlg::OnButtonOp()&&&
&&&&int&nCurSel&=&m_cbList.GetCurSel();&&
&&&&if(nCurSel&==&-1)&&&
&&&&&&&&MessageBox("探测磁盘信息");&&&&&
&&&&&&&&return;&&
&&&&CString&strBootFileP&&
&&&&m_eBootFilePath.GetWindowText(strBootFilePath);&&
&&&&if(strBootFilePath&==&"")&&
&&&&&&&&MessageBox("请先选择需要烧录的引导文件");&&&&&&
&&&&&&&&return;&&&
&&&&CString&strT&&
&&&&m_cbList.GetLBText(m_cbList.GetCurSel(),strText);&&
&&&&char&cPart&=&strText[0];&&
&&&&ULONG&nPhysicalDriveNumber&=&GetPhysicalDriveNumber(cPart);&&
&&&&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&strL&&
&&&&&&&&strLog.Format("读取MBR成功");&&
&&&&&&&&WriteLog(strLog);&&&&&
&&&&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;&&
&&&&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_&&
&&&&#define&MOVI_TOTAL_BLKCNT&0x40000 &&
&&&&BYTE&buffer_utoot[MOVI_TOTAL_BLKCNT];&&
&&&&memset(buffer_utoot,0,sizeof(buffer_utoot));&&
&&&&CFile&&&
&&&&cf.Open(strBootFilePath,CFile::modeRead);&&
&&&&DWORD&uboot_size&=&min(MOVI_TOTAL_BLKCNT,cf.GetLength());&&
&&&&cf.Read(buffer_utoot,uboot_size);&&
&&&&cf.Close();&&
&&&&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&strL&&
&&&&&&&&strLog.Format("写入引导8k字节成功");&&
&&&&&&&&WriteLog(strLog);&&&&&
&&&&dwReturn&=&BlockDataWrite(nPhysicalDriveNumber,bl2_begin,buffer_utoot,uboot_size);&&
&&&&if(dwReturn&<&uboot_size)&&
&&&&&&&&MessageBox("写入引导失败");&&
&&&&&&&&return;&&
&&&&&&&&CString&strL&&
&&&&&&&&strLog.Format("引导文件写入完成,磁盘总扇区数:%d",count_block_total);&&
&&&&&&&&WriteLog(strLog);&&&&&
}&&void CSC6410BootLoaderWriterDlg::OnButtonOp()
// TODO: Add your control notification handler code here
int nCurSel = m_cbList.GetCurSel();
if(nCurSel == -1)
MessageBox("探测磁盘信息");
CString strBootFileP
m_eBootFilePath.GetWindowText(strBootFilePath);
if(strBootFilePath == "")
MessageBox("请先选择需要烧录的引导文件");
// 获得驱动器盘符
CString strT
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);
CString strL
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);
// 获得磁盘的扇区总数
本分区隐含扇区数
该盘实际使用扇区数(不包括隐含扇区)
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_
// 另一种方法 获得 扇区总数
// #define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX 458912
struct _DISK_GEOMETRY_EX
// { DISK_GEOMETRY
LARGE_INTEGER
// } 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));
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字节失败");
CString strL
strLog.Format("写入引导8k字节成功");
WriteLog(strLog);
dwReturn = BlockDataWrite(nPhysicalDriveNumber,bl2_begin,buffer_utoot,uboot_size);
if(dwReturn < uboot_size)
MessageBox("写入引导失败");
CString strL
strLog.Format("引导文件写入完成,磁盘总扇区数:%d",count_block_total);
WriteLog(strLog);
到这里,我们就可以完全分析清楚,并可以自主的制作一个S3C6410的启动SD卡了,附后为一些参考资料,这里没办法贴附件,问题给我留言吧
后面的内容中,我们将进入UBOOT,对UBOOT进行修改,请关注下一节《如何计算内存大小,并在UBOOT中调整内存大小》
四、参考资料
下载 uboot1.1.6 (支持 movinand)
使uboot支持S3C6410的SD启动
《S3C6410_Internal_ROM_Booting.pdf》
《s3c6410_rev12.pdf》
《smdk6410_users_manual_rev1.0.pdf》
《K4X51163PC.pdf》
《OK6410开发板LINUX2.6用户手册.pdf》
《OK6410开发板硬件手册2.1.pdf》
阅读(144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
请登录后评论。

我要回帖

更多关于 怎么把刷机包放进sd卡 的文章

 

随机推荐