Skip to content

Commit 264dbe2

Browse files
author
Jamie Smith
authored
SDBlockDevice: revert HW CS support, add async support (ARMmbed#181)
* SDBlockDevice: revert HW CS support, add async support * Convert one last call * Turn off debug mode, whoops * Run formatter
1 parent 1ed5f1f commit 264dbe2

File tree

2 files changed

+66
-103
lines changed

2 files changed

+66
-103
lines changed

storage/blockdevice/COMPONENT_SD/include/SD/SDBlockDevice.h

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@
5858
*/
5959
class SDBlockDevice : public mbed::BlockDevice {
6060
public:
61-
/** Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map).
61+
/** Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map)
6262
*
6363
* @param mosi SPI master out, slave in pin
6464
* @param miso SPI master in, slave out pin
6565
* @param sclk SPI clock pin
66-
* @param cs SPI chip select pin. This constructor needs a *hardware* chip select pin.
66+
* @param cs SPI chip select pin. Currently, GPIO chip selects are always used.
6767
* @param hz Clock speed of the SPI bus (defaults to 1MHz)
6868
* @param crc_on Enable cyclic redundancy check (defaults to disabled)
6969
*/
@@ -74,48 +74,14 @@ class SDBlockDevice : public mbed::BlockDevice {
7474
uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
7575
bool crc_on = MBED_CONF_SD_CRC_ENABLED);
7676

77-
/** Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map).
78-
* This version creates an SPI object that uses GPIO for its chip select line instead of
79-
* a dedicated hardware CS pin.
80-
*
81-
* @param mosi SPI master out, slave in pin
82-
* @param miso SPI master in, slave out pin
83-
* @param sclk SPI clock pin
84-
* @param cs SPI chip select pin. May be any GPIO pin.
85-
* @param hz Clock speed of the SPI bus (defaults to 1MHz)
86-
* @param crc_on Enable cyclic redundancy check (defaults to disabled)
87-
*/
88-
SDBlockDevice(mbed::use_gpio_ssel_t,
89-
PinName mosi = MBED_CONF_SD_SPI_MOSI,
90-
PinName miso = MBED_CONF_SD_SPI_MISO,
91-
PinName sclk = MBED_CONF_SD_SPI_CLK,
92-
PinName cs = MBED_CONF_SD_SPI_CS,
93-
uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
94-
bool crc_on = MBED_CONF_SD_CRC_ENABLED);
95-
96-
97-
/** Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map).
98-
* This version needs a pinmap containing a hardware chip select pin.
99-
*
100-
* @param spi_pinmap Static SPI pin-map
101-
* @param hz Clock speed of the SPI bus (defaults to 1MHz)
102-
* @param crc_on Enable cyclic redundancy check (defaults to disabled)
103-
*/
104-
SDBlockDevice(const spi_pinmap_t &spi_pinmap,
105-
uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
106-
bool crc_on = MBED_CONF_SD_CRC_ENABLED);
107-
108-
/** Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map).
109-
* This version creates an SPI object that uses GPIO for its chip select line instead of
110-
* a dedicated hardware CS pin.
77+
/** Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map)
11178
*
11279
* @param spi_pinmap Static SPI pin-map
11380
* @param cs Chip select pin (can be any GPIO)
11481
* @param hz Clock speed of the SPI bus (defaults to 1MHz)
11582
* @param crc_on Enable cyclic redundancy check (defaults to disabled)
11683
*/
11784
SDBlockDevice(const spi_pinmap_t &spi_pinmap,
118-
mbed::use_gpio_ssel_t,
11985
PinName cs = MBED_CONF_SD_SPI_CS,
12086
uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
12187
bool crc_on = MBED_CONF_SD_CRC_ENABLED);
@@ -132,6 +98,21 @@ class SDBlockDevice : public mbed::BlockDevice {
13298
*/
13399
virtual int init();
134100

101+
#if DEVICE_SPI_ASYNCH
102+
/**
103+
* @brief Configure the usage of asynchronous %SPI by this class.
104+
*
105+
* By default, async %SPI is not enabled, so this class will simply busy-wait while
106+
* communicating with the card. When async %SPI is enabled, %SPI operations
107+
* will be done in blocking asynchronous mode, so other threads may execute
108+
* in the background while data is going to and from the card.
109+
*
110+
* @param enabled Whether usage of async %SPI is enabled.
111+
* @param dma_usage_hint DMA usage hint to pass to the underlying #SPI instance.
112+
*/
113+
void set_async_spi_mode(bool enabled, DMAUsage dma_usage_hint = DMAUsage::DMA_USAGE_NEVER);
114+
#endif
115+
135116
/** Deinitialize a block device
136117
*
137118
* @return BD_ERROR_OK(0) - success
@@ -330,6 +311,10 @@ class SDBlockDevice : public mbed::BlockDevice {
330311
#if MBED_CONF_SD_CRC_ENABLED
331312
bool _crc_on;
332313
#endif
314+
315+
#if DEVICE_SPI_ASYNCH
316+
bool _async_spi_enabled = false;
317+
#endif
333318
};
334319

335320
#endif /* DEVICE_SPI */

storage/blockdevice/COMPONENT_SD/source/SDBlockDevice.cpp

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -251,43 +251,16 @@ using namespace std::chrono;
251251
// Only HC block size is supported. Making this a static constant reduces code size.
252252
const uint32_t SDBlockDevice::_block_size = BLOCK_SIZE_HC;
253253

254-
SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on)
255-
: _sectors(0), _spi(mosi, miso, sclk, cs), _is_initialized(0),
256254
#if MBED_CONF_SD_CRC_ENABLED
257-
_init_ref_count(0), _crc_on(crc_on)
258-
#else
259-
_init_ref_count(0)
260-
#endif
261-
{
262-
#if !MBED_CONF_SD_CRC_ENABLED
263-
// If this assert fails, this code was compiled without CRC support but you tried to use it.
264-
MBED_ASSERT(!crc_on);
265-
#endif
266-
267-
_card_type = SDCARD_NONE;
268-
269-
// Set default to 100kHz for initialisation and 1MHz for data transfer
270-
static_assert(((MBED_CONF_SD_INIT_FREQUENCY >= 100000) && (MBED_CONF_SD_INIT_FREQUENCY <= 400000)),
271-
"Initialization frequency should be between 100KHz to 400KHz");
272-
_init_sck = MBED_CONF_SD_INIT_FREQUENCY;
273-
_transfer_sck = hz;
274-
275-
_erase_size = BLOCK_SIZE_HC;
276-
}
277-
278-
SDBlockDevice::SDBlockDevice(mbed::use_gpio_ssel_t, PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on)
255+
SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on)
279256
: _sectors(0), _spi(mosi, miso, sclk, cs, use_gpio_ssel), _is_initialized(0),
280-
#if MBED_CONF_SD_CRC_ENABLED
281257
_init_ref_count(0), _crc_on(crc_on)
282258
#else
259+
SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz, bool crc_on)
260+
: _sectors(0), _spi(mosi, miso, sclk, cs, use_gpio_ssel), _is_initialized(0),
283261
_init_ref_count(0)
284262
#endif
285263
{
286-
#if !MBED_CONF_SD_CRC_ENABLED
287-
// If this assert fails, this code was compiled without CRC support but you tried to use it.
288-
MBED_ASSERT(!crc_on);
289-
#endif
290-
291264
_card_type = SDCARD_NONE;
292265

293266
// Set default to 100kHz for initialisation and 1MHz for data transfer
@@ -299,43 +272,16 @@ SDBlockDevice::SDBlockDevice(mbed::use_gpio_ssel_t, PinName mosi, PinName miso,
299272
_erase_size = BLOCK_SIZE_HC;
300273
}
301274

302-
SDBlockDevice::SDBlockDevice(const spi_pinmap_t &spi_pinmap, uint64_t hz, bool crc_on)
303-
: _sectors(0), _spi(spi_pinmap), _is_initialized(0),
304275
#if MBED_CONF_SD_CRC_ENABLED
305-
_init_ref_count(0), _crc_on(crc_on)
306-
#else
307-
_init_ref_count(0)
308-
#endif
309-
{
310-
#if !MBED_CONF_SD_CRC_ENABLED
311-
// If this assert fails, this code was compiled without CRC support but you tried to use it.
312-
MBED_ASSERT(!crc_on);
313-
#endif
314-
315-
_card_type = SDCARD_NONE;
316-
317-
// Set default to 100kHz for initialisation and 1MHz for data transfer
318-
static_assert(((MBED_CONF_SD_INIT_FREQUENCY >= 100000) && (MBED_CONF_SD_INIT_FREQUENCY <= 400000)),
319-
"Initialization frequency should be between 100KHz to 400KHz");
320-
_init_sck = MBED_CONF_SD_INIT_FREQUENCY;
321-
_transfer_sck = hz;
322-
323-
_erase_size = BLOCK_SIZE_HC;
324-
}
325-
326-
SDBlockDevice::SDBlockDevice(const spi_pinmap_t &spi_pinmap, mbed::use_gpio_ssel_t, PinName cs, uint64_t hz, bool crc_on)
276+
SDBlockDevice::SDBlockDevice(const spi_pinmap_t &spi_pinmap, PinName cs, uint64_t hz, bool crc_on)
327277
: _sectors(0), _spi(spi_pinmap, cs), _is_initialized(0),
328-
#if MBED_CONF_SD_CRC_ENABLED
329278
_init_ref_count(0), _crc_on(crc_on)
330279
#else
280+
SDBlockDevice::SDBlockDevice(const spi_pinmap_t &spi_pinmap, PinName cs, uint64_t hz, bool crc_on)
281+
: _sectors(0), _spi(spi_pinmap, cs), _is_initialized(0),
331282
_init_ref_count(0)
332283
#endif
333284
{
334-
#if !MBED_CONF_SD_CRC_ENABLED
335-
// If this assert fails, this code was compiled without CRC support but you tried to use it.
336-
MBED_ASSERT(!crc_on);
337-
#endif
338-
339285
_card_type = SDCARD_NONE;
340286

341287
// Set default to 100kHz for initialisation and 1MHz for data transfer
@@ -499,6 +445,12 @@ int SDBlockDevice::init()
499445
return BD_ERROR_OK;
500446
}
501447

448+
void SDBlockDevice::set_async_spi_mode(bool enabled, DMAUsage dma_usage_hint)
449+
{
450+
_async_spi_enabled = enabled;
451+
_spi.set_dma_usage(dma_usage_hint);
452+
}
453+
502454
int SDBlockDevice::deinit()
503455
{
504456
lock();
@@ -778,8 +730,13 @@ uint8_t SDBlockDevice::_cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg)
778730
}
779731

780732
// send a command
781-
for (int i = 0; i < PACKET_SIZE; i++) {
782-
_spi.write(cmdPacket[i]);
733+
#if DEVICE_SPI_ASYNCH
734+
if (_async_spi_enabled) {
735+
_spi.transfer_and_wait(cmdPacket, PACKET_SIZE, nullptr, 0);
736+
} else
737+
#endif
738+
{
739+
_spi.write(cmdPacket, PACKET_SIZE, nullptr, 0);
783740
}
784741

785742
// The received byte immediataly following CMD12 is a stuff byte,
@@ -966,8 +923,13 @@ int SDBlockDevice::_read_bytes(uint8_t *buffer, uint32_t length)
966923
}
967924

968925
// read data
969-
for (uint32_t i = 0; i < length; i++) {
970-
buffer[i] = _spi.write(SPI_FILL_CHAR);
926+
#if DEVICE_SPI_ASYNCH
927+
if (_async_spi_enabled) {
928+
_spi.transfer_and_wait(nullptr, 0, buffer, length);
929+
} else
930+
#endif
931+
{
932+
_spi.write(nullptr, 0, buffer, length);
971933
}
972934

973935
// Read the CRC16 checksum for the data block
@@ -1004,7 +966,16 @@ int SDBlockDevice::_read(uint8_t *buffer, uint32_t length)
1004966
}
1005967

1006968
// read data
1007-
_spi.write(NULL, 0, (char *)buffer, length);
969+
#if DEVICE_SPI_ASYNCH
970+
if (_async_spi_enabled) {
971+
if (_spi.transfer_and_wait(nullptr, 0, buffer, length) != 0) {
972+
return SD_BLOCK_DEVICE_ERROR_WRITE;
973+
}
974+
} else
975+
#endif
976+
{
977+
_spi.write(NULL, 0, (char *) buffer, length);
978+
}
1008979

1009980
// Read the CRC16 checksum for the data block
1010981
crc = (_spi.write(SPI_FILL_CHAR) << 8);
@@ -1037,7 +1008,14 @@ uint8_t SDBlockDevice::_write(const uint8_t *buffer, uint8_t token, uint32_t len
10371008
_spi.write(token);
10381009

10391010
// write the data
1040-
_spi.write((char *)buffer, length, NULL, 0);
1011+
#if DEVICE_SPI_ASYNCH
1012+
if (_async_spi_enabled) {
1013+
_spi.transfer_and_wait(buffer, length, nullptr, 0);
1014+
} else
1015+
#endif
1016+
{
1017+
_spi.write(buffer, length, nullptr, 0);
1018+
}
10411019

10421020
#if MBED_CONF_SD_CRC_ENABLED
10431021
if (_crc_on) {

0 commit comments

Comments
 (0)