引言

之前,曾经在orpsoc的平台上,测试验证过其sd card controller的linux的驱动,但是并不是很完美,经过努力,终于在eCos下完成了其全部功能的验证,包括驱动层验证,文件系统的挂载,应用层的创建文件,打开文件,复制文件,源文件与复制文件的比较等,此外,还有创建目录,切换目录等操作。

本小节就分享一下整个验证过程。

关于基于orpsoc+linux下的sd card controller验证,请参考:

http://blog.csdn.net/rill_zhen/article/details/9111213

1,硬件部分

1>基本信息

本次验证,采用的是最初的orpsoc的硬件结构,没有进行任何改动,唯一做的工作就是将硬件配置信息提前烧到了外部的spi-flash,每次上电可自动执行,省去每次调试前的FPGA配置工作。

关于如何烧写外部spi-flash,请参考:http://blog.csdn.net/rill_zhen/article/details/9162275

此外,需要了解sd卡控制器这个ipcore的一些信息,比如wishbone地址等,也在之前的blog中做过介绍,这里不再赘述。

2>sd card controller的仿真

关于ipcore的仿真,之前也做过很多实验,如果有什么问题,可以先参考之前的内容,或者写评论给我,我会尽快回答。这里只给出仿真波形和仿真输出信息。如下:

1》仿真波形

2》仿真信息

可以看出,有一个错误。但我觉得不影响使用。

# T0 Start
#
# access_to_reg TEST
# Time: 925
# TEST 0: 3 32-BIT READ-WRITE REGISTERS ( VARIOUS BUS DELAYS )
#
# ===========================================================================
# T0 test_access_to_reg Completed
# ===========================================================================
# T1 Start
#
# test_send_cmd TEST
# Time: 4435
# TEST 0: 0: Send CMD, No Response
#
# ===========================================================================
# T1 test_send_cmd Completed
# ===========================================================================
# T2 Start
#
# access_to_reg TEST
# Time: 8153
# TEST 3.0: 0: Init Seq, No Response
# V 1.0 Card, Timeout In TEST 3.0 00008004
# CID reg 1: ffffffdd
# RCA Response: 20000700
# RCA Nr for data transfer: 00002000
#
# ===========================================================================
# T2 test_init_sequence Completed
# ===========================================================================
# T3 Start
#
# access_to_reg TEST
# Time: 61583
# TEST 4.0: Send data
# V 1.0 Card, Timeout In TEST 4.0 00008004
# CID reg 1: ffffffdd
# RCA Response: 20000700
# RCA Nr for data transfer: 00002000
# 2**BUS WIDTH 4
# Card status after Bus width set 00000920
#
# ===========================================================================
# T3 test_send_data Completed
# ===========================================================================
# T4 Start
# Time: 208639
# TEST 4.0: Send data
# V 1.0 Card, Timeout In TEST 4.0 00008004
# CID reg 1: ffffffdd
# RCA Response: 20000700
# RCA Nr for data transfer: 00002000
# 2**BUS WIDTH 4
# Card status after Bus width set 00000920
#
# ===========================================================================
# T4 test_send_rec_data Completed
# ===========================================================================
# T5 Start
#
# test_send_cmd_error_rsp
# Time: 416327
# TEST 5 part 0: Send CMD, No Response
# Time: 419969
# TEST 5, part 1: Send CMD, 48-Bit Response, No error check
# Time: 426521
# TEST 5, part 2: Send CMD3, 48-Bit Response, All Error check enable
# Time: 433177
# Bus error succesfully catched, Error status register: 0000000a
# Time: 433177
# Test 5 part 4: Send CMD2, 136-Bit
#
# ===========================================================================
# T5 test_send_cmd_error_rsp Complete
# ===========================================================================
#
# access_to_reg TEST
# Time: 444277
# TEST 4.0: Send data
# V 1.0 Card, Timeout In TEST 4.0 00008004
# CID reg 1: ffffffdd
# RCA Response: 20000700
# RCA Nr for data transfer: 00002000
# 2**BUS WIDTH 4
# Card status after Bus width set 00000920
# T6 test_send_cmd_error_rsp Complete
# All Test finnished. Nr Failed: 0, Nr Succes: 7

2,软件部分

1>与上次的比较

本次验证和上次验证的最大不同是软件。

首先,OS变了,上次采用的是linux,SD controller的驱动也是参考ipcore附带的testbench,ipcore附带的裸机程序,经过自己整理,变换,最后完成的linux下的驱动。

其次,测试程序也变了,上次只在linux驱动层进行了测试,这次不仅进行了driver的测试,还进行了应用层的测试。

最后,验证形式也变了,上次只是进行了基本的I/O验证,这次验证包括了文件系统,是文件级的测试。

2>验证准备

首先要搭建eCos运行环境,请参考:http://blog.csdn.net/rill_zhen/article/details/9271721

其次是搭建ORPSoC的调试环境,请参考:http://blog.csdn.net/rill_zhen/article/details/8700937

3>软件编码

1》编写基于eCos的sd卡控制器的driver

此驱动已经在eCos工程内,路径是:eCos/packages/devs/disk/opencores/sdcmsc/current/src/if_sdcmsc.c

为了更清楚,更真实的展示验证过程,在里面增加调试信息,修改后,代码请参考附录。

2》修改eCos中关于fatfs部分的代码

eCos本身的fatfs部分有一些问题,如果不修改的话,在测试程序将无法挂载sd卡的文件系统。

在这之前,有必要梳理一下mount()函数的执行过程,如下:

a,应用程序的mount()

如下便是测试程序的部分代码:

这里需要说明的是,mount的第一个参数,必须和驱动中注册的设备名称一致。

b,eCos中mount()函数的实现入口,misc.cxx:mount()

之前说过,eCos只是一个库,并不是一个platform,所以应用程序和eCos在逻辑上是平等的,既然应用程序mount()返回错误,那么我们需要查找其具体实现。

如下图:

c,mount()对应的具体文件系统的mount实现入口,fatfs.c:fatfs_mount()

这里需要说明的有两点:

第一,fatfs_mount()会首先调用cyg_io_lookup()函数,而这个函数最终会调用驱动(if_sdcmsc.c)中的sdcmsc_disk_loopup()函数,sdcmsc_disk_loopup()函数会调用sdcmsc_disk_init(),实现SD卡的初始化工作,也就是上次基于linux的验证时,给SD卡发送一连串的命令。

第二,fatfs_mount()会调用cyg_io_lookup()函数之后,会调用fatfs_init()函数,fatfs_init()函数会首先调用read_boot_record()函数,这个函数会读取FATFS的格式化信息。

如下图:

d,读取boot record信息,fatfs_supp.c:fatfs_init()

eCos就是在这里出现了问题!eCos默认是从SD卡的第0个sector读取boot record,但是并不是所有的SD卡的文件系统格式化信息都存在那里,所以,如果你的SD卡的文件系统信息没有存在第0个sector,eCos就无法挂载。很不幸,我用的SD卡的fat fs的boot record 信息就不在第0个sector,所以一直无法挂载,出现“invalid argument”的错误。

如果想让eCos能读到boot record信息,需要修改读取地址。如何知道你的SD卡的boot record信息的起始地址在哪里呢?可以下载安装winhex这个软件来查看,安装完成后,将SD卡通过读卡器插到电脑上,打开winhex的tool->open disk,选择你的SD卡,就可以看到文件系统的格式化信息。

我的SD卡的boot record信息在第135个sector,起始地址是0x10e00,eCos里面的地址是0,所以肯定读不到正确的值,无法挂载也就可以理解了。

winhex我已上传:http://download.csdn.net/detail/rill_zhen/5776013

关于fat fs的格式化信息,请参考:http://averstak.tripod.com/fatdox/bootsec.htm#ef

fatfs_init(),如下图:

read_boot_record(),如下图:这里需要修改!

boot record的结构体,如下图:

e,code list

请参考附录部分的内容。

3,验证

验证过程是简单的。

1>配置eCos

要进行本次验证,需要增加5个package。执行如下操作:

如下所示:

1》增加依赖包:

ecosconfig new orpsoc default
ecosconfig add CYGPKG_IO_DISK
ecosconfig add CYGPKG_IO_FILEIO
ecosconfig add CYGPKG_FS_FAT
ecosconfig add CYGPKG_BLOCK_LIB
ecosconfig add CYGPKG_LINUX_COMPAT

2》检查冲突,要没有冲突才行

ecosconfig check

3》编译

ecosconfig tree

make

4》编译测试

make tests

2>编译测试文件

到测试文件所在目录,执行make即可。

如果有问题,请参考:http://blog.csdn.net/rill_zhen/article/details/9271721

3>下载验证

将生成的测试文件,通过or32-elf-gdb烧到板子上。

当然,如果你的板子的硬件配置没有事先烧到spi-flash里面,需要用jtag将orpsoc_top.svf 烧到板子上。

这一步的具体操作过程,之前也有介绍,这里不再赘述。

4,验证结果

如果一切顺利,你会看到如下打印信息。

从中可以看出,我的SD卡是FAT16格式的,卡的capacity是1.9G左右,mount成功,可以read,write文件。

打印信息如下:

openrisc@openrisc-VirtualBox:~/share/ecos_sdc_test$ picocom --b 115200 --p n --d 8 --f xon /dev/ttyUSB2
picocom v1.4 port is : /dev/ttyUSB2
flowcontrol : xon/xoff
baudrate is : 115200
parity is : none
databits are : 8
escape is : C-a
noinit is : no
noreset is : no
nolock is : no
send_cmd is : ascii_xfr -s -v -l10
receive_cmd is : rz -vv Terminal ready
is_v20:0x1
is_sdhc:0x0
rca:0xe6240000
card capacity:0x3af000
sdc init success!
data:0x2dbe8
fatfs boot record:--->
sig:0x29
marker0:0x55
marker1:0xaa
jump:0x3ceb
oem_name[0]:M
oem_name[1]:S
oem_name[2]:D
oem_name[3]:O
oem_name[4]:S
oem_name[5]:5
oem_name[6]:.
oem_name[7]:0
bytes_per_sec:0x200
sec_per_clu:0x40
res_sec_num:0x8
fat_tbls_num:0x2
max_root_dents:0x200
sec_num_32:0x0
media_desc:0xf8
sec_per_fat:0xec
sec_per_track:0x3f
heads_num:0xff
hsec_num:0x87
sec_num:0x3ae039
sec_num_32:0x0
sec_num_32:0x0
marker0:0x55
marker1:0xaa
sec_per_fat_32:0x290f4
ext_flags:0x2
fs_ver:0x836c
root_cluster:0x0
fs_info_sec:0x2
bk_boot_sec:0xdc5c
drv_num:0x80
ext_sig:0x29
ser_num:0x6eef0577
vol_name[0]:N
vol_name[1]:O
vol_name[2]:
vol_name[3]:N
vol_name[4]:A
vol_name[5]:M
vol_name[6]:E
vol_name[7]:
vol_name[8]:
vol_name[9]:
vol_name[10]:
fat_name[0]:F
fat_name[1]:A
fat_name[2]:T
fat_name[3]:1
fat_name[4]:6
fat_name[5]:
fat_name[6]:
fat_name[7]:
mount ok!
chdir ok!
<INFO>: reading directory /
<INFO>: entry RILL [mode 00000008 ino 00000009 nlink 1 size 10]
<INFO>: entry FOO [mode 00000008 ino 00000003 nlink 1 size 10]
<INFO>: entry FEE [mode 00000008 ino 00000004 nlink 1 size 10]
<INFO>: entry FP_FILE [mode 00000008 ino 00000008 nlink 1 size 10]
<INFO>: create file /mkg_rill size 10
<INFO>: check file mkg_rill
<INFO>: copy file mkg_rill -> mkg_rill_bak
<INFO>: check file mkg_rill_bak
<INFO>: compare files mkg_rill_bak == /mkg_rill
buf1[0](00) == buf2[0](00)
buf1[1](01) == buf2[1](01)
buf1[2](02) == buf2[2](02)
buf1[3](03) == buf2[3](03)
buf1[4](04) == buf2[4](04)
buf1[5](05) == buf2[5](05)
buf1[6](06) == buf2[6](06)
buf1[7](07) == buf2[7](07)
buf1[8](08) == buf2[8](08)
buf1[9](09) == buf2[9](09)
PASS:<fatfs1>
EXIT:<done>

5,小结

经过努力,基于ORPSoC的SD卡控制器的验证工作终于可以告一段落了。通过目前的工作,有如下收获:

首先,证明了opencores上面的这个sd卡控制器的硬件是没有问题的。

其次,ORPSoC对这个ipcore的集成,也是没问题的。

第三,得到了一个可以work的SD卡控制器的基于eCos的驱动。

6,future work

1,将if_sdcmsc.c移植到linux上,实现SD卡的基本I/O操作。

2,基于linux系统,实现SD卡文件系统的挂载。

3,修改eCos的fatfs代码,使之能自动识别boot record的起始地址。

7,附录 code list

1>驱动:if_sdcmsc.c

//=========================================================================
//
// if_sdcmsc.c
//
// Provide a disk device driver for SDCard Mass Storage Controller
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2004, 2006 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author: Piotr Skrzypek
// Date: 2012-05-01
//
//####DESCRIPTIONEND####
//========================================================================== #include <pkgconf/system.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_if.h>
#include <cyg/hal/hal_intr.h>
#include <string.h>
#include <errno.h>
#include <cyg/io/io.h>
#include <cyg/io/devtab.h>
#include <cyg/io/disk.h> // Settings exported from CDL
#include <pkgconf/devs_disk_opencores_sdcmsc.h> // SDCMSC address space
#define SDCMSC_BASE 0x9e000000 // Register space
#define SDCMSC_ARGUMENT 0x00
#define SDCMSC_COMMAND 0x04
#define SDCMSC_CARD_STATUS 0x08
#define SDCMSC_RESPONSE 0x0C
#define SDCMSC_CONTROLLER_SETTING 0x1C
#define SDCMSC_BLOCK_SIZE 0x20
#define SDCMSC_POWER_CONTROL 0x24
#define SDCMSC_SOFTWARE_RESET 0x28
#define SDCMSC_TIMEOUT 0x2C
#define SDCMSC_NORMAL_INT_STATUS 0x30
#define SDCMSC_ERROR_INT_STATUS 0x34
#define SDCMSC_NORMAL_INT_ENABLE 0x38
#define SDCMSC_ERROR_INT_ENABLE 0x3C
#define SDCMSC_CAPABILITY 0x48
#define SDCMSC_CLOCK_DIVIDER 0x4C
#define SDCMSC_BD_BUFFER_STATUS 0x50
#define SDCMSC_DAT_INT_STATUS 0x54
#define SDCMSC_DAT_INT_ENABLE 0x58
#define SDCMSC_BD_RX 0x60
#define SDCMSC_BD_TX 0x80 // SDCMSC_COMMAND bits
#define SDCMSC_COMMAND_CMDI(x) (x << 8)
#define SDCMSC_COMMAND_CMDW(x) (x << 6)
#define SDCMSC_COMMAND_CICE 0x10
#define SDCMSC_COMMAND_CIRC 0x08
#define SDCMSC_COMMAND_RTS_48 0x02
#define SDCMSC_COMMAND_RTS_136 0x01 //SDCMSC_CARD_STATUS bits
#define SDCMSC_CARD_STATUS_CICMD 0x01 // SDCMSC_NORMAL_INT_STATUS bits
#define SDCMSC_NORMAL_INT_STATUS_EI 0x8000
#define SDCMSC_NORMAL_INT_STATUS_CC 0x0001 // SDCMSC_DAT_INT_STATUS
#define SDCMSC_DAT_INT_STATUS_TRS 0x01 typedef struct cyg_sdcmsc_disk_info_t {
int is_v20;
int is_sdhc;
cyg_uint32 rca;
int connected;
} cyg_sdcmsc_disk_info_t; static int sdcmsc_card_cmd(cyg_uint32 cmd,
cyg_uint32 arg,
cyg_uint32 *response) { // Send command to card
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_COMMAND, cmd);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_ARGUMENT, arg); // Wait for response
cyg_uint32 reg;
cyg_uint32 mask = SDCMSC_NORMAL_INT_STATUS_EI |
SDCMSC_NORMAL_INT_STATUS_CC; do {
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_NORMAL_INT_STATUS, reg);
} while(!(reg & mask));
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_NORMAL_INT_STATUS, 0); // Optionally read response register
if(response) {
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_RESPONSE, *response);
} // Check for errors
if(reg & SDCMSC_NORMAL_INT_STATUS_EI) {
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_ERROR_INT_STATUS, reg);
if(reg & (1 << 3)) diag_printf("Command index error\n");
if(reg & (1 << 1)) diag_printf("Command CRC error\n");
if(reg & (1 << 0)) diag_printf("Command timeout\n");
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_ERROR_INT_STATUS, 0);
return 0;
}
else {
return 1;
}
} // Card initialization and identification implemented according to
// Physical Layer Simplified Specification Version 3.01
static int sdcmsc_card_init(cyg_sdcmsc_disk_info_t *data,
char *serial,
char *firmware_rev,
char *model_num,
cyg_uint32 *capacity) { cyg_uint32 reg;
cyg_uint32 cmd;
cyg_uint32 arg; // Send CMD0 to switch the card to idle state
cmd = SDCMSC_COMMAND_CMDI(0);
if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0; // Send CMD8 offering 2.7V to 3.6V range
// If the card doesn't responde it means either:
// 1. Card supports v2.0 but can't communicate using
// current voltage levels
// 2. Card does not support v2.0
cmd = SDCMSC_COMMAND_CMDI(8) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
data->is_v20 = sdcmsc_card_cmd(cmd, 0x1AA, NULL);
diag_printf("is_v20:0x%x\n",data->is_v20);//rill add debug
do {
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_CARD_STATUS, reg);
} while(reg & SDCMSC_CARD_STATUS_CICMD); // Repeat ACMD41 until card set the busy bit to 1
// Since ACMD is an extended command, it must be preceded
// by CMD55
do {
cmd = SDCMSC_COMMAND_CMDI(55) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0; cmd = SDCMSC_COMMAND_CMDI(41) |
SDCMSC_COMMAND_RTS_48;
arg = data->is_v20 ?
0x40FF8000 :
0x00FF8000;
if(!sdcmsc_card_cmd(cmd, arg, ®)) return 0; } while(!(reg & 0x80000000)); data->is_sdhc = !!(reg & 0x40000000);
diag_printf("is_sdhc:0x%x\n",data->is_sdhc);
// Issue CMD2 to switch from ready state to ident. Unfortunately, it is
// not possible to read whole CID because the command can be issued only
// once, and the peripheral can store only 32bit of the command at once.
cmd = SDCMSC_COMMAND_CMDI(2) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0; // Issue CMD3 to get RCA and switch from ident state to stby.
cmd = SDCMSC_COMMAND_CMDI(3) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, 0, ®)) return 0;
data->rca = reg & 0xFFFF0000;
diag_printf("rca:0x%x\n",data->rca);
// Calculate card capacity. Use information stored in CSD register.
cyg_uint32 card_capacity;
if(data->is_sdhc) {
cmd = SDCMSC_COMMAND_CMDI(9) |
SDCMSC_COMMAND_CMDW(1) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
card_capacity = reg & 0x3F;
card_capacity <<= 16; cmd = SDCMSC_COMMAND_CMDI(9) |
SDCMSC_COMMAND_CMDW(2) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
reg >>= 16;
card_capacity |= reg;
card_capacity += 1;
card_capacity *= 1000;
}
else {
cmd = SDCMSC_COMMAND_CMDI(9) |
SDCMSC_COMMAND_CMDW(1) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
cyg_uint32 read_bl_len = (reg >> 16) & 0x0F;
cyg_uint32 c_size = reg & 0x3FF;
c_size <<= 2; cmd = SDCMSC_COMMAND_CMDI(9) |
SDCMSC_COMMAND_CMDW(2) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
c_size |= (reg >> 30) & 0x03;
cyg_uint32 c_size_mult = (reg >> 15) & 0x07;
card_capacity = c_size + 1;
card_capacity *= 1 << (c_size_mult + 2);
card_capacity *= 1 << (read_bl_len);
card_capacity >>= 9;
}
diag_printf("card capacity:0x%x\n",card_capacity);
// Fill disk identification struct using information in CID register
// use OEM/APPlication ID field to fill model_num,
// Product revision field to fill firmware_rev,
// and Product serial number to field to fill serial
cmd = SDCMSC_COMMAND_CMDI(10) |
SDCMSC_COMMAND_CMDW(0) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
model_num[0] = (reg >> 16) & 0xFF;
model_num[1] = (reg >> 8) & 0xFF;
model_num[2] = 0; cmd = SDCMSC_COMMAND_CMDI(10) |
SDCMSC_COMMAND_CMDW(2) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
firmware_rev[0] = (reg >> 24) & 0xFF;
firmware_rev[1] = 0;
serial[0] = (reg >> 16) & 0xFF;
serial[1] = (reg >> 8) & 0xFF;
serial[2] = reg & 0xFF; cmd = SDCMSC_COMMAND_CMDI(10) |
SDCMSC_COMMAND_CMDW(3) |
SDCMSC_COMMAND_RTS_136;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
serial[3] = (reg >> 24) & 0xFF; // Put card in transfer state
cmd = SDCMSC_COMMAND_CMDI(7) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
if(reg != 0x700) return 0; // Set block size to 512
cmd = SDCMSC_COMMAND_CMDI(16) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, 512, NULL)) return 0; // Set 4-bits bus mode
cmd = SDCMSC_COMMAND_CMDI(55) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, data->rca, NULL)) return 0; cmd = SDCMSC_COMMAND_CMDI(6) |
SDCMSC_COMMAND_CICE |
SDCMSC_COMMAND_CIRC |
SDCMSC_COMMAND_RTS_48;
if(!sdcmsc_card_cmd(cmd, 0x02, NULL)) return 0;
diag_printf("sdc init success!\n");
return 1;
} static int sdcmsc_card_queue(cyg_sdcmsc_disk_info_t *data,
int direction_transmit,
int block_addr,
cyg_uint32 buffer_addr) { // SDSC cards use byte addressing, while SDHC use block addressing.
// It is therefore required to multiply the address by 512 if
// we are dealing with SDSC card, to remain compatible with the API.
if(!data->is_sdhc) {
block_addr <<= 9;
} if(direction_transmit) {
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_TX, buffer_addr);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_TX, block_addr);
}
else {
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_RX, buffer_addr);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_RX, block_addr);
} // Now wait for the response
cyg_uint32 reg;
do {
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_DAT_INT_STATUS, reg);
} while(!reg);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_DAT_INT_STATUS, 0); // Check for errors
if(reg == SDCMSC_DAT_INT_STATUS_TRS) {
return 1;
}
else {
if(reg & (1 << 5)) diag_printf("Transmission error\n");
if(reg & (1 << 4)) diag_printf("Command error\n");
if(reg & (1 << 2)) diag_printf("FIFO error\n");
if(reg & (1 << 1)) diag_printf("Retry error\n");
return 0;
}
} // This is an API function. Is is called once, in the beginning
static cyg_bool sdcmsc_disk_init(struct cyg_devtab_entry* tab) { // Set highest possible timeout
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_TIMEOUT, 0xFFFE); // Reset the peripheral
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_SOFTWARE_RESET, 1);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_CLOCK_DIVIDER, 2);
HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_SOFTWARE_RESET, 0); // Call upper level
disk_channel* ch = (disk_channel*) tab->priv;
return (*ch->callbacks->disk_init)(tab);
} // This function is called when user mounts the disk
static Cyg_ErrNo sdcmsc_disk_lookup(struct cyg_devtab_entry** tab,
struct cyg_devtab_entry *sub_tab,
const char* name) { disk_channel *ch = (disk_channel*) (*tab)->priv;
cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv; // If the card was not initialized yet, it's time to do it
// and call disk_connected callback
if(!data->connected) { cyg_disk_identify_t id; // Pass dummy CHS geometry and hope the upper level
// will use LBA mode. To guess CHS we would need to
// analyze partition table and confront LBA and CHS
// addresses. And it would work only if proper LBA
// field is stored in MBR. Is is definitely something
// that should be done by upper level.
id.cylinders_num = 1;
id.heads_num = 1;
id.sectors_num = 1; id.phys_block_size = 1;
id.max_transfer = 512; // Initialize the card
data->connected = sdcmsc_card_init(data,
id.serial,
id.firmware_rev,
id.model_num,
&id.lba_sectors_num); if(data->connected) {
// Let upper level know there is a new disk
(*ch->callbacks->disk_connected)(*tab, &id);
}
} // Call upper level
return (*ch->callbacks->disk_lookup)(tab, sub_tab, name);
} // API function to read block from the disk
static Cyg_ErrNo sdcmsc_disk_read(disk_channel* ch,
void* buf,
cyg_uint32 blocks,
cyg_uint32 first_block) { cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv; int i;
int result;
cyg_uint32 reg;
for(i = 0; i < blocks; i++) { // Check for free receive buffers
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_BD_BUFFER_STATUS, reg);
reg >>= 8;
reg &= 0xFF;
if(reg == 0) {
return -EIO;
} result = sdcmsc_card_queue(data, 0, first_block, (cyg_uint32) buf);
if(!result) {
return -EIO;
}
} return ENOERR; } // API function to write block to disk
static Cyg_ErrNo sdcmsc_disk_write(disk_channel* ch,
const void* buf,
cyg_uint32 blocks,
cyg_uint32 first_block) { cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv; int i;
int result;
cyg_uint32 reg;
for(i = 0; i < blocks; i++) { // Check for free transmit buffers
HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_BD_BUFFER_STATUS, reg);
reg &= 0xFF;
if(reg == 0) {
return -EIO;
} result = sdcmsc_card_queue(data, 1, first_block, (cyg_uint32) buf);
if(!result) {
return -EIO;
}
} return ENOERR; } // API function to fetch driver configuration and disk info.
static Cyg_ErrNo sdcmsc_disk_get_config(disk_channel* ch,
cyg_uint32 key,
const void* buf,
cyg_uint32* len) { CYG_UNUSED_PARAM(disk_channel*, ch);
CYG_UNUSED_PARAM(cyg_uint32, key);
CYG_UNUSED_PARAM(const void*, buf);
CYG_UNUSED_PARAM(cyg_uint32*, len); return -EINVAL;
} // API function to update driver status information.
static Cyg_ErrNo sdcmsc_disk_set_config(disk_channel* ch,
cyg_uint32 key,
const void* buf,
cyg_uint32* len) { cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv; if(key == CYG_IO_SET_CONFIG_DISK_UMOUNT) {
if(ch->info->mounts == 0) {
data->connected = false;
return (ch->callbacks->disk_disconnected)(ch);
}
else {
return ENOERR;
}
}
else {
return -EINVAL;
} } // Register the driver in the system static cyg_sdcmsc_disk_info_t cyg_sdcmsc_disk0_hwinfo = {
.connected = 0
}; DISK_FUNS(cyg_sdcmsc_disk_funs,
sdcmsc_disk_read,
sdcmsc_disk_write,
sdcmsc_disk_get_config,
sdcmsc_disk_set_config
); DISK_CONTROLLER(cyg_sdcmsc_disk_controller_0, cyg_sdcmsc_disk0_hwinfo); DISK_CHANNEL(cyg_sdcmsc_disk0_channel,
cyg_sdcmsc_disk_funs,
cyg_sdcmsc_disk0_hwinfo,
cyg_sdcmsc_disk_controller_0,
true, //mbr supported
4 //partitions
); BLOCK_DEVTAB_ENTRY(cyg_sdcmsc_disk0_devtab_entry,
CYGDAT_DEVS_DISK_OPENCORES_SDCMSC_DISK0_NAME,
0,
&cyg_io_disk_devio,
&sdcmsc_disk_init,
&sdcmsc_disk_lookup,
&cyg_sdcmsc_disk0_channel); // EOF if_sdcmsc.c

2>测试程序:helloworld.c,Makefile

1》helloworld.c

//==========================================================================
//
// fatfs1.c
//
// Test fileio system
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 2000-05-25
// Purpose: Test fileio system
// Description: This test uses the testfs to check out the initialization
// and basic operation of the fileio system
//
//
//
//
//
//
//
//####DESCRIPTIONEND####
//
//========================================================================== #include <pkgconf/hal.h>
#include <pkgconf/io_fileio.h>
#include <pkgconf/fs_fat.h> #include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros #include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <stdio.h> #include <cyg/fileio/fileio.h> #include <cyg/infra/testcase.h>
#include <cyg/infra/diag.h> // HAL polled output
#include <cyg/fs/fatfs.h> //========================================================================== #define SHOW_RESULT( _fn, _res ) \
diag_printf("<FAIL>: " #_fn "() returned %d %s\n", _res, _res<0?strerror(errno):""); //========================================================================== #define IOSIZE 100 #define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1"
#define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2" //========================================================================== #ifndef CYGPKG_LIBC_STRING char *strcat( char *s1, const char *s2 )
{
char *s = s1;
while( *s1 ) s1++;
while( (*s1++ = *s2++) != 0);
return s;
} #endif //========================================================================== static void listdir( char *name, int statp, int numexpected, int *numgot )
{
int err;
DIR *dirp;
int num=0; diag_printf("<INFO>: reading directory %s\n",name); dirp = opendir( name );
if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); for(;;)
{
struct dirent *entry = readdir( dirp ); if( entry == NULL )
break;
num++;
diag_printf("<INFO>: entry %14s",entry->d_name);
#ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE
diag_printf(" d_type %2x", entry->d_type);
#endif
if( statp )
{
char fullname[PATH_MAX];
struct stat sbuf; if( name[0] )
{
strcpy(fullname, name );
if( !(name[0] == '/' && name[1] == 0 ) )
strcat(fullname, "/" );
}
else fullname[0] = 0; strcat(fullname, entry->d_name ); err = stat( fullname, &sbuf );
if( err < 0 )
{
if( errno == ENOSYS )
diag_printf(" <no status available>");
else SHOW_RESULT( stat, err );
}
else
{
diag_printf(" [mode %08x ino %08x nlink %d size %ld]",
sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,(long)sbuf.st_size);
}
#ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE
if ((entry->d_type & S_IFMT) != (sbuf.st_mode & S_IFMT))
CYG_TEST_FAIL("File mode's don't match between dirent and stat");
#endif
} diag_printf("\n");
} err = closedir( dirp );
if( err < 0 ) SHOW_RESULT( stat, err );
if (numexpected >= 0 && num != numexpected)
CYG_TEST_FAIL("Wrong number of dir entries\n");
if ( numgot != NULL )
*numgot = num;
} //========================================================================== static void createfile( char *name, size_t size )
{
char buf[IOSIZE];
int fd;
ssize_t wrote;
int i;
int err; diag_printf("<INFO>: create file %s size %zd \n",name,size); err = access( name, F_OK );
if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; fd = open( name, O_WRONLY|O_CREAT );
if( fd < 0 ) SHOW_RESULT( open, fd ); while( size > 0 )
{
ssize_t len = size;
if ( len > IOSIZE ) len = IOSIZE; wrote = write( fd, buf, len );
if( wrote != len ) SHOW_RESULT( write, (int)wrote ); size -= wrote;
} err = close( fd );
if( err < 0 ) SHOW_RESULT( close, err );
} //========================================================================== static void maxfile( char *name )
{
char buf[IOSIZE];
int fd;
ssize_t wrote;
int i;
int err;
size_t size = 0;
size_t prevsize = 0; diag_printf("<INFO>: create maximal file %s\n",name);
diag_printf("<INFO>: This may take a few minutes\n"); err = access( name, F_OK );
if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; fd = open( name, O_WRONLY|O_CREAT );
if( fd < 0 ) SHOW_RESULT( open, fd ); do
{
wrote = write( fd, buf, IOSIZE );
//if( wrote < 0 ) SHOW_RESULT( write, wrote ); if( wrote >= 0 )
size += wrote; if( (size-prevsize) > 100000 )
{
diag_printf("<INFO>: size = %zd \n", size);
prevsize = size;
} } while( wrote == IOSIZE ); diag_printf("<INFO>: file size == %zd\n",size); err = close( fd );
if( err < 0 ) SHOW_RESULT( close, err );
} //========================================================================== static void checkfile( char *name )
{
char buf[IOSIZE];
int fd;
ssize_t done;
int i;
int err;
off_t pos = 0; diag_printf("<INFO>: check file %s\n",name); err = access( name, F_OK );
if( err != 0 ) SHOW_RESULT( access, err ); fd = open( name, O_RDONLY );
if( fd < 0 ) SHOW_RESULT( open, fd ); for(;;)
{
done = read( fd, buf, IOSIZE );
if( done < 0 ) SHOW_RESULT( read, (int)done ); if( done == 0 ) break; for( i = 0; i < done; i++ )
if( buf[i] != i%256 )
{
diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256);
CYG_TEST_FAIL("Data read not equal to data written\n");
} pos += done;
} err = close( fd );
if( err < 0 ) SHOW_RESULT( close, err );
} #ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
//========================================================================== static void checkattrib(const char *name,
const cyg_fs_attrib_t test_attrib )
{
int err;
cyg_fs_attrib_t file_attrib; diag_printf("<INFO>: check attrib %s\n",name); err = cyg_fs_get_attrib(name, &file_attrib);
if( err != 0 ) SHOW_RESULT( stat, err ); if ( (file_attrib & S_FATFS_ATTRIB) != test_attrib )
diag_printf("<FAIL>: attrib %s incorrect\n\tExpected %x Was %x\n",
name,test_attrib,(file_attrib & S_FATFS_ATTRIB));
}
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES //========================================================================== static void copyfile( char *name2, char *name1 )
{ int err;
char buf[IOSIZE];
int fd1, fd2;
ssize_t done, wrote; diag_printf("<INFO>: copy file %s -> %s\n",name2,name1); err = access( name1, F_OK );
if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); err = access( name2, F_OK );
if( err != 0 ) SHOW_RESULT( access, err ); fd1 = open( name1, O_WRONLY|O_CREAT );
if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); fd2 = open( name2, O_RDONLY );
if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); for(;;)
{
done = read( fd2, buf, IOSIZE );
if( done < 0 ) SHOW_RESULT( read, (int)done ); if( done == 0 ) break; wrote = write( fd1, buf, done );
if( wrote != done ) SHOW_RESULT( write, (int) wrote ); if( wrote != done ) break;
} err = close( fd1 );
if( err < 0 ) SHOW_RESULT( close, err ); err = close( fd2 );
if( err < 0 ) SHOW_RESULT( close, err ); } //========================================================================== static void comparefiles( char *name2, char *name1 )
{
int err;
char buf1[IOSIZE];
char buf2[IOSIZE];
int fd1, fd2;
ssize_t done1, done2;
int i; diag_printf("<INFO>: compare files %s == %s\n",name2,name1); err = access( name1, F_OK );
if( err != 0 ) SHOW_RESULT( access, err ); err = access( name1, F_OK );
if( err != 0 ) SHOW_RESULT( access, err ); fd1 = open( name1, O_RDONLY );
if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); fd2 = open( name2, O_RDONLY );
if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); for(;;)
{
done1 = read( fd1, buf1, IOSIZE );
if( done1 < 0 ) SHOW_RESULT( read, (int)done1 ); done2 = read( fd2, buf2, IOSIZE );
if( done2 < 0 ) SHOW_RESULT( read, (int)done2 ); if( done1 != done2 )
diag_printf("Files different sizes\n"); if( done1 == 0 ) break; for( i = 0; i < done1; i++ )
if( buf1[i] != buf2[i] )
{
diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]);
CYG_TEST_FAIL("Data in files not equal\n");
}
else
{
diag_printf("buf1[%d](%02x) == buf2[%d](%02x)\n",i,buf1[i],i,buf2[i]);
}
} err = close( fd1 );
if( err < 0 ) SHOW_RESULT( close, err ); err = close( fd2 );
if( err < 0 ) SHOW_RESULT( close, err ); } //========================================================================== void checkcwd( const char *cwd )
{
static char cwdbuf[PATH_MAX];
char *ret; ret = getcwd( cwdbuf, sizeof(cwdbuf));
if( ret == NULL ) SHOW_RESULT( getcwd, (int)ret ); if( strcmp( cwdbuf, cwd ) != 0 )
{
diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd );
CYG_TEST_FAIL( "Current directory mismatch");
}
} //==========================================================================
// main int main( int argc, char **argv )
{
int err;
int existingdirents=-1;
int fd = 0;
char buff[20] = {0};
char buff1[20] = {0};
int loop = 0;
FILE *fp = NULL; CYG_TEST_INIT(); err = mount("/dev/mmcdisk0/","/","fatfs");
if( err < 0 )
{
SHOW_RESULT( mount, err );
}
else
{
diag_printf("mount ok!\n");
} err = chdir( "/" );
if( err < 0 )
{
SHOW_RESULT( chdir, err );
}
else
{
diag_printf("chdir ok!\n");
} checkcwd( "/" ); listdir( "/", true, -1, &existingdirents ); createfile( "/mkg_rill", 10 );
checkfile( "mkg_rill" );
copyfile( "mkg_rill", "mkg_rill_bak");
checkfile( "mkg_rill_bak" );
comparefiles( "mkg_rill_bak", "/mkg_rill" ); #if 0
diag_printf("<INFO>: mkdir bar\n");
err = mkdir( "/bar", 0 );
if( err < 0 ) SHOW_RESULT( mkdir, err ); listdir( "/" , true, existingdirents+3, NULL ); copyfile( "fee", "/bar/fum" );
checkfile( "bar/fum" );
comparefiles( "/fee", "bar/fum" ); diag_printf("<INFO>: cd bar\n");
err = chdir( "bar" );
if( err < 0 ) SHOW_RESULT( chdir, err ); checkcwd( "/bar" ); diag_printf("<INFO>: rename /foo bundy\n");
err = rename( "/foo", "bundy" );
if( err < 0 ) SHOW_RESULT( rename, err ); listdir( "/", true, existingdirents+2, NULL );
listdir( "" , true, 4, NULL ); checkfile( "/bar/bundy" );
comparefiles("/fee", "bundy" ); diag_printf("<INFO>: unlink fee\n");
err = unlink( "/fee" );
if( err < 0 ) SHOW_RESULT( unlink, err ); diag_printf("<INFO>: unlink fum\n");
err = unlink( "fum" );
if( err < 0 ) SHOW_RESULT( unlink, err ); diag_printf("<INFO>: unlink /bar/bundy\n");
err = unlink( "/bar/bundy" );
if( err < 0 ) SHOW_RESULT( unlink, err ); diag_printf("<INFO>: cd /\n");
err = chdir( "/" );
if( err < 0 ) SHOW_RESULT( chdir, err ); checkcwd( "/" ); diag_printf("<INFO>: rmdir /bar\n");
err = rmdir( "/bar" );
if( err < 0 ) SHOW_RESULT( rmdir, err ); listdir( "/", false, existingdirents, NULL );
#endif err = umount( "/" );
if( err < 0 ) SHOW_RESULT( umount, err ); CYG_TEST_PASS_FINISH("fatfs1");
} // -------------------------------------------------------------------------
// EOF fatfs1.c

2》Makefile

# This variable should point to the directory where you
# installed your eCos build.
ECOS_INSTALL := /home/openrisc/share/eCos/ecos-work/install # As part of the build process, eCos automatically creates
# a file with compiler flags. Those flags are computed based
# on the ecc configuration file. It is smart to use them when
# compiling your application.
include $(ECOS_INSTALL)/include/pkgconf/ecos.mak # Unfortunately, some flags are C++ flags and some are C. We
# need to separate them. The file rules.mak shipped with the eCos
# repository contains the rules to do it. So we need to include
# this file in the end of the makefile and use more generic
# names. We also add the paths to the installation directory.
CFLAGS := $(ECOS_GLOBAL_CFLAGS) -I $(ECOS_INSTALL)/include
LDFLAGS := $(ECOS_GLOBAL_LDFLAGS) -L $(ECOS_INSTALL)/lib -T $(ECOS_INSTALL)/lib/target.ld # Rules to build the application
all: hello_world hello_world: hello_world.c
$(ECOS_COMMAND_PREFIX)gcc $(ACTUAL_CFLAGS) $(LDFLAGS) $< -o $@ # Now include the file with rules. This file must be included
# in the end, otherwise it interferes with the makefile target.
#include $(ECOS_REPOSITORY)/pkgconf/rules.mak
include /home/openrisc/share/eCos/packages/pkgconf/rules.mak

3>read_boot_record()函数修改

static int
read_boot_record(fatfs_disk_t *disk, fat_boot_record_t *fbr)
{
cyg_uint8 data[0x5A];
cyg_uint32 len;
int err; len = 0x5A;
err = disk_read(disk, (void*)data, &len, 0x10e00);//Rill modify at 130717
if (err != ENOERR)
return err; GET_WORD(data, fbr->jump, 0x00);
GET_BYTES(data, fbr->oem_name, 8, 0x03);
GET_WORD(data, fbr->bytes_per_sec, 0x0B);
GET_BYTE(data, fbr->sec_per_clu, 0x0D);
GET_WORD(data, fbr->res_sec_num, 0x0E);
GET_BYTE(data, fbr->fat_tbls_num, 0x10);
GET_WORD(data, fbr->max_root_dents, 0x11);
GET_WORD(data, fbr->sec_num_32, 0x13);
GET_BYTE(data, fbr->media_desc, 0x15);
GET_WORD(data, fbr->sec_per_fat, 0x16);
GET_WORD(data, fbr->sec_per_track, 0x18);
GET_WORD(data, fbr->heads_num, 0x1A);
GET_DWORD(data, fbr->hsec_num, 0x1C);
GET_DWORD(data, fbr->sec_num, 0x20); // This is a quick check for FAT12/16 or FAT32 boot record.
// The sec_per_fat field must be 0 on FAT32, since this
// field plays a crucial role in detection of the FAT type
// (12,16,32) it is quite safe to make this assumption.
if (0 == fbr->sec_per_fat)
{
GET_DWORD(data, fbr->sec_per_fat_32, 0x24);
GET_WORD(data, fbr->ext_flags, 0x28);
GET_WORD(data, fbr->fs_ver, 0x2A);
GET_DWORD(data, fbr->root_cluster, 0x2C);
GET_WORD(data, fbr->fs_info_sec, 0x30);
GET_WORD(data, fbr->bk_boot_sec, 0x32);
GET_BYTE(data, fbr->drv_num, 0x40);
GET_BYTE(data, fbr->ext_sig, 0x42);
GET_DWORD(data, fbr->ser_num, 0x43);
GET_BYTES(data, fbr->vol_name, 11, 0x47);
GET_BYTES(data, fbr->fat_name, 8, 0x52);
}
else
{
GET_BYTE(data, fbr->drv_num, 0x24);
GET_BYTE(data, fbr->ext_sig, 0x26);
GET_DWORD(data, fbr->ser_num, 0x27);
GET_BYTES(data, fbr->vol_name, 11, 0x2B);
GET_BYTES(data, fbr->fat_name, 8, 0x36);
} // Read the end marker
len = 0x02;
err = disk_read(disk, (void*)data, &len, 0x1FE);
if (err != ENOERR)
return err; GET_BYTES(data, fbr->exe_marker, 2, 0); // Zero terminate strings
fbr->oem_name[8] = '\0';
fbr->vol_name[11] = '\0';
fbr->fat_name[8] = '\0'; #if TDE
print_boot_record(fbr);
#endif return ENOERR;
}

OpenRisc-35-基于orpsoc,eCos的sd card controller的测试实验的更多相关文章

  1. OpenRisc-30-SD card controller模块分析与验证

    引言 ORPSoC的硬件平台是包含SD card controller控制器的,但是对应的linux里面却没有对应的linux的驱动程序,这使ORPSoC的SD card的使用收到了很大的限制.没有驱 ...

  2. SD card技术了解并WINCE下SDHC驱动开发(updated)

    Suumary: 简单介绍了一下SD卡的历史和发展,同时结合MX31 ADS上的WINCE 下SDHC驱动更深入的了解该硬件的一些行为特点. 了解SD card SD是Secure Digital C ...

  3. [OrangePi] Backup internal EMMC to SD Card

    Boot your Orange PI board from EMMC without SD Card inserted login insert your SD Card Run: sudo ins ...

  4. [OrangePi] Installation on SD Card

    Download any of the available images (xz archive) from Mega or GoogleDrive Download scriptbin_kernel ...

  5. I.MX6 uSDHC SD card register

    /**************************************************************************** * I.MX6 uSDHC SD card ...

  6. 【转】VirtualBox direct access to SD Card in Windows--不错

    原文网址:http://www.sandyscott.net/2013/08/14/virtualbox-direct-drive-access/ I’ve trying to get my Rasp ...

  7. 【译】基于主机的卡仿真(Host-based Card Emulation)

    基于主机的卡仿真(Host-based Card Emulation) 能提供NFC功能很多Android手机已经支持NFC卡模拟.在大多数情况下,该卡是由设备中的单独的芯片仿真,所谓的安全元件.由无 ...

  8. Python Kivy writes / read the file on the SD card

    Path to SD card from jnius import autoclass # SDcard Android # Get path to SD card Android try: Envi ...

  9. Using Android Phone to recover SD card formatted with DD command under linux

    Using Android Phone to recover SD card formatted with DD command under linux 1. Formatted a sd card ...

随机推荐

  1. 转:requirejs打包压缩r.js使用示例

    为了应对日益复杂,大规模的JavaScript开发.我们化整为零,化繁为简.将复杂的逻辑划分一个个小单元,各个击破.这时一个项目可能会有几十个甚至上百个JS文件,每个文件为一个模块单元.如果上线时都是 ...

  2. VS2010/MFC对话框二:为对话框添加控件)

    为对话框添加控件 创建对话框资源需要创建对话框模板.修改对话框属性.为对话框添加各种控件等步骤,前面一讲中已经讲了创建对话框模板和修改对话框属性,本节继续讲如何为对话框添加控件. 上一讲中创建了一个名 ...

  3. CSDN排名第一和第二的人

    http://blog.csdn.net/phphot http://blog.csdn.net/yuanmeng001

  4. 从零开始学C++之IO流类库(四):输出流格式化(以操纵子方式格式化 以ios类成员函数方式格式化)

    一.以操纵子方式格式化 数据输入输出的格式控制使用系统头文件<iomanip>中提供的操纵符.把它们作为插入操作符<<的输出对象即可.如setiosflags.setw.set ...

  5. float 覆盖元素的问题

    <span class="right-span"><a href="/xxx/" class="btn">增加Ser ...

  6. PHP - __clone 对象克隆

    <?php /** * 此例子解释什么是深克隆. * 克隆学生类. */ class Student { public $name = '张三'; public $age = 12; //所属老 ...

  7. 【Eclipse】Tomcat 改变发布路径

    关闭服务,删除里面的所有项目,clean,然后双击服务,发布路径修改就可以点击了.当重新发布了项目后,发布路径修改的按钮又会恢复不可点击状态.

  8. zIndex属性在IE中无效

    在ie中他的子类的zindex就以父类为准: <!doctype html> <html> <head> <meta charset="utf-8& ...

  9. iOS 常用开源代码整理

    本文章不定期整理. 1.AFNetworking AFNetworking 采用 NSURLConnection + NSOperation, 主要方便与服务端 API 进行数据交换, 操作简单, 功 ...

  10. XCode 6 出现 no identity found: Command /usr/bin/codesign failed with exit code 1 解决方法汇总

    1, 解决办法,进入开发者账号重建一个 Provisioning Profiles(或配套证书) 文件,把证书添加正确就可以了 (应该是最有效的) 2, 将p12文件重新安装下 3, 在 iPhone ...