espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.32k stars 7.2k forks source link

REQ: ESP32-S3: Assign efuse bits for PSRAM bus type (IDFGH-7538) #9101

Open henrygab opened 2 years ago

henrygab commented 2 years ago

Is your feature request related to a problem? Please describe.

Currently, ESP32-S3 does not have appear to support storing manually selected PSRAM settings. This prevents having a single binary for the ESP32-S3 chip variant (which was possible for ESP32 and ESP32-S2). Currently, there is no programmatic way to detect the PSRAM, and having a mismatch between bootloader and binary will cause boot loop. These are causing confusion and frustration. See, for example, bootloop and bootloader issues.

Describe the solution you'd like

I request that Espressif allocate at least three efuse bits on ESP32-S3 for the purpose of storing manually selected type of PSRAM attached to the processor.

As an example, one solution, similar to the flash's voltage(*) requirement, would be:

This provides a backwards-compatible method of using the efuses to detect the stored setting, and allows existing modules to have their efuses be updated in-the-field, or at any point in supply chain, as needed.

Out-of-scope for this issue, but enables...

For clarity, I've pushed this section into a collapsible node. These are **_NOT_** part of this issue, but rather show how this will enable transitioning to a better experience in a smooth manner.... As soon as it's official which bits are allocated, the following can then occur **_in parallel, without any bottlenecks or cross-dependencies_**: 1. Update of espefuse.py to interpret, display, and allow setting of these bits 2. Update of 3rd party bootloaders to query and use (if set) these bits 3. Update of esptool.py (and 3rd party uploading tools) to avoid mismatch between bootloader and application binary


**Describe alternatives you've considered**
Verbose, so moved to collapsible node...

1. **Not assigning efuse bits.** Without an official location to store this critical information, it becomes necessary to keep (and continually update) a list of modules, and what connection type is used. The updating adds perpetual costs to the maintenance of multiple projects, where the preferred goal (for many reasons) is a **_single binary per platform_**. 1. **Using customer-defined EFUSE bits.** However, this would **_not_** resolve issues in hobbyist community, and would **_not_** allow tools to be updated to interpret this setting. 1. **Using only two bits.** The use of only two bits was considered. However, three bits were used to more closely align with existing similar efuse bits defined by espressif (e.g., flash voltage). 1. **Not defining bit pattern `11b` as invalid.** However, `11b` reflects un-set efuses. Defining this as "not set" reduces the number of user errors. This also makes an explicit choice for the board mandatory. 1. **Not defining a bit patter as `No PSRAM`**. However, an explicit setting for `No PSRAM` is preferred, so bootloaders could then avoid fallback / autodetection techniques when explicitly indicates no PSRAM is available. 1. **Alternate bit patterns.** Specifically, the bit pattern of `00b` to indicate `No PSRAM` was selected to allow a safety fall-back, in case the EFUSE is accidentally programmed with the wrong PSRAM type. That is, it is possible to transition from either QSPI or OPI PSRAM settings (`01b` or `10b`) to disabling PSRAM (`00b`), because EFUSE may transition only from `1` to `0`.


**Additional context** See also: https://github.com/espressif/arduino-esp32/discussions/6426#discussioncomment-2835597 See also: https://github.com/espressif/arduino-esp32/issues/6646
Example of how a bootloader could use the information

Pseudo-code ``` ... if (SetupAndValidateKnownPSRAM()) { // boot the app } else { // No valid settings in eFuse ... // Once efuses are defined, might be possible to define list of all shipped modules // and act accordingly. // Otherwise, try to boot anyways (backwards compatibility) } bool SetupAndValidateKnownPSRAM(void) { if (!isAvailable) { return false; } // Read the expected PSRAM type from the active app's header enum PSRAM_BUS_TYPE appExpectedBusType = ReadActiveAppSettings(); bool isAvailable = read_efuse( efuse::PSRAM_BUS_TYPE_AVAILABLE ); enum PSRAM_BUS_TYPE busType = read_efuse( efuse::EFUSE_PSRAM_BUS_TYPE ); switch (busType) { default: case PSRAM_BUS_TYPE:Invalid: WarnAboutInvalidEFuseSetting(); return false; case PSRAM_BUS_TYPE::QSPI: SetupForQspiBasedSPRAM(); break; case PSRAM_BUS_TYPE::OPI: SetupForOpiBasedSPRAM(); break; case PSRAM_BUS_TYPE::NoPSRAM: break; } if (appExpectedBusType == PSRAM_BUS_TYPE::NoPSRAM) { return true; // OK to boot app that does not use PSRAM } if (appExpectedBusType != busType) { // attempting to boot mismatched APP causes bootloop WarnAboutMismatchedApplicationPSRAMBusTypeSetting(); InfiniteLoop__OR__EnterProgrammingMode(); } } ```


P.S. -- THANK YOU for shipping ESP32-S3 modules with efuses indicating flash voltage settings! This solved large pain points from hobbyists attaching IO12 to various electronics, and having difficult-to-track boot failures.
Jason2866 commented 2 years ago

+1

ginkgm commented 2 years ago

Hi @henrygab ,

Thanks for your proposal. We will consider this (runtime detection of OPI flash/psram). But since it's a major change (all changes to efuses are not simple), we need a lot more time to discuss about it.

henrygab commented 2 years ago

@ginkgm -- This issue is NOT asking for runtime detection of OPI. After all, as you have said, that would be a major change.

Rather, this issue is limited to asking that some e-fuse bits be allocated officially by Espressif (and meaning defined). This will NOT require automatic detection, is 100% backwards-compatible / safe, and enables a smooth(*) transition time.

Please do consider this, in view of understanding the much more limited scope of this request!

(*) Smooth is defined as, "no worse than exists today".

P.S. -- Moved a section in original issue to clarify scope.

Jason2866 commented 2 years ago

Any news?

henrygab commented 2 years ago

@ginkgm ... Any update?

I ask because it seems there was some confusion about my request. You wrote that I was requesting, "runtime detection of OPI flash/psram" ... although my request was only for the EFUSE bits be allocated from the reserved block of Espressif-controlled bits.

Until the bits are allocated, all attempts to fix the issues are essentially blocked (or require hacks that will cause other problems).

Again ... this is NOT requesting runtime detection to exist(*) ... it's only requesting that three bits be allocated to this purpose (one bit to indicate this information exists / is valid, two bits to indicate the values).

(*) Runtime detection is NOT part if this request ... it's understood that automatic detection may be technically impossible in some scenarios; Rather, this just allows STORING a (manually-supplied) value.

ginkgm commented 1 year ago

Hi @henrygab , @Jason2866 ,

But you still need to use them at runtime, don't you?

From the point of view of maintaining the SDK (ESP-IDF), we almost can't add any logic that rely on this efuse bit, because not all products can correctly get this efuse field burnt. There are:

But if the user have to do it, why it has to be in the efuse rather than the flash, which is possible to overwrite? And the simplest way to record some information in the flash is a simple Kconfig option.

Jason2866 commented 1 year ago

Still a reservation of a efuse would be nice. I do understand that you can not burn the fuses by default. So board manufacturers can do for there boards. At the moment it is a mess, since boards with the same name are sold with all kind of flash/Psram types and sizes. Many users do not manage to get the boards going. If this is not possible a detection utility (esptool.py?) is needed which prints out the size and type of flash and psram. I opened a feature request.

henrygab commented 1 year ago

Jason2866 responded, and I agree with his statements.

If I understood you, because not all products will have the efuse burnt at factory, you are wondering why it's worthwhile to have in efuses vs. flash.

I will try to simplify to two reasons:

  1. Users cannot rely on the flash, especially when fully erasing / updating bootloader. See, for example, bootloader issues (and other issues linked above).

  2. While it enables a solution for X% at factory (opt-in, backwards-compatible), it also provides a solution for another Y% at board manufacters, and provides a solution for another Z% (any end user / IT department can rely on the information regardless of if the flash was erased).

  3. It provides the foundation for single-bootloader for all "ESP32-S3" devices that have the efuse set. (If I understood correctly, this is currently not possible... but would be after reservation of the bits occurs.)

This is a solution that enables progress towards fewer error conditions. Defining the bits and their meaning is the first step. After this is done, all the following are possible without any synchronization (fully backwards compatible ... unset bits == no information on PSRAM):

These are not in scope for this issue ... but they are gated by / blocked by this issue.

TD-er commented 1 year ago

Another reason why it would be really useful to check at runtime how the flash/PSRAM is wired is to allow for some pins to be used or not. For example if the pins for OPI are wired to PSRAM (and/or flash) then this could affect how usable these pins are for other uses. In my firmware (ESPEasy), I can then disable those GPIO pins for a user to select, while extra pins could be very useful for others to have if they are safe to use.

And the other way around, if the bootloader can also act on these fuse bits, perhaps issues like I had today with the Lilygo T-dongle S3 (16M) could have been prevented. With QIO_OPI set as memory type, this board completely froze even when flashing or erasing the flash. Esptool.py reported even typical Windows USB errors. With QIO_QSPI set the board works fine.

henrygab commented 1 year ago

Hi @henrygab ,

Thanks for your proposal. We will consider this (runtime detection of OPI flash/psram). But since it's a major change (all changes to efuses are not simple), we need a lot more time to discuss about it.

PLEASE consider just officially MARKING three efuse bits from the reserved pool (reserved == future use by espressif) for this purpose, and defining them as noted above. The sheer number of bootloader variants that must be supported otherwise is geometrically increasing, and is a constant source of friction to the use of these modules.

What this does do is provide an OPTION for those who desire to move forward with a solution ... it provides a BACKWARDS COMPATIBLE way forward, without impact on any existing items.

Please?

blazoncek commented 1 year ago

+1

softhack007 commented 1 year ago

👍 +1

henrygab commented 1 year ago

Community Ask: Please set aside some bits in efuse for explicit use of indicating different flash and PSRAM configurations.

Espressif response: Store settings in flash.

But ... flash isn't accessible if the board is fully erased, so it leaves the community confused.

Community Ask: Just reserve three efuse bits ... nothing else!

Espressif response: Any change we make to efuse tooling requires lots of work.

Community Ask: No tooling... Just reserve three efuse bits ... nothing else!

Espressif response: We cannot use this ourselves in manufacturing on all product lines. Therefore, this is not useful.

Community is left confused, since simple zero-overhead solution was rejected.

Jason2866 commented 1 year ago

It seems there is activity. https://github.com/espressif/esptool/commit/b70ead2b7ff97a276ff0df753b4c655fc399af3f

henrygab commented 1 year ago

It seems there is activity. espressif/esptool@b70ead2

I'm not so sure... From the commit:

Item 0b000 0b001 0b010 0b011 0b100 0b101 0b110 0b111
FLASH_CAP None 8MB 4MB resv'd resv'd resv'd resv'd resv'd
PSRAM_CAP None 8MB 2MB resv'd n/a n/a n/a n/a
FLASH_TEMP ? ? ? ? n/a n/a n/a n/a
FLASH_VENDOR ? ? ? ? ? ? ? ?
PSRAM_TEMP ? ? ? ? n/a n/a n/a n/a
PSRAM_VENDOR ? ? ? ? n/a n/a n/a n/a

On the positive side, it's possible to go from any FLASH_CAP or PSRAM_CAP efuse settings to indicate None, so that's great for when you let the magic smoke out of a chip (or in manu., detect a non-usable chip).

However, unless either:

Then I think those changes may be tangential....