Hi,
I came across this blog yesterday.
https://blog.thea.codes/sam-d21-brown-out-detector/
It appears the bootloader protection on the QT Py SAMD21 isn't enabled by default.
QT Py SAMD21 Bootloader Protection
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_mike
- Posts: 67454
- Joined: Thu Feb 11, 2010 2:51 pm
Re: QT Py SAMD21 Bootloader Protection
That's correct.
It's a design tradeoff: with memory protection enabled, the bootloader wouldn't be able to update itself when a newer version is released. You'd have to use a JTAG programmer to disable memory protection, then flash the new bootloader.
It's a design tradeoff: with memory protection enabled, the bootloader wouldn't be able to update itself when a newer version is released. You'd have to use a JTAG programmer to disable memory protection, then flash the new bootloader.
- leafon
- Posts: 32
- Joined: Thu Sep 22, 2022 12:40 am
Re: QT Py SAMD21 Bootloader Protection
Thanks Mike.
So when I use the uf2conv.py script (from https://github.com/microsoft/uf2/tree/master/utils) to generate the uf2 files from the bin file, and update a QT Py, does the bootloader get updated?
Is there a way to enable to the bootloader protection and enable the brown-out detector without using the SAMD21's SWD interface?
So when I use the uf2conv.py script (from https://github.com/microsoft/uf2/tree/master/utils) to generate the uf2 files from the bin file, and update a QT Py, does the bootloader get updated?
Is there a way to enable to the bootloader protection and enable the brown-out detector without using the SAMD21's SWD interface?
- adafruit_support_mike
- Posts: 67454
- Joined: Thu Feb 11, 2010 2:51 pm
Re: QT Py SAMD21 Bootloader Protection
Yes.leafon wrote: ↑Mon Jan 23, 2023 9:06 pm So when I use the uf2conv.py script (from https://github.com/microsoft/uf2/tree/master/utils) to generate the uf2 files from the bin file, and update a QT Py, does the bootloader get updated?
Nope. You have to set fuses to enable those features, and that can only be done through the JTAG interface.
- leafon
- Posts: 32
- Joined: Thu Sep 22, 2022 12:40 am
Re: QT Py SAMD21 Bootloader Protection
According to this blog: https://blog.thea.codes/sam-d21-brown-out-detector/
"I had assumed that the bootloader we use, uf2-samdx1, would enable bootloader protection automatically. It turns out that isn't the whole story- it only enables bootloader protection in two cases:
The bootloader protection configuration is invalid
The bootloader has updated itself"
So if I update the bootloader with a new uf2 file, wouldn't the bootloader protection be turned on?
"I had assumed that the bootloader we use, uf2-samdx1, would enable bootloader protection automatically. It turns out that isn't the whole story- it only enables bootloader protection in two cases:
The bootloader protection configuration is invalid
The bootloader has updated itself"
So if I update the bootloader with a new uf2 file, wouldn't the bootloader protection be turned on?
- adafruit_support_mike
- Posts: 67454
- Joined: Thu Feb 11, 2010 2:51 pm
Re: QT Py SAMD21 Bootloader Protection
The chip can't write new data to the bootloader memory if protection for that block is turned on.
By that definition, it's impossible for the bootloader to update itself if the memory is protected. The goals are mutually exclusive. You can have one or the other, but not both.
By that definition, it's impossible for the bootloader to update itself if the memory is protected. The goals are mutually exclusive. You can have one or the other, but not both.
- leafon
- Posts: 32
- Joined: Thu Sep 22, 2022 12:40 am
Re: QT Py SAMD21 Bootloader Protection
Thank you.
On a related topic, how do I enable the brown-out detector on SAMD21?
Do I modify this file: https://github.com/adafruit/uf2-samdx1/ ... src/main.c
It appears the brown-out detector is enabled for SAMD51 and disabled for SAMD21 by default. Why is that the case?
On a related topic, how do I enable the brown-out detector on SAMD21?
Do I modify this file: https://github.com/adafruit/uf2-samdx1/ ... src/main.c
It appears the brown-out detector is enabled for SAMD51 and disabled for SAMD21 by default. Why is that the case?
- adafruit2
- Posts: 22148
- Joined: Fri Mar 11, 2005 7:36 pm
Re: QT Py SAMD21 Bootloader Protection
we dont recall - it could have been an error in programming. we can look to see if its possible to enable it post-install!
- leafon
- Posts: 32
- Joined: Thu Sep 22, 2022 12:40 am
Re: QT Py SAMD21 Bootloader Protection
To summarize, could you please answer the following questions?
1. On the existing QT Py M0 boards, is the only way to enable the bootloader protection is to use the SWD interface and set the fuses?
2. Is it possible to use the .uf2 file update method to enable the brown out detector?
3. If we were to update the QT Py M0 boards using the SWD interface to flash the .bin file, how do we modify the files at https://github.com/adafruit/uf2-samdx1
to enable the brown out detector and boot loader protection?
1. On the existing QT Py M0 boards, is the only way to enable the bootloader protection is to use the SWD interface and set the fuses?
2. Is it possible to use the .uf2 file update method to enable the brown out detector?
3. If we were to update the QT Py M0 boards using the SWD interface to flash the .bin file, how do we modify the files at https://github.com/adafruit/uf2-samdx1
to enable the brown out detector and boot loader protection?
- danhalbert
- Posts: 4654
- Joined: Tue Aug 08, 2017 12:37 pm
Re: QT Py SAMD21 Bootloader Protection
I would suggest doing #2, since that should enable the bootloader protect fuse. If you do #3, just use the updater UF2 as you would do for #2, and rewrite the bootloader. That is easier than building a new bootloader.
I looked at the three QT Py M0's that I have, and they all have these fuse values:
It's been a while since I looked at this, but I believe the '2' indicates BOOTPROT is set to protect the first 8kB, as described in the datasheet. Here is a short Arduino program to report the current fuse values:
I looked at the three QT Py M0's that I have, and they all have these fuse values:
Code: Select all
D800C772
FFFF005D
Code: Select all
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
// Reasonable fuse values, set by the fuse repairer in the UF2 bootloader,
// but not necessarily what you will encounter from the factory.
// [0] 0xD8E0C7FA
// [1] 0xFFFFFC5D
uint32_t fuse0 = ((uint32_t *)NVMCTRL_AUX0_ADDRESS)[0];
uint32_t fuse1 = ((uint32_t *)NVMCTRL_AUX0_ADDRESS)[1];
Serial.println(fuse0, HEX);
Serial.println(fuse1, HEX);
Serial.println();
delay(2000);
}
- danhalbert
- Posts: 4654
- Joined: Tue Aug 08, 2017 12:37 pm
Re: QT Py SAMD21 Bootloader Protection
Mike, I believe we do enable BOOTPROT, since the bootloader updater can turn it off if desired.
- danhalbert
- Posts: 4654
- Joined: Tue Aug 08, 2017 12:37 pm
Re: QT Py SAMD21 Bootloader Protection
Re the brownout detector: we saw the spurious write problems that smashed things on low-voltage power up only on the SAMD51. One the SAMD21, enabling the brownout detector might cause the board not to boot when voltage was marginal, and some people might want to operate at marginal voltage. So if I remember right, we decided not to eliminate that possibility for the SAMD21, since we hadn't seen any bootloader smashing on SAMD21.
But it appears from your experiences and Thea's, that was an incorrect assumption.
https://github.com/adafruit/uf2-samdx1/issues/170
But it appears from your experiences and Thea's, that was an incorrect assumption.
https://github.com/adafruit/uf2-samdx1/issues/170
- adafruit_support_mike
- Posts: 67454
- Joined: Thu Feb 11, 2010 2:51 pm
Re: QT Py SAMD21 Bootloader Protection
Thanks for the correction Dan!danhalbert wrote: ↑Wed Jan 25, 2023 10:53 pm Mike, I believe we do enable BOOTPROT, since the bootloader updater can turn it off if desired.
- leafon
- Posts: 32
- Joined: Thu Sep 22, 2022 12:40 am
Re: QT Py SAMD21 Bootloader Protection
Dan,
Thank you for looking into this.
I can assure you that the BOOTPROT is disabled on the QT Py M0 boards.
I connected a brand new QT Py M0 board to a J-Link and dumped its flash content. As you can see, the BOOTPROT[2:0] is 0x7.
This matches what's on line 73 to 75 of the selfmain.c file:
https://github.com/adafruit/uf2-samdx1/ ... selfmain.c
#if defined(SAMD21)
fuses[0] = 0xD8E0C7FF;
fuses[1] = 0xFFFFFC5D;
Thank you for looking into this.
I can assure you that the BOOTPROT is disabled on the QT Py M0 boards.
I connected a brand new QT Py M0 board to a J-Link and dumped its flash content. As you can see, the BOOTPROT[2:0] is 0x7.
This matches what's on line 73 to 75 of the selfmain.c file:
https://github.com/adafruit/uf2-samdx1/ ... selfmain.c
#if defined(SAMD21)
fuses[0] = 0xD8E0C7FF;
fuses[1] = 0xFFFFFC5D;
- danhalbert
- Posts: 4654
- Joined: Tue Aug 08, 2017 12:37 pm
Re: QT Py SAMD21 Bootloader Protection
Hmm, yes, but further down in selfmain.c, the FF value is changed to the passed in `bootprot` value:
https://github.com/adafruit/uf2-samdx1/ ... .c#L96-L97
Further down, in `main()`, at line 147, this routine is called to turn off BOOTPROT:
Then, after the updated bootloader is written, BOOTPROT is set to 8k (line 204 ff.)
In any case, this code is in selfmain.c, which is used only by the update-bootloader UF2. If you load one of those UF2's, you'll find that the fuses are set properly. I ran https://github.com/adafruit/uf2-samdx1/ ... 3.14.0.uf2 on on one my QT Py's, and after running, the fuses are:
-------------------------------------
The code above is not used at the factory when the initial bootloader is programmed. There is a separate non-published program that takes the original bootloader .bin file. It is supposed to fix up BOOTPROT afterwards, and it appears it is not. I will investigate that. Thank you very much for finding this.
In the meantime, you can fix BOOTPROT all your QT Py M0's by running the update-bootloader .UF2 linked to above. I realize this is tedious, and am sorry for this. Of course try one or two to confirm.
-------------------------------------
This does not address the brownout issue. That is something separate we perhaps should address in the bootloader, or in startup code. What code are you running on these QT Py's? Is it Arduino-based, or is it custom ASF3 or ASF4 or other firmware?
https://github.com/adafruit/uf2-samdx1/ ... .c#L96-L97
Code: Select all
// Update fuses BOOTPROT value with desired value.
fuses[0] = (fuses[0] & ~NVMCTRL_FUSES_BOOTPROT_Msk) | (new_bootprot << NVMCTRL_FUSES_BOOTPROT_Pos);
Code: Select all
#ifdef SAMD21
// Disable BOOTPROT while updating bootloader.
set_fuses_and_bootprot(7); // 0k - See "Table 22-2 Boot Loader Size" in datasheet.
#endif
Code: Select all
#ifdef SAMD21
// Re-enable BOOTPROT
set_fuses_and_bootprot(2); // 8k
#endif
Code: Select all
D800C772
FFFF005D
The code above is not used at the factory when the initial bootloader is programmed. There is a separate non-published program that takes the original bootloader .bin file. It is supposed to fix up BOOTPROT afterwards, and it appears it is not. I will investigate that. Thank you very much for finding this.
In the meantime, you can fix BOOTPROT all your QT Py M0's by running the update-bootloader .UF2 linked to above. I realize this is tedious, and am sorry for this. Of course try one or two to confirm.
-------------------------------------
This does not address the brownout issue. That is something separate we perhaps should address in the bootloader, or in startup code. What code are you running on these QT Py's? Is it Arduino-based, or is it custom ASF3 or ASF4 or other firmware?
Please be positive and constructive with your questions and comments.