Skip to content

MSC Device: Add asynchronous IO support #2967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
11 changes: 9 additions & 2 deletions examples/device/cdc_msc/src/msc_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
}

// Check for overflow of offset + bufsize
if ( offset + bufsize > DISK_BLOCK_SIZE ) {
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
return -1;
}

Expand Down Expand Up @@ -223,7 +223,14 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
(void) lun;

// out of ramdisk
if ( lba >= DISK_BLOCK_NUM ) return -1;
if ( lba >= DISK_BLOCK_NUM ) {
return -1;
}

// Check for overflow of offset + bufsize
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
return -1;
}

#ifndef CFG_EXAMPLE_MSC_READONLY
uint8_t* addr = msc_disk[lba] + offset;
Expand Down
3 changes: 2 additions & 1 deletion examples/device/cdc_msc_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
static void usb_device_task(void *param);
void led_blinking_task(void* param);
void cdc_task(void *params);

extern void msc_disk_init(void);
//--------------------------------------------------------------------+
// Main
//--------------------------------------------------------------------+
Expand Down Expand Up @@ -123,6 +123,7 @@ static void usb_device_task(void *param) {
board_init_after_tusb();
}

msc_disk_init();
// RTOS forever loop
while (1) {
// put this thread to waiting state until there is new events
Expand Down
113 changes: 101 additions & 12 deletions examples/device/cdc_msc_freertos/src/msc_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@

#if CFG_TUD_MSC

#if CFG_EXAMPLE_MSC_ASYNC_IO

#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
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 io_task(void *params);
#endif

void msc_disk_init(void);

// whether host does safe-eject
static bool ejected = false;

Expand Down Expand Up @@ -119,6 +145,43 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
README_CONTENTS
};

#if CFG_EXAMPLE_MSC_ASYNC_IO
void msc_disk_init() {

#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
io_queue = xQueueCreate(1, sizeof(io_ops_t));
xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL);
#endif
}

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 {
#ifndef CFG_EXAMPLE_MSC_READONLY
uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset;
memcpy(addr, io_ops.buffer, io_ops.bufsize);
#endif
}

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

// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
Expand Down Expand Up @@ -191,18 +254,28 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff

// out of ramdisk
if ( lba >= DISK_BLOCK_NUM ) {
return -1;
return TUD_MSC_RET_ERROR;
}

// Check for overflow of offset + bufsize
if ( offset + bufsize > DISK_BLOCK_SIZE ) {
return -1;
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
return TUD_MSC_RET_ERROR;
}

#if CFG_EXAMPLE_MSC_ASYNC_IO
io_ops_t io_ops = { .is_read = true, .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
uint8_t const* addr = msc_disk[lba] + offset;
memcpy(buffer, addr, bufsize);
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);

return (int32_t) bufsize;
return bufsize;
#endif
}

bool tud_msc_is_writable_cb (uint8_t lun)
Expand All @@ -220,19 +293,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;

// out of ramdisk
if ( lba >= DISK_BLOCK_NUM ) return -1;
if ( lba >= DISK_BLOCK_NUM ) {
return TUD_MSC_RET_ERROR;
}

#ifndef CFG_EXAMPLE_MSC_READONLY
// Check for overflow of offset + bufsize
if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) {
return TUD_MSC_RET_ERROR;
}

#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
uint8_t* addr = msc_disk[lba] + offset;
memcpy(addr, buffer, bufsize);
#else
(void) lba; (void) offset; (void) buffer;
#endif
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);

return (int32_t) bufsize;
return bufsize;
#endif
}

// Callback invoked when received an SCSI command not in built-in list below
Expand Down
6 changes: 6 additions & 0 deletions examples/device/cdc_msc_freertos/src/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512

// 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
}
#endif
Expand Down
Loading
Loading