Skip to content

Commit 1ca1887

Browse files
committed
Add SDIO driver.
Took the work done as part of PR ARMmbed/mbed-os#8634 Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent e4eac1c commit 1ca1887

File tree

2 files changed

+435
-0
lines changed

2 files changed

+435
-0
lines changed

SDIOBlockDevice.cpp

+296
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "SDIOBlockDevice.h"
18+
#include "platform/mbed_debug.h"
19+
#include "target/sdio_device.h"
20+
21+
using namespace mbed;
22+
23+
/*
24+
* defines
25+
*/
26+
27+
#define SD_DBG 0 /*!< 1 - Enable debugging */
28+
#define SD_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */
29+
30+
#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */
31+
#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */
32+
#define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */
33+
#define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */
34+
#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */
35+
#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */
36+
#define SD_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */
37+
#define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */
38+
#define SD_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */
39+
#define SD_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */
40+
#define SD_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */
41+
#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */
42+
#define SD_BLOCK_DEVICE_ERROR_READBLOCKS -5013 /*!< read data blocks from SD failed */
43+
#define SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS -5014 /*!< write data blocks to SD failed */
44+
#define SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS -5015 /*!< erase data blocks to SD failed */
45+
46+
#define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */
47+
48+
// Types
49+
#define SDCARD_NONE 0 /**< No card is present */
50+
#define SDCARD_V1 1 /**< v1.x Standard Capacity */
51+
#define SDCARD_V2 2 /**< v2.x Standard capacity SD card */
52+
#define SDCARD_V2HC 3 /**< v2.x High capacity SD card */
53+
#define CARD_UNKNOWN 4 /**< Unknown or unsupported card */
54+
55+
#ifndef MBED_CONF_SD_TIMEOUT
56+
#define MBED_CONF_SD_TIMEOUT (30 * 1000) /* ms */
57+
#endif
58+
59+
SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect),
60+
_is_initialized(0),
61+
_sectors(0),
62+
_init_ref_count(0)
63+
{
64+
// Only HC block size is supported.
65+
_block_size = BLOCK_SIZE_HC;
66+
_erase_size = BLOCK_SIZE_HC;
67+
}
68+
69+
SDIOBlockDevice::~SDIOBlockDevice()
70+
{
71+
if (_is_initialized) {
72+
deinit();
73+
}
74+
}
75+
76+
int SDIOBlockDevice::init()
77+
{
78+
debug_if(SD_DBG, "init Card...\r\n");
79+
80+
lock();
81+
82+
if (!_is_initialized) {
83+
_init_ref_count = 0;
84+
}
85+
86+
_init_ref_count++;
87+
88+
if (_init_ref_count != 1) {
89+
unlock();
90+
return BD_ERROR_OK;
91+
}
92+
93+
if (isPresent() == false) {
94+
unlock();
95+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
96+
}
97+
98+
int status = SDIO_Init();
99+
if (BD_ERROR_OK != status) {
100+
unlock();
101+
return BD_ERROR_DEVICE_ERROR;
102+
}
103+
104+
_is_initialized = true;
105+
106+
// get sectors count from cardinfo
107+
_sectors = SDIO_GetBlockCount();
108+
if (BLOCK_SIZE_HC != SDIO_GetBlockSize()) {
109+
unlock();
110+
return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE;
111+
}
112+
113+
unlock();
114+
115+
return status;
116+
}
117+
118+
int SDIOBlockDevice::deinit()
119+
{
120+
debug_if(SD_DBG, "deinit Card...\r\n");
121+
lock();
122+
123+
if (!_is_initialized) {
124+
_init_ref_count = 0;
125+
unlock();
126+
return BD_ERROR_OK;
127+
}
128+
129+
_init_ref_count--;
130+
131+
if (_init_ref_count) {
132+
unlock();
133+
return BD_ERROR_OK;
134+
}
135+
136+
int status = SDIO_DeInit();
137+
_is_initialized = false;
138+
139+
_sectors = 0;
140+
141+
unlock();
142+
return status;
143+
}
144+
145+
int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
146+
{
147+
//debug_if(SD_DBG, "read Card...\r\n");
148+
lock();
149+
if (isPresent() == false) {
150+
unlock();
151+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
152+
}
153+
if (!is_valid_read(addr, size)) {
154+
unlock();
155+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
156+
}
157+
158+
if (!_is_initialized)
159+
{
160+
unlock();
161+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
162+
}
163+
164+
uint32_t *buffer = static_cast<uint32_t *>(b);
165+
166+
// ReadBlocks uses byte unit address
167+
// SDHC and SDXC Cards different addressing is handled in ReadBlocks()
168+
bd_addr_t blockCnt = size / _block_size;
169+
addr = addr / _block_size;
170+
171+
// receive the data : one block/ multiple blocks is handled in ReadBlocks()
172+
int status = SDIO_ReadBlocks(buffer, addr, blockCnt);
173+
debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt);
174+
175+
if (status != MSD_OK) {
176+
debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
177+
status = SD_BLOCK_DEVICE_ERROR_READBLOCKS;
178+
}
179+
180+
unlock();
181+
182+
return status;
183+
}
184+
185+
int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
186+
{
187+
//debug_if(SD_DBG, "program Card...\r\n");
188+
lock();
189+
190+
if (isPresent() == false) {
191+
unlock();
192+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
193+
}
194+
if (!is_valid_program(addr, size)) {
195+
unlock();
196+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
197+
}
198+
199+
if (!_is_initialized) {
200+
unlock();
201+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
202+
}
203+
204+
//uint32_t *buffer = static_cast< uint32_t *>(b);
205+
// HAL layer uses uint32_t for addr/size
206+
uint32_t *buffer = (uint32_t *)(b);
207+
208+
// Get block count
209+
bd_size_t blockCnt = size / _block_size;
210+
addr = addr / _block_size;
211+
212+
int status = SDIO_WriteBlocks(buffer, addr, blockCnt);
213+
214+
debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt);
215+
216+
if (status != MSD_OK) {
217+
debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
218+
status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS;
219+
}
220+
221+
unlock();
222+
223+
return status;
224+
}
225+
226+
int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size)
227+
{
228+
debug_if(SD_DBG, "trim Card...\r\n");
229+
lock();
230+
if (isPresent() == false) {
231+
unlock();
232+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
233+
}
234+
if (!_is_valid_trim(addr, size)) {
235+
unlock();
236+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
237+
}
238+
239+
if (!_is_initialized) {
240+
unlock();
241+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
242+
}
243+
244+
bd_size_t blockCnt = size / _block_size;
245+
addr = addr / _block_size;
246+
247+
int status = SDIO_Erase(addr, blockCnt);
248+
if (status != 0) {
249+
debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
250+
status = SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS;
251+
}
252+
253+
unlock();
254+
return status;
255+
}
256+
257+
bd_size_t SDIOBlockDevice::get_read_size() const
258+
{
259+
return _block_size;
260+
}
261+
262+
bd_size_t SDIOBlockDevice::get_program_size() const
263+
{
264+
return _block_size;
265+
}
266+
267+
bd_size_t SDIOBlockDevice::size() const
268+
{
269+
return _block_size * _sectors;
270+
}
271+
272+
void SDIOBlockDevice::debug(bool dbg)
273+
{
274+
}
275+
276+
bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size)
277+
{
278+
return (
279+
addr % _erase_size == 0 &&
280+
size % _erase_size == 0 &&
281+
addr + size <= this->size());
282+
}
283+
284+
bool SDIOBlockDevice::isPresent(void)
285+
{
286+
if (_cardDetect.is_connected())
287+
return (_cardDetect.read() == 0);
288+
else
289+
return true;
290+
}
291+
292+
const char *SDIOBlockDevice::get_type() const
293+
{
294+
return "SDIO";
295+
}
296+

0 commit comments

Comments
 (0)