Skip to content

Commit 7fb810f

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 7fb810f

File tree

2 files changed

+434
-0
lines changed

2 files changed

+434
-0
lines changed

SDIOBlockDevice.cpp

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

0 commit comments

Comments
 (0)