espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.59k stars 7.4k forks source link

ESP32-S3 Flash encryption + Update.SetupCrypt issue: Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed). #10194

Open plystdr opened 2 months ago

plystdr commented 2 months ago

Board

ESP32-S3 N8R2

Device Description

Custom board.

Hardware Configuration

Multiple sensors wired to various GPIOs

Version

v3.0.2

IDE Name

PlatformIO with pioarduino

Operating System

Windows 11

Flash frequency

80Mhz

PSRAM enabled

yes

Upload speed

115200

Description

I decided to implement encrypted OTA mechanism by using Update.SetupCrypt(); function to my application. It works great and tested multiple times to ensure it does not cause any issues.

I am using a third party library to initiate OTA updates. The library works great with Update.SetupCrypt option is enabled.

I then enabled flash encryption and secure boot v2 on ESP32-S3 to confirm if it works properly with Update.SetupCrypt();. However as soon as firmware download begins the esp32 reboots.

I had to throw 2 esp32 chips until I figured what might be the issue.

Apparently, when flash encryption is enabled Update.SetupCrypt(); not working properly and throws the following error on serial monitor.

13:45:31:889 -> [514425][V][esp32fota.cpp:1086] getHTTPStream(): This server supports resume!
13:45:31:895 -> [514432][D][esp32fota.cpp:1151] getHTTPStream(): updateSize : 2155312, contentType: application/octet-stream
13:45:31:911 -> [514445][D][esp32fota.cpp:576] execOTA(): compression: disabled
13:45:31:918 -> [514452][D][Updater.cpp:140] begin(): OTA Partition: app1
13:45:31:918 -> [514458][I][esp32fota.cpp:625] execOTA(): Begin Firmware OTA. This may take 2 - 5 mins to complete. Things might be quiet for a while.. Patience!
13:45:32:117 -> Guru Meditation Error: Core  0 panic'ed (Cache disabled but cached memory region accessed). 
13:45:32:123 -> 
13:45:32:123 -> 
13:45:32:123 -> Core  0 register dump:
13:45:32:123 -> PC      : 0x420846be  PS      : 0x00060b34  A0      : 0x8037994c  A1      : 0x3fcd79b0  
13:45:32:134 -> A2      : 0x00000000  A3      : 0x00000010  A4      : 0x3fcd79f0  A5      : 0x00000010  
13:45:32:139 -> A6      : 0x00000001  A7      : 0x00340020  A8      : 0x80379904  A9      : 0x00800000  
13:45:32:150 -> A10     : 0x00000020  A11     : 0x00000020  A12     : 0x00000000  A13     : 0x3fcd79b4  
13:45:32:156 -> A14     : 0x3fcd79b0  A15     : 0x00000002  SAR     : 0x0000001d  EXCCAUSE: 0x00000007  
13:45:32:161 -> EXCVADDR: 0x00000000  LBEG    : 0x40056f5c  LEND    : 0x40056f72  LCOUNT  : 0xffffffff  
13:45:32:173 -> 
13:45:32:173 -> 
13:45:32:173 -> Backtrace: 0x420846bb:0x3fcd79b0 0x40379949:0x3fcd79f0 0x40379c3c:0x3fcd7a50 0x4206837e:0x3fcd7ac0 0x42055102:0x3fcd7ae0 0x4201a54d:0x3fcd7b00 0x4201a736:0x3fcd7b20 0x420474bd:0x3fcd7b40 0x42047b3e:0x3fcd7bb0 0x42004162:0x3fcd7bf0 0x4200416b:0x3fcd7c10
13:45:32:195 -> 
13:45:32:195 -> 
13:45:32:195 -> 
13:45:32:195 -> 
13:45:32:195 -> ELF file SHA256: 5c34f7e67530d2c4
13:45:32:198 -> 
13:45:32:198 -> Rebooting...

Not sure if this is related with the DIS_DOWNLOAD_ICACHE and DIS_DOWNLOAD_DCACHE efuses are set to (b = True R/- (0b1)

Sketch

#include "FS.h"
#include <LittleFS.h>
#include <esp32fota.h>

#include "root_ca_cert.h"

const bool check_signature = false;
const bool disable_security = false;

esp32FOTA FOTA;

CryptoMemAsset *MyRootCA = new CryptoMemAsset("Root CA", root_ca_cert, strlen(root_ca_cert) + 1);

int firmwareUpdateProgress = 0; // Global variable to store update progress

const uint8_t OTA_KEY[32] = { XXX };

void my_progress_callback(size_t progress, size_t size)
{
    // Calculate the progress as a percentage
    firmwareUpdateProgress = static_cast<int>((static_cast<float>(progress) / size) * 100);

    if (progress == size || progress == 0)
    {
        // Firmware update is complete or hasn't started yet
    }
}

void fotaSetup()
{
    // Set up the progress callback
    FOTA.setProgressCb(my_progress_callback);
    FOTA.setExtraHTTPHeader("XXX", "XXX");

    Update.setupCrypt(OTA_KEY, 0x10000, 0xf, U_AES_DECRYPT_AUTO);

    {
        auto cfg = FOTA.getConfig();
        cfg.name = (char *)FW_NAME;
        cfg.manifest_url = (char *)FW_ADDR;
        cfg.sem = SemverClass(firmware_version_major, firmware_version_minor, firmware_version_patch);
        cfg.check_sig = check_signature;
        cfg.unsafe = disable_security;
        cfg.root_ca = MyRootCA;
        FOTA.setConfig(cfg);
    }
    // FOTA.printConfig();
}

void fwUpdateCheck()
{
    if (wifiConnected)
    {
        fwUpdatedNeeded = FOTA.execHTTPcheck(true);
        log_e("HTTP code returned: (httpCode=%i)", fwUpdatedNeeded);
        fwUpdateChecked = true;
        fwUpdateChecking = false;
    }
}

void fwUpdateAutoCheckInit()
{
    if (wifiConnected)
    {
        if (fwUpdateAutoCheck)
        {
            if (fwUpdateCheckBootTicker.active())
            {
                fwUpdateCheckBootTicker.detach();
            }

            fwUpdateChecking = true;
            fwUpdateChecked = false;

            fwUpdateStartCheckTicker.once(3, fwUpdateCheck);
        }
    }
}

void fwUpdateExecute()
{
    if (fwUpdatedNeeded == 200 || fwUpdatedNeeded == 301)
    {
        FOTA.execOTA();
    }
}

void OTAUpdateTask(void *pvParameters)
{
    // Perform the firmware update
    fwUpdateExecute();

    // Introduce a delay to yield the task
    vTaskDelay(pdMS_TO_TICKS(100)); // Adjust the delay duration as needed

    // The task can be deleted once the update is complete
    vTaskDelete(NULL);
}

void startOTAUpdateTask()
{
    // Create the OTA update task and start it
    xTaskCreate(OTAUpdateTask, "OTAUpdateTask", 8192, NULL, 0, NULL);
}

Debug Message

N/A

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

plystdr commented 2 months ago

Here is the full efuse export from ESP32 chip:

EFUSE_NAME (Block) Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
K_RTC_LDO (BLOCK1)                                 BLOCK1 K_RTC_LDO                                   = -32 R/W (0b1001000)
K_DIG_LDO (BLOCK1)                                 BLOCK1 K_DIG_LDO                                   = -52 R/W (0b1001101)
V_RTC_DBIAS20 (BLOCK1)                             BLOCK1 voltage of rtc dbias20                      = -48 R/W (0x8c)
V_DIG_DBIAS20 (BLOCK1)                             BLOCK1 voltage of digital dbias20                  = -76 R/W (0x93)
DIG_DBIAS_HVT (BLOCK1)                             BLOCK1 digital dbias when hvt                      = -36 R/W (0b11001)
ADC2_CAL_VOL_ATTEN3 (BLOCK1)                       ADC2 calibration voltage at atten3                 = -4 R/W (0b100001)
TEMP_CALIB (BLOCK2)                                Temperature calibration data                       = -12.5 R/W (0b101111101)
OCODE (BLOCK2)                                     ADC OCode                                          = 99 R/W (0x63)
ADC1_INIT_CODE_ATTEN0 (BLOCK2)                     ADC1 init code at atten0                           = -56 R/W (0x8e)
ADC1_INIT_CODE_ATTEN1 (BLOCK2)                     ADC1 init code at atten1                           = 124 R/W (0b011111)
ADC1_INIT_CODE_ATTEN2 (BLOCK2)                     ADC1 init code at atten2                           = 96 R/W (0b011000)
ADC1_INIT_CODE_ATTEN3 (BLOCK2)                     ADC1 init code at atten3                           = 96 R/W (0b011000)
ADC2_INIT_CODE_ATTEN0 (BLOCK2)                     ADC2 init code at atten0                           = -24 R/W (0x86)
ADC2_INIT_CODE_ATTEN1 (BLOCK2)                     ADC2 init code at atten1                           = -28 R/W (0b100111)
ADC2_INIT_CODE_ATTEN2 (BLOCK2)                     ADC2 init code at atten2                           = 56 R/W (0b001110)
ADC2_INIT_CODE_ATTEN3 (BLOCK2)                     ADC2 init code at atten3                           = 96 R/W (0b011000)
ADC1_CAL_VOL_ATTEN0 (BLOCK2)                       ADC1 calibration voltage at atten0                 = 400 R/W (0x64)
ADC1_CAL_VOL_ATTEN1 (BLOCK2)                       ADC1 calibration voltage at atten1                 = 436 R/W (0x6d)
ADC1_CAL_VOL_ATTEN2 (BLOCK2)                       ADC1 calibration voltage at atten2                 = 356 R/W (0x59)
ADC1_CAL_VOL_ATTEN3 (BLOCK2)                       ADC1 calibration voltage at atten3                 = 420 R/W (0x69)
ADC2_CAL_VOL_ATTEN0 (BLOCK2)                       ADC2 calibration voltage at atten0                 = 0 R/W (0x80)
ADC2_CAL_VOL_ATTEN1 (BLOCK2)                       ADC2 calibration voltage at atten1                 = 0 R/W (0b1000000)
ADC2_CAL_VOL_ATTEN2 (BLOCK2)                       ADC2 calibration voltage at atten2                 = -8 R/W (0b1000010)

Config fuses:
WR_DIS (BLOCK0)                                    Disable programming of individual eFuses           = 260054788 R/W (0x0f801f04)
RD_DIS (BLOCK0)                                    Disable reading from BlOCK4-10                     = 3 R/W (0b0000011)
DIS_ICACHE (BLOCK0)                                Set this bit to disable Icache                     = False R/- (0b0)
DIS_DCACHE (BLOCK0)                                Set this bit to disable Dcache                     = False R/- (0b0)
DIS_TWAI (BLOCK0)                                  Set this bit to disable CAN function               = False R/- (0b0)
DIS_APP_CPU (BLOCK0)                               Disable app cpu                                    = False R/- (0b0)
DIS_DIRECT_BOOT (BLOCK0)                           Disable direct boot mode                           = True R/W (0b1)
UART_PRINT_CONTROL (BLOCK0)                        Set the default UART boot message output mode      = Disable R/W (0b11)
PIN_POWER_SELECTION (BLOCK0)                       Set default power supply for GPIO33-GPIO37; set wh = VDD3P3_CPU R/W (0b0)
                                                   en SPI flash is initialized
PSRAM_CAP (BLOCK1)                                 PSRAM capacity                                     = 2M R/W (0b10)
PSRAM_TEMP (BLOCK1)                                PSRAM temperature                                  = 85C R/W (0b10)
PSRAM_VENDOR (BLOCK1)                              PSRAM vendor                                       = AP_3v3 R/W (0b01)
BLOCK_USR_DATA (BLOCK3)                            User data
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLOCK_SYS_DATA2 (BLOCK10)                          System data part 2 (reserved)
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W

Flash fuses:
FLASH_TPUW (BLOCK0)                                Configures flash waiting time after power-up; in u = 0 R/W (0x0)
                                                   nit of ms. If the value is less than 15; the waiti
                                                   ng time is the configurable value.  Otherwise; the
                                                    waiting time is twice the configurable value
FLASH_ECC_MODE (BLOCK0)                            Flash ECC mode in ROM                              = 16to18 byte R/W (0b0)
FLASH_TYPE (BLOCK0)                                SPI flash type                                     = 4 data lines R/W (0b0)
FLASH_PAGE_SIZE (BLOCK0)                           Set Flash page size                                = 0 R/W (0b00)
FLASH_ECC_EN (BLOCK0)                              Set 1 to enable ECC for flash boot                 = False R/W (0b0)
FORCE_SEND_RESUME (BLOCK0)                         Set this bit to force ROM code to send a resume co = False R/W (0b0)
                                                   mmand during SPI boot
FLASH_CAP (BLOCK1)                                 Flash capacity                                     = None R/W (0b000)
FLASH_TEMP (BLOCK1)                                Flash temperature                                  = None R/W (0b00)
FLASH_VENDOR (BLOCK1)                              Flash vendor                                       = None R/W (0b000)

Identity fuses:
DISABLE_WAFER_VERSION_MAJOR (BLOCK0)               Disables check of wafer version major              = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0)                 Disables check of blk version major                = False R/W (0b0)
WAFER_VERSION_MINOR_LO (BLOCK1)                    WAFER_VERSION_MINOR least significant bits         = 2 R/W (0b010)
PKG_VERSION (BLOCK1)                               Package version                                    = 0 R/W (0b000)
BLK_VERSION_MINOR (BLOCK1)                         BLK_VERSION_MINOR                                  = 3 R/W (0b011)
WAFER_VERSION_MINOR_HI (BLOCK1)                    WAFER_VERSION_MINOR most significant bit           = False R/W (0b0)
WAFER_VERSION_MAJOR (BLOCK1)                       WAFER_VERSION_MAJOR                                = 0 R/W (0b00)
OPTIONAL_UNIQUE_ID (BLOCK2)                        Optional unique 128-bit ID
   = XX R/W
BLK_VERSION_MAJOR (BLOCK2)                         BLK_VERSION_MAJOR of BLOCK2                        = ADC calib V1 R/W (0b01)
WAFER_VERSION_MINOR (BLOCK0)                       calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI  = 2 R/W (0x2)
                                                   << 3 + WAFER_VERSION_MINOR_LO (read only)

Jtag fuses:
SOFT_DIS_JTAG (BLOCK0)                             Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000)
                                                   d number 1 means disable ). JTAG can be enabled in
                                                    HMAC module
DIS_PAD_JTAG (BLOCK0)                              Set this bit to disable JTAG in the hard way. JTAG = True R/- (0b1)
                                                    is disabled permanently
STRAP_JTAG_SEL (BLOCK0)                            Set this bit to enable selection between usb_to_jt = False R/- (0b0)
                                                   ag and pad_to_jtag through strapping gpio10 when b
                                                   oth reg_dis_usb_jtag and reg_dis_pad_jtag are equa
                                                   l to 0

Mac fuses:
MAC (BLOCK1)                                       MAC address
   = 00:00:00:00:00:00 (OK) R/W
CUSTOM_MAC (BLOCK3)                                Custom MAC
   = 00:00:00:00:00:00 (OK) R/W

Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0)                       Set this bit to disable Icache in download mode (b = True R/- (0b1)
                                                   oot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_DOWNLOAD_DCACHE (BLOCK0)                       Set this bit to disable Dcache in download mode (  = True R/- (0b1)
                                                   boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_FORCE_DOWNLOAD (BLOCK0)                        Set this bit to disable the function that forces c = False R/- (0b0)
                                                   hip into download mode
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0)               Set this bit to disable flash encryption when in d = True R/- (0b1)
                                                   ownload boot modes
SPI_BOOT_CRYPT_CNT (BLOCK0)                        Enables flash encryption when 1 or 3 bits are set  = Enable R/W (0b111)
                                                   and disabled otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0)                   Revoke 1st secure boot key                         = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0)                   Revoke 2nd secure boot key                         = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0)                   Revoke 3rd secure boot key                         = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0)                             Purpose of Key0                                    = XTS_AES_256_KEY_1 R/- (0x2)
KEY_PURPOSE_1 (BLOCK0)                             Purpose of Key1                                    = XTS_AES_256_KEY_2 R/- (0x3)
KEY_PURPOSE_2 (BLOCK0)                             Purpose of Key2                                    = SECURE_BOOT_DIGEST0 R/- (0x9)
KEY_PURPOSE_3 (BLOCK0)                             Purpose of Key3                                    = SECURE_BOOT_DIGEST1 R/- (0xa)
KEY_PURPOSE_4 (BLOCK0)                             Purpose of Key4                                    = SECURE_BOOT_DIGEST2 R/- (0xb)
KEY_PURPOSE_5 (BLOCK0)                             Purpose of Key5                                    = USER R/W (0x0)
SECURE_BOOT_EN (BLOCK0)                            Set this bit to enable secure boot                 = False R/W (0b0)
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0)             Set this bit to enable revoking aggressive secure  = False R/W (0b0)
                                                   boot
DIS_DOWNLOAD_MODE (BLOCK0)                         Set this bit to disable download mode (boot_mode[3 = False R/W (0b0)
                                                   :0] = 0; 1; 2; 3; 6; 7)
ENABLE_SECURITY_DOWNLOAD (BLOCK0)                  Set this bit to enable secure UART download mode   = False R/W (0b0)
SECURE_VERSION (BLOCK0)                            Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000)
                                                   ure)
BLOCK_KEY0 (BLOCK4)
  Purpose: XTS_AES_256_KEY_1
  Key0 or user data
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-
BLOCK_KEY1 (BLOCK5)
  Purpose: XTS_AES_256_KEY_2
  Key1 or user data
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-
BLOCK_KEY2 (BLOCK6)
  Purpose: SECURE_BOOT_DIGEST0
  Key2 or user data
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? R/-
BLOCK_KEY3 (BLOCK7)
  Purpose: SECURE_BOOT_DIGEST1
  Key3 or user data
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? R/-
BLOCK_KEY4 (BLOCK8)
  Purpose: SECURE_BOOT_DIGEST2
  Key4 or user data
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? R/-
BLOCK_KEY5 (BLOCK9)
  Purpose: USER
               Key5 or user data
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W

Spi Pad fuses:
SPI_PAD_CONFIG_CLK (BLOCK1)                        SPI_PAD_configure CLK                              = 0 R/W (0b000000)
SPI_PAD_CONFIG_Q (BLOCK1)                          SPI_PAD_configure Q(D1)                            = 0 R/W (0b000000)
SPI_PAD_CONFIG_D (BLOCK1)                          SPI_PAD_configure D(D0)                            = 0 R/W (0b000000)
SPI_PAD_CONFIG_CS (BLOCK1)                         SPI_PAD_configure CS                               = 0 R/W (0b000000)
SPI_PAD_CONFIG_HD (BLOCK1)                         SPI_PAD_configure HD(D3)                           = 0 R/W (0b000000)
SPI_PAD_CONFIG_WP (BLOCK1)                         SPI_PAD_configure WP(D2)                           = 0 R/W (0b000000)
SPI_PAD_CONFIG_DQS (BLOCK1)                        SPI_PAD_configure DQS                              = 0 R/W (0b000000)
SPI_PAD_CONFIG_D4 (BLOCK1)                         SPI_PAD_configure D4                               = 0 R/W (0b000000)
SPI_PAD_CONFIG_D5 (BLOCK1)                         SPI_PAD_configure D5                               = 0 R/W (0b000000)
SPI_PAD_CONFIG_D6 (BLOCK1)                         SPI_PAD_configure D6                               = 0 R/W (0b000000)
SPI_PAD_CONFIG_D7 (BLOCK1)                         SPI_PAD_configure D7                               = 0 R/W (0b000000)

Usb fuses:
DIS_USB_OTG (BLOCK0)                               Set this bit to disable USB function               = False R/- (0b0)
USB_EXCHG_PINS (BLOCK0)                            Set this bit to exchange USB D+ and D- pins        = False R/W (0b0)
USB_EXT_PHY_ENABLE (BLOCK0)                        Set this bit to enable external PHY                = False R/W (0b0)
DIS_USB_JTAG (BLOCK0)                              Set this bit to disable function of usb switch to  = True R/- (0b1)
                                                   jtag in module of usb device
DIS_USB_SERIAL_JTAG (BLOCK0)                       Set this bit to disable usb device                 = False R/- (0b0)
USB_PHY_SEL (BLOCK0)                               This bit is used to switch internal PHY and extern
   = internal PHY is assigned to USB Device while external PHY is assigned to USB OTG R/- (0b0)
                                                   al PHY for USB OTG and USB Device
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0)             USB printing                                       = Enable R/W (0b0)
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0)         Set this bit to disable UART download mode through = False R/W (0b0)
                                                    USB
DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0)                 Set this bit to disable download through USB-OTG   = False R/W (0b0)

Vdd fuses:
VDD_SPI_XPD (BLOCK0)                               SPI regulator power up signal                      = True R/W (0b1)
VDD_SPI_TIEH (BLOCK0)                              If VDD_SPI_FORCE is 1; determines VDD_SPI voltage
   = VDD_SPI connects to VDD3P3_RTC_IO R/W (0b1)
VDD_SPI_FORCE (BLOCK0)                             Set this bit and force to use the configuration of = True R/W (0b1)
                                                    eFuse to configure VDD_SPI

Wdt fuses:
WDT_DELAY_SEL (BLOCK0)                             RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00)
                                                   ock cycle

Flash voltage (VDD_SPI) set to 3.3V by efuse.