Skip to content

Commit 2f646f9

Browse files
iabdalkaderdpgeorge
authored andcommitted
mimxrt: Add optional MSC support.
Add MSC support using internal flash storage or SD card. Note this is disabled by default, and can be enabled by boards if needed. Signed-off-by: iabdalkader <[email protected]>
1 parent 0a433a0 commit 2f646f9

File tree

6 files changed

+180
-0
lines changed

6 files changed

+180
-0
lines changed

ports/mimxrt/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ SRC_C += \
217217
modmimxrt.c \
218218
mphalport.c \
219219
mpnetworkport.c \
220+
msc_disk.c \
220221
network_lan.c \
221222
pendsv.c \
222223
pin.c \

ports/mimxrt/main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "led.h"
4040
#include "pendsv.h"
4141
#include "modmachine.h"
42+
#include "modmimxrt.h"
4243

4344
#if MICROPY_PY_LWIP
4445
#include "lwip/init.h"
@@ -55,6 +56,7 @@
5556

5657
#include "systick.h"
5758
#include "extmod/modnetwork.h"
59+
#include "extmod/vfs.h"
5860

5961
extern uint8_t _sstack, _estack, _gc_heap_start, _gc_heap_end;
6062

@@ -113,6 +115,19 @@ int main(void) {
113115
// Execute _boot.py to set up the filesystem.
114116
pyexec_frozen_module("_boot.py", false);
115117

118+
#if MICROPY_HW_USB_MSC
119+
// Set the USB medium to flash block device.
120+
mimxrt_msc_medium = &mimxrt_flash_type;
121+
122+
#if MICROPY_PY_MACHINE_SDCARD
123+
const char *path = "/sdcard";
124+
// If SD is mounted, set the USB medium to SD.
125+
if (mp_vfs_lookup_path(path, &path) != MP_VFS_NONE) {
126+
mimxrt_msc_medium = &machine_sdcard_type;
127+
}
128+
#endif
129+
#endif
130+
116131
// Execute user scripts.
117132
int ret = pyexec_file_if_exists("boot.py");
118133

ports/mimxrt/modmimxrt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
static const mp_rom_map_elem_t mimxrt_module_globals_table[] = {
3232
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mimxrt) },
3333
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&mimxrt_flash_type) },
34+
#if MICROPY_HW_USB_MSC
35+
{ MP_ROM_QSTR(MP_QSTR_MSC), MP_ROM_TRUE },
36+
#endif
3437
};
3538
static MP_DEFINE_CONST_DICT(mimxrt_module_globals, mimxrt_module_globals_table);
3639

ports/mimxrt/modmimxrt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@
3030

3131
extern const mp_obj_type_t mimxrt_flash_type;
3232
extern const mp_obj_module_t mp_module_mimxrt;
33+
extern const mp_obj_type_t *mimxrt_msc_medium;
3334

3435
#endif // MICROPY_INCLUDED_MIMXRT_MODMIMXRT_H

ports/mimxrt/mpconfigport.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,15 @@ uint32_t trng_random_u32(void);
151151
#endif
152152

153153
#define MICROPY_HW_ENABLE_USBDEV (1)
154+
// Enable USB-CDC serial port
155+
#ifndef MICROPY_HW_USB_CDC
154156
#define MICROPY_HW_USB_CDC (1)
155157
#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
158+
#endif
159+
// Enable USB Mass Storage with FatFS filesystem.
160+
#ifndef MICROPY_HW_USB_MSC
161+
#define MICROPY_HW_USB_MSC (0)
162+
#endif
156163

157164
// Hooks to add builtins
158165

ports/mimxrt/msc_disk.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2020-2021 Damien P. George
5+
* Copyright (c) 2024-2025 Ibrahim Abdelkader <[email protected]>
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*
25+
*/
26+
#include "tusb.h"
27+
#if CFG_TUD_MSC
28+
#include "flash.h"
29+
#include BOARD_FLASH_OPS_HEADER_H
30+
#include "stdlib.h"
31+
#include "modmimxrt.h"
32+
#if MICROPY_PY_MACHINE_SDCARD
33+
#include "sdcard.h"
34+
35+
#ifndef MICROPY_HW_SDCARD_SDMMC
36+
#define MICROPY_HW_SDCARD_SDMMC (1)
37+
#endif
38+
39+
#define MSC_SDCARD_INDEX (MICROPY_HW_SDCARD_SDMMC - 1)
40+
#endif
41+
42+
// This implementation does Not support Flash sector caching.
43+
// MICROPY_FATFS_MAX_SS must be identical to SECTOR_SIZE_BYTES
44+
#define BLOCK_SIZE (SECTOR_SIZE_BYTES)
45+
#define BLOCK_COUNT (MICROPY_HW_FLASH_STORAGE_BYTES / BLOCK_SIZE)
46+
#define FLASH_BASE_ADDR (MICROPY_HW_FLASH_STORAGE_BASE)
47+
48+
static bool msc_ejected = false;
49+
50+
const mp_obj_type_t *mimxrt_msc_medium = NULL;
51+
52+
// Invoked when received SCSI_CMD_INQUIRY
53+
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
54+
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
55+
memcpy(vendor_id, MICROPY_HW_USB_MSC_INQUIRY_VENDOR_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_VENDOR_STRING), 8));
56+
memcpy(product_id, MICROPY_HW_USB_MSC_INQUIRY_PRODUCT_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_PRODUCT_STRING), 16));
57+
memcpy(product_rev, MICROPY_HW_USB_MSC_INQUIRY_REVISION_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_REVISION_STRING), 4));
58+
}
59+
60+
// Invoked when received Test Unit Ready command.
61+
// return true allowing host to read/write this LUN e.g SD card inserted
62+
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
63+
if (msc_ejected || mimxrt_msc_medium == NULL) {
64+
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
65+
return false;
66+
}
67+
return true;
68+
}
69+
70+
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
71+
// Application update block count and block size
72+
void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) {
73+
if (mimxrt_msc_medium == &mimxrt_flash_type) {
74+
*block_size = BLOCK_SIZE;
75+
*block_count = BLOCK_COUNT;
76+
#if MICROPY_PY_MACHINE_SDCARD
77+
} else if (mimxrt_msc_medium == &machine_sdcard_type) {
78+
mimxrt_sdcard_obj_t *card = &mimxrt_sdcard_objs[MSC_SDCARD_INDEX];
79+
*block_size = card->block_len;
80+
*block_count = card->block_count;
81+
#endif
82+
}
83+
}
84+
85+
// Invoked when received Start Stop Unit command
86+
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
87+
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
88+
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
89+
if (load_eject) {
90+
if (start) {
91+
// load disk storage
92+
msc_ejected = false;
93+
} else {
94+
// unload disk storage
95+
msc_ejected = true;
96+
}
97+
}
98+
return true;
99+
}
100+
101+
// Callback invoked when received READ10 command.
102+
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
103+
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
104+
if (mimxrt_msc_medium == &mimxrt_flash_type) {
105+
flash_read_block(FLASH_BASE_ADDR + lba * BLOCK_SIZE, buffer, bufsize);
106+
#if MICROPY_PY_MACHINE_SDCARD
107+
} else if (mimxrt_msc_medium == &machine_sdcard_type) {
108+
mimxrt_sdcard_obj_t *card = &mimxrt_sdcard_objs[MSC_SDCARD_INDEX];
109+
sdcard_read(card, buffer, lba, bufsize / card->block_len);
110+
#endif
111+
}
112+
return bufsize;
113+
}
114+
115+
// Callback invoked when received WRITE10 command.
116+
// Process data in buffer to disk's storage and return number of written bytes
117+
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
118+
if (mimxrt_msc_medium == &mimxrt_flash_type) {
119+
// Erase count sectors starting at lba
120+
for (int n = 0; n < (bufsize / BLOCK_SIZE); n++) {
121+
flash_erase_sector(FLASH_BASE_ADDR + (lba + n) * BLOCK_SIZE);
122+
}
123+
flash_write_block(FLASH_BASE_ADDR + lba * BLOCK_SIZE, buffer, bufsize);
124+
#if MICROPY_PY_MACHINE_SDCARD
125+
} else if (mimxrt_msc_medium == &machine_sdcard_type) {
126+
mimxrt_sdcard_obj_t *card = &mimxrt_sdcard_objs[MSC_SDCARD_INDEX];
127+
sdcard_write(card, buffer, lba, bufsize / card->block_len);
128+
129+
#endif
130+
}
131+
return bufsize;
132+
}
133+
134+
// Callback invoked when received an SCSI command not in built-in list below
135+
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
136+
// - READ10 and WRITE10 has their own callbacks
137+
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
138+
int32_t resplen = 0;
139+
switch (scsi_cmd[0]) {
140+
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
141+
// Sync the logical unit if needed.
142+
break;
143+
144+
default:
145+
// Set Sense = Invalid Command Operation
146+
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
147+
// negative means error -> tinyusb could stall and/or response with failed status
148+
resplen = -1;
149+
break;
150+
}
151+
return resplen;
152+
}
153+
#endif

0 commit comments

Comments
 (0)