-
Notifications
You must be signed in to change notification settings - Fork 1k
[Beta] Jump to system memory boot from user application #710
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
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 :)
p.s. tested it with F401
@stas2z
It should be fine to find why it is not reset setting 1200.
Did you try manually without upload scripts?
@stas2z
It should be fine to find why it is not reset setting 1200.
Did you try manually without upload scripts?
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...
You set the USB CDC port at 1200 not an HardwareSerial port ?
I've just tested with a Nucleo-F401RE and a USB shield and this work fine...
You set the USB CDC port at 1200 not an HardwareSerial port ?
yes, sure
im using connection to ttyACM0 as my device appeared in dmesg (blackpill F401CC)
Could you try with (several time if needed):
stty -F /dev/ttyACM0 1200
stty -F /dev/ttyACM0 1200
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
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
__HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_HSE);
__HAL_RCC_SYSCFG_CLK_ENABLE();
In fact I used the backup register to ensure having original config and no feature configured.
I'm surprise to see HSE in your code as it should be HSI.
In fact I used the backup register to ensure having original config and no feature configured.
I'm surprise to see HSE in your code as it should be HSI.
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.
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.
0ed4b83 to
3bc114c
Compare
its weird, but 1200 baud reset working under windows for me, without rebuilding
but for linux it's not, even with sudo (any terminal app works fine, but 1200 baudrate reset not)
which Linux OS do you used?
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
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
OK thanks @ladyada for the feedback.
I will update it on monday.
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 <frederic.pillon@st.com>
99ba762 to
a37e822
Compare
rohitsam
commented
Nov 4, 2020
@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 would be great if this feature could be merged.
It would be great if this feature could be merged.
It will be when ready. 😉
There is an issue with the
upload.use_1200bps_touch=trueThe first time you want to flash a board thanks DFU, there is no com port available, so no port displayed in the menu (port is grayed). The board is manually start in STM32 BOOTLOADER mode thanks the BOOT0 pin and the upload is OK. The 1200 touch does nothing.
@fpistm Could you please tell if this is the only issue with this PR that still remains or there any others?
Thanks.
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:
I also wondered if this should support jumping to custom bootloaders (e.g. not the system bootloader, but a bootloader in flash). However, I just realized that if these are used, they will likely live at the start of flash, so just a normal reset will start them (possibly combined with writing some RTC value as, e.g. see here). So, the jump-to-bootloader code from this PR does not need to handle jumping to those bootloaders, (...)
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 BootIntoBootloaderAfterReset variable in RAM (i.e. by just using that location for something else), the jumpToBootloaderIfRequested function will jump to system ROM bootloader, even when it is not requested (and even more, makes no sense). In general, jumping to the ROM bootloader makes no sense when combined with a custom bootloader, so this probably needs a board-dependent define to disable all the jump-to-bootloader handling (or maybe automatically disabled if LD_FLASH_OFFSET and/or VECT_TAB_OFFSET is set, which effectively means a reset does not reach us. Or maybe it would be better to disable this explicitly and check against these defines as a sanity check).. This might be part of some refactoring to include the jump-to-custom bootloader (HID and the other one I think) in the same structure as jump-to-custom bootloader.
Also, I noticed this previous comment from @fpistm:
If for any reason the Serial monitor is opened and the board is disconnected then the port still selected in the menu and in this case the 1200 touch failed and the upload is ended. I think it should only report that the COM port is not found and try to upload anyway. In my case I've simply restart my board manually in STM32 bootloader mode so the upload would work properly.
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
adragomir
commented
Oct 15, 2021
@fpistm if it helps, I rechecked that this works, applying the patches on 2.0.0, with an STM32F405RGT flavor board (like Adafruit Feather Express STM32F405, or Sparkfun Thing Plus STM32F405)
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 dfu-util -l
jiri-jirus
commented
Feb 3, 2022
Oh, all 3d printers based on STM32F446 would need this feature badly.
Kamoool
commented
Mar 13, 2022
Hello,
Any news on that feature? I'm waiting so badly for that to use in my STM32L432 projects.
Kamoool
commented
Jul 7, 2022
Hey,
Has anyone checked that with 2.3.0?
Hey, Has anyone checked that with 2.3.0?
I have to rebase and finish it. When I will have time...
kingovchouffe
commented
Jan 9, 2024
Hi, is there any news on this feature ? I have a custom F446 devellopment board I can test on my side if this help.
Uh oh!
There was an error while loading. Please reload this page.
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