adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.09k stars 1.22k forks source link

storage.usb_drive_enabled() #9136

Closed p3lim closed 6 months ago

p3lim commented 6 months ago

The storage module provides methods to enable or disable the usb drive, but there is nothing (that I can see) to query if it is already enabled or not. I'm trying to add a toggle for it, so knowing the state would be useful.

dhalbert commented 6 months ago

You have to do the enabling/disabling in boot.py, which runs only after a hard reset, and before USB is set up. You cannot use it in code.py. So there is no state to check, since a hard reset resets everything.

You can remember states in, say microcontroller.nvm, or in the file system, if you want to remember the state past a hard-reset or power-cycle.

p3lim commented 6 months ago

Ah ok, good to know.

I'd like to hide the device by default, but press a button to show it. If that requires a reboot that's fine, but I'd need to store some state that I can read in boot.py to not run storage.disable_usb_drive().

I guess I'll read up on the documentation some more, closing this issue.

If you do however have an example of storing state like this I'd appreciate it.

Edit: was easier than I thought, microcontroller.nvm was the solution :)

dhalbert commented 6 months ago

The usual technique is to check the state of a button during boot.py. ISo you can hold down the button while pressing reset to avoid the disable code. Here's a discussion: https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial#dont-lock-yourself-out-3096636.

dglaude commented 6 months ago

The usual technique is to check the state of a button during boot.py. ISo you can hold down the button while pressing reset to avoid the disable code. Here's a discussion: https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial#dont-lock-yourself-out-3096636.

Exactly the guide I was trying to locate and the current recommended way to do that. With the added difficulties that on some hardware, we only have one user button that is also the boot button from the RP2040 like on the QT2040 Trinkey: https://circuitpython.org/board/adafruit_qt2040_trinkey/ so you don't have a button to be used to choose a different behavior (like stealth mode) at boot.

Edit: was easier than I thought, microcontroller.nvm was the solution :)

Could you elaborate on a minimal working example? And in what condition this works (like only for warm reboot?).

I don't know/use microcontroller.nvm but I know and use alarm.sleep_memory[0] as used in this project: https://learn.adafruit.com/adafruit-magtag-project-selector

So if the guide could be updated with your knowledge/solution, that would be really helpfull.

I want my Trinkey to boot stealth (not CIRCUITPY drive, not REPL, ...) and I want to be able to restart it in "configuration mode" to adapt the code. So if I can use the boot button (after CP has booted) to order a restart in new condition, that would be great.

p3lim commented 6 months ago

I prefer not to have the drive connected at all times, instead only when I need it.

In boot.py I have this:

import storage
import microcontroller

if microcontroller.nvm[0] == 1:
  storage.enable_usb_drive() # probably redundant
else:
  storage.disable_usb_drive()

Then in code.py I have something that will trigger this function:

def toggle_mount():
  import microcontroller
  microcontroller.nvm[0] = int(not microcontroller.nvm[0])
  microcontroller.reset()

That function will essentially just toggle the volume mount.

My exact usecase is that I use CircuitPython as the firmware for a keyboard, and I have a key combination to trigger that function.

dhalbert commented 6 months ago

My exact usecase is that I use CircuitPython as the firmware for a keyboard, and I have a key combination to trigger that function.

You can also check for a key being held down during reset rather than toggling. You can't use keypad to do that, since the key will not transition during boot.py unless you added a delay to monitor it. If it's a key matrix it's a bit tricky: you'll need to make the row be an output or and column be in input, or vice versa, depending on the diodes and how it's wired. But anyway, you can read the key "manually" that way in boot.py.

dhalbert commented 6 months ago

I don't know/use microcontroller.nvm but I know and use alarm.sleep_memory[0] as used in this project: https://learn.adafruit.com/adafruit-magtag-project-selector

So if the guide could be updated with your knowledge/solution, that would be really helpful.

sleep memory does not survive a power-cycle. microntroller.nvm stores bytes in flash. t's pretty easy to use: https://docs.circuitpython.org/en/latest/shared-bindings/nvm/index.html

p3lim commented 6 months ago

You can also check for a key being held down during reset rather than toggling

I do that too, but having a full on toggle like this is nice when I'm working on the firmware.