-
Notifications
You must be signed in to change notification settings - Fork 976
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
[Beta] Jump to system memory boot from user application #710
base: main
Are you sure you want to change the base?
Conversation
Woohoo, it realy works) but i failed resetting it by 1200 baud and added simple mapple style reset (if "leaf" trigger recieved) so now it resets and uploads flawlessly using mapple's upload-reset and cubeprog in dfu mode after :) |
@stas2z |
yes, ive tried to connect with arduino terminal using 1200 baudrate and also with putty, ive uploaded a simple echo fw to it and it works as expected at 1200 without reset |
I've just tested with a Nucleo-F401RE and a USB shield and this work fine... |
yes, sure |
Could you try with (several time if needed): |
No, its not working for my board Also i found a problem i got when i tried to implement it by myself, it just reboots without entering a bootloader if any gpio pin initialized, just make pinMode for builtin led and it will stop loading boot. resolved it by adding following code before remapping and jump to boot
|
In fact I used the backup register to ensure having original config and no feature configured. |
Ok, it's my fault, HSI is also works and seems like will be better. But it's not important, cuz SysTick reg values reset do the magic. Reiniting RCC i found by googling, but in my case it can be skipped. Also ive tried reset by 1200 baud my another F4 board (black F407VE), and still no luck (maple reset works flawlessly), probably problem on my side, will try to find what i did wrong while i appleid this pull request to my local repo copy |
Ok. In fact I've made the minimum to work. Resetting systick an RCC could be added, I guess. Maybe also HAL_DeInit as it is init for backup access. |
Anyway, it works already, for me at least :) reset procedure is not so important, also usb is not only way to use it, cuz im going silently update slave devices built with chips with only serial dfu supported, so bootloader reboot requests can be implemented as hwserial commands or gpio pins. |
Right, this is not only for USB. |
its weird, but 1200 baud reset working under windows for me, without rebuilding |
which Linux OS do you used? |
mint 19.2 (ubuntu 18.04 based) |
Ok, I'v tested on 14.04 and 16.04 anyway this should be the same or a usb driver issue as the speed is not relevant for this kind of device |
Seems like it was a usb driver glitch, ive rebooted back to linux and everything works as it should, sorry for this inconvinience |
OK so now it is fine on Windows and Linux ? |
@fpistm yep, both |
Good news, Ive successfully rebooted stm32f051c8t6 to bootloader mode using this PR. Will check stm32f030c8t6 a bit later. |
i 'tested' this with windows by manually opening the port at 1200 which did in fact kick into the DFU bootloader! then i uploaded. so we need an update to the tool, like linux has, and it should work. @fpistm im not great at bat files but i could try making the change |
On most CPUs, detecting the system flash address is not needed, since they can remap the system flash onto adress 0x0 and the bootloader reset vector can be read from there. This approach also more closely mimics a bootloader start using the BOOTx pins. For CPUs that cannot remap flash, this hardcodes the address of system flash and jumps there instead. For H7 and F7, this is also how it works when using the BOOT pins. For F1, remapping can be done using the BOOT pins, but not from software, resulting in a difference with a BOOT-activated bootloader. This puts the code that figures out where the bootloader lives back in a separate function. This makes the code easier to read, and makes it easier to jump to custom bootloaders (e.g. in normal flash instead of in system flash). TODO: Check value for H7, AN2606 and reference manual disagree
This ensures that the SP is not modified after loading it and ensures a jump instruction is used. The assembly code was based on micropython and another STM32 core: https://github.com/micropython/micropython/blob/f6375ac3ebac28656a0a757952d32c265b1ba7aa/ports/stm32/powerctrl.c#L71-L78 https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/bacc184288a4644b2ee6a97672334983f3e788ab/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L166
This waits for 250ms, just like the Arduino SAM and SAMD cores do (AVR waits only 120ms), to allow the USB host and application a bit more time to close the port and clean up.
This function calls HAL_Delay, which relies on the systick timer to be running, so this results in an infinite loop. This should probably be fixed in HAL_Delay, but for now just remove the calls to USB_DevDisconnect and USB_DevConnect and replace it with the bit twiddles needed for some chip families (e.g. the F4), breaking compilation and/or functionality for others.
This adds support for the DFU runtime protocol, which allows resetting into the bootloader using a DFU command. This allows e.g. dfu-util to handle the complete firmware upload, including the needed reset. This consists of a number of changes: - An extra interface is added to the USB configuration descriptor. This descriptor has two parts (interface descriptor and functional descriptor) which together indicate to a host that this device supports DFU. - Control packets to this new interface are detected by the CDC code an forwarded to a new USBD_DFU_Runtime_Control() function. - This new function handles the DFU GET_STATE, GET_STATUS and DFU_DETACH commands. The former are optional, but simple enough, the latter is mandatory and handles resetting into the bootloader. - The CDC device descriptor is changed to become a composite device (CDC and DFU). This allows operating systems (in particular Windows, Linux did not really need this) to identify two different subdevices, and install different drivers for each (on Windows, this is serusb for the CDC part and WinUSB/libusb for the DFU part). Without this, dfu-util on Windows could not access the DFU commands when the serial driver was loaded. Because the CDC functionality already exposes two interfaces (which together form a single serial port), an IAD (Interface Association Descriptor) is inserted before these interfaces to group them together in a single subdevice. No IAD is needed for the DFU interface, since it is just a single interface. To become a composite device, the device class must be changed from CDC to a composite device class. This was originally class 0/0/0, but together with the IAD, a new EF/2/1 deviceclass was also introduced, which is used now. Note that this only adds descriptors and a command handler on the default control endpoint, so no extra (scarce) endpoints are used by this, just a bit of memory. This commit is still a bit rough, because: - The DFU descriptors and code are now pulled in directly by the CDC code (and HID is not supported yet). Ideally, there should be some kind of pluggable USB library where different interfaces can be registered independent of each other (see also stm32duino#687). - The interface number is hardcoded in the DFU descriptor. - The reset to bootloader happens immediately, while it might be better to wait a short while to allow the current USB transaction to complete. - DFU support is unconditionally advertised, while not all boards might support DFU.
Bootloader management is not applicable for this serie. Signed-off-by: Frederic Pillon <[email protected]>
@fpistm This is a very cool feature, I have tested this PR on my Windows10 machine for my 32f411Disco-boards and Blackpill works absolutely fine. this reduces lot of my efforts in uploading code. |
It will be when ready. 😉 |
@fpistm Could you please tell if this is the only issue with this PR that still remains or there any others? |
AFAIK there's still a few other bits of code that work but are too hardcoded or break on some boards, see for example #710 (comment). Also, I think the DFU-descriptor and handling might also need to be slightly more generalized. There might be other issues too. |
I worked on another board with custom bootloader running my version of this PR and ran into an issue, related to what I previously commented:
It seems that a custom bootloader at the start of flash is not compatible with the noinit variable approach I used. The bootloader runs before the sketch, so when it does a software reset, does not clear the reset reason and writes to the noinit Also, I noticed this previous comment from @fpistm:
There has been some work in arduino-cli recently that touches upon this, though I don't think it actually fixes this, though. For reference: arduino/arduino-cli#1263 and arduino/arduino-cli#1267 |
@fpistm if it helps, I rechecked that this works, applying the patches on 2.0.0, with an Also had success getting it to work on a platform.io project, using an STM32F405RGT board with a build hook that bounces the port manually and then waits for |
Oh, all 3d printers based on STM32F446 would need this feature badly. |
Hello, Any news on that feature? I'm waiting so badly for that to use in my STM32L432 projects. |
Hey, |
I have to rebase and finish it. When I will have time... |
Hi, is there any news on this feature ? I have a custom F446 devellopment board I can test on my side if this help. |
This PR add support of automatically jump to system memory bootloader.
Currently, this is trigger only thanks a Serial over USB (USB CDC have to be enabled).
By setting the port at 1200 speed this request the restart by setting a magic number (0x515B) in a backup register then require a system reset.
Then when restart, this value is checked and jump is performed if match to go in bootloader mode.
STM32 Cube programmer scripts is currently under update.
See stm32duino/Arduino_Tools#44
Tested under Linux:
Under Windows manually set speed at 1200 works as expected. Script under update.
Fixes #706