引言

之前,曾经在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》仿真信息

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

  1. # T0 Start
  2. #
  3. # access_to_reg TEST
  4. # Time: 925
  5. # TEST 0: 3 32-BIT READ-WRITE REGISTERS ( VARIOUS BUS DELAYS )
  6. #
  7. # ===========================================================================
  8. # T0 test_access_to_reg Completed
  9. # ===========================================================================
  10. # T1 Start
  11. #
  12. # test_send_cmd TEST
  13. # Time: 4435
  14. # TEST 0: 0: Send CMD, No Response
  15. #
  16. # ===========================================================================
  17. # T1 test_send_cmd Completed
  18. # ===========================================================================
  19. # T2 Start
  20. #
  21. # access_to_reg TEST
  22. # Time: 8153
  23. # TEST 3.0: 0: Init Seq, No Response
  24. # V 1.0 Card, Timeout In TEST 3.0 00008004
  25. # CID reg 1: ffffffdd
  26. # RCA Response: 20000700
  27. # RCA Nr for data transfer: 00002000
  28. #
  29. # ===========================================================================
  30. # T2 test_init_sequence Completed
  31. # ===========================================================================
  32. # T3 Start
  33. #
  34. # access_to_reg TEST
  35. # Time: 61583
  36. # TEST 4.0: Send data
  37. # V 1.0 Card, Timeout In TEST 4.0 00008004
  38. # CID reg 1: ffffffdd
  39. # RCA Response: 20000700
  40. # RCA Nr for data transfer: 00002000
  41. # 2**BUS WIDTH 4
  42. # Card status after Bus width set 00000920
  43. #
  44. # ===========================================================================
  45. # T3 test_send_data Completed
  46. # ===========================================================================
  47. # T4 Start
  48. # Time: 208639
  49. # TEST 4.0: Send data
  50. # V 1.0 Card, Timeout In TEST 4.0 00008004
  51. # CID reg 1: ffffffdd
  52. # RCA Response: 20000700
  53. # RCA Nr for data transfer: 00002000
  54. # 2**BUS WIDTH 4
  55. # Card status after Bus width set 00000920
  56. #
  57. # ===========================================================================
  58. # T4 test_send_rec_data Completed
  59. # ===========================================================================
  60. # T5 Start
  61. #
  62. # test_send_cmd_error_rsp
  63. # Time: 416327
  64. # TEST 5 part 0: Send CMD, No Response
  65. # Time: 419969
  66. # TEST 5, part 1: Send CMD, 48-Bit Response, No error check
  67. # Time: 426521
  68. # TEST 5, part 2: Send CMD3, 48-Bit Response, All Error check enable
  69. # Time: 433177
  70. # Bus error succesfully catched, Error status register: 0000000a
  71. # Time: 433177
  72. # Test 5 part 4: Send CMD2, 136-Bit
  73. #
  74. # ===========================================================================
  75. # T5 test_send_cmd_error_rsp Complete
  76. # ===========================================================================
  77. #
  78. # access_to_reg TEST
  79. # Time: 444277
  80. # TEST 4.0: Send data
  81. # V 1.0 Card, Timeout In TEST 4.0 00008004
  82. # CID reg 1: ffffffdd
  83. # RCA Response: 20000700
  84. # RCA Nr for data transfer: 00002000
  85. # 2**BUS WIDTH 4
  86. # Card status after Bus width set 00000920
  87. # T6 test_send_cmd_error_rsp Complete
  88. # 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文件。

打印信息如下:

  1. openrisc@openrisc-VirtualBox:~/share/ecos_sdc_test$ picocom --b 115200 --p n --d 8 --f xon /dev/ttyUSB2
  2. picocom v1.4
  3.  
  4. port is : /dev/ttyUSB2
  5. flowcontrol : xon/xoff
  6. baudrate is : 115200
  7. parity is : none
  8. databits are : 8
  9. escape is : C-a
  10. noinit is : no
  11. noreset is : no
  12. nolock is : no
  13. send_cmd is : ascii_xfr -s -v -l10
  14. receive_cmd is : rz -vv
  15.  
  16. Terminal ready
  17. is_v20:0x1
  18. is_sdhc:0x0
  19. rca:0xe6240000
  20. card capacity:0x3af000
  21. sdc init success!
  22. data:0x2dbe8
  23. fatfs boot record:--->
  24. sig:0x29
  25. marker0:0x55
  26. marker1:0xaa
  27. jump:0x3ceb
  28. oem_name[0]:M
  29. oem_name[1]:S
  30. oem_name[2]:D
  31. oem_name[3]:O
  32. oem_name[4]:S
  33. oem_name[5]:5
  34. oem_name[6]:.
  35. oem_name[7]:0
  36. bytes_per_sec:0x200
  37. sec_per_clu:0x40
  38. res_sec_num:0x8
  39. fat_tbls_num:0x2
  40. max_root_dents:0x200
  41. sec_num_32:0x0
  42. media_desc:0xf8
  43. sec_per_fat:0xec
  44. sec_per_track:0x3f
  45. heads_num:0xff
  46. hsec_num:0x87
  47. sec_num:0x3ae039
  48. sec_num_32:0x0
  49. sec_num_32:0x0
  50. marker0:0x55
  51. marker1:0xaa
  52. sec_per_fat_32:0x290f4
  53. ext_flags:0x2
  54. fs_ver:0x836c
  55. root_cluster:0x0
  56. fs_info_sec:0x2
  57. bk_boot_sec:0xdc5c
  58. drv_num:0x80
  59. ext_sig:0x29
  60. ser_num:0x6eef0577
  61. vol_name[0]:N
  62. vol_name[1]:O
  63. vol_name[2]:
  64. vol_name[3]:N
  65. vol_name[4]:A
  66. vol_name[5]:M
  67. vol_name[6]:E
  68. vol_name[7]:
  69. vol_name[8]:
  70. vol_name[9]:
  71. vol_name[10]:
  72. fat_name[0]:F
  73. fat_name[1]:A
  74. fat_name[2]:T
  75. fat_name[3]:1
  76. fat_name[4]:6
  77. fat_name[5]:
  78. fat_name[6]:
  79. fat_name[7]:
  80. mount ok!
  81. chdir ok!
  82. <INFO>: reading directory /
  83. <INFO>: entry RILL [mode 00000008 ino 00000009 nlink 1 size 10]
  84. <INFO>: entry FOO [mode 00000008 ino 00000003 nlink 1 size 10]
  85. <INFO>: entry FEE [mode 00000008 ino 00000004 nlink 1 size 10]
  86. <INFO>: entry FP_FILE [mode 00000008 ino 00000008 nlink 1 size 10]
  87. <INFO>: create file /mkg_rill size 10
  88. <INFO>: check file mkg_rill
  89. <INFO>: copy file mkg_rill -> mkg_rill_bak
  90. <INFO>: check file mkg_rill_bak
  91. <INFO>: compare files mkg_rill_bak == /mkg_rill
  92. buf1[0](00) == buf2[0](00)
  93. buf1[1](01) == buf2[1](01)
  94. buf1[2](02) == buf2[2](02)
  95. buf1[3](03) == buf2[3](03)
  96. buf1[4](04) == buf2[4](04)
  97. buf1[5](05) == buf2[5](05)
  98. buf1[6](06) == buf2[6](06)
  99. buf1[7](07) == buf2[7](07)
  100. buf1[8](08) == buf2[8](08)
  101. buf1[9](09) == buf2[9](09)
  102. PASS:<fatfs1>
  103. 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

  1. //=========================================================================
  2. //
  3. // if_sdcmsc.c
  4. //
  5. // Provide a disk device driver for SDCard Mass Storage Controller
  6. //
  7. //==========================================================================
  8. // ####ECOSGPLCOPYRIGHTBEGIN####
  9. // -------------------------------------------
  10. // This file is part of eCos, the Embedded Configurable Operating System.
  11. // Copyright (C) 2004, 2006 Free Software Foundation, Inc.
  12. //
  13. // eCos is free software; you can redistribute it and/or modify it under
  14. // the terms of the GNU General Public License as published by the Free
  15. // Software Foundation; either version 2 or (at your option) any later
  16. // version.
  17. //
  18. // eCos is distributed in the hope that it will be useful, but WITHOUT
  19. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  20. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  21. // for more details.
  22. //
  23. // You should have received a copy of the GNU General Public License
  24. // along with eCos; if not, write to the Free Software Foundation, Inc.,
  25. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  26. //
  27. // As a special exception, if other files instantiate templates or use
  28. // macros or inline functions from this file, or you compile this file
  29. // and link it with other works to produce a work based on this file,
  30. // this file does not by itself cause the resulting work to be covered by
  31. // the GNU General Public License. However the source code for this file
  32. // must still be made available in accordance with section (3) of the GNU
  33. // General Public License v2.
  34. //
  35. // This exception does not invalidate any other reasons why a work based
  36. // on this file might be covered by the GNU General Public License.
  37. // -------------------------------------------
  38. // ####ECOSGPLCOPYRIGHTEND####
  39. //==========================================================================
  40. //#####DESCRIPTIONBEGIN####
  41. //
  42. // Author: Piotr Skrzypek
  43. // Date: 2012-05-01
  44. //
  45. //####DESCRIPTIONEND####
  46. //==========================================================================
  47.  
  48. #include <pkgconf/system.h>
  49. #include <cyg/infra/cyg_type.h>
  50. #include <cyg/infra/cyg_ass.h>
  51. #include <cyg/infra/diag.h>
  52. #include <cyg/hal/hal_arch.h>
  53. #include <cyg/hal/hal_if.h>
  54. #include <cyg/hal/hal_intr.h>
  55. #include <string.h>
  56. #include <errno.h>
  57. #include <cyg/io/io.h>
  58. #include <cyg/io/devtab.h>
  59. #include <cyg/io/disk.h>
  60.  
  61. // Settings exported from CDL
  62. #include <pkgconf/devs_disk_opencores_sdcmsc.h>
  63.  
  64. // SDCMSC address space
  65. #define SDCMSC_BASE 0x9e000000
  66.  
  67. // Register space
  68. #define SDCMSC_ARGUMENT 0x00
  69. #define SDCMSC_COMMAND 0x04
  70. #define SDCMSC_CARD_STATUS 0x08
  71. #define SDCMSC_RESPONSE 0x0C
  72. #define SDCMSC_CONTROLLER_SETTING 0x1C
  73. #define SDCMSC_BLOCK_SIZE 0x20
  74. #define SDCMSC_POWER_CONTROL 0x24
  75. #define SDCMSC_SOFTWARE_RESET 0x28
  76. #define SDCMSC_TIMEOUT 0x2C
  77. #define SDCMSC_NORMAL_INT_STATUS 0x30
  78. #define SDCMSC_ERROR_INT_STATUS 0x34
  79. #define SDCMSC_NORMAL_INT_ENABLE 0x38
  80. #define SDCMSC_ERROR_INT_ENABLE 0x3C
  81. #define SDCMSC_CAPABILITY 0x48
  82. #define SDCMSC_CLOCK_DIVIDER 0x4C
  83. #define SDCMSC_BD_BUFFER_STATUS 0x50
  84. #define SDCMSC_DAT_INT_STATUS 0x54
  85. #define SDCMSC_DAT_INT_ENABLE 0x58
  86. #define SDCMSC_BD_RX 0x60
  87. #define SDCMSC_BD_TX 0x80
  88.  
  89. // SDCMSC_COMMAND bits
  90. #define SDCMSC_COMMAND_CMDI(x) (x << 8)
  91. #define SDCMSC_COMMAND_CMDW(x) (x << 6)
  92. #define SDCMSC_COMMAND_CICE 0x10
  93. #define SDCMSC_COMMAND_CIRC 0x08
  94. #define SDCMSC_COMMAND_RTS_48 0x02
  95. #define SDCMSC_COMMAND_RTS_136 0x01
  96.  
  97. //SDCMSC_CARD_STATUS bits
  98. #define SDCMSC_CARD_STATUS_CICMD 0x01
  99.  
  100. // SDCMSC_NORMAL_INT_STATUS bits
  101. #define SDCMSC_NORMAL_INT_STATUS_EI 0x8000
  102. #define SDCMSC_NORMAL_INT_STATUS_CC 0x0001
  103.  
  104. // SDCMSC_DAT_INT_STATUS
  105. #define SDCMSC_DAT_INT_STATUS_TRS 0x01
  106.  
  107. typedef struct cyg_sdcmsc_disk_info_t {
  108. int is_v20;
  109. int is_sdhc;
  110. cyg_uint32 rca;
  111. int connected;
  112. } cyg_sdcmsc_disk_info_t;
  113.  
  114. static int sdcmsc_card_cmd(cyg_uint32 cmd,
  115. cyg_uint32 arg,
  116. cyg_uint32 *response) {
  117.  
  118. // Send command to card
  119. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_COMMAND, cmd);
  120. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_ARGUMENT, arg);
  121.  
  122. // Wait for response
  123. cyg_uint32 reg;
  124. cyg_uint32 mask = SDCMSC_NORMAL_INT_STATUS_EI |
  125. SDCMSC_NORMAL_INT_STATUS_CC;
  126.  
  127. do {
  128. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_NORMAL_INT_STATUS, reg);
  129. } while(!(reg & mask));
  130. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_NORMAL_INT_STATUS, 0);
  131.  
  132. // Optionally read response register
  133. if(response) {
  134. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_RESPONSE, *response);
  135. }
  136.  
  137. // Check for errors
  138. if(reg & SDCMSC_NORMAL_INT_STATUS_EI) {
  139. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_ERROR_INT_STATUS, reg);
  140. if(reg & (1 << 3)) diag_printf("Command index error\n");
  141. if(reg & (1 << 1)) diag_printf("Command CRC error\n");
  142. if(reg & (1 << 0)) diag_printf("Command timeout\n");
  143. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_ERROR_INT_STATUS, 0);
  144. return 0;
  145. }
  146. else {
  147. return 1;
  148. }
  149. }
  150.  
  151. // Card initialization and identification implemented according to
  152. // Physical Layer Simplified Specification Version 3.01
  153. static int sdcmsc_card_init(cyg_sdcmsc_disk_info_t *data,
  154. char *serial,
  155. char *firmware_rev,
  156. char *model_num,
  157. cyg_uint32 *capacity) {
  158.  
  159. cyg_uint32 reg;
  160. cyg_uint32 cmd;
  161. cyg_uint32 arg;
  162.  
  163. // Send CMD0 to switch the card to idle state
  164. cmd = SDCMSC_COMMAND_CMDI(0);
  165. if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0;
  166.  
  167. // Send CMD8 offering 2.7V to 3.6V range
  168. // If the card doesn't responde it means either:
  169. // 1. Card supports v2.0 but can't communicate using
  170. // current voltage levels
  171. // 2. Card does not support v2.0
  172. cmd = SDCMSC_COMMAND_CMDI(8) |
  173. SDCMSC_COMMAND_CICE |
  174. SDCMSC_COMMAND_CIRC |
  175. SDCMSC_COMMAND_RTS_48;
  176. data->is_v20 = sdcmsc_card_cmd(cmd, 0x1AA, NULL);
  177. diag_printf("is_v20:0x%x\n",data->is_v20);//rill add debug
  178. do {
  179. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_CARD_STATUS, reg);
  180. } while(reg & SDCMSC_CARD_STATUS_CICMD);
  181.  
  182. // Repeat ACMD41 until card set the busy bit to 1
  183. // Since ACMD is an extended command, it must be preceded
  184. // by CMD55
  185. do {
  186. cmd = SDCMSC_COMMAND_CMDI(55) |
  187. SDCMSC_COMMAND_CICE |
  188. SDCMSC_COMMAND_CIRC |
  189. SDCMSC_COMMAND_RTS_48;
  190. if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0;
  191.  
  192. cmd = SDCMSC_COMMAND_CMDI(41) |
  193. SDCMSC_COMMAND_RTS_48;
  194. arg = data->is_v20 ?
  195. 0x40FF8000 :
  196. 0x00FF8000;
  197. if(!sdcmsc_card_cmd(cmd, arg, ®)) return 0;
  198.  
  199. } while(!(reg & 0x80000000));
  200.  
  201. data->is_sdhc = !!(reg & 0x40000000);
  202. diag_printf("is_sdhc:0x%x\n",data->is_sdhc);
  203. // Issue CMD2 to switch from ready state to ident. Unfortunately, it is
  204. // not possible to read whole CID because the command can be issued only
  205. // once, and the peripheral can store only 32bit of the command at once.
  206. cmd = SDCMSC_COMMAND_CMDI(2) |
  207. SDCMSC_COMMAND_RTS_136;
  208. if(!sdcmsc_card_cmd(cmd, 0, NULL)) return 0;
  209.  
  210. // Issue CMD3 to get RCA and switch from ident state to stby.
  211. cmd = SDCMSC_COMMAND_CMDI(3) |
  212. SDCMSC_COMMAND_CICE |
  213. SDCMSC_COMMAND_CIRC |
  214. SDCMSC_COMMAND_RTS_48;
  215. if(!sdcmsc_card_cmd(cmd, 0, ®)) return 0;
  216. data->rca = reg & 0xFFFF0000;
  217. diag_printf("rca:0x%x\n",data->rca);
  218. // Calculate card capacity. Use information stored in CSD register.
  219. cyg_uint32 card_capacity;
  220. if(data->is_sdhc) {
  221. cmd = SDCMSC_COMMAND_CMDI(9) |
  222. SDCMSC_COMMAND_CMDW(1) |
  223. SDCMSC_COMMAND_RTS_136;
  224. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  225. card_capacity = reg & 0x3F;
  226. card_capacity <<= 16;
  227.  
  228. cmd = SDCMSC_COMMAND_CMDI(9) |
  229. SDCMSC_COMMAND_CMDW(2) |
  230. SDCMSC_COMMAND_RTS_136;
  231. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  232. reg >>= 16;
  233. card_capacity |= reg;
  234. card_capacity += 1;
  235. card_capacity *= 1000;
  236. }
  237. else {
  238. cmd = SDCMSC_COMMAND_CMDI(9) |
  239. SDCMSC_COMMAND_CMDW(1) |
  240. SDCMSC_COMMAND_RTS_136;
  241. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  242. cyg_uint32 read_bl_len = (reg >> 16) & 0x0F;
  243. cyg_uint32 c_size = reg & 0x3FF;
  244. c_size <<= 2;
  245.  
  246. cmd = SDCMSC_COMMAND_CMDI(9) |
  247. SDCMSC_COMMAND_CMDW(2) |
  248. SDCMSC_COMMAND_RTS_136;
  249. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  250. c_size |= (reg >> 30) & 0x03;
  251. cyg_uint32 c_size_mult = (reg >> 15) & 0x07;
  252. card_capacity = c_size + 1;
  253. card_capacity *= 1 << (c_size_mult + 2);
  254. card_capacity *= 1 << (read_bl_len);
  255. card_capacity >>= 9;
  256. }
  257. diag_printf("card capacity:0x%x\n",card_capacity);
  258. // Fill disk identification struct using information in CID register
  259. // use OEM/APPlication ID field to fill model_num,
  260. // Product revision field to fill firmware_rev,
  261. // and Product serial number to field to fill serial
  262. cmd = SDCMSC_COMMAND_CMDI(10) |
  263. SDCMSC_COMMAND_CMDW(0) |
  264. SDCMSC_COMMAND_RTS_136;
  265. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  266. model_num[0] = (reg >> 16) & 0xFF;
  267. model_num[1] = (reg >> 8) & 0xFF;
  268. model_num[2] = 0;
  269.  
  270. cmd = SDCMSC_COMMAND_CMDI(10) |
  271. SDCMSC_COMMAND_CMDW(2) |
  272. SDCMSC_COMMAND_RTS_136;
  273. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  274. firmware_rev[0] = (reg >> 24) & 0xFF;
  275. firmware_rev[1] = 0;
  276. serial[0] = (reg >> 16) & 0xFF;
  277. serial[1] = (reg >> 8) & 0xFF;
  278. serial[2] = reg & 0xFF;
  279.  
  280. cmd = SDCMSC_COMMAND_CMDI(10) |
  281. SDCMSC_COMMAND_CMDW(3) |
  282. SDCMSC_COMMAND_RTS_136;
  283. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  284. serial[3] = (reg >> 24) & 0xFF;
  285.  
  286. // Put card in transfer state
  287. cmd = SDCMSC_COMMAND_CMDI(7) |
  288. SDCMSC_COMMAND_CICE |
  289. SDCMSC_COMMAND_CIRC |
  290. SDCMSC_COMMAND_RTS_48;
  291. if(!sdcmsc_card_cmd(cmd, data->rca, ®)) return 0;
  292. if(reg != 0x700) return 0;
  293.  
  294. // Set block size to 512
  295. cmd = SDCMSC_COMMAND_CMDI(16) |
  296. SDCMSC_COMMAND_CICE |
  297. SDCMSC_COMMAND_CIRC |
  298. SDCMSC_COMMAND_RTS_48;
  299. if(!sdcmsc_card_cmd(cmd, 512, NULL)) return 0;
  300.  
  301. // Set 4-bits bus mode
  302. cmd = SDCMSC_COMMAND_CMDI(55) |
  303. SDCMSC_COMMAND_CICE |
  304. SDCMSC_COMMAND_CIRC |
  305. SDCMSC_COMMAND_RTS_48;
  306. if(!sdcmsc_card_cmd(cmd, data->rca, NULL)) return 0;
  307.  
  308. cmd = SDCMSC_COMMAND_CMDI(6) |
  309. SDCMSC_COMMAND_CICE |
  310. SDCMSC_COMMAND_CIRC |
  311. SDCMSC_COMMAND_RTS_48;
  312. if(!sdcmsc_card_cmd(cmd, 0x02, NULL)) return 0;
  313. diag_printf("sdc init success!\n");
  314. return 1;
  315. }
  316.  
  317. static int sdcmsc_card_queue(cyg_sdcmsc_disk_info_t *data,
  318. int direction_transmit,
  319. int block_addr,
  320. cyg_uint32 buffer_addr) {
  321.  
  322. // SDSC cards use byte addressing, while SDHC use block addressing.
  323. // It is therefore required to multiply the address by 512 if
  324. // we are dealing with SDSC card, to remain compatible with the API.
  325. if(!data->is_sdhc) {
  326. block_addr <<= 9;
  327. }
  328.  
  329. if(direction_transmit) {
  330. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_TX, buffer_addr);
  331. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_TX, block_addr);
  332. }
  333. else {
  334. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_RX, buffer_addr);
  335. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_BD_RX, block_addr);
  336. }
  337.  
  338. // Now wait for the response
  339. cyg_uint32 reg;
  340. do {
  341. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_DAT_INT_STATUS, reg);
  342. } while(!reg);
  343. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_DAT_INT_STATUS, 0);
  344.  
  345. // Check for errors
  346. if(reg == SDCMSC_DAT_INT_STATUS_TRS) {
  347. return 1;
  348. }
  349. else {
  350. if(reg & (1 << 5)) diag_printf("Transmission error\n");
  351. if(reg & (1 << 4)) diag_printf("Command error\n");
  352. if(reg & (1 << 2)) diag_printf("FIFO error\n");
  353. if(reg & (1 << 1)) diag_printf("Retry error\n");
  354. return 0;
  355. }
  356. }
  357.  
  358. // This is an API function. Is is called once, in the beginning
  359. static cyg_bool sdcmsc_disk_init(struct cyg_devtab_entry* tab) {
  360.  
  361. // Set highest possible timeout
  362. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_TIMEOUT, 0xFFFE);
  363.  
  364. // Reset the peripheral
  365. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_SOFTWARE_RESET, 1);
  366. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_CLOCK_DIVIDER, 2);
  367. HAL_WRITE_UINT32(SDCMSC_BASE + SDCMSC_SOFTWARE_RESET, 0);
  368.  
  369. // Call upper level
  370. disk_channel* ch = (disk_channel*) tab->priv;
  371. return (*ch->callbacks->disk_init)(tab);
  372. }
  373.  
  374. // This function is called when user mounts the disk
  375. static Cyg_ErrNo sdcmsc_disk_lookup(struct cyg_devtab_entry** tab,
  376. struct cyg_devtab_entry *sub_tab,
  377. const char* name) {
  378.  
  379. disk_channel *ch = (disk_channel*) (*tab)->priv;
  380. cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv;
  381.  
  382. // If the card was not initialized yet, it's time to do it
  383. // and call disk_connected callback
  384. if(!data->connected) {
  385.  
  386. cyg_disk_identify_t id;
  387.  
  388. // Pass dummy CHS geometry and hope the upper level
  389. // will use LBA mode. To guess CHS we would need to
  390. // analyze partition table and confront LBA and CHS
  391. // addresses. And it would work only if proper LBA
  392. // field is stored in MBR. Is is definitely something
  393. // that should be done by upper level.
  394. id.cylinders_num = 1;
  395. id.heads_num = 1;
  396. id.sectors_num = 1;
  397.  
  398. id.phys_block_size = 1;
  399. id.max_transfer = 512;
  400.  
  401. // Initialize the card
  402. data->connected = sdcmsc_card_init(data,
  403. id.serial,
  404. id.firmware_rev,
  405. id.model_num,
  406. &id.lba_sectors_num);
  407.  
  408. if(data->connected) {
  409. // Let upper level know there is a new disk
  410. (*ch->callbacks->disk_connected)(*tab, &id);
  411. }
  412. }
  413.  
  414. // Call upper level
  415. return (*ch->callbacks->disk_lookup)(tab, sub_tab, name);
  416. }
  417.  
  418. // API function to read block from the disk
  419. static Cyg_ErrNo sdcmsc_disk_read(disk_channel* ch,
  420. void* buf,
  421. cyg_uint32 blocks,
  422. cyg_uint32 first_block) {
  423.  
  424. cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv;
  425.  
  426. int i;
  427. int result;
  428. cyg_uint32 reg;
  429. for(i = 0; i < blocks; i++) {
  430.  
  431. // Check for free receive buffers
  432. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_BD_BUFFER_STATUS, reg);
  433. reg >>= 8;
  434. reg &= 0xFF;
  435. if(reg == 0) {
  436. return -EIO;
  437. }
  438.  
  439. result = sdcmsc_card_queue(data, 0, first_block, (cyg_uint32) buf);
  440. if(!result) {
  441. return -EIO;
  442. }
  443. }
  444.  
  445. return ENOERR;
  446.  
  447. }
  448.  
  449. // API function to write block to disk
  450. static Cyg_ErrNo sdcmsc_disk_write(disk_channel* ch,
  451. const void* buf,
  452. cyg_uint32 blocks,
  453. cyg_uint32 first_block) {
  454.  
  455. cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv;
  456.  
  457. int i;
  458. int result;
  459. cyg_uint32 reg;
  460. for(i = 0; i < blocks; i++) {
  461.  
  462. // Check for free transmit buffers
  463. HAL_READ_UINT32(SDCMSC_BASE + SDCMSC_BD_BUFFER_STATUS, reg);
  464. reg &= 0xFF;
  465. if(reg == 0) {
  466. return -EIO;
  467. }
  468.  
  469. result = sdcmsc_card_queue(data, 1, first_block, (cyg_uint32) buf);
  470. if(!result) {
  471. return -EIO;
  472. }
  473. }
  474.  
  475. return ENOERR;
  476.  
  477. }
  478.  
  479. // API function to fetch driver configuration and disk info.
  480. static Cyg_ErrNo sdcmsc_disk_get_config(disk_channel* ch,
  481. cyg_uint32 key,
  482. const void* buf,
  483. cyg_uint32* len) {
  484.  
  485. CYG_UNUSED_PARAM(disk_channel*, ch);
  486. CYG_UNUSED_PARAM(cyg_uint32, key);
  487. CYG_UNUSED_PARAM(const void*, buf);
  488. CYG_UNUSED_PARAM(cyg_uint32*, len);
  489.  
  490. return -EINVAL;
  491. }
  492.  
  493. // API function to update driver status information.
  494. static Cyg_ErrNo sdcmsc_disk_set_config(disk_channel* ch,
  495. cyg_uint32 key,
  496. const void* buf,
  497. cyg_uint32* len) {
  498.  
  499. cyg_sdcmsc_disk_info_t *data = (cyg_sdcmsc_disk_info_t*) ch->dev_priv;
  500.  
  501. if(key == CYG_IO_SET_CONFIG_DISK_UMOUNT) {
  502. if(ch->info->mounts == 0) {
  503. data->connected = false;
  504. return (ch->callbacks->disk_disconnected)(ch);
  505. }
  506. else {
  507. return ENOERR;
  508. }
  509. }
  510. else {
  511. return -EINVAL;
  512. }
  513.  
  514. }
  515.  
  516. // Register the driver in the system
  517.  
  518. static cyg_sdcmsc_disk_info_t cyg_sdcmsc_disk0_hwinfo = {
  519. .connected = 0
  520. };
  521.  
  522. DISK_FUNS(cyg_sdcmsc_disk_funs,
  523. sdcmsc_disk_read,
  524. sdcmsc_disk_write,
  525. sdcmsc_disk_get_config,
  526. sdcmsc_disk_set_config
  527. );
  528.  
  529. DISK_CONTROLLER(cyg_sdcmsc_disk_controller_0, cyg_sdcmsc_disk0_hwinfo);
  530.  
  531. DISK_CHANNEL(cyg_sdcmsc_disk0_channel,
  532. cyg_sdcmsc_disk_funs,
  533. cyg_sdcmsc_disk0_hwinfo,
  534. cyg_sdcmsc_disk_controller_0,
  535. true, //mbr supported
  536. 4 //partitions
  537. );
  538.  
  539. BLOCK_DEVTAB_ENTRY(cyg_sdcmsc_disk0_devtab_entry,
  540. CYGDAT_DEVS_DISK_OPENCORES_SDCMSC_DISK0_NAME,
  541. 0,
  542. &cyg_io_disk_devio,
  543. &sdcmsc_disk_init,
  544. &sdcmsc_disk_lookup,
  545. &cyg_sdcmsc_disk0_channel);
  546.  
  547. // EOF if_sdcmsc.c

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

1》helloworld.c

  1. //==========================================================================
  2. //
  3. // fatfs1.c
  4. //
  5. // Test fileio system
  6. //
  7. //==========================================================================
  8. // ####ECOSGPLCOPYRIGHTBEGIN####
  9. // -------------------------------------------
  10. // This file is part of eCos, the Embedded Configurable Operating System.
  11. // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
  12. //
  13. // eCos is free software; you can redistribute it and/or modify it under
  14. // the terms of the GNU General Public License as published by the Free
  15. // Software Foundation; either version 2 or (at your option) any later
  16. // version.
  17. //
  18. // eCos is distributed in the hope that it will be useful, but WITHOUT
  19. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  20. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  21. // for more details.
  22. //
  23. // You should have received a copy of the GNU General Public License
  24. // along with eCos; if not, write to the Free Software Foundation, Inc.,
  25. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  26. //
  27. // As a special exception, if other files instantiate templates or use
  28. // macros or inline functions from this file, or you compile this file
  29. // and link it with other works to produce a work based on this file,
  30. // this file does not by itself cause the resulting work to be covered by
  31. // the GNU General Public License. However the source code for this file
  32. // must still be made available in accordance with section (3) of the GNU
  33. // General Public License v2.
  34. //
  35. // This exception does not invalidate any other reasons why a work based
  36. // on this file might be covered by the GNU General Public License.
  37. // -------------------------------------------
  38. // ####ECOSGPLCOPYRIGHTEND####
  39. //==========================================================================
  40. //#####DESCRIPTIONBEGIN####
  41. //
  42. // Author(s): nickg
  43. // Contributors: nickg
  44. // Date: 2000-05-25
  45. // Purpose: Test fileio system
  46. // Description: This test uses the testfs to check out the initialization
  47. // and basic operation of the fileio system
  48. //
  49. //
  50. //
  51. //
  52. //
  53. //
  54. //
  55. //####DESCRIPTIONEND####
  56. //
  57. //==========================================================================
  58.  
  59. #include <pkgconf/hal.h>
  60. #include <pkgconf/io_fileio.h>
  61. #include <pkgconf/fs_fat.h>
  62.  
  63. #include <cyg/infra/cyg_trac.h> // tracing macros
  64. #include <cyg/infra/cyg_ass.h> // assertion macros
  65.  
  66. #include <unistd.h>
  67. #include <fcntl.h>
  68. #include <sys/stat.h>
  69. #include <errno.h>
  70. #include <string.h>
  71. #include <dirent.h>
  72. #include <stdio.h>
  73.  
  74. #include <cyg/fileio/fileio.h>
  75.  
  76. #include <cyg/infra/testcase.h>
  77. #include <cyg/infra/diag.h> // HAL polled output
  78. #include <cyg/fs/fatfs.h>
  79.  
  80. //==========================================================================
  81.  
  82. #define SHOW_RESULT( _fn, _res ) \
  83. diag_printf("<FAIL>: " #_fn "() returned %d %s\n", _res, _res<0?strerror(errno):"");
  84.  
  85. //==========================================================================
  86.  
  87. #define IOSIZE 100
  88.  
  89. #define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1"
  90. #define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2"
  91.  
  92. //==========================================================================
  93.  
  94. #ifndef CYGPKG_LIBC_STRING
  95.  
  96. char *strcat( char *s1, const char *s2 )
  97. {
  98. char *s = s1;
  99. while( *s1 ) s1++;
  100. while( (*s1++ = *s2++) != 0);
  101. return s;
  102. }
  103.  
  104. #endif
  105.  
  106. //==========================================================================
  107.  
  108. static void listdir( char *name, int statp, int numexpected, int *numgot )
  109. {
  110. int err;
  111. DIR *dirp;
  112. int num=0;
  113.  
  114. diag_printf("<INFO>: reading directory %s\n",name);
  115.  
  116. dirp = opendir( name );
  117. if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
  118.  
  119. for(;;)
  120. {
  121. struct dirent *entry = readdir( dirp );
  122.  
  123. if( entry == NULL )
  124. break;
  125. num++;
  126. diag_printf("<INFO>: entry %14s",entry->d_name);
  127. #ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE
  128. diag_printf(" d_type %2x", entry->d_type);
  129. #endif
  130. if( statp )
  131. {
  132. char fullname[PATH_MAX];
  133. struct stat sbuf;
  134.  
  135. if( name[0] )
  136. {
  137. strcpy(fullname, name );
  138. if( !(name[0] == '/' && name[1] == 0 ) )
  139. strcat(fullname, "/" );
  140. }
  141. else fullname[0] = 0;
  142.  
  143. strcat(fullname, entry->d_name );
  144.  
  145. err = stat( fullname, &sbuf );
  146. if( err < 0 )
  147. {
  148. if( errno == ENOSYS )
  149. diag_printf(" <no status available>");
  150. else SHOW_RESULT( stat, err );
  151. }
  152. else
  153. {
  154. diag_printf(" [mode %08x ino %08x nlink %d size %ld]",
  155. sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,(long)sbuf.st_size);
  156. }
  157. #ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE
  158. if ((entry->d_type & S_IFMT) != (sbuf.st_mode & S_IFMT))
  159. CYG_TEST_FAIL("File mode's don't match between dirent and stat");
  160. #endif
  161. }
  162.  
  163. diag_printf("\n");
  164. }
  165.  
  166. err = closedir( dirp );
  167. if( err < 0 ) SHOW_RESULT( stat, err );
  168. if (numexpected >= 0 && num != numexpected)
  169. CYG_TEST_FAIL("Wrong number of dir entries\n");
  170. if ( numgot != NULL )
  171. *numgot = num;
  172. }
  173.  
  174. //==========================================================================
  175.  
  176. static void createfile( char *name, size_t size )
  177. {
  178. char buf[IOSIZE];
  179. int fd;
  180. ssize_t wrote;
  181. int i;
  182. int err;
  183.  
  184. diag_printf("<INFO>: create file %s size %zd \n",name,size);
  185.  
  186. err = access( name, F_OK );
  187. if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
  188.  
  189. for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256;
  190.  
  191. fd = open( name, O_WRONLY|O_CREAT );
  192. if( fd < 0 ) SHOW_RESULT( open, fd );
  193.  
  194. while( size > 0 )
  195. {
  196. ssize_t len = size;
  197. if ( len > IOSIZE ) len = IOSIZE;
  198.  
  199. wrote = write( fd, buf, len );
  200. if( wrote != len ) SHOW_RESULT( write, (int)wrote );
  201.  
  202. size -= wrote;
  203. }
  204.  
  205. err = close( fd );
  206. if( err < 0 ) SHOW_RESULT( close, err );
  207. }
  208.  
  209. //==========================================================================
  210.  
  211. static void maxfile( char *name )
  212. {
  213. char buf[IOSIZE];
  214. int fd;
  215. ssize_t wrote;
  216. int i;
  217. int err;
  218. size_t size = 0;
  219. size_t prevsize = 0;
  220.  
  221. diag_printf("<INFO>: create maximal file %s\n",name);
  222. diag_printf("<INFO>: This may take a few minutes\n");
  223.  
  224. err = access( name, F_OK );
  225. if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
  226.  
  227. for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256;
  228.  
  229. fd = open( name, O_WRONLY|O_CREAT );
  230. if( fd < 0 ) SHOW_RESULT( open, fd );
  231.  
  232. do
  233. {
  234. wrote = write( fd, buf, IOSIZE );
  235. //if( wrote < 0 ) SHOW_RESULT( write, wrote );
  236.  
  237. if( wrote >= 0 )
  238. size += wrote;
  239.  
  240. if( (size-prevsize) > 100000 )
  241. {
  242. diag_printf("<INFO>: size = %zd \n", size);
  243. prevsize = size;
  244. }
  245.  
  246. } while( wrote == IOSIZE );
  247.  
  248. diag_printf("<INFO>: file size == %zd\n",size);
  249.  
  250. err = close( fd );
  251. if( err < 0 ) SHOW_RESULT( close, err );
  252. }
  253.  
  254. //==========================================================================
  255.  
  256. static void checkfile( char *name )
  257. {
  258. char buf[IOSIZE];
  259. int fd;
  260. ssize_t done;
  261. int i;
  262. int err;
  263. off_t pos = 0;
  264.  
  265. diag_printf("<INFO>: check file %s\n",name);
  266.  
  267. err = access( name, F_OK );
  268. if( err != 0 ) SHOW_RESULT( access, err );
  269.  
  270. fd = open( name, O_RDONLY );
  271. if( fd < 0 ) SHOW_RESULT( open, fd );
  272.  
  273. for(;;)
  274. {
  275. done = read( fd, buf, IOSIZE );
  276. if( done < 0 ) SHOW_RESULT( read, (int)done );
  277.  
  278. if( done == 0 ) break;
  279.  
  280. for( i = 0; i < done; i++ )
  281. if( buf[i] != i%256 )
  282. {
  283. diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256);
  284. CYG_TEST_FAIL("Data read not equal to data written\n");
  285. }
  286.  
  287. pos += done;
  288. }
  289.  
  290. err = close( fd );
  291. if( err < 0 ) SHOW_RESULT( close, err );
  292. }
  293.  
  294. #ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
  295. //==========================================================================
  296.  
  297. static void checkattrib(const char *name,
  298. const cyg_fs_attrib_t test_attrib )
  299. {
  300. int err;
  301. cyg_fs_attrib_t file_attrib;
  302.  
  303. diag_printf("<INFO>: check attrib %s\n",name);
  304.  
  305. err = cyg_fs_get_attrib(name, &file_attrib);
  306. if( err != 0 ) SHOW_RESULT( stat, err );
  307.  
  308. if ( (file_attrib & S_FATFS_ATTRIB) != test_attrib )
  309. diag_printf("<FAIL>: attrib %s incorrect\n\tExpected %x Was %x\n",
  310. name,test_attrib,(file_attrib & S_FATFS_ATTRIB));
  311. }
  312. #endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
  313.  
  314. //==========================================================================
  315.  
  316. static void copyfile( char *name2, char *name1 )
  317. {
  318.  
  319. int err;
  320. char buf[IOSIZE];
  321. int fd1, fd2;
  322. ssize_t done, wrote;
  323.  
  324. diag_printf("<INFO>: copy file %s -> %s\n",name2,name1);
  325.  
  326. err = access( name1, F_OK );
  327. if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
  328.  
  329. err = access( name2, F_OK );
  330. if( err != 0 ) SHOW_RESULT( access, err );
  331.  
  332. fd1 = open( name1, O_WRONLY|O_CREAT );
  333. if( fd1 < 0 ) SHOW_RESULT( open, fd1 );
  334.  
  335. fd2 = open( name2, O_RDONLY );
  336. if( fd2 < 0 ) SHOW_RESULT( open, fd2 );
  337.  
  338. for(;;)
  339. {
  340. done = read( fd2, buf, IOSIZE );
  341. if( done < 0 ) SHOW_RESULT( read, (int)done );
  342.  
  343. if( done == 0 ) break;
  344.  
  345. wrote = write( fd1, buf, done );
  346. if( wrote != done ) SHOW_RESULT( write, (int) wrote );
  347.  
  348. if( wrote != done ) break;
  349. }
  350.  
  351. err = close( fd1 );
  352. if( err < 0 ) SHOW_RESULT( close, err );
  353.  
  354. err = close( fd2 );
  355. if( err < 0 ) SHOW_RESULT( close, err );
  356.  
  357. }
  358.  
  359. //==========================================================================
  360.  
  361. static void comparefiles( char *name2, char *name1 )
  362. {
  363. int err;
  364. char buf1[IOSIZE];
  365. char buf2[IOSIZE];
  366. int fd1, fd2;
  367. ssize_t done1, done2;
  368. int i;
  369.  
  370. diag_printf("<INFO>: compare files %s == %s\n",name2,name1);
  371.  
  372. err = access( name1, F_OK );
  373. if( err != 0 ) SHOW_RESULT( access, err );
  374.  
  375. err = access( name1, F_OK );
  376. if( err != 0 ) SHOW_RESULT( access, err );
  377.  
  378. fd1 = open( name1, O_RDONLY );
  379. if( fd1 < 0 ) SHOW_RESULT( open, fd1 );
  380.  
  381. fd2 = open( name2, O_RDONLY );
  382. if( fd2 < 0 ) SHOW_RESULT( open, fd2 );
  383.  
  384. for(;;)
  385. {
  386. done1 = read( fd1, buf1, IOSIZE );
  387. if( done1 < 0 ) SHOW_RESULT( read, (int)done1 );
  388.  
  389. done2 = read( fd2, buf2, IOSIZE );
  390. if( done2 < 0 ) SHOW_RESULT( read, (int)done2 );
  391.  
  392. if( done1 != done2 )
  393. diag_printf("Files different sizes\n");
  394.  
  395. if( done1 == 0 ) break;
  396.  
  397. for( i = 0; i < done1; i++ )
  398. if( buf1[i] != buf2[i] )
  399. {
  400. diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]);
  401. CYG_TEST_FAIL("Data in files not equal\n");
  402. }
  403. else
  404. {
  405. diag_printf("buf1[%d](%02x) == buf2[%d](%02x)\n",i,buf1[i],i,buf2[i]);
  406. }
  407. }
  408.  
  409. err = close( fd1 );
  410. if( err < 0 ) SHOW_RESULT( close, err );
  411.  
  412. err = close( fd2 );
  413. if( err < 0 ) SHOW_RESULT( close, err );
  414.  
  415. }
  416.  
  417. //==========================================================================
  418.  
  419. void checkcwd( const char *cwd )
  420. {
  421. static char cwdbuf[PATH_MAX];
  422. char *ret;
  423.  
  424. ret = getcwd( cwdbuf, sizeof(cwdbuf));
  425. if( ret == NULL ) SHOW_RESULT( getcwd, (int)ret );
  426.  
  427. if( strcmp( cwdbuf, cwd ) != 0 )
  428. {
  429. diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd );
  430. CYG_TEST_FAIL( "Current directory mismatch");
  431. }
  432. }
  433.  
  434. //==========================================================================
  435. // main
  436.  
  437. int main( int argc, char **argv )
  438. {
  439. int err;
  440. int existingdirents=-1;
  441. int fd = 0;
  442. char buff[20] = {0};
  443. char buff1[20] = {0};
  444. int loop = 0;
  445. FILE *fp = NULL;
  446.  
  447. CYG_TEST_INIT();
  448.  
  449. err = mount("/dev/mmcdisk0/","/","fatfs");
  450. if( err < 0 )
  451. {
  452. SHOW_RESULT( mount, err );
  453. }
  454. else
  455. {
  456. diag_printf("mount ok!\n");
  457. }
  458.  
  459. err = chdir( "/" );
  460. if( err < 0 )
  461. {
  462. SHOW_RESULT( chdir, err );
  463. }
  464. else
  465. {
  466. diag_printf("chdir ok!\n");
  467. }
  468.  
  469. checkcwd( "/" );
  470.  
  471. listdir( "/", true, -1, &existingdirents );
  472.  
  473. createfile( "/mkg_rill", 10 );
  474. checkfile( "mkg_rill" );
  475. copyfile( "mkg_rill", "mkg_rill_bak");
  476. checkfile( "mkg_rill_bak" );
  477. comparefiles( "mkg_rill_bak", "/mkg_rill" );
  478.  
  479. #if 0
  480. diag_printf("<INFO>: mkdir bar\n");
  481. err = mkdir( "/bar", 0 );
  482. if( err < 0 ) SHOW_RESULT( mkdir, err );
  483.  
  484. listdir( "/" , true, existingdirents+3, NULL );
  485.  
  486. copyfile( "fee", "/bar/fum" );
  487. checkfile( "bar/fum" );
  488. comparefiles( "/fee", "bar/fum" );
  489.  
  490. diag_printf("<INFO>: cd bar\n");
  491. err = chdir( "bar" );
  492. if( err < 0 ) SHOW_RESULT( chdir, err );
  493.  
  494. checkcwd( "/bar" );
  495.  
  496. diag_printf("<INFO>: rename /foo bundy\n");
  497. err = rename( "/foo", "bundy" );
  498. if( err < 0 ) SHOW_RESULT( rename, err );
  499.  
  500. listdir( "/", true, existingdirents+2, NULL );
  501. listdir( "" , true, 4, NULL );
  502.  
  503. checkfile( "/bar/bundy" );
  504. comparefiles("/fee", "bundy" );
  505.  
  506. diag_printf("<INFO>: unlink fee\n");
  507. err = unlink( "/fee" );
  508. if( err < 0 ) SHOW_RESULT( unlink, err );
  509.  
  510. diag_printf("<INFO>: unlink fum\n");
  511. err = unlink( "fum" );
  512. if( err < 0 ) SHOW_RESULT( unlink, err );
  513.  
  514. diag_printf("<INFO>: unlink /bar/bundy\n");
  515. err = unlink( "/bar/bundy" );
  516. if( err < 0 ) SHOW_RESULT( unlink, err );
  517.  
  518. diag_printf("<INFO>: cd /\n");
  519. err = chdir( "/" );
  520. if( err < 0 ) SHOW_RESULT( chdir, err );
  521.  
  522. checkcwd( "/" );
  523.  
  524. diag_printf("<INFO>: rmdir /bar\n");
  525. err = rmdir( "/bar" );
  526. if( err < 0 ) SHOW_RESULT( rmdir, err );
  527.  
  528. listdir( "/", false, existingdirents, NULL );
  529. #endif
  530.  
  531. err = umount( "/" );
  532. if( err < 0 ) SHOW_RESULT( umount, err );
  533.  
  534. CYG_TEST_PASS_FINISH("fatfs1");
  535. }
  536.  
  537. // -------------------------------------------------------------------------
  538. // EOF fatfs1.c

2》Makefile

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

3>read_boot_record()函数修改

  1. static int
  2. read_boot_record(fatfs_disk_t *disk, fat_boot_record_t *fbr)
  3. {
  4. cyg_uint8 data[0x5A];
  5. cyg_uint32 len;
  6. int err;
  7.  
  8. len = 0x5A;
  9. err = disk_read(disk, (void*)data, &len, 0x10e00);//Rill modify at 130717
  10. if (err != ENOERR)
  11. return err;
  12.  
  13. GET_WORD(data, fbr->jump, 0x00);
  14. GET_BYTES(data, fbr->oem_name, 8, 0x03);
  15. GET_WORD(data, fbr->bytes_per_sec, 0x0B);
  16. GET_BYTE(data, fbr->sec_per_clu, 0x0D);
  17. GET_WORD(data, fbr->res_sec_num, 0x0E);
  18. GET_BYTE(data, fbr->fat_tbls_num, 0x10);
  19. GET_WORD(data, fbr->max_root_dents, 0x11);
  20. GET_WORD(data, fbr->sec_num_32, 0x13);
  21. GET_BYTE(data, fbr->media_desc, 0x15);
  22. GET_WORD(data, fbr->sec_per_fat, 0x16);
  23. GET_WORD(data, fbr->sec_per_track, 0x18);
  24. GET_WORD(data, fbr->heads_num, 0x1A);
  25. GET_DWORD(data, fbr->hsec_num, 0x1C);
  26. GET_DWORD(data, fbr->sec_num, 0x20);
  27.  
  28. // This is a quick check for FAT12/16 or FAT32 boot record.
  29. // The sec_per_fat field must be 0 on FAT32, since this
  30. // field plays a crucial role in detection of the FAT type
  31. // (12,16,32) it is quite safe to make this assumption.
  32. if (0 == fbr->sec_per_fat)
  33. {
  34. GET_DWORD(data, fbr->sec_per_fat_32, 0x24);
  35. GET_WORD(data, fbr->ext_flags, 0x28);
  36. GET_WORD(data, fbr->fs_ver, 0x2A);
  37. GET_DWORD(data, fbr->root_cluster, 0x2C);
  38. GET_WORD(data, fbr->fs_info_sec, 0x30);
  39. GET_WORD(data, fbr->bk_boot_sec, 0x32);
  40. GET_BYTE(data, fbr->drv_num, 0x40);
  41. GET_BYTE(data, fbr->ext_sig, 0x42);
  42. GET_DWORD(data, fbr->ser_num, 0x43);
  43. GET_BYTES(data, fbr->vol_name, 11, 0x47);
  44. GET_BYTES(data, fbr->fat_name, 8, 0x52);
  45. }
  46. else
  47. {
  48. GET_BYTE(data, fbr->drv_num, 0x24);
  49. GET_BYTE(data, fbr->ext_sig, 0x26);
  50. GET_DWORD(data, fbr->ser_num, 0x27);
  51. GET_BYTES(data, fbr->vol_name, 11, 0x2B);
  52. GET_BYTES(data, fbr->fat_name, 8, 0x36);
  53. }
  54.  
  55. // Read the end marker
  56. len = 0x02;
  57. err = disk_read(disk, (void*)data, &len, 0x1FE);
  58. if (err != ENOERR)
  59. return err;
  60.  
  61. GET_BYTES(data, fbr->exe_marker, 2, 0);
  62.  
  63. // Zero terminate strings
  64. fbr->oem_name[8] = '\0';
  65. fbr->vol_name[11] = '\0';
  66. fbr->fat_name[8] = '\0';
  67.  
  68. #if TDE
  69. print_boot_record(fbr);
  70. #endif
  71.  
  72. return ENOERR;
  73. }

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. 如何配置和使用Tomcat访问日志

    配置位置在log下的server.xml,(tomcat容器) <Engine defaultHost="localhost" name="Catalina&quo ...

  2. Python+Django+SAE系列教程11-----request/pose/get/表单

    表单request,post,get 首先我们来看看Request对象,在这个对象中包括了一些实用的信息,学过B/S开发的人来说这并不陌生,我们来看看在Django中是怎样实现的: 属性/方法 说明 ...

  3. 【SVN】is out of date

    右击项目(team->update 或者 team->freash/cleanup),再操作,提交就可以了.

  4. Android空指针异常的常见情况

    把我经常遇到的nullpoitException写在这里,以便以后自己查找原因. 1.用findViewById(param )的方法获取一个view对象的时候,有的时候其实应该是获取一个layout ...

  5. CentOS6.5 下在Nginx中添加SSL证书以支持HTTPS协议访问

    参考文献: 1. NginxV1.8.0安装与配置 2. CentOS下在Nginx中添加SSL证书以支持HTTPS协议访问 3. nginx配置ssl证书的方法 4.nginx强制使用https访问 ...

  6. Ural 1086 - Cryptography

    While preparing this problem set the jury has run into the following problem: it was necessary to se ...

  7. 那些年搞不懂的"协变"和"逆变"

    博主之前也不是很清楚协变与逆变,今天在书上看到了有关于协变还是逆变的介绍感觉还是不太懂,后来看了一篇园子里面一位朋友的文章,顿时茅塞顿开.本文里面会有自己的一些见解也会引用博友的一些正文,希望通过本篇 ...

  8. Windows系统命令行net user命令用法

    在Windows渗透测试过程中,最常用的要数net user 命令了,但是非常多的时候我们都是对Linux命令非常熟悉,对Windows命令非常熟悉或者了解用法的少只有少,为了以后工作方便,这里记录一 ...

  9. Android自定义组合控件:UIScrollLayout(支持界面滑动及左右菜单滑动)

    一.前言: 我之前很早的时候,写过一篇<左右滑出菜单>的文章: http://blog.csdn.net/qingye_love/article/details/8776650 用的是对V ...

  10. CMake初步(2)

    转自:<你所不知的OSG>第一章:CMake初步(2) http://bbs.osgchina.org/forum.php?mod=viewthread&tid=1229& ...