8000 ESP32 S2/S3 USB MSC support? · Issue #8426 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

ESP32 S2/S3 USB MSC support? #8426

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
MichaelDu9226 opened this issue Mar 18, 2022 · 54 comments
Open

ESP32 S2/S3 USB MSC support? #8426

MichaelDu9226 opened this issue Mar 18, 2022 · 54 comments
Labels
enhancement Feature requests, new feature implementations port-esp32

Comments

@MichaelDu9226
Copy link

Are there any plans to increase MSC support here?

CDC+MSC may be great

Thanks

@peterhinch
Copy link
Contributor

MSC mode is a can of worms for this reason.

@stephanelsmith
Copy link
Contributor

Bump, this would be a neat feature. In my application, it'd be preferable to present a controlled list as opposed to automatically using the literal file listing. Maybe like how ble does it, an irq callback when a listing is requested, file read or write. I know very little about USB Msc support, maybe a naive idea on my part, but I think would be cool!

@weilian1977
Copy link

test result shows filesystem corruption maybe happen

@t35tB0t
Copy link
t35tB0t commented Apr 23, 2022

@peterhinch - From experience I'll counter that USB MSC is not at all a can of worms but actually a significant development accelerator. It already works beautifully on STM32's. I'd never cripple my development system by turning it off (during development). Espressif also realized the value of USB and so went to great trouble to trade silicon real estate for USB support. As such, I'm have a serious look at ESP32-S3 as a challenging STM32's in some use-cases.

IMHO, it would be a huge mistake for the micropython community to delay or limit TinyUSB integration. Many will simply drop mpy and move on to circuitpython over something like this. For good reasons, Adafruit appears to be making it a policy to focus on devices which support USB MSC. After doing some significant development on STM32's with USB MSC and having zero issues with flash corruption, I'll strongly favor devices with USB MSC.

Note that ESP32-S3 with USB MSC storage enabled works right now on the circuitpython fork. I begrudgingly flashed cpy onto my hardware and it "just worked". Now looking forward to same on micropython (or micropython on zephyr).

@Red-M
Copy link
Contributor
Red-M commented May 22, 2022

The only time this would be an actual issue is if someone wrote self writing code which edited main.py and/or boot.py or another file that was being actively developed on, but someone that would be doing that would understand what they're doing and know how to safely exit those loops to be able to write to them again.

I feel like this answer is another cop out for not wanting to fix the mess that is the USB stack on micropython.
Expect contributions soon™

8000
@peterhinch
Copy link
Contributor

File corruption is a risk if a program modifies the filesystem in any way. The issue crops up repeatedly in the forum. I found myself answering the question so frequently that I wrote the FAQ referenced above.

@robert-hh
Copy link
Contributor

@Red-M @t35tB0t As Peter said, the problem with MSC origins from a PC and Pyboard assuming to have exclusive access to the filesystem and being able to modify it - writing files, directories and the FAT. In addition to the PC caching and deferring accesses this will a file system corruption sooner or later. Even if you understand the risks and try to avoid it.
Circuitpython avoids that problem by making file system modifications exclusive. Either it's the PC or CircuitPython which can modify the file system, and to switch between the modes you have to unmount and remount the file system. That's safe, but inconvenient. @iabdalkader suggested for his RP2040 implementation of MSC a kind of dynamic access arbitration. As long as the board is mounted to a PC, the local MicroPython is not allowed to write. Once unmounted form the PC, local access is allowed. That avoids the need for manual switching. I did not follow the discussion about whether that was implemented.
Still, the problem of caching by the PC exists. But that is not different to USB drives.
A minor drawback of using MSC is the limitation to a FAT file system for the MicroPython board, which does not support wear leveling.
b.t.w.: TinyUSB is used by some MicroPython ports.

@iabdalkader
Copy link
Contributor
iabdalkader commented May 22, 2022

I did not follow the discussion about whether that was implemented.

It was implemented, but it was never merged. I kept the commit that adds it here: 3589583 if anyone wants to reuse it somewhere feel free to do so.

@t35tB0t
Copy link
t35tB0t commented May 22, 2022
8000

@Red-M Yes, thank you for detailing the factors for others here. However, I really do understand these factors and have been using USB MSC on mounted SDcards with STM32 for 1000's hours with no corruption. The repeated assertion here that using USB MSC will sooner or later corrupt the file system is not accurate.

What will corrupt your flash is power disruption, or bad code, or bad user behavior. But fundamentally, an embedded system that is writing to its system flash is fundamentally less robust regardless if you have USB or not. Note that I'm somewhat centric to SDcard usage because I'm developing applications that are too large for typical MCU internal flash. The latest ESP32's are interesting but have storage performance issues. SD cards have an embedded ARM controller and do their own wear leveling now. If they are not powered down properly and are crashed during a write, their wear leveling will corrupt the entire file system. So, the recommendation is to use Industrial Grade SDcards which have more support for avoiding such corruption.

As far as making USB MSC safe to use, simply consider the following and you'll be fine...

  • User apps should not be randomly writing to "system" flash - this is not "best practice" and user design problem
  • There is no need for access arbitration. Dynamic automatic arbitration (locking) would be cool but isn't essential
  • Host PC write caching should be turned OFF, that's a user dev environment problem not MicroPython's
  • Reboot MicroPython after writing to flash from Host PC. OK to write during normal execution, but need to reboot to use
  • If apps such as FTP are active, don't write to the flash from PC until FTP disconnects. Be a responsible developer
  • Never power off a target while flash is being written do (obviously)
  • Never remove an SDcard while system is running

I hope I'm not just in a minority who is writing larger/more complex MicroPython applications (500K to 1MB source code)? Unfortunately, I have seen no alternative development path that compares to the efficiency and cycle time of using USB MSC. It really works really well. If unavoidable flash corruption exists, with these large projects and heavy USB MSC use, then file system corruption would be a problem for me. It isn't. What is a problem is a lack of any good alternative to USB MSC.

Thonny and rshell are incapable or supporting these projects effectively. If there is anything that compares to the performance and utility of USB MSC, please let us know here.

@peterhinch
Copy link
Contributor

If there is anything that compares to the performance and utility of USB MSC, please let us know here.

mpremote is the official solution.

@t35tB0t
Copy link
t35tB0t commented May 24, 2022

@peterhinch - As far as link behavior goes, the official mpremote is not architecturally different than Thonny or rshell. I've found both Thonny and rshell to be unusable for larger projects. A faster interface is needed: USB MSC is an obvious choice that has proven to be fast and useful without corrupting SDcards. USB over Ethernet might be interesting as an extension but even having FTP in c-code below micropython would be a relief.

I must discount these other tools which are using REPL over a slow default serial connection. The raw USB rate is nearly 100x faster. The default UART speed at 0.1152 Mbits/sec is actually 10x slower than the UART hardware can actually do. Even with a UART speed-up, the USB will still be 10x faster to we should be using it.

Thus, we have no comparison to USB MSC. Two key facts here are that USB MSC has been extremely reliable on STM32s and that CircuitPython has USB MSC working on the ESP32-S3 already.

Are we aware of any intention to implement USB MSC on Micropython for the ESP32-S3?

@Red-M
Copy link
Contributor
Red-M commented May 24, 2022

I plan to but I'd prefer a regular dev to provide such a feature as this codebase seems to have very particular rules for contributions.

I really want to get MSC working and then work on the actual thing I want being USB HID as honestly, MP should really be noticing the features that CP has since its a major driving force to the amount of people around it.

If I can get some traction on #8689 as I have a bunch of expresif ESP-S3 devboards that need this compile time flag to work (I have N8R8 DevKits), I can start to work on some of the shortcomings of USB under MP.

@t35tB0t
Copy link
t35tB0t commented May 24, 2022

@Red-M - I have some N8R8's as well. I fiddled with TinyUSB in MP but only got it partly integrated in an evening. The USB event callback with ESP SDK is a bit convoluted and CP's approach is vastly different than the legacy MP USB so I stopped there. If you do make progress on USB MSC on the N8R8s, I'll gladly do some debugging/testing. Fortunately, I also have a stack of STM32's - apparently the global supply of STM32 ICs has all but vanished.

@Red-M
Copy link
Contributor
Red-M commented May 24, 2022

Realistically I just want to make a keyboard with some custom firmware but this would be way easier with threads on an RTOS because I want low latency on the key loop.

Somehow this is a hard ask as CP has a good USB stack but has decided that threads are "too hard" for most people and thus have removed threads entirely (not disabled). MP on the other hand will let you use such interfaces but the USB stack is a mess and doesn't have a concept of HALs for interfacing with hardware so the same library interfaces have to be maintained between ports instead of a unified interface into the port specific HAL, which makes maintenance a huge strain.

I'm fine to try for USB MSC support but I already have some really dumb tooling that did what I needed enough to test out and play with MP but this constant dodging of features is making people move to CP instead because they have features but not much power in terms of multicore support (where as MP has much better support)

@t35tB0t
Copy link
t35tB0t commented May 25, 2022

@Red-M - Agreed. CP as a dumbed down MP fork was a waste of developer time and my time to try to make something useful with it. Perhaps Zephyr will mature and change the solution space here. Meanwhile, patching in USB MSC (along with other USB modes) to the ESP32-S3 would make these N8R8s pretty nice. It would be a leap forward in usefulness. Of course, some serious work addressing Octal Flash and PSRAM issue(s) is also needed.

We could also try to find some high-speed UART rate combos on PC/target to work around the divider mis-matched bauds. Not as sweet as USB MSC but we might at least give folks more useful interface performance with e.g. Thonny. I've done this before so just need to dig up some notes, re-implement, and then test stability perhaps with a BER pattern.

@M-D-777
Copy link
M-D-777 commented May 25, 2022

Hi, all

Any interest in adding MSC support for ESP32 S3? #8699

I have added this feature by referring to the pull request of @iabdalkader #7402

The MSC feature is configurable with sdkconfig.usb_msc.

MSC with sdcard will be later.

@t35tB0t
Copy link
t35tB0t commented May 26, 2022

@M-D-777 - Nice. Thank you for this. Will try your MSC implementation this weekend then see if I can add SDcard and maybe RAM disk blk dev support as well. But these are just stop-gap measures. Zephyr is moving to fill this hardware interface gap far better than MP or CP ever can. So we're eager to have that kind of full featured platform running MP.

@tsaost
Copy link
tsaost commented Aug 29, 2022

First of all, I am not familiar with the internals of MP at all, so maybe this is a bad idea that has been rejected already.

Why not have two partitions in flash, one that is writable by PC but only readable by MP (so this partition will hold .py code, configuration etc.), and another partition that is only writable by MP (it would be nice, but not strictly necessary for it to be readable by PC) so that it can be used by MP code for logging data, saving states, etc.)

This should cover most of the common usage that people want to use USB MSC for, i.e., be able to save modified Python code quickly to the ESP32, and for MP code to save data without worrying about data corruption. The only issue is how to get the saved data out from the ESP32 to PC, but this can probably done using some kind of file transfer over Wifi.

If this a bad idea, or it is too much trouble to implement, I'd say make USB MSC an optional feature that can be turn on and off. It should be OFF by default, and one should be given a warning that this is an "adult feature" that could cause data corruption if used indiscriminately. Those who consider themselves adult can then turn it on and bear the responsibility for the consequences :-)

Edit: Sorry for making this unnecessary suggestion. Lots of ideas, pros and cons, have already been discussed in rp2: Add MSC support.

@jimmo
Copy link
Member
jimmo commented Aug 29, 2022

Why not have two partitions in flash, one that is writable by PC but only readable by MP (so this partition will hold .py code, configuration etc.), and another partition that is only writable by MP (it would be nice, but not strictly necessary for it to be readable by PC) so that it can be used by MP code for logging data, saving states, etc.)

You can already set up this exact scenario on the stm32 and rp2 ports (and it would work on ESP32 if we had MSC support). It's unfortunate to have to fragment the flash into two parts though (in terms of wasted space).

With a read-only-from-micropython partition, you still have to have a way to know exactly when the filesystem is in a valid state for reading. i.e. if the PC is in the middle of of a file operation (e.g. saving code.py), the device needs to know that all blocks are flushed (at every layer from the host PC to the host disk cache, to the device's flash cache) before being able to read. Obviously it's not nearly as bad as two concurrent writers, but even a concurrent writer and reader isn't safe.

I think CircuitPython has some heuristics to detect completed write operations to make this work (e.g. idle timeout?), i.e. this is how they trigger the "code.py has change, do soft reset" thing. Honestly I think the way CircuitPython implement this is a good compromise in the complexity-vs-ease-of-use tradeoff.

If only MTP was usable on the host PC... and we wouldn't need to worry about this.

I'd say make USB MSC an optional feature that can be turn on and off. It should be OFF by default, and one should be given a warning that this is an "adult feature" that could cause data corruption if used indiscriminately.

Yes, see #7402 (comment)

(Edit: sorry just saw your edit to link to the exact same comment :) )

@dhalbert
Copy link
Contributor
dhalbert commented Aug 29, 2022

I think CircuitPython has some heuristics to detect completed write operations to make this work (e.g. idle timeout?), i.e. this is how they trigger the "code.py has change, do soft reset" thing. Honestly I think the way CircuitPython implement this is a good compromise in the complexity-vs-ease-of-use tradeoff.

CircuitPython waits 0.75 seconds (used to be 0.5 seconds) after the last write before triggering an auto-reload. We still see delayed writes on Linux and Windows. macOS is much better about it. Windows supposedly fixed the worst delayed writes (which were on FAT12 only, probably a legacy of floppy support) many years after we reported the problem, but I haven't checked again recently.

@robert-hh
Copy link
Contributor

@iabdalkader made a PR #8814 for rp2 and I did for the mimxrt port #8820, setting the filesystem to r/o by Micropython as long as the drive is mounted at the PC, and setting it to r/w after it had been unmounted. For my test configuration of mimxrt boards and debian Linux I found, that the Micro had to go through a warm reset to ensure, that all modifications done by the PC are noticed by the Micro. So it it a three state logic. That's not overly comfortable, but seems safe. For the rp2 set-up this did not seem to be necessary, which I'm skeptic about.
There is also a boot mode option to disable MSC at all. And yes, MPT will solve that. I looked around for MTP implementations, but did not find any.

@t35tB0t
Copy link
t35tB0t commented Aug 29, 2022 via email

@dhylands
Copy link
Contributor

I have encountered numerous corruptions when using MSC with STM32, which is what motivated me to write rshell, so while they may be less frequent, they are definitely still there.

With MSC, the host assumes it has exclusive access and it will happily overwrite changes made by the micropython board. This is why the volume needs to be RO when the host has it mounted.

@t35tB0t
Copy link
t35tB0t commented Aug 29, 2022 via email

@tsaost
Copy link
tsaost commented Aug 29, 2022

@jimmo
Thank you for your comments. I agree that even with the two partitions solution, in theory there are still synchronization issues. But frankly most people will not see the problem because developers will need to be "trained" to soft reset MP after uploading new code so that the new code will take effect (CircuitPython's auto reload is neat but I'd rather have manual control). IMHO there can be no foolproof solution to any problem because the world will just produce a better fool :-)

I also agree that there will be wasted space, but the two partitions solution also offer the advantage that the "internal" partition writable by MP can then be set to Littlefs and have better wear leveling. Actually, as you pointed out, the current STM32 port already offered this exact solution, as explained by Hybrid (STM32)

@t35tB0t I agree with your sentiment regarding the usefulness of USB MSC, and I'd like to see it supported by MP whenever the hardware supports it. But wouldn't the slow uploading problem be partially alleviated by breaking a large project into a number of smaller .py modules during development?

@t35tB0t
Copy link
t35tB0t commented Aug 29, 2022 via email

@peterhinch
Copy link
Contributor

@t35tB0t

Add separate data flash or support data partitions if you must log continuously. But NEVER write to your own code space.

That is good advice for professional users and advanced amateurs who can easily add flash chips. Many of the users we support are hobbyists whose first project is a simple data logger - they are unhappy when their only filesystem is corrupted.

@t35tB0t
Copy link
t35tB0t commented Aug 30, 2022 via email

@Red-M
Copy link
Contributor
Red-M commented Aug 30, 2022

Y'all heard of a semaphore?

@Meekdai
Copy link
Meekdai commented Sep 9, 2022

I think ESP32 S2 S3 can completely follow the way of RP2(#7402 ) first, and it is up to the user to decide whether to use MSC or not.

// Enable USB Mass Storage with FatFS filesystem.
#define MICROPY_HW_USB_MSC  (1)

@paulftw
Copy link
paulftw commented Sep 9, 2022

I received a lolin s2 mini yesterday and my mind was blown when I saw how easy it is to update code in CP compared to the painfully slow rshell.

Seriously considering teaching CP instead of MP in my next workshop just for that reason alone.

The choice to withhold this extremely time saving and user friendly feature because it’ll affect some users down the road leads to bad learning experience, cripples adoption, slows down community growth.

if you care about a small subset of users who will write to flash and hit a bug it is logical to care even more about a much larger subset of users who will want to upload custom code to their board.

MSC should be supported, enabled by default or at least mentioned on the first pages of the tutorial.

If the problem is as serious as some argue (while others, seemingly just as experienced, are claiming it’s a non-issue in real life scenarios) I as a user would understand if enabling MSC disables writing to FS from Python.
even a drastic measure of having FS read-only by default would be worth it as long as a one liner to enable writes is provided plus a mention of associated dangers.

@robert-hh
Copy link
Contributor

Uploading custom code to flash is easy, using mpremote or ftp for devices with network support.
If you just have applications that do not write to flash than having MSC support with the flash set to r/o is not an issue. Besides that, there is a common understanding that device which can support MSC should do that. Only it's not yet implemented or merged.

  • For the STM32 port, MSC is implemented, with the board's file system in r/w mode. That cause me a lot of trouble, until I decided to disable MSC.
  • For rp2 there is an implementation, enabled currently for just one board. And there is a PR open with a kind of automatic r/o mode as long as the board's drive is mounted to the PC.
  • For the MIMXRT port, there is a PR open, with a automatic r/o mechanism.

For the other ports, someone has to implement it. I could do that for the SAMD port, once the other previous commits for that port are merged. An implementation for the NRF port should be possible based on the rp2 implementation. ESP32 is more difficult F438 since it uses a different USB stack.

@t35tB0t
Copy link
t35tB0t commented Sep 9, 2022 via email

@victorallume
Copy link
Contributor

I too have had various issues with corruption using MSC on a pyboard, due to simultaneous FS access from the PC and microcontroller. However, it's pretty useful, as long as you're careful. The main way I ensure safety is to drop the microcontroller into a REPL before using MSC. Would it be feasible to only allow MSC access when the micro is in a REPL mode?

@t35tB0t
Copy link
t35tB0t commented Oct 4, 2022 via email

@robert-hh
Copy link
Contributor

@iabdalkader has implemented a lock mechanism for the RP2 board, and I did so in the MSC PR for the mimxrt port. It sets the file system to read-only for the board as long as it is mounter by the host. Similar to what Adafruit does, but kind of automatic. To get R/W access at the board, you just have to eject it at the host. For most users it is useful. If you have a usage pattern which does not use mixed write accesses, then this is not needed.

@t35tB0t
Copy link
t35tB0t commented Oct 11, 2022 via email

@t35tB0t
Copy link
t35tB0t commented Oct 11, 2022 via email

@peterhinch
Copy link
Contributor

I have no desire to enter a debate on this, merely to reiterate an empirical observation from forum support: novice Pyboard users were regularly scribbling over their filesystems. Advice from experienced users was to turn off MSC support in boot.py.

The automatic r/o mechanism described by @robert-hh sounds good.

@t35tB0t
Copy link
t35tB0t commented Oct 12, 2022 via email

@jimmo
Copy link
Member
jimmo commented Oct 13, 2022

@t35tB0t

Yet we shall correct your
empirical observation because it may be misleading folks into thinking
that all experienced users are telling folks to turn MSC off.

Peter is just reporting what he's seen. There's nothing to "correct". I have the same empirical observations, and as an experienced MicroPython user I also provide the same advice -- for most users, using MSC to transfer files to/from the device is not the best option when you weigh up all the competing factors (assumed experience, convenience, risk of corruption, etc).

But one of the key things about MicroPython is that we strive provide building blocks, and users who want to combine them in ways that make sense for them should definitely do so! #7402 (comment) is a good summary from Damien for the same issue on the rp2 port. We're aiming to get to the point that this can all be configured in boot.py however the user likes, and at a per-partition level. (But there is some work to get there!)

For deployment of larger projects such as the sort of thing you're talking about, we're also working on the "mapfs" feature #8381 -- this has the advantage of saving significant amounts of RAM (because the .mpy files run from flash after being copied to the device) as well as making deployment a lot faster... see notes on this at the bottom of this post!

@tsaost USB is operating at 12MHz and SerialCom defaults to 0.115MHz.

This may be true when accessing serial over a USB/UART converter, but in this case the point is moot -- MSC would have been unavailable anyway. When accessing USB serial over a CDC ACM device it does not run at 115200 -- the speed setting when opening an ACM device is just forwarded through to the other end and it is free to do whatever it chooses with this information (e.g. if you were implementing a USB/UART that is the speed you should open your UART at).

Awesome to hear that you're teaching embedded Python and
agreed that the utility of USB MSC is literally a 100x benefit.

When you are teaching MicroPython, from a lot of personal experience I find that although MSC is a huge benefit in terms of simplicity, it is basically guaranteed filesystem corruption for new MicroPython users. And the only really efficient workflow that involves working with MSC is to edit directly from the device, and so filesystem corruption means the student loses their code. CircuitPython has fine tuned their workflow to make this as reliable as possible (and it's one of the key differentiators of CircuitPython and one of the many reasons why I'm glad that CircuitPython exists -- it's a great alternative to MicroPython in the education space).

Another note -- one thing that trips up new users is that when they copy the files, they still need a serial console to do anything useful. So it's neat to be able to "just copy main.py" but anything above the most trivial program you need a serial terminal -- you might as well install mpremote or similar. And it's confusing when you copy the file over MSC, you still need to trigger a soft reset to remount the filesystem to be able to see the new files for importing). (CircuitPython again solve this by having a heuristic to trigger soft reset automatically on write, which works well for them).

For small projects, "mpremote mount" is an amazing workflow that gives you the best of all worlds -- the files live on the PC, they run automatically from the device, and no risk of filesystem corruption.

In any case, my example project has like a hundred py files and related
configuration files.

I tried out a similar scenario on a pyboard v1.1 by creating 50 small files (random sizes between 200 and 1400 bytes).

  • Copying with MSC to FAT: 41.3 seconds.
  • Copying with mpremote to FAT: 90.8 seconds.
  • Copying with mpremote to LittleFS: 64.0 seconds.
  • Copying with mpremote deploy-mapfs: 3.0 seconds. (!!!!)

I think we can possibly optimise mpremote-littlefs a bit here, and in particular a rsync-like partial update would be useful. Additionally, at least half of the mpremote-littlefs copy time is rewriting the same pages over and over again and this could be improved. Given the other benefits of both LittleFS and mpremote, the extra copy time is a worthwhile tradeoff for most users and I will continue to recommend disabling MSC.

As maintainers though, as you can see the the mapfs feature is likely to take a higher priority because it is such a huge win in every way (reduced RAM, > 10x faster copy, etc). The copy is so fast because it does a single erase for the whole region and then it's just streaming writes.

@t35tB0t
Copy link
t35tB0t commented Oct 13, 2022 via email

@TonyWeston
Copy link
TonyWeston commented Oct 25, 2023

Its been a while since this was updated, but to add my 2c.

Regardless of if MSC is a 'Can or worms' or not. The ESP32/S2/S3 has the hardware to support it, so support should be developed. Unless MSC is marked as deprecated across the entire micropython project, we should not be deciding what or what does not go into the specific ESP32 port.

Otherwise the ESP32 will become divergent from the micropython standard - this is the worse option, in my opinion, and will hurt micropython as a whole, with developers now uncertain which boards their code will run on, or not.

A solution to the corruption problem, would simply to lock the filesystem to python writes, if that filesystem is opened on the host PC. If, MSC is never developed (because the ESP32 micropython developers have decided that MSC should not be there) then solutions like this would never come to light.

@robert-hh
Copy link
Contributor

MSC is atm supported for the stm32 port and one rp2040 board variant. So it is not very common across MP ports. There is an PR to support Python coded USB devices. That would be a portable way to have various USB device types and modes. Then users can decide whether the install it to their boards or not.
I had implemented MSC support for the mimxrt port including a locking mechanism that you mentioned. It worked. The PR for it is not online any more. I closed it in favour of the python variant.
Note that the initial ESP32 MCUs cannot support MSC, lacking USB hardware.

@t35tB0t
Copy link
t35tB0t commented Oct 26, 2023

MSC is not the problem with corruption - humans are.

If a system on a chip includes a mainstream hardware feature - it is expected to be supported by firmware. Cutting out mainstream features in order to chase a goal of fully normalizing MicroPython across all platforms is not going to end well. An exaggerated example would be limiting precision to integers because not all hardware has floating point.

The reason a particular piece of silicon invests all the transistors needed to implement hardware USB block is likely because that device has the horsepower to justify such an interface. It follows then that a more powerful development interface is going to be useful if not essential if one expects to use all that horsepower effectively. From experience, I'll assert that its really simple to use MSC safely and effortlessly even without extra locks. What is the "PR for Python-coded USB devices" trying to solve? The MSC Interface needs to be fast and not running in python environment.

Plan A - beg for MicroPython Devs to retain and extend embedded USB support to all relevant hardware modules
Plan B - use Zephyr RTOS and microPython as an app so my hardware isn't gimped
Plan C - lear 10670 n all the low-level USB stuff and code it myself (not likely because I'm busy frying bigger fi$h here)
Plan D - use CircuitPython (just kidding, I tried it and it was worse than awful - they perverted Python beyond tolerance).

After so much time has past on this topic and ESP-S3's still don't have a solid MSC solution, I'm suspecting that only Plan B will yield useful results in the long run.

@Red-M
Copy link
Contributor
Red-M commented Nov 25, 2023

I was going with Plan B anyway/aswell, its probably better that micropython as a whole moves to becoming a zepher app because its easier for board/hardware support.

@jonnor
Copy link
Contributor
jonnor commented Aug 26, 2024

USBDevice support landed in recent MicroPython. And there is an MR for ESP32-S3 at #15108

@jonnor jonnor added the enhancement Feature requests, new feature implementations label Sep 8, 2024
@emard
Copy link
emard commented Apr 30, 2025

So general idea of this issue is that it would be
handy to manage files of esp32s3 like a usb stick
but problem with mounted block devices changes
by both PC and/or esp32s3 or unplugging before
unmount/safe_remove risk of data corruption.

elegant solution of this is PTP, a light file-based
usb network filesystem usually used on digital
camera and androids. It appears like a plugged
usb stick but it is not mounted blockwise but
file-wise.

I have micropython proof of concept here
https://github.com/emard/esp32s3-ptp
all in micropython, my dirty coded but
small example of 2 directors and 2 files works.

for PTP protocol needs some unique 32-bit id
for each object (file or directory)

micropython should probably buffer at least part
of if not whole filesystem tree, for esp32 there's
not much but if we plug SD card it may be memory tight.

So here is WISHLIST if micropython would implement in function
os.ilistdir("path") nonzero "inode" parameter it is
now 0 after 32768 or 16384.
it should be unique file id 32-bit so that any
file or directory should be accesible only using this id,
this would simplify PTP and free us from buffering
full or partial directory tree and giving objects unique ids

import os
a=os.ilistdir("/")
for x in a:
... print(x)
('lib', 16384, 0, 0)
('ptp.py', 32768, 0, 28672)

@andrewleech
Copy link
Contributor

@emard that's fantastic, thanks for sharing! I've long wanted MTP / PTP working on micropython and have been occasionally working on my own driver for it here: https://github.com/andrewleech/micropython-lib/tree/usb-mtp2/micropython/usb/usb-device-mtp

Mine connects on PC, shows file listings, delete works etc but actually transferring files from device to PC is locking up, I'm super keen to look at your version and compare the two, maybe there's learnings we can both share here!

Regarding inode's I don't think it's really possible to have them provided by micropython because the default underlying filesystem drivers (LFS2 or FAT) don't have these as far as I'm aware. I didn't think about the inode / handles that much, it just handle += 1 in my code currently when it first builds up the filesystem tree. Not particularly repeatable though, might be one of the bugs affecting it. I would assume that hash("/full/path/to/file") would be a better option, it's repeatable and fast to generate, though not completly guaranteed to be unique.

@emard
Copy link
emard commented May 1, 2025 via email

@emard
Copy lin F8CC k
emard commented May 4, 2025 via email

@jonnor
Copy link
Contributor
jonnor commented May 4, 2025

It would be fantastic if we could get a working PTP and/or MTP example code that we could include in micropython-lib together with the other USB device examples.

@emard
Copy link
emard commented May 4, 2025 via email

@emard
Copy link
emard commented May 5, 2025

If interface is named "MTP" then protocol will become MTP
instead PTP.
With MTP currently my code doesn't work, I will try to see what's
the difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests, new feature implementations port-esp32
Projects
None yet
Development

No branches or pull requests

0