Skip to content

Commit a9deb13

Browse files
committed
initial commit
add SDIOBlockdevice implementation for STM32F4
1 parent e4eac1c commit a9deb13

File tree

11 files changed

+4639
-0
lines changed

11 files changed

+4639
-0
lines changed

SDIOBlockDevice.cpp

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
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 <errno.h>
18+
#include "platform/mbed_debug.h"
19+
#include "platform/mbed_wait_api.h"
20+
#include "SDIOBlockDevice.h"
21+
22+
namespace mbed
23+
{
24+
25+
/*
26+
* defines
27+
*/
28+
29+
#define SD_DBG 0 /*!< 1 - Enable debugging */
30+
#define SD_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */
31+
32+
#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */
33+
#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */
34+
#define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */
35+
#define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */
36+
#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */
37+
#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */
38+
#define SD_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */
39+
#define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */
40+
#define SD_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */
41+
#define SD_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */
42+
#define SD_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */
43+
#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */
44+
#define SD_BLOCK_DEVICE_ERROR_READBLOCKS -5013 /*!< read data blocks from SD failed */
45+
#define SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS -5014 /*!< write data blocks to SD failed */
46+
#define SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS -5015 /*!< erase data blocks to SD failed */
47+
48+
#define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */
49+
50+
// Types
51+
#define SDCARD_NONE 0 /**< No card is present */
52+
#define SDCARD_V1 1 /**< v1.x Standard Capacity */
53+
#define SDCARD_V2 2 /**< v2.x Standard capacity SD card */
54+
#define SDCARD_V2HC 3 /**< v2.x High capacity SD card */
55+
#define CARD_UNKNOWN 4 /**< Unknown or unsupported card */
56+
57+
#ifndef MBED_CONF_SD_TIMEOUT
58+
#define MBED_CONF_SD_TIMEOUT (30 * 1000) /* ms */
59+
#endif
60+
61+
SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect),
62+
_is_initialized(0),
63+
_sectors(0),
64+
_init_ref_count(0)
65+
{
66+
_card_type = SDCARD_NONE;
67+
68+
// Only HC block size is supported.
69+
_block_size = BLOCK_SIZE_HC;
70+
_erase_size = BLOCK_SIZE_HC;
71+
}
72+
73+
SDIOBlockDevice::~SDIOBlockDevice()
74+
{
75+
if (_is_initialized)
76+
{
77+
deinit();
78+
}
79+
}
80+
81+
int SDIOBlockDevice::init()
82+
{
83+
debug_if(SD_DBG, "init Card...\r\n");
84+
85+
lock();
86+
87+
if (!_is_initialized)
88+
{
89+
_init_ref_count = 0;
90+
}
91+
92+
_init_ref_count++;
93+
94+
if (_init_ref_count != 1)
95+
{
96+
unlock();
97+
return BD_ERROR_OK;
98+
}
99+
100+
if (isPresent() == false)
101+
{
102+
unlock();
103+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
104+
}
105+
106+
int status = SD_Init();
107+
if (BD_ERROR_OK != status)
108+
{
109+
unlock();
110+
return BD_ERROR_DEVICE_ERROR;
111+
}
112+
113+
SD_GetCardInfo(&_cardInfo);
114+
_is_initialized = true;
115+
debug_if(SD_DBG, "SD initialized: type: %d version: %d class: %d\n",
116+
_cardInfo.CardType, _cardInfo.CardVersion, _cardInfo.Class);
117+
debug_if(SD_DBG, "SD size: %d MB\n",
118+
_cardInfo.LogBlockNbr / 2 / 1024);
119+
120+
// get sectors count from cardinfo
121+
_sectors = _cardInfo.LogBlockNbr;
122+
if (BLOCK_SIZE_HC != _cardInfo.BlockSize)
123+
{
124+
unlock();
125+
return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE;
126+
}
127+
128+
unlock();
129+
return status;
130+
}
131+
132+
int SDIOBlockDevice::deinit()
133+
{
134+
debug_if(SD_DBG, "deinit Card...\r\n");
135+
lock();
136+
137+
if (!_is_initialized)
138+
{
139+
_init_ref_count = 0;
140+
unlock();
141+
return BD_ERROR_OK;
142+
}
143+
144+
_init_ref_count--;
145+
146+
if (_init_ref_count)
147+
{
148+
unlock();
149+
return BD_ERROR_OK;
150+
}
151+
152+
int status = SD_DeInit();
153+
_is_initialized = false;
154+
155+
_sectors = 0;
156+
157+
unlock();
158+
return status;
159+
}
160+
161+
int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
162+
{
163+
//debug_if(SD_DBG, "read Card...\r\n");
164+
lock();
165+
if (isPresent() == false)
166+
{
167+
unlock();
168+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
169+
}
170+
if (!is_valid_read(addr, size))
171+
{
172+
unlock();
173+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
174+
}
175+
176+
if (!_is_initialized)
177+
{
178+
unlock();
179+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
180+
}
181+
182+
uint32_t *buffer = static_cast<uint32_t *>(b);
183+
184+
// ReadBlocks uses byte unit address
185+
// SDHC and SDXC Cards different addressing is handled in ReadBlocks()
186+
bd_addr_t blockCnt = size / _block_size;
187+
addr = addr / _block_size;
188+
189+
// make sure card is ready
190+
while (SD_GetCardState() != SD_TRANSFER_OK)
191+
{
192+
// wait until SD ready
193+
wait_ms(1);
194+
}
195+
196+
// receive the data : one block/ multiple blocks is handled in ReadBlocks()
197+
int status = SD_ReadBlocks_DMA(buffer, addr, blockCnt);
198+
debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt);
199+
200+
if (status == MSD_OK)
201+
{
202+
// wait until DMA finished
203+
while (SD_DMA_ReadPending() != SD_TRANSFER_OK)
204+
{
205+
uint32_t tickstart = HAL_GetTick();
206+
if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT)
207+
{
208+
unlock();
209+
return SD_BLOCK_DEVICE_ERROR_READBLOCKS;
210+
}
211+
}
212+
// make sure card is ready
213+
while (SD_GetCardState() != SD_TRANSFER_OK)
214+
{
215+
// wait until SD ready
216+
wait_ms(10);
217+
}
218+
}
219+
else
220+
{
221+
debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
222+
debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode);
223+
status = SD_BLOCK_DEVICE_ERROR_READBLOCKS;
224+
}
225+
226+
unlock();
227+
return status;
228+
}
229+
230+
int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
231+
{
232+
//debug_if(SD_DBG, "program Card...\r\n");
233+
lock();
234+
235+
if (isPresent() == false)
236+
{
237+
unlock();
238+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
239+
}
240+
if (!is_valid_program(addr, size))
241+
{
242+
unlock();
243+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
244+
}
245+
246+
if (!_is_initialized)
247+
{
248+
unlock();
249+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
250+
}
251+
252+
//uint32_t *buffer = static_cast< uint32_t *>(b);
253+
// HAL layer uses uint32_t for addr/size
254+
uint32_t *buffer = (uint32_t *)(b);
255+
256+
// Get block count
257+
bd_size_t blockCnt = size / _block_size;
258+
addr = addr / _block_size;
259+
260+
// make sure card is ready
261+
while (SD_GetCardState() != SD_TRANSFER_OK)
262+
{
263+
// wait until SD ready
264+
wait_ms(1);
265+
}
266+
267+
int status = SD_WriteBlocks_DMA(buffer, addr, blockCnt);
268+
debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt);
269+
270+
if (status == MSD_OK)
271+
{
272+
// wait until DMA finished
273+
while (SD_DMA_WritePending() != SD_TRANSFER_OK)
274+
{
275+
uint32_t tickstart = HAL_GetTick();
276+
if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT)
277+
{
278+
unlock();
279+
status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS;
280+
}
281+
}
282+
// make sure card is ready
283+
while (SD_GetCardState() != SD_TRANSFER_OK)
284+
{
285+
// wait until SD ready
286+
wait_ms(1);
287+
}
288+
}
289+
else
290+
{
291+
debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
292+
debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode);
293+
status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS;
294+
}
295+
296+
unlock();
297+
return status;
298+
}
299+
300+
int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size)
301+
{
302+
debug_if(SD_DBG, "trim Card...\r\n");
303+
lock();
304+
if (isPresent() == false)
305+
{
306+
unlock();
307+
return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
308+
}
309+
if (!_is_valid_trim(addr, size))
310+
{
311+
unlock();
312+
return SD_BLOCK_DEVICE_ERROR_PARAMETER;
313+
}
314+
315+
if (!_is_initialized)
316+
{
317+
unlock();
318+
return SD_BLOCK_DEVICE_ERROR_NO_INIT;
319+
}
320+
321+
bd_size_t blockCnt = size / _block_size;
322+
addr = addr / _block_size;
323+
324+
int status = SD_Erase(addr, blockCnt);
325+
if (status != 0)
326+
{
327+
debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt);
328+
status = SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS;
329+
}
330+
else
331+
{
332+
while (SD_GetCardState() != SD_TRANSFER_OK)
333+
{
334+
// wait until SD ready
335+
wait_ms(10);
336+
}
337+
}
338+
339+
unlock();
340+
return status;
341+
}
342+
343+
bd_size_t SDIOBlockDevice::get_read_size() const
344+
{
345+
return _block_size;
346+
}
347+
348+
bd_size_t SDIOBlockDevice::get_program_size() const
349+
{
350+
return _block_size;
351+
}
352+
353+
bd_size_t SDIOBlockDevice::size() const
354+
{
355+
return _block_size * _sectors;
356+
}
357+
358+
void SDIOBlockDevice::debug(bool dbg)
359+
{
360+
}
361+
362+
bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size)
363+
{
364+
return (
365+
addr % _erase_size == 0 &&
366+
size % _erase_size == 0 &&
367+
addr + size <= this->size());
368+
}
369+
370+
bool SDIOBlockDevice::isPresent(void)
371+
{
372+
if (_cardDetect.is_connected())
373+
return (_cardDetect.read() == 0);
374+
else
375+
return true;
376+
}
377+
378+
} // namespace mbed

0 commit comments

Comments
 (0)