QT Py SAMD21 Bootloader Protection

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

I will be working on enabling BOD; feel free to subscribe to the issue if you have not already.

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

Update:

I got a couple of QT Py M0's of about the same vintage as what you have. They came with the bootloader unprotected, BOOTPROT = 0x7. They came with bootloader 3.14.0. Loading update-bootloader-QTPy_m0-v3.14.0.uf2 on them successfully changes BOOTPROT to 0x2.

I should be receiving your RMA'd QT Py's very soon, and will take a look at them.

I am testing some BOD33 code for the bootloader right now.

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

Hi leafon,

I received your two RMA's QT Py M0's. They are packaged identically to the two I got from Mouser: same kind of bag, exact same label.

I understand you are probably using a Mac, so I tested this on a Mac Mini M1 running Ventura 13.2.

1. The Qt Py out of the bag runs a NeoPixel "swirl" program that changes the color of the NeoPixel rapidly.
2. I loaded the print_samd21_fuses.uf2 file attached in a post above, by double-clicking and then dragging in the Finder to QTPY_BOOT. Then I used tio to monitor the serial port to see what the fuse printer was printing. As with the previous samples I found, the fuses show no BOOTPROT protection (which is a mistake):

Code: Select all

0x804000: 0xD8E0C7FF
0x804004: 0xFFFFFC5D
3. I then double-clicked again, and dragged https://github.com/adafruit/uf2-samdx1/ ... 3.14.0.uf2 to QTPY_BOOT.
4. After step 3, I waited about 10 seconds until the NeoPixel turned from off to green, showing that the bootloader had restarted.
5. I reloaded print_samd21_fuses.uf2. It prints

Code: Select all

0x804000: 0xD8E0C7FA
0x804004: 0xFFFFFC5D
showing that BOOTPROT is now set correctly.

I repeated the above with the second RMA'd QT Py, except that I used `cp` instead of the Finder. I got the same result.

If I understand correctly, you did the same thing as above, but when you loaded print_samd21_fuses.uf2, it showed no change. If you did what I did, I am at loss to explain why it consistently does not fix BOOTPROT for you, and it consistently does fix BOOTPROT for me.

A few questions:
a. Are you waiting in step 4 for the NeoPixel to turn green? This takes a little while.
b. Are you on a Mac as described? Is it running Ventura 13.2 or something else? There was a bug in 13.0 and 13.01 related to copying UF2's via the Finder, but it's fairly obvious: you would have seen an error. See https://blog.adafruit.com/2022/10/31/up ... uitpython/ for background on this.

User avatar
leafon
 
Posts: 32
Joined: Thu Sep 22, 2022 12:40 am

Re: QT Py SAMD21 Bootloader Protection

Post by leafon »

Hi Dan,

Thank you very much for looking into this issue on a weekend!

I repeated exactly what you did and confirmed the SAMD21 fuses changed to:

0x804000: 0xD8E0C7FA
0x804004: 0xFFFFFC5D

What I did incorrectly previously was not waiting long enough after step 3. I only waited a few seconds after copying the uf2 file over and the drive disappears from Finder. Previously, when I modified and compiled the uf2-samdx1 source code and copied the uf2 file (using the uf2conv.py script on the bin file) to the QT Py, I didn't need to wait ~10 seconds for the bootloader to update.

On this particular machine, I'm using Monterey (12.6.2).

After step 5, I flashed the QT Py with my own uf2 file and confirmed with JLink the fuses are still

0x804000: 0xD8E0C7FA
0x804004: 0xFFFFFC5D

So for the next step, after you make the changes to BOD33, do I need to update every QT Py board twice?
1. Update with the update-bootloader-QTPy_m0-v3.15.0.uf2 file to enable BOD33 and bootloader protection.
2. Update with my own uf2 file

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

leafon wrote: Sun Feb 12, 2023 7:59 pm 1. Update with the update-bootloader-QTPy_m0-v3.15.0.uf2 file to enable BOD33 and bootloader protection.
2. Update with my own uf2 file
Yes, because the update-bootloader uf2 in 1. will overwrite whatever program is there.

Here is a PR that adds the BOD33 protection and removes that long delay before restarting for update-bootloader:
https://github.com/adafruit/uf2-samdx1/pull/198

And here are test builds for you:
QTPy-BOD33.zip
(14.07 KiB) Downloaded 3 times
Do you have an easy way to test the BOD33 enabling? I tested it with a Nordic PPK2 power profiler on a Feather M0, lowering the voltage until it did not restart. I have a minor thing to fix there, because it left the NeoPixel on, which isn't great if the battery is low.

User avatar
leafon
 
Posts: 32
Joined: Thu Sep 22, 2022 12:40 am

Re: QT Py SAMD21 Bootloader Protection

Post by leafon »

Thank you Dan!

I'll try the test build right away!

What's the threshold level you set for the BOD33? Perhaps we can test it by try another build that enables the BOD33 and disables the bootloader protection, then methodically power cycles the SAMD21.

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

The BOD33 level is 39, which is about 2.8V. External flash chips, like the one on the QT Py, are usually specified foto require at least 2.7V.

Here is a build that has BOD33 but leaves the bootloader unprotected:
QTPy_m0-no-BOOTPROT-yes-BOD33.uf2
for test use only
(19.5 KiB) Downloaded 3 times
With the SAMD51, without BOD33, we still got internal flash erases, but they did not erase the BOOTPROT region. They did erase the beginning of the program, just past the BOOTPROT area.

User avatar
leafon
 
Posts: 32
Joined: Thu Sep 22, 2022 12:40 am

Re: QT Py SAMD21 Bootloader Protection

Post by leafon »

Hi Dan,

Regarding the files you provided earlier: QTPy-BOD33.zip.

I noticed if I flash a QT Py board with corrupted bootloader with the "bootloader-QTPy_m0-v3.14.0-12-g6451787.bin" file, it doesn't update the fuses. Is that the correct behavior?

Only after I copy the "update-bootloader-QTPy_m0-v3.14.0-12-g6451787.uf2" to QT Py, it updates the fuses to enable the bootloader protection.

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

That's right, the bootloader itself only updates the fuses if the first fuse word has been reset to all ones (0xffffffff). This would reflect that the fuse page has been completely erased but not rewritten. If the fuses are all ones, it enables the watchdog timer with a short period, which will cause a boot loop after a few seconds. So we check for that, but not other things. We don't necessarily want to second-guess the user who may have wanted to undo the BOOTPROT for other reasons, such as rewriting the bootloader without erasing the whole chip.

The bootloader updater also only resets the fuses to "reasonable values" if the first fuse word is 0xffffffff. Again this is to handle the case that the user wants an unusual fuse configuration. But it does always set the BOOTPROT properly, because that's usually what people want, and because uploading the updater replaces any existing program.

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: QT Py SAMD21 Bootloader Protection

Post by danhalbert »

https://github.com/adafruit/uf2-samdx1/ ... ag/v3.15.0 has the changes in the test version I gave you.

User avatar
leafon
 
Posts: 32
Joined: Thu Sep 22, 2022 12:40 am

Re: QT Py SAMD21 Bootloader Protection

Post by leafon »

So the bootloader protection is still off by default in v3.15.0?
The v3.15.0 bootloader does not have code to set the bootloader protection if it is off. There is a catch-22 with how the update-bootloader UF2 works. However, if you update with any update-bootloader UF2, it will enable the bootloader protection. The v3.15.0 update-bootloader does not spend time flashing the status LED and waiting until the flashing is done before writing the BOOTPROT, which is what was confusing before. So it will finish much faster. When you see QTPY_BOOT again, BOOTPROT will be enabled.

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”