arduino-esp32 icon indicating copy to clipboard operation
arduino-esp32 copied to clipboard

The Preferences function of ESP32-S3-WROOM-1U-N4R8 in USBHID mode does not work.

Open Ccccraz opened this issue 7 months ago • 11 comments

Board

ESP32-S3-WROOM-1U-N4R8

Device Description

Image

For reference, below is my board.json configuration, and I believe the flash configuration here should be correct:

{
  "build": {
    "arduino":{
      "ldscript": "esp32s3_out.ld",
      "memory_type": "qio_opi"
    },
    "core": "esp32",
    "extra_flags": [
      "-DBOARD_HAS_PSRAM",
      "-DARDUINO_ESP32S3_DEV",
      "-DARDUINO_USB_MODE=0",
      "-DARDUINO_RUNNING_CORE=1",
      "-DARDUINO_EVENT_RUNNING_CORE=1"
    ],
    "f_cpu": "240000000L",
    "f_flash": "80000000L",
    "flash_mode": "qio",
    "hwids": [
      [
        "0x303A",
        "0x1001"
      ]
    ],
    "mcu": "esp32s3",
    "variant": "esp32s3"
  },
}

I don't know where this problem comes from? Maybe it's the USB? Or I made some stupid mistakes in the code that I didn't notice.

Hardware Configuration

GPIO19, GPIO20 directly used as USB signal lines

Version

latest stable Release (if not listed below)

IDE Name

VScode

Operating System

Windows 11

Flash frequency

80Mhz

PSRAM enabled

yes

Upload speed

460800

Description

I am developing a HID project based on the ESP32S3 using platformIO. Everything is going smoothly. However, today when I tried to use Preferences.h to persist some data, I found that I couldn’t do it.

I found a similar issue at https://github.com/espressif/arduino-esp32/issues/8429, and later I confirmed that the flash of the ESP32-S3-WROOM-1U-N4R8 I am using is operating in qio mode, so the solution in this issue does not work to me.

Sketch

AT8236HID::AT8236HID(uint8_t in1_pin, uint8_t in2_pin, float speed)
    : _in1_pin(in1_pin), _in2_pin(in2_pin), _speed(constrain(speed, 0.0f, 1.0f))
{
    pump_prefs.begin(pref_namespace, true);

    if (!pump_prefs.isKey(pref_device_id))
    {
        pump_prefs.end();
        pump_prefs.begin(pref_namespace, false);
        pump_prefs.putUInt(pref_device_id, 2);
        pump_prefs.end();
        pump_prefs.begin(pref_namespace, true);
    }

    _device_id = pump_prefs.getUInt(pref_device_id);
    pump_prefs.end();
}

auto AT8236HID::_onSetFeature(uint8_t report_id, const uint8_t *buffer, uint16_t len) -> void
{
    feature_t feature{};
    memcpy(&feature, buffer, sizeof(feature));

    if (feature.device_id != _device_id)
        return;

    _device_id = feature.new_device_id;

    pump_prefs.begin(pref_namespace, false);
    pump_prefs.putUInt(pref_device_id, _device_id);
    pump_prefs.end();
}


I initialize them here:

    const char *pref_namespace{"app-name"};
    const char *pref_device_id{"device_id"};
    Preferences pump_prefs{};

Debug Message

In USBHID mode, I don't know how to obtain the debug output.

Other Steps to Reproduce

I'm trying to build a minimal example to reproduce this problem.

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

  • [x] I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Ccccraz avatar Apr 23 '25 14:04 Ccccraz

Please post your complete platformio.ini

Jason2866 avatar Apr 23 '25 16:04 Jason2866

Hi thanks for your follow up, here is my platformio.ini

[env:simia]
platform = espressif32
board = waveshare_esp32s3_zero
framework = arduino
lib_deps = 
	ccccraz/simia_embedded@^0.0.2
	mathertel/OneButton@^2.6.1

it is pretty simple.

I've just built a simple usbcdc environment for testing. I found that there is an error when I use preferences in the class, but there is no problem when I only use it in setup() or loop(). I'm checking if this is a known issue.

Ccccraz avatar Apr 23 '25 16:04 Ccccraz

I think you want flash_mode to be dio even when memory_type is qio_opi. This behavior of the flash is a symptom of memory misconfiguration.

lbernstone avatar Apr 23 '25 16:04 lbernstone

Hi, guys. Although I haven't figured out this problem yet, I fixed my problem by moving all the preferences objects out of the class and using them directly in the setup() and loop()

Ccccraz avatar Apr 23 '25 16:04 Ccccraz

I think you want flash_mode to be dio even when memory_type is qio_opi. This behavior of the flash is a symptom of memory misconfiguration.

Oh, thank you very much for your advice. I'll do a test quickly.

Ccccraz avatar Apr 23 '25 16:04 Ccccraz

Hi, guys. Although I haven't figured out this problem yet, I fixed my problem by moving all the preferences objects out of the class and using them directly in the setup() and loop()

Make sure that you aren't losing track of the handle in localizing. IE, don't try to re-use a handle/object from outside, keep the nvs handle (aka, the state) completely internal to the class.

lbernstone avatar Apr 23 '25 16:04 lbernstone

I think you want flash_mode to be dio even when memory_type is qio_opi. This behavior of the flash is a symptom of memory misconfiguration.

Hi! If my understanding is correct, I modify my board.json to:

{
  "build": {
    "arduino": {
      "ldscript": "esp32s3_out.ld",
      "memory_type": "qio_opi"
    },
    "core": "esp32",
    "extra_flags": [
      "-DBOARD_HAS_PSRAM",
      "-DARDUINO_ESP32S3_DEV",
      "-DARDUINO_USB_CDC_ON_BOOT",
      "-DARDUINO_USB_MODE=0",
      "-DARDUINO_RUNNING_CORE=1",
      "-DARDUINO_EVENT_RUNNING_CORE=1"
    ],
    "f_cpu": "240000000L",
    "f_flash": "80000000L",
    "flash_mode": "dio",
    "hwids": [
      [
        "0x303A",
        "0x1001"
      ]
    ],
    "mcu": "esp32s3",
    "variant": "esp32s3"
  },
}

then I create a very sample class:

#ifndef TMP_H
#define TMP_H

#include <Preferences.h>

class Tmp
{
  private:
  public:
    Preferences tmp_prefs;
    const char *tmp_prefs_name = "tmp-app";
    const char *tmp_prefs_key = "tmp";

    uint32_t value{0};

    Tmp();
    void getTmp();
    ~Tmp() = default;
};

Tmp::Tmp()
{
    tmp_prefs.begin(tmp_prefs_name, false);
    tmp_prefs.putUInt(tmp_prefs_key, 100);
    tmp_prefs.end();
}

inline void Tmp::getTmp()
{
    tmp_prefs.begin(tmp_prefs_name, true);
    value = tmp_prefs.getUInt(tmp_prefs_key, 10);
    tmp_prefs.end();
}

#endif // TMP_H

and a main func:

#include <Arduino.h>

#include "USB.h"
#include "tmp.h"

USBCDC USBSerial;

Tmp tmp{};

void setup()
{
    Serial.begin(115200);
    Serial.setDebugOutput(true);

    tmp.getTmp();

    USBSerial.begin();
    USB.begin();
}

void loop()
{
    while (true)
    {
        USBSerial.println(tmp.value);
        delay(1000);
    }
}

The verification logic here is: tmp is written with 100 during initialization, and tmp.getTmp() will modify tmp.value to the value written during initialization. So in theory, I should be able to see 100 in the serial monitor. However, the final result is 60, which is the value I wrote during the last test:

Image

As you've just added, in this example, the handle of preferences should always be kept internally.

This test code was tested in a header-only environment. I also tested it in a normal environment and removed all the "inline" keywords, and the results were the same.

Ccccraz avatar Apr 23 '25 17:04 Ccccraz

The entry flash_modewill be auto corrected if the entry memory_type is set See https://github.com/pioarduino/platform-espressif32/blob/b5f52780f89ec1055f91ece174cd2e9be02d06dd/builder/main.py#L90-L108

The boards json is fine as it is. NOT the reason for issues. BUT with your platformio.ini you are not using latest actual Arduino core. change to:

[env:simia]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
board = waveshare_esp32s3_zero
framework = arduino
lib_deps = 
	ccccraz/simia_embedded@^0.0.2
	mathertel/OneButton@^2.6.1

Jason2866 avatar Apr 23 '25 18:04 Jason2866

The entry flash_modewill be auto corrected if the entry memory_type is set See https://github.com/pioarduino/platform-espressif32/blob/b5f52780f89ec1055f91ece174cd2e9be02d06dd/builder/main.py#L90-L108

The boards json is fine as it is. NOT the reason for issues. BUT with your platformio.ini you are not using latest actual Arduino core. change to:

[env:simia]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
board = waveshare_esp32s3_zero
framework = arduino
lib_deps = 
	ccccraz/simia_embedded@^0.0.2
	mathertel/OneButton@^2.6.1

Ok cool! I will test it tomorrow morning! thanks for your help!

Ccccraz avatar Apr 23 '25 18:04 Ccccraz

The entry flash_modewill be auto corrected if the entry memory_type is set See https://github.com/pioarduino/platform-espressif32/blob/b5f52780f89ec1055f91ece174cd2e9be02d06dd/builder/main.py#L90-L108

The boards json is fine as it is. NOT the reason for issues. BUT with your platformio.ini you are not using latest actual Arduino core. change to:

[env:simia]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
board = waveshare_esp32s3_zero
framework = arduino
lib_deps = 
	ccccraz/simia_embedded@^0.0.2
	mathertel/OneButton@^2.6.1

hi, I update my platformio.ini to:

[env:simia]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
board = simia
framework = arduino

Tests were carried out when "flash_mode" was set to "qio" and "dio"

In both tests, "memory_type" was kept as "qio_opi"

The test code being run is the one mentioned here: https://github.com/espressif/arduino-esp32/issues/11284#issuecomment-2824981164

However, the result is still unsuccessful. I can only see the old values in the serial port monitor:

Image

Ccccraz avatar Apr 24 '25 07:04 Ccccraz

Getting closer, since it is core independent (by changing the platform entry, different cores are used), the code is the reason for not working.

Jason2866 avatar Apr 24 '25 13:04 Jason2866