-
Notifications
You must be signed in to change notification settings - Fork 7.3k
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
[TW#16349] External flash chain bootloader #1205
Comments
When you say "burning efuses", you mean for SPI flash pin remapping? So you want something like:
We don't support such a configuration but it is certainly possible with a custom second stage bootloader. You should be able to call the following ROM function from the second stage loader to configure the pins (the ROM function doesn't anything particularly magic, just sets the GPIO matrix, but given it already exists you may as well use it): The "spiconfig" param to this function has the pin numbers (apart from WP pin) encoded as per the results of this function: But you don't need to read these from efuse, you can build the integer using the macros at the above link. There may be some additional complexity because the first stage ROM bootloader has already initialised the SPI flash chip. Noone has probably tested this exact configuration (starting from one flash chip and then switching). But the above should get you most of the way there, if you get stuck then let me know. Presumably once we have a fix for espressif/esptool#243 this may also illuminate this (I'm not sure what's going on there, unfortunately it will probably be a couple of weeks before I'm in a position to test it properly). Given this is more of a discussion than an "issue" in IDF then a good place to continue discussing it is probably the forums - https://esp32.com |
Yes, "burning efuses" refers to
My initial concept is to just #define the pins in code rather than acquiring the information. I believe I can use the ROM functions to set the configuration. However, the key is going to be what happens after configuration. Ideally, I would like to just call a "warm boot" function in ROM that would use the now updated SPI configuration. I intended this to be more a supported "feature request" than a "discussion". If I am to author it myself, then I agree its a "discussion" and better suited to the forum. |
I think you should be able to continue with the normal bootloader process after the SPI flash hardware is reconfigured with the new pins (assuming that the "new" external flash contains the partition table and all of the app partitions). For the case where pins are remapped in efuse, the second stage bootloader and IDF apps rely on the initial ROM bootloader to have configured the SPI flash hardware. ie AFAIK there isn't anywhere in software which reads the efuses and changes SPI flash behaviour based on these (if it turns out there is, we can change it to read the current GPIO matrix configuration instead, but I'm fairly sure there is not).
We're unlikely to add this as a directly supported feature. There would be quite a bit of tooling to support runtime bootloader flash configurations, and anyone who needs this feature will have quite specific requirements. Supporting these in a generic way "out of the box" will be difficult. However, something which we are planning on doing is to make the bootloader "hookable" so there are some levels of customization available between "use IDF bootloader as-is" and "write your own custom bootloader". We should be able to consider this use case as part of this (ie there can be a hook function which is called before the partition table or any other data is read from flash, and you can implement a hook here that reads some external configuration from somewhere and reconfigures SPI flash as needed before continuing the boot process). Will that help you achieve the goal you have? |
That does indeed sound like a good solution. Is the current bootloader code open source somewhere? |
Great!
Yes: A lot of the related functionality is also in the IDF bootloader_support component (which contains code which can be compiled either for the bootloader or for inclusion in an ESP-IDF app). Note this is the second stage bootloader which is read from offset 0x1000 in flash. The initial bootloader in ROM initialises SPI flash based on efuse, loads this bootloader into RAM, and then executes it. But there's no reason this bootloader should not be able to re-initialise SPI flash differently before continuing. The ESP-IDF boot process is explained in detail here: |
I have started testing reconfiguring the flash using the |
I should probably explicitly state my concern is that burning the efuses to this configuration also will not work since it seems to be an issue. This would render any ESP32 with this configuration a "brick". [edit] [edit2] [edit3] [edit4] |
I have settled on the following solution: Rather than calling ROM routines, I am directly manipulating the GPIO configuration:
The above lines are placed in the bootloader just before This causes the rest of initialization to use the external flash. It is testing and working with my application. The reported configuration is 80Mhz, QIO, 16MB. The "SLOW READ" issue was resolved by re-wiring. With the above, boot starts on the WROOM32 4MB flash and continues on a 16MB external flash. The '--no-stub' flag is still required for esptool.py to write to the external flash. |
@OtherCrashOverride
I flash the ESP with "make flash" command. After that when serial monitor starts, the log shows me the message:
2 stuff here:
Thank you |
I documented it in the issue referenced. Adding "--no-stub" to the esptool.py command allows flashing the external chip. I believe that 'make' outputs the commands required to flash your project's data. Simply add the "--no-stub" and flash chip options to the commands shown by it. Note that GPIO5 is in a different power domain (VIO) than GPIO16 (VSDIO). Ensure your flash chip is compatible with esp-idf for detection and using the correct power. For testing, you may wish to wire /CS to IO16 since its known to work and the procedure is documented. After verifying operation, you can move it to the IO pin of your choice to isolate the issue. |
Hello, thanks for the reply.
As you can see the auto-detect flash size is correct: 16MB The problem, however, is that I can not boot from the external memory: I have applied the patch proposed by you above, but it does not seem to work.When I launch the monitor, the code loaded on the 4 MB memory is started instead of the one loaded in the 16 MB memory. In summary, I made 2 steps:
Did I forget something? Do you know if in the last few months there have been additions of functions to facilitate this custom setting? Thank you |
Did you flash the modified bootloader to internal flash (without --no-stub and --spi-configuration)? |
Thanks, I had not done it now. However, it still does not work. In particular, I flashed the bootloader (with the patch) in the 4MB flash, then I took the command suggested at the end of the compilation and I added --no-stub and --spi-configuration. So I loaded the firmware into the 16MB flash (the logs confirm it). All this by repeating the addresses of the partitions. Then the partiton.bin at the address 0x8000 and the app at the address 0x10000 of the flash 16MB. I also modified the bootloader to print the flash size detected before and after changing the GPIO configuration.
When I start the card it tells me 2 times that the flash is 4MB. So the modification of the GPIO seems to be ignored. What may be the problem now? |
The flash size info from the header is based on a value set in menuconfig not based on reading the hardware registers of the flash chip |
Are you sure? because in the menuconfig I set the flash 16MB, but during the boot it prints 2 times that the flash is 4MB |
You would have to flash the bootloader with a header set to 16mb to the external flash for it to read that. But if you erase the internal flash and only have a bootloader there and your app runs then you know it is running from external |
Hi Guys, I'm here again yet without success. This is my custom partition table:
(As you can see at the moment I do not exploit all the 16MB, just because I'm trying to make the code work as it is in the external flash. This should not create problems.) This is the bootloader patch in the bootloader_init.c after line 155:
I set the I compiled the code (bootloader patched) with I erase the internal 4MB flash. Then I flashed the bootloader only in the internal 4 MB flash at 0x1000 with the following command (without --no-stub and --spi-configuration):
After that i flashed the external 16MB flash with the partition table (at 0x8000) and firmware(at 0x10000) with the following commands:
then everything should be ok, so i start monitor
As you can see, the double print of spi information (after and before the pin reconfiguration in the bootloader patch) show always the same 4MB size although I set the 16MB in the menuconfig as @negativekelvin suggest. If i flash all the code in the internal 4MB flash with make flash command, the make monitor command give me:
[Edit] Any suggestions? Thanks! |
If bootloader_flash_read is reading a valid header and there is no bootloader on the external flash then you are still using internal flash. |
@negativekelvin Yes, in fact I expect that during the reading of the bootloader header after the change of the CS pins for the flash memory, it will give me an error. In your opinion, are the steps described in the previous post correct? Other insights:
Note the double print of 16MB If instead load the partition table also in the 16MB flash, the application starts correctly, but the booting takes place in the 4MB flash, because in the 16MB there is only the partition table. Do you have any other suggestions on how to modify the bootloader in order to start it from the 4MB flash and then load the partition table and the various partitions on the 16MB external flash? I attach the modified bootloader_init.c file: I'm going crazy ... please ... help me XD |
I do not have any further information to add. I published my findings at the time in the hope someone would find it useful, but the final solution used was to just de-lid a module and physically replace the flash. |
@Buckler89 I don't know if you're still stuck on this, but it may be worth opening a thread on https://esp32.com as this has become more of a discussion topic ("how to modify IDF bootloader to achieve X") rather than an issue in IDF that we can fix directly. |
Changed Flashmode to DIO due board only supports DIO
Rather than burning efuses, it is desirable to have a bootloader that can be written to WROOM32 module flash that will configure SPI for off-module flash and continue booting from there (disabling module flash).
This provides a benefit for prototyping designs since the WROOM32 does not need to be thrown away if the configuration changes. This also provides benefit for production by offering configuration flexibility.
[edit]
"configuration change" = using different physical IO pins. There is no way to update efuse values once set.
The text was updated successfully, but these errors were encountered: