Skip to content

Commit 5fefcbf

Browse files
committed
Make mass storage reliable
1 parent e347fd3 commit 5fefcbf

File tree

2 files changed

+154
-36
lines changed

2 files changed

+154
-36
lines changed

libraries/USBMSD/Singleton.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,79 @@
55

66
using namespace arduino;
77

8+
/*
9+
struct disk_info {
10+
mbed::bd_addr_t addr;
11+
mbed::bd_size_t size;
12+
uint8_t data[4096];
13+
bool erase;
14+
};
15+
16+
static rtos::Thread _t(osPriorityHigh, 32 * 1024, NULL, "msd");
17+
static rtos::Mail<struct disk_info, 16> mail_box;
18+
19+
class FlashIAPBlockDeviceMutexFriendly: public FlashIAPBlockDevice {
20+
21+
public:
22+
FlashIAPBlockDeviceMutexFriendly(uint32_t address, uint32_t size) : FlashIAPBlockDevice(address, size)
23+
{
24+
_base = address;
25+
}
26+
27+
void begin() {
28+
_t.start(mbed::callback(this, &FlashIAPBlockDeviceMutexFriendly::deferred_action));
29+
}
30+
31+
int read(void *buffer, mbed::bd_addr_t virtual_address, mbed::bd_size_t size) {
32+
memcpy(buffer, (void*)(virtual_address + _base), size);
33+
return 0;
34+
}
35+
36+
int erase(mbed::bd_addr_t virtual_address, mbed::bd_size_t size) {
37+
struct disk_info* info = mail_box.alloc();
38+
if (info == NULL) {
39+
return -1;
40+
}
41+
info->addr = virtual_address;
42+
info->size = size;
43+
info->erase = true;
44+
mail_box.put(info);
45+
}
46+
47+
int program(const void *buffer, mbed::bd_addr_t virtual_address, mbed::bd_size_t size) {
48+
struct disk_info* info = mail_box.alloc();
49+
if (info == NULL) {
50+
return -1;
51+
}
52+
info->addr = virtual_address;
53+
info->size = size;
54+
info->erase = false;
55+
memcpy(info->data, buffer, get_erase_size());
56+
mail_box.put(info);
57+
}
58+
59+
void deferred_action() {
60+
while (true) {
61+
osEvent evt = mail_box.get();
62+
if (evt.status == osEventMail) {
63+
struct disk_info *info = (struct disk_info*)evt.value.p;
64+
65+
if (info->erase == true) {
66+
FlashIAPBlockDevice::erase(info->addr, info->size);
67+
} else {
68+
FlashIAPBlockDevice::program(info->data, info->addr, info->size);
69+
}
70+
mail_box.free(info);
71+
}
72+
}
73+
}
74+
75+
private:
76+
uint32_t _base;
77+
};
78+
*/
79+
80+
//static FlashIAPBlockDeviceMutexFriendly bd(0x80000, 0x80000);
881
static FlashIAPBlockDevice bd(0x80000, 0x80000);
982

1083
void USBMSD::begin()

libraries/USBMSD/USBMSD.cpp

+81-36
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,36 @@ USBMSD::USBMSD(USBPhy *phy, mbed::BlockDevice *bd, uint16_t vendor_id, uint16_t
8181
PluggableUSBD().plug(this);
8282
}
8383

84-
static rtos::Thread _t(osPriorityRealtime, 64 * 1024);
85-
static events::EventQueue _queue(64*sizeof(int));
84+
static rtos::Thread _t(osPriorityHigh, 32 * 1024, NULL, "msd");
85+
86+
struct disk_info {
87+
uint64_t block;
88+
uint8_t count;
89+
mbed::BlockDevice *_bd;
90+
uint8_t data[4096];
91+
};
92+
93+
static rtos::Mail<struct disk_info, 16> mail_box;
94+
95+
static int _writes_i = 0;
96+
97+
static void write_chunk() {
98+
while (true) {
99+
osEvent evt = mail_box.get();
100+
if (evt.status == osEventMail) {
101+
struct disk_info *info = (struct disk_info*)evt.value.p;
102+
mbed::bd_addr_t addr = info->block * info->_bd->get_erase_size();
103+
mbed::bd_size_t size = info->count * info->_bd->get_erase_size();
104+
105+
int ret = info->_bd->erase(addr, size);
106+
if (ret != 0) {
107+
return;
108+
}
109+
ret = info->_bd->program(info->data, addr, size);
110+
mail_box.free(info);
111+
}
112+
}
113+
}
86114

87115
void USBMSD::init(EndpointResolver& resolver)
88116
{
@@ -103,7 +131,7 @@ void USBMSD::init(EndpointResolver& resolver)
103131
_page = NULL;
104132
connect();
105133

106-
_t.start(callback(&_queue, &events::EventQueue::dispatch_forever));
134+
_t.start(write_chunk);
107135
}
108136

109137
USBMSD::~USBMSD()
@@ -115,21 +143,21 @@ USBMSD::~USBMSD()
115143

116144
bool USBMSD::connect()
117145
{
118-
_mutex_init.lock();
119-
_mutex.lock();
146+
//_mutex_init.lock();
147+
//_mutex.lock();
120148

121149
// already initialized
122150
if (_initialized) {
123-
_mutex.unlock();
124-
_mutex_init.unlock();
151+
//_mutex.unlock();
152+
//_mutex_init.unlock();
125153
return false;
126154
}
127155

128156
//disk initialization
129157
if (disk_status() & NO_INIT) {
130158
if (disk_initialize()) {
131-
_mutex.unlock();
132-
_mutex_init.unlock();
159+
//_mutex.unlock();
160+
//_mutex_init.unlock();
133161
return false;
134162
}
135163
}
@@ -146,30 +174,30 @@ bool USBMSD::connect()
146174
free(_page);
147175
_page = (uint8_t *)malloc(_block_size * sizeof(uint8_t));
148176
if (_page == NULL) {
149-
_mutex.unlock();
150-
_mutex_init.unlock();
177+
//_mutex.unlock();
178+
//_mutex_init.unlock();
151179
return false;
152180
}
153181
}
154182
} else {
155-
_mutex.unlock();
156-
_mutex_init.unlock();
183+
//_mutex.unlock();
184+
//_mutex_init.unlock();
157185
return false;
158186
}
159187

160188
//connect the device
161189
//USBDevice::connect();
162190
_initialized = true;
163191
_media_removed = false;
164-
_mutex.unlock();
165-
_mutex_init.unlock();
192+
//_mutex.unlock();
193+
//_mutex_init.unlock();
166194
return true;
167195
}
168196

169197
void USBMSD::disconnect()
170198
{
171-
_mutex_init.lock();
172-
_mutex.lock();
199+
//_mutex_init.lock();
200+
//_mutex.lock();
173201

174202
//USBDevice::disconnect();
175203
_initialized = false;
@@ -178,13 +206,12 @@ void USBMSD::disconnect()
178206
free(_page);
179207
_page = NULL;
180208

181-
_mutex.unlock();
182-
_mutex_init.unlock();
209+
//_mutex.unlock();
210+
//_mutex_init.unlock();
183211
}
184212

185213
void USBMSD::process()
186214
{
187-
_queue.dispatch();
188215
}
189216

190217
void USBMSD::attach(mbed::Callback<void()> cb)
@@ -198,13 +225,30 @@ bool USBMSD::media_removed()
198225

199226
int USBMSD::disk_read(uint8_t *data, uint64_t block, uint8_t count)
200227
{
201-
mbed::bd_addr_t addr = block * _bd->get_erase_size();
228+
// this operation must be executed in another thread
229+
mbed::bd_addr_t addr = block * _bd->get_erase_size();
202230
mbed::bd_size_t size = count * _bd->get_erase_size();
231+
/*
203232
return _bd->read(data, addr, size);
233+
*/
234+
memcpy(data, (void*)(addr + 0x80000), size);
235+
return 0;
204236
}
205237

206238
int USBMSD::disk_write(const uint8_t *data, uint64_t block, uint8_t count)
207239
{
240+
// this operation must be executed in another thread
241+
struct disk_info* info = mail_box.alloc();
242+
if (info == NULL) {
243+
return -1;
244+
}
245+
memcpy(info->data, data, _bd->get_erase_size());
246+
info->block = block;
247+
info->count = count;
248+
info->_bd = _bd;
249+
mail_box.put(info);
250+
return 0;
251+
/*
208252
mbed::bd_addr_t addr = block * _bd->get_erase_size();
209253
mbed::bd_size_t size = count * _bd->get_erase_size();
210254
int ret = _bd->erase(addr, size);
@@ -213,6 +257,7 @@ int USBMSD::disk_write(const uint8_t *data, uint64_t block, uint8_t count)
213257
}
214258
215259
return _bd->program(data, addr, size);
260+
*/
216261
}
217262

218263
int USBMSD::disk_initialize()
@@ -238,20 +283,20 @@ int USBMSD::disk_status()
238283

239284
void USBMSD::_isr_out()
240285
{
241-
_queue.call(_out_task);
286+
_out();
242287
}
243288

244289
void USBMSD::_isr_in()
245290
{
246-
_queue.call(_in_task);
291+
_in();
247292
}
248293

249294
void USBMSD::callback_state_change(USBDevice::DeviceState new_state)
250295
{
251296
// called in ISR context
252297

253298
if (new_state != USBDevice::Configured) {
254-
_queue.call(_reset_task);
299+
_reset();
255300
}
256301
}
257302

@@ -285,7 +330,7 @@ bool USBMSD::callback_set_configuration(uint8_t configuration)
285330
{
286331
// called in ISR context
287332

288-
_queue.call(_configure_task);
333+
_configure();
289334
return true;
290335
}
291336

@@ -370,38 +415,38 @@ const uint8_t *USBMSD::configuration_desc(uint8_t index)
370415

371416
void USBMSD::_out()
372417
{
373-
_mutex.lock();
418+
//_mutex.lock();
374419

375420
_bulk_out_size = read_finish(_bulk_out);
376421
_out_ready = true;
377422
_process();
378423

379-
_mutex.unlock();
424+
//_mutex.unlock();
380425
}
381426

382427
void USBMSD::_in()
383428
{
384-
_mutex.lock();
429+
//_mutex.lock();
385430

386431
write_finish(_bulk_in);
387432
_in_ready = true;
388433
_process();
389434

390-
_mutex.unlock();
435+
//_mutex.unlock();
391436
}
392437

393438
void USBMSD::_reset()
394439
{
395-
_mutex.lock();
440+
//_mutex.lock();
396441

397442
msd_reset();
398443

399-
_mutex.unlock();
444+
//_mutex.unlock();
400445
}
401446

402447
uint32_t USBMSD::_control(const USBDevice::setup_packet_t *setup, USBDevice::RequestResult *result, uint8_t** data)
403448
{
404-
//_mutex.lock();
449+
////_mutex.lock();
405450

406451
static const uint8_t maxLUN[1] = {0};
407452

@@ -424,13 +469,13 @@ uint32_t USBMSD::_control(const USBDevice::setup_packet_t *setup, USBDevice::Req
424469
}
425470
}
426471

427-
//_mutex.unlock();
472+
////_mutex.unlock();
428473
return size;
429474
}
430475

431476
void USBMSD::_configure()
432477
{
433-
_mutex.lock();
478+
//_mutex.lock();
434479

435480
// Configure endpoints > 0
436481
PluggableUSBD().endpoint_add(_bulk_in, MAX_PACKET, USB_EP_TYPE_BULK, mbed::callback(this, &USBMSD::_isr_in));
@@ -444,12 +489,12 @@ void USBMSD::_configure()
444489
//activate readings
445490
read_start(_bulk_out, _bulk_out_buf, sizeof(_bulk_out_buf));
446491

447-
_mutex.unlock();
492+
//_mutex.unlock();
448493
}
449494

450495
void USBMSD::_process()
451496
{
452-
// Mutex must be locked by caller
497+
// //_mutex must be locked by caller
453498

454499
switch (_stage) {
455500
// the device has to decode the CBW received

0 commit comments

Comments
 (0)