@@ -28,16 +28,28 @@
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
|
||||
// Simulate read/write operation time
|
||||
#define SIM_IO_TIME_MS 0
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
|
||||
#if CFG_TUD_MSC_ASYNC_IO
|
||||
TimerHandle_t sim_io_ops_timer;
|
||||
static int32_t bytes_processed;
|
||||
#define IO_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
typedef struct {
|
||||
uint8_t lun;
|
||||
bool is_read;
|
||||
uint32_t lba;
|
||||
uint32_t offset;
|
||||
void* buffer;
|
||||
uint32_t bufsize;
|
||||
} io_ops_t;
|
||||
|
||||
QueueHandle_t io_queue;
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
StaticTimer_t sim_io_ops_timer_buf;
|
||||
uint8_t io_queue_buf[sizeof(io_ops_t)];
|
||||
StaticQueue_t io_queue_static;
|
||||
StackType_t io_stack[IO_STACK_SIZE];
|
||||
StaticTask_t io_taskdef;
|
||||
#endif
|
||||
static void sim_io_ops_done_cb(TimerHandle_t xTimer);
|
||||
|
||||
static void io_task(void *params);
|
||||
#endif
|
||||
|
||||
void msc_disk_init(void);
|
||||
@@ -133,20 +145,37 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
|
||||
README_CONTENTS
|
||||
};
|
||||
|
||||
#if CFG_TUD_MSC_ASYNC_IO
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
void msc_disk_init() {
|
||||
|
||||
#if configSUPPORT_DYNAMIC_ALLOCATION
|
||||
sim_io_ops_timer = xTimerCreate("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb);
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static);
|
||||
xTaskCreateStatic(io_task, "io", IO_STACK_SIZE, NULL, 2, io_stack, &io_taskdef);
|
||||
#else
|
||||
sim_io_ops_timer = xTimerCreateStatic("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb, &sim_io_ops_timer_buf);
|
||||
io_queue = xQueueCreate(1, sizeof(io_ops_t));
|
||||
xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sim_io_ops_done_cb(TimerHandle_t xTimer) {
|
||||
(void) xTimer;
|
||||
tud_msc_async_io_done(bytes_processed);
|
||||
static void io_task(void *params) {
|
||||
(void) params;
|
||||
io_ops_t io_ops;
|
||||
while (1) {
|
||||
if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) {
|
||||
if (io_ops.is_read) {
|
||||
uint8_t const* addr = msc_disk[io_ops.lba] + io_ops.offset;
|
||||
memcpy(io_ops.buffer, addr, io_ops.bufsize);
|
||||
} else {
|
||||
uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset;
|
||||
memcpy(addr, io_ops.buffer, io_ops.bufsize);
|
||||
}
|
||||
|
||||
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);
|
||||
tud_msc_async_io_done(io_ops.bufsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void msc_disk_init() {}
|
||||
#endif
|
||||
@@ -220,33 +249,31 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo
|
||||
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
(void) lun;
|
||||
int32_t ret = bufsize;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) {
|
||||
ret = -1;
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
// Check for overflow of offset + bufsize
|
||||
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
|
||||
ret = -1;
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
if (ret != -1) {
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
}
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
io_ops_t io_ops = { .is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize };
|
||||
|
||||
#if CFG_TUD_MSC_ASYNC_IO
|
||||
// Simulate background read operation
|
||||
bytes_processed = ret;
|
||||
xTimerStart(sim_io_ops_timer, 0);
|
||||
#elif SIM_IO_TIME_MS > 0
|
||||
// Simulate read operation
|
||||
tusb_time_delay_ms_api(SIM_IO_TIME_MS);
|
||||
// Send IO operation to IO task
|
||||
TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS);
|
||||
|
||||
return TUD_MSC_RET_ASYNC;
|
||||
#else
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);
|
||||
|
||||
return bufsize;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tud_msc_is_writable_cb (uint8_t lun)
|
||||
@@ -264,38 +291,35 @@ bool tud_msc_is_writable_cb (uint8_t lun)
|
||||
// Process data in buffer to disk's storage and return number of written bytes
|
||||
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
(void) lun;
|
||||
int32_t ret = bufsize;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) {
|
||||
ret = -1;
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
// Check for overflow of offset + bufsize
|
||||
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
|
||||
ret = -1;
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
if (ret != -1) {
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
}
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
(void) lun; (void) buffer;
|
||||
return bufsize;
|
||||
#endif
|
||||
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
io_ops_t io_ops = { .is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize };
|
||||
|
||||
// Send IO operation to IO task
|
||||
TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS);
|
||||
|
||||
return TUD_MSC_RET_ASYNC;
|
||||
#else
|
||||
(void) lba; (void) offset; (void) buffer;
|
||||
#endif
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);
|
||||
|
||||
#if CFG_TUD_MSC_ASYNC_IO
|
||||
// Simulate background write operation
|
||||
bytes_processed = ret;
|
||||
xTimerStart(sim_io_ops_timer, 0);
|
||||
#elif SIM_IO_TIME_MS > 0
|
||||
// Simulate write operation
|
||||
tusb_time_delay_ms_api(SIM_IO_TIME_MS);
|
||||
return bufsize;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Callback invoked when received an SCSI command not in built-in list below
|
||||
|
@@ -114,9 +114,11 @@
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_EP_BUFSIZE 512
|
||||
|
||||
// Enable Async IO on MSC
|
||||
#define CFG_TUD_MSC_ASYNC_IO 0
|
||||
// Use async IO in example or not
|
||||
#define CFG_EXAMPLE_MSC_ASYNC_IO 1
|
||||
|
||||
// Simulate read/write operation delay
|
||||
#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Reference in New Issue
Block a user