Starting T1000-E Bootloader in uf2 mode

Hello
I have a Zephyr application that I’m porting to run on T1000-E.
To enter the bootloader in uf2 mode, where it mounts the usb volume to drag and drop firmware images, I use the same code as Meshtastic does
With the exception of sd_softdevice_disable() because I’m on Zephyr
However the bootloader does not start - it starts my app instead.
I looked at the bootloader code and it checks the NRF_POWER->GPREGRET value and if is set to 0x57 it starts the tinyusb and mounts the volume. That’s not happening on my T1000-E
I can still enter the bootloader manually using this sequence
Press button
Connect-disconnect-connect charger
Wait ~1second.
Release the button
I noticed that when the bootloader usb volume is mounted the “INFO_UF2.TXT” file has the following information
UF2 Bootloader 1.00
Model: Seeed T1000-E for LoRaWAN
Board-ID: nRF52840-T1000-E-v1
This is not the same version as Arduino github has so I’m assuming this is a custom branch, right?
Any ideas why the bootloader does not start for me?
Thank you!

Hi there,

This sounds to me like a mismatch between how UF2 bootloader is expected to be triggered (as designed for Adafruit/Arduino stack) and how Zephyr interacts with the nRF52840 boot and power registers, especially with regard to GPREGRET-based bootloader entry.

and that the mounted bootloader reports:

UF2 Bootloader 1.00
Model: Seeed T1000-E for LoRaWAN
Board-ID: nRF52840-T1000-E-v1

This differs from the stock Adafruit bootloader, so you suspected it may be a custom bootloader.

Yes, you’re absolutely right to suspect that.
That INFO_UF2.TXT file shows custom board ID and bootloader version, so it’s a Seeed-specific fork.

Even if you set NRF_POWER->GPREGRET = 0x57, the bootloader may not honor that value unless Seeed implemented that logic explicitly.

In Adafruit’s UF2 bootloader, setting GPREGRET to 0x57 is the standard way to trigger UF2 mode from code.

However, Seeed’s custom bootloader may:

Require additional bits set (e.g. specific RAM values or softdevice flags)

Not support software entry into UF2 mode at all

Only support manual button sequence, which you described works fine.

  1. Confirm if GPREGRET is supported by the Seeed bootloader:

Try writing NRF_POWER->GPREGRET = 0x57; NVIC_SystemReset(); and immediately reboot. If it still skips bootloader, it’s not implemented in their fork.

HTH
GL :grin: PJ :v:

I have a strong hunch ,button only is built that way? Maybe a security reason , above my pay grade .:+1:

Meshtastic firmware works with a WebFlasher app. It has UI to download a firmware image to a connected device. The app sends a byte over a serial connection and in response Meshtastic firmware does the following

void enterDfuMode()
{
// SDK kit does not have native USB like almost all other NRF52 boards
#ifdef NRF_USE_SERIAL_DFU <–only defined in the wio-sdk-wm1000 variant
enterSerialDfu();
#else
enterUf2Dfu();
#endif
}
And enterUf2Dfu() in Aurduino SDK sets NRF_POWER->GPREGRET = 0x57, and calls NVIC_SystemReset();
My zephyr code does exactly that but bootloader is not entered. The only thing I’m doing differently is not call sd_softdevice_disable() which disables the Softdevice. But Nordic says this is only for directly accessing the GPREGRET register which cannot be done while SoftDevice is running. So I’m at a loss why the same code works on Meshtastic (built with nRF SDK and Segger) and does not work in my Zephyr app. Is there a way to examine the bootloader code that runs on T1000-E ? Who do I ask?
Thanks

Hi there,

Yes Indeed , I’m familiar with the App, very much so. you have done your homework and have you verified the GPREGRET = 0x57, stay and indeed is set? Have you tested that ?
Try writing NRF_POWER->GPREGRET = 0x57; NVIC_SystemReset(); and immediately reboot.
If it still skips bootloader, it’s not implemented
, so then I would send an e-mail to tech support at seeed and see what comes back, I’m certain there is a person responsible and or a group of seeedineers that could say one way or the other. Would be good to know the Answer.:+1:
, but as I intimated , it may be for security reasons beyond my limited understanding when dealing with Meshtastic devices :person_shrugging:

HTH
GL :slight_smile: PJ :v:

Yes, my app uses the same code as meshtastic in the links I provided earlier and sets GPREGRET=0x57.
NVIC_SystemReset() resets the board so not sure what you mean by “immediately reboot”
Upon board reset it does not enter the bootloader.
I verified that GPREGRET is set to 0x57 before rebooting. So unless NVIC_SystemReset does something to that register I’m reasonably certain that it contains the value 0x57. Of course I have no way to verify it 100% as I don’t have access to the bootloader code.

Hi there,

Yes, agree you are doing the same, the difference is the seeed bootloader is ignoring the GPREGRET being set. fire the e-mail to seeed
see what comes back. something is missing maybe they can tell us.

I think they have a number of Meshtasic devices so I’m relatively certain , someone there knows what’s what in the BL dept.

HTH
GL :slight_smile: PJ :v:

Sorry I’m a newbie here :slight_smile:
Who should I send the email to ? I thought this is the place as the forum is for “seedstudio”
Thanks
Andy

Hi there,

not to worry , we all started the same. So

go there and click message.

Yes this is the user support forum, they monitor it mostly jumping in when they can, You need a specific piece of info and your not asking like it’s a hand-out or needs a SPOON… anyone can see you posted and put in the work, looked at the info and found :grin: the lack of any for the BL flashing directions. If they used the vanilla BL it wouldn’t be a thing
I’m hoping a answer comes back for both.

HTH
GL :slight_smile: PJ :v:

Got it, thank you much, I’ll update here

1 Like

My colleague was able to enter the uf2 mode programmatically using the same calls as Meshtastic.
The only difference is the bootloader version on our T1000 devices
On my device the UF2_INFO.TXT reads:

UF2 Bootloader 1.00
Model: Seeed T1000-E for LoRaWAN
Board-ID: nRF52840-T1000-E-v1

His reads

UF2 Bootloader 0.9.1-5-g488711a lib/nrfx (v2.0.0) lib/tinyusb (0.12.0-145-g9775e7691) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)
Model: Seeed T1000-E for Meshtastic
Board-ID: nRF52840-T1000-E-v1
Date: Jul 15 2024
SoftDevice: S140 7.3.0

This must be the smoking gun

1 Like

Hi there,

Nice, I most definitely agree. They look to be built from different SDK’s it seems? and no build metadata. probably Seeed’s stock LoRaWAN bootloader that in this version often doesn’t respond to programmatic resets into UF2 unless Seeed implemented the GPREGRET check manually. ?
The othere Clearly built from a newer UF2 bootloader branch, probably from the Adafruit nrf52 fork or Meshtastic’s own fork. YMMV and AI agrees

" Example Reference:

Meshtastic’s fork of the Adafruit UF2 bootloader for T1000-E likely comes from a branch like this:

You’ll notice the same versioning and build signatures as seen in your colleague’s device. The LoRaWAN version is more of a production/stable bootloader and may intentionally omit features like USB DFU or GPREGRET handling.

Great info though :+1:

HTH
GL :slight_smile: PJ :v: