-
Notifications
You must be signed in to change notification settings - Fork 110
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
stub support (ESF-126) #103
Conversation
b4d52b9
to
fed960a
Compare
Hello @higaski thanks for the contribution! I will investigate the issue you are having as soon as I can. Currently, our intent is to use the Rust flasher stub for |
Sure, feel free to change the way the stub loader gets generated (and or included) to whatever way you prefer. I already thought that the JSON conversion would be more of a temporary thing. |
I'm not sure we should do both compile and run-time stub toggling this way. In the case of run-time toggling, if the compiler has visibility into the fact that stubs are not used at compile-time, it will still mark all unused symbols for removal by the linker. Conversely, we could just leave the compile-time toggle and simplify the code. Cases where we would try stub flashing and then fall back if something doesn't work should be extreme. Personally, I would add a boolean flag |
Regarding the Edit: I realize this is not what you are reffering to, according to the code, |
include/esp_loader.h
Outdated
* - ESP_LOADER_SUCCESS Success | ||
*/ | ||
#if STUB_ENABLED | ||
esp_loader_error_t esp_loader_no_stub(bool no_stub); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A name like esp_loader_use_stub
/esp_loader_dont_use_stub
would be more verbose.
Stub support should be gated behind |
The reason I've added both, compile- and run-time toggling is that embedded systems might not want to add the stubs if they don't need them. I assume adding all stubs takes a reasonable amount of flash memory. Run-time toggling on the other hand is useful for things like x86 applications where the footprint of all stubs isn't an issue...
I don't see how this could happen. The compiler can't optimize away the stubs if their usage depends on another run-time value.
I like that, it sounds like a clean solution. It would also make
esp-serial-flasher/examples/common/example_common.c Lines 257 to 273 in 2851591
then detecting the flash size fails. if (esp_loader_flash_detect_size(&flash_size) == ESP_LOADER_SUCCESS) {
if (image_size + offset > flash_size) {
return ESP_LOADER_ERROR_IMAGE_SIZE;
}
loader_port_start_timer(DEFAULT_TIMEOUT);
RETURN_ON_ERROR( loader_spi_parameters(flash_size) );
} else {
loader_port_debug_print("Flash size detection failed, falling back to default");
} More specifically this call here esp-serial-flasher/src/esp_loader.c Line 265 in 2851591
I can't find documentation of an |
It will happen if the value is known at compile time and the effect is visible in that translation unit. In the case of using the config struct, it will not happen without link-time optimization, however if we have a separate |
So that I understand you correctly. Let's drop compile-time support in favor of a separate |
Yes, either that or only use compile-time toggling. Two toggles complicate code, and over time will create bugs when people forget to check both. If you're concerned about the approach, try mocking up a quick test and see if the stubs are dropped by looking at the mapfile. |
I assume that is again because of this line: RETURN_ON_ERROR( loader_spi_parameters(flash_size) ); Reading flash ID is also done by Edit: looks like there is a difference in the command for changing the baudrate: https://github.com/espressif/esptool/blob/master/esptool/loader.py#L1138 |
When writing to RAM, we need to check if we are overwriting the stub. |
Yes, this works. Now I'm starting to miss function overloads... esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate) The stub version would require the old baud rate as second parameter. typedef struct {
uint32_t sync_timeout; /*!< Maximum time to wait for response from serial interface. */
int32_t trials; /*!< Number of trials to connect to target. If greater than 1,
100 millisecond delay is inserted after each try. */
uint32_t baudrate; /*!< Like this maybe? */
} esp_loader_connect_args_t; and then store a local copy of it. This would then allow setting the old baud rate for the CHANGE_BAUDRATE command depending on whether the stub loader is used or not. /edit esp_loader_error_t esp_loader_change_transmission_rate_from_to(uint32_t from, uint32_t to) but then the user would have to know those subtle differences between stub and ROM loader. |
src/protocol_common.c
Outdated
|
||
// stub loader sends a custom SLIP packet of the sequence OHAI | ||
uint8_t buff[4]; | ||
err = SLIP_receive_packet(buff, sizeof(buff) / sizeof(buff[0])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a problem here where the UART/USB specific protocol details are bleeding into the common source file, and we are adding an ugly #ifdef
to a common module, defeating the purpose.
Can we move loader_run_stub()
into protocol_uart.c
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
But half of the functions inside the common module are already not really common are they? The header contains an ifdef as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is true, however
- We can address this at a later time
- They will be common once stub gets adapted for use over SPI (though they will depend on the stub use)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved loader_run_stub
to protocol_uart.c
https://github.com/higaski/esp-serial-flasher/commit/928dd73850c2c2cd689ecdeb854afe7b2b159622
For this reason, the fact that we now have to track if the stub is running for some things (like checking whether we are overwriting it), and the fact that stubs are now a part of the build process, whether users use them or not (along with attempting to pull from esptool repo) I am leaning more and more to a preprocessor only toggle without the possibility of deciding on stub use at runtime at all. @dobairoland WDYT? |
I'd like to keep the runtime toggle if possible. I've already built it into my application. /edit |
Unless I am missing something, if we always upload the stub with |
When uploading the bootloader (mem* functions) you can't check for RAM being overwritten. Of course the stub loader gets written to the stub loader destination. So, even with a compile time switch you'd need a flag for this special case to make sure that check does not run before the stub is in place. Maybe we can find a compromise and have both again, compile- and run time switch? /edit |
Sorry, maybe I didn't elaborate well enough. To upload anything using |
Then the stub loader would require its own esp_loader_mem_start (and friends) functions. Currently I use it to upload the stub and those functions don't know if the stub is already in place or not. |
You're correct, my apologies. |
cmake/gen_flasher_stub.py
Outdated
"stub_flasher_32c3.json", # ESP32C3_CHIP | ||
"stub_flasher_32s3.json", # ESP32S3_CHIP | ||
"stub_flasher_32c2.json", # ESP32C2_CHIP | ||
"reserved.json", # ESP32_RESERVED0_CHIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to cause an exception, and write " // " + file_to_download + "\n" " {},\n" "\n"
to the file, however if we are adding support for a new chip, and mistype the .json
filename, now we're going to need to debug things to find out that the reason the stub info all 0s is because of that.
An even bigger problem is when this overwrites existing stubs for people without an internet connection at the moment of building.
Perhaps we can add special handling for reserved.json
, and either not handle the exception, or print a friendly error message that the specified file could not be found (and that it is possibly because the host has no internet connection).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The target which creates the stubs does not run during the build. I've intentionally chosen not to do that. If you don't explicitly invoke the "gen_flasher_stubs" target the stubs will not change!
I'd have preferred to scan the GitHub repo and only download existing .json files, but I wanted to match the existing target enumeration order. That's also the reason why there absolutely needs to be a hole for the currently reserved target. Otherwise the following enum value would be off by one.
I agree that this isn't ideal though, but getting rid of the "reserved" value is not an option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason my brain hallucinated the PRE_BUILD
argument, my bad.
Still, we should not fail by writing zeroes, but instead notify the user. We don't have to get rid of the "reserved" value, just add a check for it and work around it by writing " // " + file_to_download + "\n" " {},\n" "\n"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codegen of the stubs now fails if the HTTP request fails for whatever reason.
https://github.com/higaski/esp-serial-flasher/commit/e4cbcae6c606b79850abc46dbd9a30457a613752
Overall, the PR seems in a solid state now, I will dedicate some time to test it on hardware. @radimkarnis If you have the time please take a look as well. |
I apologize, I should learn to read with comprehension... I've thought esp-flasher-stub is GPL but actually the esptool is. So, in fact, my tool is currently violating GPL (oops 🙈 ). The URL option would solve my problem of course, but it sounds like an unreasonable amount of work for... well... just me. How much time would you estimate to get the >16MB issue done? Because if you can manage that over the next few months, your time would probably be better spent there. |
Well? |
Unfortunately we cannot commit to a timeframe at the moment, but it is quite possible that we will add the >16MB feature to the Rust flasher stub within the next few months. I am currently resolving an issue with the first packet being lost after the baudrate change with the Rust stub, but I expect that the stub support will be merged shortly after. If you are fine with this, we will proceed without adding additional support for using the |
Sounds good to me, thanks! |
Hi @higaski , please take a look at the changes merged and adapt your usecase. We've added support for overriding the stub sources as well, so you can use the |
I appreciate the effort of adding an override for the stub sources, but I can't figure out how to use it properly. E.g., the ESP32 one is called So even if the path gets overriden the python code gen is going to fail isn't it? if stub_override_path:
with open(f"{stub_override_path}/{file_to_download}") as file_path:
cfile.write(read_stub_json(file_path)) |
Sorry for the confusion, I forgot to mention that the |
Sorry for the confusion, I forgot to mention that the esptool stub has been moved to a new repository which will have releases with the same naming conventions. @higaski The release is done: https://github.com/espressif/esptool-legacy-flasher-stub/releases |
Little user guide would have been helpful: This seems to work "SERIAL_FLASHER_STUB_PULL_VERSION 1.1.0"
"SERIAL_FLASHER_STUB_PULL_SOURCE https://github.com/espressif/esptool-legacy-flasher-stub/releases/download" |
@DNedic Here's a log of a failed try And here one writing the same binaries but with my old branch /edit |
Hi @higaski , the timing issues we had were due to the flasher stub not being ready for a new command immedeately after responding to a previous one. For this reason, we have added this delay. It looks like the issue you are having has identical symptoms to the ones we faced. With One other way we could solve this is to make retries apply to all commands. |
@DNedic |
If you have a logic analyzer, or an oscilloscope, is it possible for you to compare the timing between the ESP port and your own port? That might give us some clues. |
@DNedic /edit |
You mentioned using 1.4.0, we should have fixed this issue in 1.4.1 |
Problem still exists for me in 1.4.1 According to the trace the stub response looks strange
Command 0x13 (SPI_FLASH_MD5) does trigger a response with 0x12. /edit 55 0e 40 72 d4 2f 93 1b 96 90 05 bd 63 99 20 9b is exactly what get's calculated inside |
This is rather strange @higaski , unfortunately I was not able to reproduce it with the ESP32 port example. The problem, from your log does seem to be that the command for the response is wrong, however this makes me suspicious of it being a hardware problem. Can you reproduce this exact output every time or are different bytes also wrong from time to time? |
No, it always looks like this. Just tried an ESP32S3-DevKitC instead (checksum is different obviously):
|
Is it possible for you to get a logic analyzer trace of this? Also, since you're using an user port we really need to be sure that the problem is in the library and not the port/hardware combination itself. |
Sure, give me some time though. I'll see to get it done till the end of the upcoming week. |
Thanks for the feedback @higaski ,it looks like this is a problem with either the port or the hardware, since the tracing is happening at the port level and the target is receiving and sending the correct data. You can try using different USB to Serial adapters, it is possible that there is a slight enough baud mismatch to cause this. You can also try using the esp-usb-bridge project as an USB to Serial converter. |
Wouldn't a hardware problem also be present when not doing the MD5 verify? |
It is possible, you can try checking if other instances of 0x13 get wrongly read as well, but because we cannot really reproduce your issue and the fact that tracing happens at the port level and you're using a user port means that we can't help you with the issue unfortunately. If there infact turns out to be a problem not at the port level, for instance due to memory corruption due to buffer over/underruns in the library or any other similar cause, please make sure to report that. Since the port itself runs on desktop PCs you can try using tools like Valgrind. |
@higaski Do you happen to still have the setup you had used when the MD5 issue with the stub happened? I'm wondering what the ECO version of the target chip is. |
Yes I do, will report back next week. |
Does this contain the information you're looking for? I guess it's the chip revision? rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7176
load:0x40078000,len:15564
ho 0 tail 12 room 4
load:0x40080400,len:4
load:0x40080404,len:3904
entry 0x40080640
I (31) boot: ESP-IDF v5.3 2nd stage bootloader
I (31) boot: compile time Oct 23 2024 07:27:53
I (31) boot: Multicore bootloader
I (36) boot: chip revision: v1.0 /edit rst:0xc (RTC_SW_CPU_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403758e0
SPIWP:0xee
Octal Flash Mode Enabled
For OPI Flash, Use Default Flash Boot Mode
mode:SLOW_RD, clock div:1
load:0x3fce2810,len:0x178c
load:0x403c8700,len:0x4
load:0x403c8704,len:0xcb8
load:0x403cb700,len:0x2db0
entry 0x403c8914
I (37) boot: ESP-IDF v5.3 2nd stage bootloader
I (38) boot: compile time Oct 23 2024 08:06:43
I (38) boot: Multicore bootloader
I (41) boot: chip revision: v0.1 |
Thanks for the info! I will test these exact chip revisions. It is possible (however unlikely that both suffer from it) that ROM versions for certain revisions can have bugs. |
Add stub loader support as requested by #92 and #84.
The stubs are pulled from https://github.com/espressif/esptool/tree/master/esptool/targets/stub_flasher. A CMake target called
gen_esp_stubs
pulls the json files from a specified esptool version and converts them to .h/.c files. That target does not depend on ALL and does not get created if Python isn't installed (a warning is issued though).New Kconfig option- SERIAL_FLASHER_STUB_ENABLED ~~~~ defaults to y
Additions to public API:
esp_loader_error_t esp_loader_connect_to_stub(esp_loader_connect_args_t *connect_args)
Upload stub loader, then connect to it instead of the internal ROM loader.
esp_loader_change_transmission_rate_stub(uint32_t new_transmission_rate, uint32_t old_transmission_rate)
Like
esp_loader_change_transmission_rate
but has a second parameter for the stub version of the CHANGE_BAUDRATE command.Additions to private API:
-esp_loader_error_t loader_no_stub(bool no_stub)
~~~~ Actual implementation of esp_loader_no_stub.
esp_loader_error_t loader_run_stub(target_chip_t target)
Upload and run the stub loader.
New definition- STUB_ENABLED