Skip to content
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

Download and Store multiple programs (without immediate execution) #978

Open
agordon opened this issue Mar 5, 2020 · 9 comments
Open

Download and Store multiple programs (without immediate execution) #978

agordon opened this issue Mar 5, 2020 · 9 comments

Comments

@agordon
Copy link

agordon commented Mar 5, 2020

Hello,

This request seems opposite to my previous one (#977), but this one addresses a completely different use-case and critical need.

It was mentioned in passing in a closed issue #873 (comment) : For "First Lego League" (FLL) teams, we need the ability to store multiple programs on the brick iteself.

using "MakeCode" is a recently introduced features (only Lego's software was allowed in previous years). However, the use-case for the actual competition is incompatible with the current method of "download and start immediately".

Please see an example of a Lego League Match: https://youtu.be/iEz9nzUuszg?t=4694

The kids have 1 minute to setup the robot, and then when the match starts, they start an already stored program using the brick's interface.
Not only that, but during the match they are even allowed to change programs.

If we can not have this setup using MakeCode/EV3 - it will be a serious show-stopper in regards to using MakeCode/EV3 for FLL. During development - sure, downloading and immediately starting a single program is great. But for the competition (and for practicing towards the real competition) - that's not going to work.

Thanks!
-gordon

@pelikhan
Copy link
Member

pelikhan commented Mar 5, 2020

You can download multiple different programs to the brick as long as you use a different name. Then you use the brick menu to start each of them. Is that what you are trying to do?

@agordon
Copy link
Author

agordon commented Mar 7, 2020

I see what you mean, and it's a partial solution.

  1. The "auto-start" is extremely frustrating. I understand the "low friction/seamless" reasoning, and it might might make sense if you're a single person working on a lego robot. But in a class of 15 six-graders, where some laptops are shared and the kids need to take the robot to the laptop, program it, but they hold it in their hand while it is being programmed and need to take it elsewhere in the classroom to start it - this is not convinient.

  2. There are some bugs in updating the UI of the "recent programs" and the "file manager".
    If the UF2 file is uploaded while the UI is in "file manager", the new program starts automatically (as expected), but does not appear in the "file manager" nor in the "recent programs".
    Some voodoo of playing with the UI back and forth is required to make it refresh and list the program.

  3. Deleting the programs is very annoying ( https://makecode.mindstorms.com/fll#why-can-t-i-delete-my-program-uf2-files-from-the-brick- ), and after programs are deleted they still appear in the "recent programs", and clicking on them shows "error!" message.
    I won't even ask how to delete the "file-manager" program itself...

So all in all - this is not a complete show-stopper, but it just makes "MakeCode" less attractive when having to deal with 15 kids in a class (which is sad, because from a programming and teaching POV it is far superior to LabView).

@JakubVanek
Copy link

[ this is mostly a rant ]

Hi all,

https://makecode.mindstorms.com/fll#why-can-t-i-delete-my-program-uf2-files-from-the-brick-:

There’s a bug in the firmware which prevents you from deleting the programs (*.uf2 files) from your EV3 Brick. There isn’t a firmware update to fix this yet. As a workaround, you can temporarily downgrade your firmware version, delete the files, and then upgrade back to the version that works with MakeCode.

I think this deserves some clarification. From what I've read on the internet about UF2 for microcontrollers, it is designed as only a transmission-only file format. The user is supposed to drop it to a FAT32-formatted USB pendrive emulated by the device and it then gets loaded to the flash memory. In the case of the EV3 brick, the UF2 is split into separate file segments and these are then written as .rbf, .elf and other files to where the stock firmware expects them. At least that's how I understand uf2-linux does it.

On the other hand, I believe that the message above meant that the uploaded .rbf and .elf files may not be removable either through the stock firmware browser or through the EV3-G environment. Either way, this could be solved with a cleaning program written using PXT or other native language, as it runs natively outside of the LEGO LMS2012 VM and it is not limited by it. Using an alternative program for remotely accessing the EV3 filesystem such as ev3duder should do the job as well, however that cannot be done through the browser-only interface.

The fact that the FAT32 is emulated irritates me a little. I don't know why it happened, but last time I tried to use it Linux couldn't mount such a drive. Therefore, although the web IDE is cross-platform by nature, I could not use it on Linux.

Best regards,

Jakub Vanek

@JakubVanek
Copy link

JakubVanek commented Mar 15, 2020

I've installed the new firmware and I think I see the two problems:

  • PXT generates the UF2 file in a way that puts the .elf and .rbf files directly into /home/root/lms2012/prjs/BrkProg_SAVE. This is not the most optimal way of doing this. Instead, by creating a directory /home/root/lms2012/prjs/<project name> and uploading the files as /home/root/lms2012/prjs/<project name>/<project name>.{rbf,elf}, then it would be possible to delete the files using the on-brick's file explorer (folders can be deleted). Except for the possible necessary mkdir this can be solved entirely in the online part of MakeCode. If the subdirectory would not be properly created when uploading the UF2, this could be solved by the PXT executable moving itself to the new directory (i.e. this would ideally be a part of the autostart code).
    EDIT: I start to see that this would break the viewing through the Projects folder, which may be a dealbreaker. The projects would no longer show up there, as it likely only scans the BrkProg_SAVE directory.
  • LEGO version of the UF2 userspace daemon indeed shows a Projects directory with UF2 files in the emulated FAT32 volume. These files indeed cannot be deleted. However I believe the files are an emulation as well. The UF2 file does not exist, it is rather two files amalgamated into one entity. Therefore to implement this, the daemon would have to intercept some changes to the FAT table and then remove the individual files from the internal brick file system.

[offtopic]

  • The concept of emulating FAT32 and intercepting changes seems strange to me. I think that using MTP/PTP or other file-oriented protocol would be a much better fit for this. This would allow one to also browse the EV3 file system directly, without having to emulate something. However on my part this is a pure speculation not backed by much experience, so take this point lighly. I don't know the FAT structure or the MTP/PTP protocols, so there may be various nontrivial issues and dealbreakers.

@JakubVanek
Copy link

JakubVanek commented Mar 15, 2020

  1. The "auto-start" is extremely frustrating. I understand the "low friction/seamless" reasoning, and it might might make sense if you're a single person working on a lego robot. But in a class of 15 six-graders, where some laptops are shared and the kids need to take the robot to the laptop, program it, but they hold it in their hand while it is being programmed and need to take it elsewhere in the classroom to start it - this is not convinient.

From a theoretical point of view, this could also be solved without changes to the brick firmware. It would just be necessary to generate a unique identifier for each generated UF2/ELF. During each launch, the ELF would do the following:

  • Check if /home/root/lms2012/prjs/<project name>/<project name>-id.bin exists.
  • If not, this is the first ever start of this app. The app will not start, but the file will get created, see below.
  • If it exists, read its contents. If they don't match the embedded identifier, then this is a new version
    of a previously existing application - therefore the app will not start, but the identifier will be updated.
  • If the identifiers match, then this is a not the first launch. The app will start normally.
  • Write the identifier to the file so that in the future the app will start.

This process could be controlled by a checkbox in the MakeCode UI, allowing the user to decide whether a given generated file will autostart.

There is a limitation to this - if you upload the same UF2 for the second time, it will always autostart (because the identifier didn't change).

  1. There are some bugs in updating the UI of the "recent programs" and the "file manager".
    If the UF2 file is uploaded while the UI is in "file manager", the new program starts automatically (as expected), but does not appear in the "file manager" nor in the "recent programs".
    Some voodoo of playing with the UI back and forth is required to make it refresh and list the program.

I don't know how to fix this without changing the brick firmware (lms2012 VM). The firmware needs to be poked to refresh the screen. The EV3-G environment does this via sending the opUI_WRITE(DOWNLOAD_END) direct bytecode (via the lego ev3 protocol) to the VM. This sets the UiInstance.UiUpdate flag which then (hopefully) triggers browser refresh.

Depending on what really "autostarts", there are multiple ways of approaching this.

  • if the autostart goes through <program name>.rbf (i.e. through LMS2012 VM), then it's just necessary to add the DOWNLOAD_END opcode to the file. This will play the "tududududu" tune every time the app starts, so this is a not very good idea. Alternatively, the RBF file may create and then remove some temporary file - this seems to set UiUpdate = 1 as well.
  • If the autostart is only handled through the UF2 daemon and not the lms2012 VM, then things get more difficult. One option would be to somehow send the bytecodes above to the brick, but I don't know how to do that. Alternatively, the flag is only a single byte, so perhaps PXT could try to ptrace()-attach to the VM, find the byte and modify it in place. However that is a very ugly hack that would be prone to breakages.

EDIT: I have mixed two issues together. It should be possible to just append opUI_WRITE(DOWNLOAD_END) at the end of the "file-manager.pdf"'s RBF file and that would trigger the refresh.

@JakubVanek
Copy link

JakubVanek commented Mar 16, 2020

There may be also another solution for the autostart issue. It depends on the program being auto-launched through the UF2 daemon and not via the RBF file. Then, it would be possible to add a command line parameter for PXT/ELF info the RBF file (like --launched-from-menu). The ELF file would then detect this and it would know if it was autostarted or manually started. It could then decide upon a stored autostart-enable flag what to do next.

The ELF is parented by the LMS2012 VM, therefore this is not the way to go.

@OliviliK
Copy link

@agordon
I have been a FLL coach for many years and do fully understand and support your request. In addition of the problem you did describe, I have observed how the pupils are starting a wrong program under the time pressure. Starting this year, we will use MakeCode and start only a single program, which will first check the battery and gyro. After that, there is a simplified menu system to start the different sorties to execute the game missions. In many cases, it is enough to have only 5 sorties to allow to start any of them with the 5 available buttons in EV3.

@JakubVanek
Copy link

JakubVanek commented Mar 19, 2020

Instead, by creating a directory /home/root/lms2012/prjs/<project name> and uploading the files as /home/root/lms2012/prjs/<project name>/<project name>.{rbf,elf}, then it would be possible to delete the files using the on-brick's file explorer (folders can be deleted). Except for the possible necessary mkdir this can be solved entirely in the online part of MakeCode.

This turns out not to be possible. The UF2 daemon running on the brick processes directly only the filename of the paths embedded in the UF2. The directory has to be mapped through the internal mapping table. I see this is for security reasons and I agree with it, however it complicates stuff exactly because of what it does - it's impossible to upload files anywhere else than to the /home/root/lms2012/prjs/BrkProg_SAVE directory. This is unfortunate and I don't think that this can be fixed without a new firmware. That is, however, only when uploading the UF2 via the flash drive.

EDIT: this is a part of strings output on the uf2d binary from the firmware, which looks suspiciously like https://github.com/microsoft/uf2-linux/blob/751b0f4e589583012ab6e3fac4a86f239933257b/uf2daemon/fat.c#L246.

Projects
/mnt/ramdisk/prjs/BrkProg_SAVE
SD Card
/media/card/myapps
USB Stick
/media/usb/myapps
Temporary Logs
/tmp/logs
Permanent Logs
/mnt/ramdisk/logs

The paths are therefore hardcoded in the daemon.

If the subdirectory would not be properly created when uploading the UF2, this could be solved by the PXT executable moving itself to the new directory (i.e. this would ideally be a part of the autostart code).

This still could be done - the autostarted file would recognize that it is in the "wrong" common directory and it would rename() itself to the new directory. This would also necessitate the browser refresh as hinted above using either the temporary file or the DOWNLOAD_END opcode.

@frenky-strasak
Copy link

@JakubVanek is there any solution how to mount the ev3 on Ubuntu to run programs from makecode.mindstorms.com?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants