Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
luozhenger
rt-thread
提交
f582bb5b
R
rt-thread
项目概览
luozhenger
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f582bb5b
编写于
3月 09, 2018
作者:
wuyangyong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[DeviceDrivers][SPI] format spi_msd.c
上级
1b886e78
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
199 addition
and
199 deletion
+199
-199
components/drivers/spi/spi_msd.c
components/drivers/spi/spi_msd.c
+199
-199
未找到文件。
components/drivers/spi/spi_msd.c
浏览文件 @
f582bb5b
...
...
@@ -23,9 +23,9 @@
//#define MSD_TRACE
#ifdef MSD_TRACE
#define MSD_DEBUG(...) rt_kprintf("[MSD] %d ", rt_tick_get()); rt_kprintf(__VA_ARGS__);
#define MSD_DEBUG(...) rt_kprintf("[MSD] %d ", rt_tick_get()); rt_kprintf(__VA_ARGS__);
#else
#define MSD_DEBUG(...)
#define MSD_DEBUG(...)
#endif
/* #ifdef MSD_TRACE */
#define DUMMY 0xFF
...
...
@@ -40,23 +40,23 @@ static struct msd_device _msd_device;
/* function define */
static
rt_bool_t
rt_tick_timeout
(
rt_tick_t
tick_start
,
rt_tick_t
tick_long
);
static
rt_err_t
MSD_take_owner
(
struct
rt_spi_device
*
spi_device
);
static
void
MSD_take_cs
(
struct
rt_spi_device
*
device
);
static
void
MSD_release_cs
(
struct
rt_spi_device
*
device
);
static
rt_err_t
MSD_take_owner
(
struct
rt_spi_device
*
spi_device
);
static
void
MSD_take_cs
(
struct
rt_spi_device
*
device
);
static
void
MSD_release_cs
(
struct
rt_spi_device
*
device
);
static
rt_err_t
_wait_token
(
struct
rt_spi_device
*
device
,
uint8_t
token
);
static
rt_err_t
_wait_ready
(
struct
rt_spi_device
*
device
);
static
rt_size_t
rt_msd_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_sdhc_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_sdhc_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
);
static
rt_err_t
_wait_token
(
struct
rt_spi_device
*
device
,
uint8_t
token
);
static
rt_err_t
_wait_ready
(
struct
rt_spi_device
*
device
);
static
rt_size_t
rt_msd_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_sdhc_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
);
static
rt_size_t
rt_msd_sdhc_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
);
static
rt_err_t
MSD_take_owner
(
struct
rt_spi_device
*
spi_device
)
static
rt_err_t
MSD_take_owner
(
struct
rt_spi_device
*
spi_device
)
{
rt_err_t
result
;
result
=
rt_mutex_take
(
&
(
spi_device
->
bus
->
lock
),
RT_WAITING_FOREVER
);
if
(
result
==
RT_EOK
)
if
(
result
==
RT_EOK
)
{
if
(
spi_device
->
bus
->
owner
!=
spi_device
)
{
...
...
@@ -73,7 +73,7 @@ static rt_err_t MSD_take_owner(struct rt_spi_device* spi_device)
return
result
;
}
static
void
MSD_take_cs
(
struct
rt_spi_device
*
device
)
static
void
MSD_take_cs
(
struct
rt_spi_device
*
device
)
{
struct
rt_spi_message
message
;
...
...
@@ -88,7 +88,7 @@ static void MSD_take_cs(struct rt_spi_device* device)
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
}
static
void
MSD_release_cs
(
struct
rt_spi_device
*
device
)
static
void
MSD_release_cs
(
struct
rt_spi_device
*
device
)
{
struct
rt_spi_message
message
;
...
...
@@ -109,7 +109,7 @@ static rt_bool_t rt_tick_timeout(rt_tick_t tick_start, rt_tick_t tick_long)
rt_tick_t
tick_now
=
rt_tick_get
();
rt_bool_t
result
=
RT_FALSE
;
if
(
tick_end
>=
tick_start
)
if
(
tick_end
>=
tick_start
)
{
if
(
tick_now
>=
tick_end
)
{
...
...
@@ -122,7 +122,7 @@ static rt_bool_t rt_tick_timeout(rt_tick_t tick_start, rt_tick_t tick_long)
}
else
{
if
((
tick_now
<
tick_start
)
&&
(
tick_now
>=
tick_end
)
)
if
((
tick_now
<
tick_start
)
&&
(
tick_now
>=
tick_end
)
)
{
result
=
RT_TRUE
;
}
...
...
@@ -137,7 +137,7 @@ static rt_bool_t rt_tick_timeout(rt_tick_t tick_start, rt_tick_t tick_long)
static
uint8_t
crc7
(
const
uint8_t
*
buf
,
int
len
)
{
unsigned
char
i
,
j
,
crc
,
ch
,
ch2
,
ch3
;
unsigned
char
i
,
j
,
crc
,
ch
,
ch2
,
ch3
;
crc
=
0
;
...
...
@@ -167,12 +167,12 @@ static uint8_t crc7(const uint8_t *buf, int len)
}
static
rt_err_t
_send_cmd
(
struct
rt_spi_device
*
device
,
struct
rt_spi_device
*
device
,
uint8_t
cmd
,
uint32_t
arg
,
uint8_t
crc
,
response_type
type
,
uint8_t
*
response
uint8_t
*
response
)
{
struct
rt_spi_message
message
;
...
...
@@ -187,10 +187,10 @@ static rt_err_t _send_cmd(
cmd_buffer
[
4
]
=
(
uint8_t
)(
arg
>>
8
);
cmd_buffer
[
5
]
=
(
uint8_t
)(
arg
);
if
(
crc
==
0x00
)
if
(
crc
==
0x00
)
{
crc
=
crc7
(
&
cmd_buffer
[
1
],
5
);
crc
=
(
crc
<<
1
)
|
0x01
;
crc
=
(
crc
<<
1
)
|
0x01
;
}
cmd_buffer
[
6
]
=
(
crc
);
...
...
@@ -207,7 +207,7 @@ static rt_err_t _send_cmd(
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
for
(
i
=
CARD_NCR
;
i
<
(
CARD_NCR_MAX
+
1
);
i
++
)
for
(
i
=
CARD_NCR
;
i
<
(
CARD_NCR_MAX
+
1
);
i
++
)
{
uint8_t
send
=
DUMMY
;
...
...
@@ -220,28 +220,28 @@ static rt_err_t _send_cmd(
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
if
(
0
==
(
response
[
0
]
&
0x80
))
if
(
0
==
(
response
[
0
]
&
0x80
))
{
break
;
}
}
/* wait response */
if
((
CARD_NCR_MAX
+
1
)
==
i
)
if
((
CARD_NCR_MAX
+
1
)
==
i
)
{
return
RT_ERROR
;
//fail
}
//recieve other byte
if
(
type
==
response_r1
)
if
(
type
==
response_r1
)
{
return
RT_EOK
;
}
else
if
(
type
==
response_r1b
)
else
if
(
type
==
response_r1b
)
{
rt_tick_t
tick_start
=
rt_tick_get
();
uint8_t
recv
;
while
(
1
)
while
(
1
)
{
/* initial message */
message
.
send_buf
=
RT_NULL
;
...
...
@@ -252,33 +252,33 @@ static rt_err_t _send_cmd(
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
if
(
recv
==
DUMMY
)
if
(
recv
==
DUMMY
)
{
return
RT_EOK
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
2000
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
2000
)))
{
return
RT_ETIMEOUT
;
}
}
}
else
if
(
type
==
response_r2
)
else
if
(
type
==
response_r2
)
{
/* initial message */
message
.
send_buf
=
RT_NULL
;
message
.
recv_buf
=
response
+
1
;
message
.
recv_buf
=
response
+
1
;
message
.
length
=
1
;
message
.
cs_take
=
message
.
cs_release
=
0
;
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
}
else
if
((
type
==
response_r3
)
||
(
type
==
response_r7
))
else
if
((
type
==
response_r3
)
||
(
type
==
response_r7
))
{
/* initial message */
message
.
send_buf
=
RT_NULL
;
message
.
recv_buf
=
response
+
1
;
message
.
recv_buf
=
response
+
1
;
message
.
length
=
4
;
message
.
cs_take
=
message
.
cs_release
=
0
;
...
...
@@ -293,7 +293,7 @@ static rt_err_t _send_cmd(
return
RT_EOK
;
}
static
rt_err_t
_wait_token
(
struct
rt_spi_device
*
device
,
uint8_t
token
)
static
rt_err_t
_wait_token
(
struct
rt_spi_device
*
device
,
uint8_t
token
)
{
struct
rt_spi_message
message
;
rt_tick_t
tick_start
;
...
...
@@ -309,17 +309,17 @@ static rt_err_t _wait_token(struct rt_spi_device* device, uint8_t token)
message
.
length
=
1
;
message
.
cs_take
=
message
.
cs_release
=
0
;
while
(
1
)
while
(
1
)
{
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
if
(
recv
==
token
)
if
(
recv
==
token
)
{
return
RT_EOK
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_WAIT_TOKEN_TIMES
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_WAIT_TOKEN_TIMES
)))
{
MSD_DEBUG
(
"[err] wait data start token timeout!
\r\n
"
);
return
RT_ETIMEOUT
;
...
...
@@ -327,7 +327,7 @@ static rt_err_t _wait_token(struct rt_spi_device* device, uint8_t token)
}
/* wati token */
}
static
rt_err_t
_wait_ready
(
struct
rt_spi_device
*
device
)
static
rt_err_t
_wait_ready
(
struct
rt_spi_device
*
device
)
{
struct
rt_spi_message
message
;
rt_tick_t
tick_start
;
...
...
@@ -342,17 +342,17 @@ static rt_err_t _wait_ready(struct rt_spi_device* device)
message
.
length
=
1
;
message
.
cs_take
=
message
.
cs_release
=
0
;
while
(
1
)
while
(
1
)
{
/* transfer message */
device
->
bus
->
ops
->
xfer
(
device
,
&
message
);
if
(
recv
==
DUMMY
)
if
(
recv
==
DUMMY
)
{
return
RT_EOK
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
1000
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
1000
)))
{
MSD_DEBUG
(
"[err] wait ready timeout!
\r\n
"
);
return
RT_ETIMEOUT
;
...
...
@@ -360,14 +360,14 @@ static rt_err_t _wait_ready(struct rt_spi_device* device)
}
}
static
rt_err_t
_read_block
(
struct
rt_spi_device
*
device
,
void
*
buffer
,
uint32_t
block_size
)
static
rt_err_t
_read_block
(
struct
rt_spi_device
*
device
,
void
*
buffer
,
uint32_t
block_size
)
{
struct
rt_spi_message
message
;
rt_err_t
result
;
/* wati token */
result
=
_wait_token
(
device
,
MSD_TOKEN_READ_START
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
return
result
;
}
...
...
@@ -401,7 +401,7 @@ static rt_err_t _read_block(struct rt_spi_device* device, void * buffer, uint32_
return
RT_EOK
;
}
static
rt_err_t
_write_block
(
struct
rt_spi_device
*
device
,
const
void
*
buffer
,
uint32_t
block_size
,
uint8_t
token
)
static
rt_err_t
_write_block
(
struct
rt_spi_device
*
device
,
const
void
*
buffer
,
uint32_t
block_size
,
uint8_t
token
)
{
struct
rt_spi_message
message
;
uint8_t
send_buffer
[
16
];
...
...
@@ -449,7 +449,7 @@ static rt_err_t _write_block(struct rt_spi_device* device, const void * buffer,
// response = 0x0E & recv_buffer[2];
response
=
MSD_GET_DATA_RESPONSE
(
recv_buffer
[
2
]);
if
(
response
!=
MSD_DATA_OK
)
if
(
response
!=
MSD_DATA_OK
)
{
MSD_DEBUG
(
"[err] write block fail! data response : 0x%02X
\r\n
"
,
response
);
return
RT_ERROR
;
...
...
@@ -463,13 +463,13 @@ static rt_err_t _write_block(struct rt_spi_device* device, const void * buffer,
/* RT-Thread Device Driver Interface */
static
rt_err_t
rt_msd_init
(
rt_device_t
dev
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
uint8_t
response
[
MSD_RESPONSE_MAX_LEN
];
rt_err_t
result
=
RT_EOK
;
rt_tick_t
tick_start
;
uint32_t
OCR
;
if
(
msd
->
spi_device
==
RT_NULL
)
if
(
msd
->
spi_device
==
RT_NULL
)
{
MSD_DEBUG
(
"[err] the SPI SD device has no SPI!
\r\n
"
);
return
RT_EIO
;
...
...
@@ -480,7 +480,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
struct
rt_spi_configuration
cfg
;
cfg
.
data_width
=
8
;
cfg
.
mode
=
RT_SPI_MODE_0
|
RT_SPI_MSB
;
/* SPI Compatible Modes 0 */
cfg
.
max_hz
=
1000
*
400
;
/* 400kbit/s */
cfg
.
max_hz
=
1000
*
400
;
/* 400kbit/s */
rt_spi_configure
(
msd
->
spi_device
,
&
cfg
);
}
/* config spi */
...
...
@@ -518,18 +518,18 @@ static rt_err_t rt_msd_init(rt_device_t dev)
{
tick_start
=
rt_tick_get
();
while
(
1
)
while
(
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
GO_IDLE_STATE
,
0x00
,
0x95
,
response_r1
,
response
);
MSD_release_cs
(
msd
->
spi_device
);
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_IN_IDLE_STATE
))
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_IN_IDLE_STATE
))
{
break
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
{
MSD_DEBUG
(
"[err] SD card goto IDLE mode timeout!
\r\n
"
);
result
=
RT_ETIMEOUT
;
...
...
@@ -550,12 +550,12 @@ static rt_err_t rt_msd_init(rt_device_t dev)
result
=
_send_cmd
(
msd
->
spi_device
,
SEND_IF_COND
,
0x01AA
,
0x87
,
response_r7
,
response
);
MSD_release_cs
(
msd
->
spi_device
);
if
(
result
==
RT_EOK
)
if
(
result
==
RT_EOK
)
{
MSD_DEBUG
(
"[info] CMD8 response : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X
\r\n
"
,
response
[
0
],
response
[
1
],
response
[
2
],
response
[
3
],
response
[
4
]);
if
(
response
[
0
]
&
(
1
<<
2
))
if
(
response
[
0
]
&
(
1
<<
2
))
{
/* illegal command, SD V1.x or MMC card */
MSD_DEBUG
(
"[info] CMD8 is illegal command.
\r\n
"
);
...
...
@@ -570,7 +570,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
msd
->
card_type
=
MSD_CARD_TYPE_SD_V2_X
;
}
if
((
0xAA
==
response
[
4
])
&&
(
0x00
==
response
[
3
]))
if
((
0xAA
==
response
[
4
])
&&
(
0x00
==
response
[
3
]))
{
/* SD2.0 not support current voltage */
MSD_DEBUG
(
"[err] VCA = 0, SD2.0 not surpport current operation voltage range
\r\n
"
);
...
...
@@ -580,7 +580,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
}
else
{
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
200
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
200
)))
{
MSD_DEBUG
(
"[err] CMD8 SEND_IF_COND timeout!
\r\n
"
);
result
=
RT_ETIMEOUT
;
...
...
@@ -588,29 +588,29 @@ static rt_err_t rt_msd_init(rt_device_t dev)
}
}
}
while
(
0xAA
!=
response
[
4
]);
while
(
0xAA
!=
response
[
4
]);
}
/* CMD8 */
/* Ver1.X SD Memory Card or MMC card */
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_V1_X
)
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_V1_X
)
{
rt_bool_t
is_sd_v1_x
=
RT_FALSE
;
rt_tick_t
tick_start
;
/* try SD Ver1.x */
while
(
1
)
while
(
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_OCR
,
0x00
,
0x00
,
response_r3
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] It maybe SD1.x or MMC But it is Not response to CMD58!
\r\n
"
);
goto
_exit
;
}
if
(
0
!=
(
response
[
0
]
&
0xFE
))
if
(
0
!=
(
response
[
0
]
&
0xFE
))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] It look CMD58 as illegal command so it is not SD card!
\r\n
"
);
...
...
@@ -619,12 +619,12 @@ static rt_err_t rt_msd_init(rt_device_t dev)
MSD_release_cs
(
msd
->
spi_device
);
OCR
=
response
[
1
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
MSD_DEBUG
(
"[info] OCR is 0x%08X
\r\n
"
,
OCR
);
if
(
0
==
(
OCR
&
(
0x1
<<
15
)))
if
(
0
==
(
OCR
&
(
0x1
<<
15
)))
{
MSD_DEBUG
((
"[err] SD 1.x But not surpport current voltage
\r\n
"
));
result
=
RT_ERROR
;
...
...
@@ -635,9 +635,9 @@ static rt_err_t rt_msd_init(rt_device_t dev)
tick_start
=
rt_tick_get
();
/* try CMD55 + ACMD41 */
while
(
1
)
while
(
1
)
{
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES_ACMD41
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES_ACMD41
)))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] try CMD55 + ACMD41 timeout! mabey MMC card!
\r\n
"
);
...
...
@@ -648,13 +648,13 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* CMD55 APP_CMD */
result
=
_send_cmd
(
msd
->
spi_device
,
APP_CMD
,
0x00
,
0x00
,
response_r1
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
continue
;
}
if
(
0
!=
(
response
[
0
]
&
0xFE
))
if
(
0
!=
(
response
[
0
]
&
0xFE
))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] Not SD card2 , may be MMC
\r\n
"
);
...
...
@@ -663,20 +663,20 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* ACMD41 SD_SEND_OP_COND */
result
=
_send_cmd
(
msd
->
spi_device
,
SD_SEND_OP_COND
,
0x00
,
0x00
,
response_r1
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
continue
;
}
if
(
0
!=
(
response
[
0
]
&
0xFE
))
if
(
0
!=
(
response
[
0
]
&
0xFE
))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] Not SD card4 , may be MMC
\r\n
"
);
break
;
}
if
(
0
==
(
response
[
0
]
&
0xFF
))
if
(
0
==
(
response
[
0
]
&
0xFF
))
{
MSD_release_cs
(
msd
->
spi_device
);
is_sd_v1_x
=
RT_TRUE
;
...
...
@@ -689,7 +689,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
}
/* try SD Ver1.x */
/* try MMC */
if
(
is_sd_v1_x
!=
RT_TRUE
)
if
(
is_sd_v1_x
!=
RT_TRUE
)
{
uint32_t
i
;
...
...
@@ -707,7 +707,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
message
.
length
=
sizeof
(
send_buffer
);
message
.
cs_take
=
message
.
cs_release
=
0
;
for
(
i
=
0
;
i
<
10
;
i
++
)
for
(
i
=
0
;
i
<
10
;
i
++
)
{
/* transfer message */
msd
->
spi_device
->
bus
->
ops
->
xfer
(
msd
->
spi_device
,
&
message
);
...
...
@@ -716,18 +716,18 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* send CMD0 goto IDLE state */
tick_start
=
rt_tick_get
();
while
(
1
)
while
(
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
GO_IDLE_STATE
,
0x00
,
0x95
,
response_r1
,
response
);
MSD_release_cs
(
msd
->
spi_device
);
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_IN_IDLE_STATE
))
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_IN_IDLE_STATE
))
{
break
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
{
MSD_DEBUG
(
"[err] SD card goto IDLE mode timeout!
\r\n
"
);
result
=
RT_ETIMEOUT
;
...
...
@@ -737,20 +737,20 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* send CMD1 */
tick_start
=
rt_tick_get
();
while
(
1
)
while
(
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
SEND_OP_COND
,
0x00
,
0x00
,
response_r1
,
response
);
MSD_release_cs
(
msd
->
spi_device
);
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_RESPONSE_NO_ERROR
))
if
((
result
==
RT_EOK
)
&&
(
response
[
0
]
==
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[info] It is MMC card!!!
\r\n
"
);
msd
->
card_type
=
MSD_CARD_TYPE_MMC
;
break
;
}
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES
)))
{
MSD_DEBUG
(
"[err] SD card goto IDLE mode timeout!
\r\n
"
);
result
=
RT_ETIMEOUT
;
...
...
@@ -759,19 +759,19 @@ static rt_err_t rt_msd_init(rt_device_t dev)
}
/* send CMD1 */
}
/* try MMC */
}
else
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_V2_X
)
else
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_V2_X
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_OCR
,
0x00
,
0x00
,
response_r3
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] It maybe SD2.0 But it is Not response to CMD58!
\r\n
"
);
goto
_exit
;
}
if
((
response
[
0
]
&
0xFE
)
!=
0
)
if
((
response
[
0
]
&
0xFE
)
!=
0
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] It look CMD58 as illegal command so it is not SD card!
\r\n
"
);
...
...
@@ -782,12 +782,12 @@ static rt_err_t rt_msd_init(rt_device_t dev)
MSD_release_cs
(
msd
->
spi_device
);
OCR
=
response
[
1
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
MSD_DEBUG
(
"[info] OCR is 0x%08X
\r\n
"
,
OCR
);
if
(
0
==
(
OCR
&
(
0x1
<<
15
)))
if
(
0
==
(
OCR
&
(
0x1
<<
15
)))
{
MSD_DEBUG
((
"[err] SD 1.x But not surpport current voltage
\r\n
"
));
result
=
RT_ERROR
;
...
...
@@ -801,7 +801,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
do
{
MSD_take_cs
(
msd
->
spi_device
);
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES_ACMD41
)))
if
(
rt_tick_timeout
(
tick_start
,
rt_tick_from_millisecond
(
CARD_TRY_TIMES_ACMD41
)))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] SD Ver2.x or later try CMD55 + ACMD41 timeout!
\r\n
"
);
...
...
@@ -812,13 +812,13 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* CMD55 APP_CMD */
result
=
_send_cmd
(
msd
->
spi_device
,
APP_CMD
,
0x00
,
0x65
,
response_r1
,
response
);
// if((result != RT_EOK) || (response[0] == 0x01))
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
continue
;
}
if
((
response
[
0
]
&
0xFE
)
!=
0
)
if
((
response
[
0
]
&
0xFE
)
!=
0
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] Not SD ready!
\r\n
"
);
...
...
@@ -828,7 +828,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* ACMD41 SD_SEND_OP_COND */
result
=
_send_cmd
(
msd
->
spi_device
,
SD_SEND_OP_COND
,
0x40000000
,
0x77
,
response_r1
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] ACMD41 fail!
\r\n
"
);
...
...
@@ -836,28 +836,28 @@ static rt_err_t rt_msd_init(rt_device_t dev)
goto
_exit
;
}
if
((
response
[
0
]
&
0xFE
)
!=
0
)
if
((
response
[
0
]
&
0xFE
)
!=
0
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[info] Not SD card4 , response : 0x%02X
\r\n
"
,
response
[
0
]);
// break;
}
}
while
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
);
while
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
);
MSD_release_cs
(
msd
->
spi_device
);
/* try CMD55 + ACMD41 */
/* --Read OCR again */
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_OCR
,
0x00
,
0x00
,
response_r3
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] It maybe SD2.0 But it is Not response to 2nd CMD58!
\r\n
"
);
goto
_exit
;
}
if
((
response
[
0
]
&
0xFE
)
!=
0
)
if
((
response
[
0
]
&
0xFE
)
!=
0
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] It look 2nd CMD58 as illegal command so it is not SD card!
\r\n
"
);
...
...
@@ -867,12 +867,12 @@ static rt_err_t rt_msd_init(rt_device_t dev)
MSD_release_cs
(
msd
->
spi_device
);
OCR
=
response
[
1
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
OCR
=
(
OCR
<<
8
)
+
response
[
2
];
OCR
=
(
OCR
<<
8
)
+
response
[
3
];
OCR
=
(
OCR
<<
8
)
+
response
[
4
];
MSD_DEBUG
(
"[info] OCR 2nd read is 0x%08X
\r\n
"
,
OCR
);
if
((
OCR
&
0x40000000
)
!=
0
)
if
((
OCR
&
0x40000000
)
!=
0
)
{
MSD_DEBUG
(
"[info] It is SD2.0 SDHC Card!!!
\r\n
"
);
msd
->
card_type
=
MSD_CARD_TYPE_SD_SDHC
;
...
...
@@ -890,7 +890,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
}
}
/* init SD card */
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_SDHC
)
if
(
msd
->
card_type
==
MSD_CARD_TYPE_SD_SDHC
)
{
dev
->
read
=
rt_msd_sdhc_read
;
dev
->
write
=
rt_msd_sdhc_write
;
...
...
@@ -911,7 +911,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
result
=
_send_cmd
(
msd
->
spi_device
,
CRC_ON_OFF
,
0x00
,
0x91
,
response_r1
,
response
);
#endif
MSD_release_cs
(
msd
->
spi_device
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD59 CRC_ON_OFF fail! response : 0x%02X
\r\n
"
,
response
[
0
]);
result
=
RT_ERROR
;
...
...
@@ -925,7 +925,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
SET_BLOCKLEN
,
SECTOR_SIZE
,
0x00
,
response_r1
,
response
);
MSD_release_cs
(
msd
->
spi_device
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD16 SET_BLOCKLEN fail! response : 0x%02X
\r\n
"
,
response
[
0
]);
result
=
RT_ERROR
;
...
...
@@ -943,14 +943,14 @@ static rt_err_t rt_msd_init(rt_device_t dev)
// result = _send_cmd(msd->spi_device, SEND_CSD, 0x00, 0xAF, response_r1, response);
result
=
_send_cmd
(
msd
->
spi_device
,
SEND_CSD
,
0x00
,
0x00
,
response_r1
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] CMD9 SEND_CSD timeout!
\r\n
"
);
goto
_exit
;
}
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_release_cs
(
msd
->
spi_device
);
MSD_DEBUG
(
"[err] CMD9 SEND_CSD fail! response : 0x%02X
\r\n
"
,
response
[
0
]);
...
...
@@ -960,7 +960,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
result
=
_read_block
(
msd
->
spi_device
,
CSD_buffer
,
MSD_CSD_LEN
);
MSD_release_cs
(
msd
->
spi_device
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read CSD fail!
\r\n
"
);
goto
_exit
;
...
...
@@ -981,27 +981,27 @@ static rt_err_t rt_msd_init(rt_device_t dev)
CSD_STRUCTURE
=
tmp8
>>
6
;
/* MMC CSD Analyze. */
if
(
msd
->
card_type
==
MSD_CARD_TYPE_MMC
)
if
(
msd
->
card_type
==
MSD_CARD_TYPE_MMC
)
{
uint8_t
C_SIZE_MULT
;
uint8_t
READ_BL_LEN
;
if
(
CSD_STRUCTURE
>
2
)
if
(
CSD_STRUCTURE
>
2
)
{
MSD_DEBUG
(
"[err] bad CSD Version : %d
\r\n
"
,
CSD_STRUCTURE
);
result
=
RT_ERROR
;
goto
_exit
;
}
if
(
CSD_STRUCTURE
==
0
)
if
(
CSD_STRUCTURE
==
0
)
{
MSD_DEBUG
(
"[info] CSD version No. 1.0
\r\n
"
);
}
else
if
(
CSD_STRUCTURE
==
1
)
else
if
(
CSD_STRUCTURE
==
1
)
{
MSD_DEBUG
(
"[info] CSD version No. 1.1
\r\n
"
);
}
else
if
(
CSD_STRUCTURE
==
2
)
else
if
(
CSD_STRUCTURE
==
2
)
{
MSD_DEBUG
(
"[info] CSD version No. 1.2
\r\n
"
);
}
...
...
@@ -1009,65 +1009,65 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* get TRAN_SPEED 8bit [103:96] */
tmp8
=
CSD_buffer
[
3
];
tmp8
&=
0x03
;
/* [2:0] transfer rate unit.*/
if
(
tmp8
==
0
)
if
(
tmp8
==
0
)
{
msd
->
max_clock
=
100
*
1000
;
/* 0=100kbit/s. */
}
else
if
(
tmp8
==
1
)
else
if
(
tmp8
==
1
)
{
msd
->
max_clock
=
1
*
1000
*
1000
;
/* 1=1Mbit/s. */
}
else
if
(
tmp8
==
2
)
else
if
(
tmp8
==
2
)
{
msd
->
max_clock
=
10
*
1000
*
1000
;
/* 2=10Mbit/s. */
}
else
if
(
tmp8
==
3
)
else
if
(
tmp8
==
3
)
{
msd
->
max_clock
=
100
*
1000
*
1000
;
/* 3=100Mbit/s. */
}
if
(
tmp8
==
0
)
if
(
tmp8
==
0
)
{
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dkbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
);
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dkbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
);
}
else
{
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
}
/* get READ_BL_LEN 4bit [83:80] */
tmp8
=
CSD_buffer
[
5
]
&
0x0F
;
/* 0b00001111; */
READ_BL_LEN
=
tmp8
;
/* 4 bit */
READ_BL_LEN
=
tmp8
;
/* 4 bit */
MSD_DEBUG
(
"[info] CSD : READ_BL_LEN : %d %dbyte
\r\n
"
,
READ_BL_LEN
,
(
1
<<
READ_BL_LEN
));
/* get C_SIZE 12bit [73:62] */
tmp16
=
CSD_buffer
[
6
]
&
0x03
;
/* get [73:72] 0b00000011 */
tmp16
=
tmp16
<<
8
;
tmp16
=
tmp16
<<
8
;
tmp16
+=
CSD_buffer
[
7
];
/* get [71:64] */
tmp16
=
tmp16
<<
2
;
tmp16
=
tmp16
<<
2
;
tmp8
=
CSD_buffer
[
8
]
&
0xC0
;
/* get [63:62] 0b11000000 */
tmp8
=
tmp8
>>
6
;
tmp8
=
tmp8
>>
6
;
tmp16
=
tmp16
+
tmp8
;
C_SIZE
=
tmp16
;
//12 bit
C_SIZE
=
tmp16
;
//12 bit
MSD_DEBUG
(
"[info] CSD : C_SIZE : %d
\r\n
"
,
C_SIZE
);
/* get C_SIZE_MULT 3bit [49:47] */
tmp8
=
CSD_buffer
[
9
]
&
0x03
;
//0b00000011;
tmp8
=
tmp8
<<
1
;
tmp8
=
tmp8
+
((
CSD_buffer
[
10
]
&
0x80
/*0b10000000*/
)
>>
7
);
C_SIZE_MULT
=
tmp8
;
// 3 bit
tmp8
=
tmp8
<<
1
;
tmp8
=
tmp8
+
((
CSD_buffer
[
10
]
&
0x80
/*0b10000000*/
)
>>
7
);
C_SIZE_MULT
=
tmp8
;
// 3 bit
MSD_DEBUG
(
"[info] CSD : C_SIZE_MULT : %d
\r\n
"
,
C_SIZE_MULT
);
/* memory capacity = BLOCKNR * BLOCK_LEN */
/* BLOCKNR = (C_SIZE+1) * MULT */
/* MULT = 2^(C_SIZE_MULT+2) */
/* BLOCK_LEN = 2^READ_BL_LEN */
card_capacity
=
(
1
<<
READ_BL_LEN
)
*
((
C_SIZE
+
1
)
*
(
1
<<
(
C_SIZE_MULT
+
2
)));
card_capacity
=
(
1
<<
READ_BL_LEN
)
*
((
C_SIZE
+
1
)
*
(
1
<<
(
C_SIZE_MULT
+
2
)));
msd
->
geometry
.
sector_count
=
card_capacity
/
msd
->
geometry
.
bytes_per_sector
;
MSD_DEBUG
(
"[info] card capacity : %d Mbyte
\r\n
"
,
card_capacity
/
(
1024
*
1024
));
MSD_DEBUG
(
"[info] card capacity : %d Mbyte
\r\n
"
,
card_capacity
/
(
1024
*
1024
));
}
else
/* SD CSD Analyze. */
{
if
(
CSD_STRUCTURE
==
0
)
if
(
CSD_STRUCTURE
==
0
)
{
uint8_t
C_SIZE_MULT
;
uint8_t
READ_BL_LEN
;
...
...
@@ -1076,11 +1076,11 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* get TRAN_SPEED 8bit [103:96] */
tmp8
=
CSD_buffer
[
3
];
if
(
tmp8
==
0x32
)
if
(
tmp8
==
0x32
)
{
msd
->
max_clock
=
1000
*
1000
*
10
;
/* 10Mbit/s. */
}
else
if
(
tmp8
==
0x5A
)
else
if
(
tmp8
==
0x5A
)
{
msd
->
max_clock
=
1000
*
1000
*
50
;
/* 50Mbit/s. */
}
...
...
@@ -1088,60 +1088,60 @@ static rt_err_t rt_msd_init(rt_device_t dev)
{
msd
->
max_clock
=
1000
*
1000
*
1
;
/* 1Mbit/s default. */
}
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
/* get READ_BL_LEN 4bit [83:80] */
tmp8
=
CSD_buffer
[
5
]
&
0x0F
;
/* 0b00001111; */
READ_BL_LEN
=
tmp8
;
/* 4 bit */
READ_BL_LEN
=
tmp8
;
/* 4 bit */
MSD_DEBUG
(
"[info] CSD : READ_BL_LEN : %d %dbyte
\r\n
"
,
READ_BL_LEN
,
(
1
<<
READ_BL_LEN
));
/* get C_SIZE 12bit [73:62] */
tmp16
=
CSD_buffer
[
6
]
&
0x03
;
/* get [73:72] 0b00000011 */
tmp16
=
tmp16
<<
8
;
tmp16
=
tmp16
<<
8
;
tmp16
+=
CSD_buffer
[
7
];
/* get [71:64] */
tmp16
=
tmp16
<<
2
;
tmp16
=
tmp16
<<
2
;
tmp8
=
CSD_buffer
[
8
]
&
0xC0
;
/* get [63:62] 0b11000000 */
tmp8
=
tmp8
>>
6
;
tmp8
=
tmp8
>>
6
;
tmp16
=
tmp16
+
tmp8
;
C_SIZE
=
tmp16
;
//12 bit
C_SIZE
=
tmp16
;
//12 bit
MSD_DEBUG
(
"[info] CSD : C_SIZE : %d
\r\n
"
,
C_SIZE
);
/* get C_SIZE_MULT 3bit [49:47] */
tmp8
=
CSD_buffer
[
9
]
&
0x03
;
//0b00000011;
tmp8
=
tmp8
<<
1
;
tmp8
=
tmp8
+
((
CSD_buffer
[
10
]
&
0x80
/*0b10000000*/
)
>>
7
);
C_SIZE_MULT
=
tmp8
;
// 3 bit
tmp8
=
tmp8
<<
1
;
tmp8
=
tmp8
+
((
CSD_buffer
[
10
]
&
0x80
/*0b10000000*/
)
>>
7
);
C_SIZE_MULT
=
tmp8
;
// 3 bit
MSD_DEBUG
(
"[info] CSD : C_SIZE_MULT : %d
\r\n
"
,
C_SIZE_MULT
);
/* memory capacity = BLOCKNR * BLOCK_LEN */
/* BLOCKNR = (C_SIZE+1) * MULT */
/* MULT = 2^(C_SIZE_MULT+2) */
/* BLOCK_LEN = 2^READ_BL_LEN */
card_capacity
=
(
1
<<
READ_BL_LEN
)
*
((
C_SIZE
+
1
)
*
(
1
<<
(
C_SIZE_MULT
+
2
)));
card_capacity
=
(
1
<<
READ_BL_LEN
)
*
((
C_SIZE
+
1
)
*
(
1
<<
(
C_SIZE_MULT
+
2
)));
msd
->
geometry
.
sector_count
=
card_capacity
/
msd
->
geometry
.
bytes_per_sector
;
MSD_DEBUG
(
"[info] card capacity : %d Mbyte
\r\n
"
,
card_capacity
/
(
1024
*
1024
));
MSD_DEBUG
(
"[info] card capacity : %d Mbyte
\r\n
"
,
card_capacity
/
(
1024
*
1024
));
}
else
if
(
CSD_STRUCTURE
==
1
)
else
if
(
CSD_STRUCTURE
==
1
)
{
MSD_DEBUG
(
"[info] CSD Version 2.0
\r\n
"
);
/* get TRAN_SPEED 8bit [103:96] */
tmp8
=
CSD_buffer
[
3
];
if
(
tmp8
==
0x32
)
if
(
tmp8
==
0x32
)
{
msd
->
max_clock
=
1000
*
1000
*
10
;
/* 10Mbit/s. */
}
else
if
(
tmp8
==
0x5A
)
else
if
(
tmp8
==
0x5A
)
{
msd
->
max_clock
=
1000
*
1000
*
50
;
/* 50Mbit/s. */
}
else
if
(
tmp8
==
0x0B
)
else
if
(
tmp8
==
0x0B
)
{
msd
->
max_clock
=
1000
*
1000
*
100
;
/* 100Mbit/s. */
/* UHS50 Card sets TRAN_SPEED to 0Bh (100Mbit/sec), */
/* for both SDR50 and DDR50 modes. */
}
else
if
(
tmp8
==
0x2B
)
else
if
(
tmp8
==
0x2B
)
{
msd
->
max_clock
=
1000
*
1000
*
200
;
/* 200Mbit/s. */
/* UHS104 Card sets TRAN_SPEED to 2Bh (200Mbit/sec). */
...
...
@@ -1150,13 +1150,13 @@ static rt_err_t rt_msd_init(rt_device_t dev)
{
msd
->
max_clock
=
1000
*
1000
*
1
;
/* 1Mbit/s default. */
}
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
MSD_DEBUG
(
"[info] TRAN_SPEED: 0x%02X, %dMbit/s.
\r\n
"
,
tmp8
,
msd
->
max_clock
/
1000
/
1000
);
/* get C_SIZE 22bit [69:48] */
tmp32
=
CSD_buffer
[
7
]
&
0x3F
;
/* 0b00111111 */
tmp32
=
tmp32
<<
8
;
tmp32
=
tmp32
<<
8
;
tmp32
+=
CSD_buffer
[
8
];
tmp32
=
tmp32
<<
8
;
tmp32
=
tmp32
<<
8
;
tmp32
+=
CSD_buffer
[
9
];
C_SIZE
=
tmp32
;
MSD_DEBUG
(
"[info] CSD : C_SIZE : %d
\r\n
"
,
C_SIZE
);
...
...
@@ -1164,7 +1164,7 @@ static rt_err_t rt_msd_init(rt_device_t dev)
/* memory capacity = (C_SIZE+1) * 512K byte */
card_capacity
=
(
C_SIZE
+
1
)
/
2
;
/* unit : Mbyte */
msd
->
geometry
.
sector_count
=
card_capacity
*
1024
;
/* 1 Mbyte = 512 byte X 2048 */
MSD_DEBUG
(
"[info] card capacity : %d.%d Gbyte
\r\n
"
,
card_capacity
/
1024
,
(
card_capacity
%
1024
)
*
100
/
1024
);
MSD_DEBUG
(
"[info] card capacity : %d.%d Gbyte
\r\n
"
,
card_capacity
/
1024
,
(
card_capacity
%
1024
)
*
100
/
1024
);
}
else
{
...
...
@@ -1205,9 +1205,9 @@ static rt_err_t rt_msd_close(rt_device_t dev)
return
RT_EOK
;
}
static
rt_size_t
rt_msd_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
static
rt_size_t
rt_msd_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
uint8_t
response
[
MSD_RESPONSE_MAX_LEN
];
rt_err_t
result
=
RT_EOK
;
...
...
@@ -1229,12 +1229,12 @@ static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_siz
}
/* config spi */
/* SINGLE_BLOCK? */
if
(
size
==
1
)
if
(
size
==
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_SINGLE_BLOCK
,
pos
*
msd
->
geometry
.
bytes_per_sector
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] read SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
...
...
@@ -1242,32 +1242,32 @@ static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_siz
}
result
=
_read_block
(
msd
->
spi_device
,
buffer
,
msd
->
geometry
.
bytes_per_sector
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
}
}
else
if
(
size
>
1
)
else
if
(
size
>
1
)
{
uint32_t
i
;
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_MULTIPLE_BLOCK
,
pos
*
msd
->
geometry
.
bytes_per_sector
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
goto
_exit
;
}
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
i
=
0
;
i
<
size
;
i
++
)
{
result
=
_read_block
(
msd
->
spi_device
,
(
uint8_t
*
)
buffer
+
msd
->
geometry
.
bytes_per_sector
*
i
,
msd
->
geometry
.
bytes_per_sector
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
i
;
...
...
@@ -1277,7 +1277,7 @@ static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_siz
/* send CMD12 stop transfer */
result
=
_send_cmd
(
msd
->
spi_device
,
STOP_TRANSMISSION
,
0x00
,
0x00
,
response_r1b
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK, send stop token fail!
\r\n
"
);
}
...
...
@@ -1291,9 +1291,9 @@ _exit:
return
size
;
}
static
rt_size_t
rt_msd_sdhc_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
static
rt_size_t
rt_msd_sdhc_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
uint8_t
response
[
MSD_RESPONSE_MAX_LEN
];
rt_err_t
result
=
RT_EOK
;
...
...
@@ -1315,12 +1315,12 @@ static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void* buffer, r
}
/* config spi */
/* SINGLE_BLOCK? */
if
(
size
==
1
)
if
(
size
==
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_SINGLE_BLOCK
,
pos
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] read SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
...
...
@@ -1328,32 +1328,32 @@ static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void* buffer, r
}
result
=
_read_block
(
msd
->
spi_device
,
buffer
,
msd
->
geometry
.
bytes_per_sector
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
}
}
else
if
(
size
>
1
)
else
if
(
size
>
1
)
{
uint32_t
i
;
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
READ_MULTIPLE_BLOCK
,
pos
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
goto
_exit
;
}
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
i
=
0
;
i
<
size
;
i
++
)
{
result
=
_read_block
(
msd
->
spi_device
,
(
uint8_t
*
)
buffer
+
msd
->
geometry
.
bytes_per_sector
*
i
,
msd
->
geometry
.
bytes_per_sector
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
i
;
...
...
@@ -1363,7 +1363,7 @@ static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void* buffer, r
/* send CMD12 stop transfer */
result
=
_send_cmd
(
msd
->
spi_device
,
STOP_TRANSMISSION
,
0x00
,
0x00
,
response_r1b
,
response
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] read READ_MULTIPLE_BLOCK, send stop token fail!
\r\n
"
);
}
...
...
@@ -1377,9 +1377,9 @@ _exit:
return
size
;
}
static
rt_size_t
rt_msd_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
static
rt_size_t
rt_msd_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
uint8_t
response
[
MSD_RESPONSE_MAX_LEN
];
rt_err_t
result
;
...
...
@@ -1402,11 +1402,11 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
}
/* config spi */
/* SINGLE_BLOCK? */
if
(
size
==
1
)
if
(
size
==
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
WRITE_BLOCK
,
pos
*
msd
->
geometry
.
bytes_per_sector
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD WRITE_BLOCK fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1414,13 +1414,13 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
}
result
=
_write_block
(
msd
->
spi_device
,
buffer
,
msd
->
geometry
.
bytes_per_sector
,
MSD_TOKEN_WRITE_SINGLE_START
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] write SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
}
}
else
if
(
size
>
1
)
else
if
(
size
>
1
)
{
struct
rt_spi_message
message
;
uint32_t
i
;
...
...
@@ -1428,11 +1428,11 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
MSD_take_cs
(
msd
->
spi_device
);
#ifdef MSD_USE_PRE_ERASED
if
(
msd
->
card_type
!=
MSD_CARD_TYPE_MMC
)
if
(
msd
->
card_type
!=
MSD_CARD_TYPE_MMC
)
{
/* CMD55 APP_CMD */
result
=
_send_cmd
(
msd
->
spi_device
,
APP_CMD
,
0x00
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD55 APP_CMD fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1441,7 +1441,7 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
/* ACMD23 Pre-erased */
result
=
_send_cmd
(
msd
->
spi_device
,
SET_WR_BLK_ERASE_COUNT
,
size
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] ACMD23 SET_BLOCK_COUNT fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1451,7 +1451,7 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
#endif
result
=
_send_cmd
(
msd
->
spi_device
,
WRITE_MULTIPLE_BLOCK
,
pos
*
msd
->
geometry
.
bytes_per_sector
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD WRITE_MULTIPLE_BLOCK fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1459,13 +1459,13 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
}
/* write all block */
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
i
=
0
;
i
<
size
;
i
++
)
{
result
=
_write_block
(
msd
->
spi_device
,
(
const
uint8_t
*
)
buffer
+
msd
->
geometry
.
bytes_per_sector
*
i
,
msd
->
geometry
.
bytes_per_sector
,
MSD_TOKEN_WRITE_MULTIPLE_START
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] write SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
i
;
...
...
@@ -1492,7 +1492,7 @@ static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer
/* wait ready */
result
=
_wait_ready
(
msd
->
spi_device
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[warning] wait WRITE_MULTIPLE_BLOCK stop token ready timeout!
\r\n
"
);
}
...
...
@@ -1506,9 +1506,9 @@ _exit:
return
size
;
}
static
rt_size_t
rt_msd_sdhc_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
static
rt_size_t
rt_msd_sdhc_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
uint8_t
response
[
MSD_RESPONSE_MAX_LEN
];
rt_err_t
result
;
...
...
@@ -1530,11 +1530,11 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
}
/* config spi */
/* SINGLE_BLOCK? */
if
(
size
==
1
)
if
(
size
==
1
)
{
MSD_take_cs
(
msd
->
spi_device
);
result
=
_send_cmd
(
msd
->
spi_device
,
WRITE_BLOCK
,
pos
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD WRITE_BLOCK fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1542,13 +1542,13 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
}
result
=
_write_block
(
msd
->
spi_device
,
buffer
,
msd
->
geometry
.
bytes_per_sector
,
MSD_TOKEN_WRITE_SINGLE_START
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] write SINGLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
0
;
}
}
else
if
(
size
>
1
)
else
if
(
size
>
1
)
{
struct
rt_spi_message
message
;
uint32_t
i
;
...
...
@@ -1558,7 +1558,7 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
#ifdef MSD_USE_PRE_ERASED
/* CMD55 APP_CMD */
result
=
_send_cmd
(
msd
->
spi_device
,
APP_CMD
,
0x00
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD55 APP_CMD fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1567,7 +1567,7 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
/* ACMD23 Pre-erased */
result
=
_send_cmd
(
msd
->
spi_device
,
SET_WR_BLK_ERASE_COUNT
,
size
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] ACMD23 SET_BLOCK_COUNT fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1576,7 +1576,7 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
#endif
result
=
_send_cmd
(
msd
->
spi_device
,
WRITE_MULTIPLE_BLOCK
,
pos
,
0x00
,
response_r1
,
response
);
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
if
((
result
!=
RT_EOK
)
||
(
response
[
0
]
!=
MSD_RESPONSE_NO_ERROR
))
{
MSD_DEBUG
(
"[err] CMD WRITE_MULTIPLE_BLOCK fail!
\r\n
"
);
size
=
0
;
...
...
@@ -1584,13 +1584,13 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
}
/* write all block */
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
i
=
0
;
i
<
size
;
i
++
)
{
result
=
_write_block
(
msd
->
spi_device
,
(
const
uint8_t
*
)
buffer
+
msd
->
geometry
.
bytes_per_sector
*
i
,
msd
->
geometry
.
bytes_per_sector
,
MSD_TOKEN_WRITE_MULTIPLE_START
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[err] write MULTIPLE_BLOCK #%d fail!
\r\n
"
,
pos
);
size
=
i
;
...
...
@@ -1616,7 +1616,7 @@ static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* b
}
result
=
_wait_ready
(
msd
->
spi_device
);
if
(
result
!=
RT_EOK
)
if
(
result
!=
RT_EOK
)
{
MSD_DEBUG
(
"[warning] wait WRITE_MULTIPLE_BLOCK stop token ready timeout!
\r\n
"
);
}
...
...
@@ -1632,7 +1632,7 @@ _exit:
static
rt_err_t
rt_msd_control
(
rt_device_t
dev
,
int
cmd
,
void
*
args
)
{
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
struct
msd_device
*
msd
=
(
struct
msd_device
*
)
dev
;
RT_ASSERT
(
dev
!=
RT_NULL
);
...
...
@@ -1651,13 +1651,13 @@ static rt_err_t rt_msd_control(rt_device_t dev, int cmd, void *args)
return
RT_EOK
;
}
rt_err_t
msd_init
(
const
char
*
sd_device_name
,
const
char
*
spi_device_name
)
rt_err_t
msd_init
(
const
char
*
sd_device_name
,
const
char
*
spi_device_name
)
{
rt_err_t
result
=
RT_EOK
;
struct
rt_spi_device
*
spi_device
;
struct
rt_spi_device
*
spi_device
;
spi_device
=
(
struct
rt_spi_device
*
)
rt_device_find
(
spi_device_name
);
if
(
spi_device
==
RT_NULL
)
if
(
spi_device
==
RT_NULL
)
{
MSD_DEBUG
(
"spi device %s not found!
\r\n
"
,
spi_device_name
);
return
-
RT_ENOSYS
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录