renaming PYBFLASH mount point from PyBoard code

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: renaming PYBFLASH mount point from PyBoard code

Post by dbc » Sat Oct 17, 2015 7:03 pm

You can tell if the USB mode is in MSD mode (mass storage) but I don't think there is any reliable way to detect if the volume is mounted.
If boot.py runs before the PyBoard is in MSD, then it might make sense to allow setting the label.
There might be patterns of sector read/write for a particular OS that mean mount or unmount, but that's hard to get working.
This seems like the road to grief. Too unreliable to be worthy of program flash space, IMHO. Changing the label after the MSD is mounted is not going to be a good thing, so any system call that allows changing the label must be able to raise a "You're way too late for that, dude." exception. Anything else leads to user confusion and bugs.

On the topic of serial numbers, I dug around a bit and found:

Code: Select all

ATTRS{idVendor}=="067b",ATTRS{idProduct}=="2303",SYMLINK+="ttyBeagle"
ATTRS{idVendor}=="2108",ATTRS{idProduct}=="780b",SYMLINK+="ttyXV11",MODE="0666"
in my udev rules for one system. What is missing is an ATTRS{serial}=="12345" clause, which I have used in the past to distinguish between different FTDI cables, but can't lay my hands on an example at the moment. This allows a fixed symbolic link to be set up regardless of which /dev/ttyACM<n> a particular unit shows up under.

After thinking further about my code deployment options, I could live with manually set volume names. A system call to set the volume name must be able to tell if the PyBoard is in MSD mode and raise an exception if it is. Which pre-supposes the ability to run code before the PyBoard is in MSD mode.

The serial number in the CDCACM device descriptor seems like the right thing to do on general principals, and worth the effort.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: renaming PYBFLASH mount point from PyBoard code

Post by dhylands » Sat Oct 17, 2015 8:31 pm

You can use udevadm to find out all of the various fields that you can use. For example, with my pyboard with the serial number PR patch applied, I see:

Code: Select all

2659 >udevadm info -a -n /dev/ttyACM0
If you search for serial you should see a line something like:

Code: Select all

    ATTRS{serial}=="385435603432"
You could also use the list command with usb-ser-mon.py:

Code: Select all

2660 >~/python/usb-ser-mon/usb-ser-mon.py -l
USB Serial Device with vendor 'MicroPython' serial '385435603432' found @/dev/ttyACM0
You can find usb-ser-mon.py over here https://github.com/dhylands/usb-ser-mon, if you're interested. It allows you to connect to usb serial devices and use attributes like the name, or the serial number. So I could do:

Code: Select all

2661 >~/python/usb-ser-mon/usb-ser-mon.py -s 385435603432
USB Serial device with vendor 'MicroPython' serial '385435603432' connected @/dev/ttyACM0
Use Control-X to exit.
MicroPython v1.4.6-91-g641f348-dirty on 2015-10-17; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> 
There is also a find_port.py script that may be useful inside other scripts:

Code: Select all

2662 >find_port.py -s 385435603432
/dev/ttyACM0
Anyways, now that we kno which ATTR to use, we can write the udev rule:

Code: Select all

# f055:9800, 9801, 9802 MicroPython pyboard
ATTRS{idVendor}=="f055", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="f055", ENV{MTP_NO_PROBE}="1"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="f055", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="f055", ATTRS{serial}=="385435603432", SYMLINK+="pyboard", MODE:="0666"
Note that I don't use the idProduct since that changes between 9800, 9801, and 9802 depending on which mode (CDC or CDC+HID, or CDC+MSC) is in effect. The MM_DEVICE_IGNORE line tells the modem manager to ignore this serial port, and MTP_NO_PROBE tells MTP to not probe. The usb line controls the permissions on the device node which shows up in /dev/bus/usb which is used by dfu-util or pydfu.py during DFU programming. I use the following script to tell udev to reload: https://github.com/dhylands/dotfiles/bl ... dev-reload and then unplug and replug the device to make it take effect.

Damien
Site Admin
Posts: 647
Joined: Mon Dec 09, 2013 5:02 pm

Re: renaming PYBFLASH mount point from PyBoard code

Post by Damien » Sat Oct 17, 2015 9:21 pm

Yes, if the pyboard is hard reset then when boot.py runs the USB device is not yet initialised. So at that point you could set the label.

The new "hardware API" (which covers more than just the machine module) now includes os.mkfs. We can add an option to this to set the label when the fs is created. But that means your pyboard filesystem will be erased when you label it, but I guess that's ok since it'll only be done once.

But with @dhyland's code to set the CDC iSerial attribute (which is now merged into master), I think querying this is a much more robust way to dectect which particular pyboard is attached. Is there any benefit of using the fs label over the CDC iSerial attribute?

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: renaming PYBFLASH mount point from PyBoard code

Post by dbc » Sat Oct 17, 2015 10:20 pm

Yes, if the pyboard is hard reset then when boot.py runs the USB device is not yet initialised. So at that point you could set the label.
Good.
The new "hardware API" (which covers more than just the machine module) now includes os.mkfs. We can add an option to this to set the label when the fs is created. But that means your pyboard filesystem will be erased when you label it, but I guess that's ok since it'll only be done once.
Well, that's not my use case. I want to read configuration switches and set the board's personality from that, including the fslabel. If changing configuration switches wipes the flash, that would be...... unhelpful.
But with @dhyland's code to set the CDC iSerial attribute (which is now merged into master), I think querying this is a much more robust way to dectect which particular pyboard is attached. Is there any benefit of using the fs label over the CDC iSerial attribute?
They solve different problems. The iSerial patch means that a particular board's console can always be associated with a particular name. Name follows physical board, which is a Good Thing. What I was trying to get at with the fslabel is name-follows-config-jumpers, which is a different thing.

After thinking about what I need versus what is convenient, the iSerial patch is a need, relabeling the volume from within the PyBoard is convenient, but not worth a lot of flash space. That said, since os.mkfs will need to call fs_setlabel at some point, it seems like the cost is 1 extra entry point and code for an exception check, which then expose os.fs_label(name=None) which could set the label if name!=None and in any case return the label. Although I suspect I might be the only user -- it is probably still not worth the flash space in the general case. I'd be happy to keep a private patch, or build with a switch.

@dhylands: Thanks for the iSerial patch and the very complete udev rules. I predict that to be popular.

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: renaming PYBFLASH mount point from PyBoard code

Post by dbc » Tue Oct 20, 2015 12:15 am

So one last note on this. As @dhylands pointed out separately, because the host is caching information from the flash file system, mounting the flash directly will always be problematic. My latest thought is that extending dhylands' rshell with a fake level of file system hierarchy might be a much better solution for me. Now that we can have tty names driven off of USB serial numbers, it is possible to build a dictionary mapping tty names to roles. (Well, perhaps even without serial numbers, tty names can be mapped to roles.)

So I am imagining a file on each PyBoard named something like /sd/identity.py which contains role identification information. Then rshell could be extended with an additional level of hierarchy in remote file system names like so: /<role>.pyb/sd and /<role>.pyb/flash or similar. One final tweak so that the rshell 'repl' command takes a parameter 'repl <role>' to get an interactive prompt on a particular PyBoard, and controlling the octopus from a single shell is complete.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: renaming PYBFLASH mount point from PyBoard code

Post by dhylands » Tue Oct 20, 2015 1:56 am

Yeah - something like that could be quite workable.

I'd probably do something like the following:

1 - Have rshell automatically scan and recognizes boards with a vendor of Micro_Python (or some set of recognized vendor names).
2 - I was thinking that identity.py should probably be some type of data file (json/yaml) rather than being a python script. That way we can extend things down the road.
3 - I think that having /role/sd/... /role/flash/... for every board and perhaps have /flash /sd map to the first board (most people will only hav one pyboard).
4 - add a boards command (or something) that would list info about each board, including its role.
5 - Add a command which allows boards/roles to be assigned/manipulated manually, and perhaps update the configuration file.

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: renaming PYBFLASH mount point from PyBoard code

Post by dbc » Tue Oct 20, 2015 2:51 am

I'd probably do something like the following:

1 - Have rshell automatically scan and recognizes boards with a vendor of Micro_Python (or some set of recognized vendor names).
Yes, could do. I was thinking of matching on /dev/<foo> symbolic links, and passing in a regular expression as an option. One doesn't preclude the other.
2 - I was thinking that identity.py should probably be some type of data file (json/yaml) rather than being a python script. That way we can extend things down the road.
My reason for making it a Python file is that my main script needs to understand it's role, too. I'd like to set the role in exactly one place, rather than try to keep two files consistent. I see the file consisting of a very small number of <name>=<value> statements that could be imported on either side. I guess since json is built into the PyBoard image it isn't hard to have the application script read that instead of doing an import. It just seems to me that a simple Python file is sufficient.
3 - I think that having /role/sd/... /role/flash/... for every board and perhaps have /flash /sd map to the first board (most people will only hav one pyboard).
4 - add a boards command (or something) that would list info about each board, including its role.
5 - Add a command which allows boards/roles to be assigned/manipulated manually, and perhaps update the configuration file.
Yes, that would all be nice.

I guess if you autoscan, and don't find a config file, you can give the board the mount point /<serialnumber>/flash, which alone should be motivation to create an easier to type role name... But anyway with that you could simply attach another board, rescan, and then do the configuration from the shell at that point. I don't think having rshell respond to hot plug events is worth any effort at all -- but a command to force rescan after plugging in a new board would be useful.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: renaming PYBFLASH mount point from PyBoard code

Post by dhylands » Tue Oct 20, 2015 3:20 am

I already have code which can autoscan usb devices in find_port.py. I just need to update it to be Python3 compatible.

I was thinking that while autoscan works for usb serial, it wouldn't necessarily work for all ways of connecting. For example - connecting to the WiPy, or using non-usb serial ports or devices connected through some other wireless modality (like bluetooth, or ZigBee, etc). And even if there was a way to autoscan the network, it may make sense to cache that information so that you wouldn't necessarily have to scan every time its started.

I think that what I would do is to create the notion of an rshell script, and at startup there would be some script which could be provided and it could contain rshell commands.

I've also been meaning to improve rshell's handling of dropped usb links and some other things, so I think that there will be a bunch of restructuring.

I think you've convinced me that using a .py file would work fine to configure the role.

I'm going to start working on this tonight - you've got me interested!

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: renaming PYBFLASH mount point from PyBoard code

Post by dbc » Wed Oct 21, 2015 4:24 am

Very cool. I forked your code and started reading it, but if you are already implementing it, then you will probably be done before I have started coding. I'm ready to help test any time.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: renaming PYBFLASH mount point from PyBoard code

Post by dhylands » Wed Oct 21, 2015 4:31 am

I have it mostly working. Just needs a few more tests (it probably needs more features too). I haven't added the autoscan yet. I'll let you know when I've pushed it.

Post Reply