Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,19 @@ has another name, or `M5UNIFIED_ARDUINO_COMPONENT=OFF` to disable this.
|Current<BR>Voltage<BR>Monitor| --- | --- | --- | --- | --- | --- | --- | --- |`INA3221`<BR>40h/41h<BR>(opt)|Current<BR>Voltage<BR>Monitor|




### Fixed-board firmware

Defining a positive `BOARD_ID` when building an application using M5Unified fixes
its device identity to that `board_t` value. An undefined, explicitly empty, or zero value
keeps automatic detection. Fixed startup reads only variants needed by the
selected board and does not use NVS or probe other board families.
An accepted fixed identity takes precedence over `config_t::fallback_board`,
including when display startup fails. Call `M5.begin()` before initializing
`M5.Display` for this configuration to take effect.

A positive `BOARD_ID` unsupported by the chip also stops automatic detection;
it does not fall back to probing another board. `BOARD_ID` has no effect if
`M5.Display.init()` runs before `M5.begin()`. A valueless compiler option
`-DBOARD_ID` defines the value as 1 (M5Stack), rather than an empty value.
37 changes: 26 additions & 11 deletions src/M5Unified.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,13 @@ namespace m5
// Skipped when the application already ran Display.init(): GPIO46 may then carry the display
// bus (StopWatch QSPI io2), which this output would overwrite. The hold is applied below,
// once the pin map is known, only on boards that use GPIO46 as their power hold.
#if defined (BOARD_ID) && ((BOARD_ID + 0) > 0)
// A fixed board can use GPIO46 for its display rather than power hold.
const bool gpio46_hold = Display.getBoard() == board_t::board_unknown
&& _get_power_hold_pin(static_cast<board_t>(BOARD_ID)) == GPIO_NUM_46;
#else
const bool gpio46_hold = (Display.getBoard() == m5gfx::board_t::board_unknown);
#endif
m5gfx::gpio::pin_backup_t gpio46_backup(GPIO_NUM_46);
if (gpio46_hold)
{
Expand All @@ -357,6 +363,13 @@ namespace m5
}
#endif

m5gfx::detect_config_t detect_config;
detect_config.fallback_board = cfg.fallback_board;
// A positive BOARD_ID fixes the device to its board_t value in M5Unified.
#if defined (BOARD_ID) && ((BOARD_ID + 0) > 0)
detect_config.fixed_board = static_cast<board_t>(BOARD_ID);
#endif
Display.setDetectConfig(detect_config);
auto brightness = Display.getBrightness();
Display.setBrightness(0);
bool res = false;
Expand All @@ -365,20 +378,21 @@ namespace m5
} else {
res = Display.init_without_reset(false);
}
auto board = Display.getBoard();
// printf("auto detect board:%d\n",board);
const auto fixed_board = Display.getFixedBoard();
auto board = fixed_board != board_t::board_unknown ? fixed_board : Display.getBoard();
bool board_detected = (board != board_t::board_unknown);
if (!board_detected)
if (fixed_board != board_t::board_unknown)
{
// Accepted firmware identity survives display startup failure.
if (cfg.fallback_board != board_t::board_unknown && cfg.fallback_board != fixed_board)
{
Log(ESP_LOG_WARN, "fallback board:%u ignored for fixed board:%u",
static_cast<unsigned>(cfg.fallback_board), static_cast<unsigned>(fixed_board));
}
}
else if (!board_detected)
{
board = cfg.fallback_board;
// UIFlow selects board-specific firmware with BOARD_ID and M5GFX_BOARD.
#if defined (CONFIG_IDF_TARGET_ESP32P4) && defined (BOARD_ID)
#if BOARD_ID == 31
if (board == board_t::board_unknown) { board = board_t::board_M5CoreP4X; }
#elif BOARD_ID == 35
if (board == board_t::board_unknown) { board = board_t::board_M5Tab5X; }
#endif
#endif
if (board == board_t::board_unknown) { board = Display.getBoardCandidate(); }
if (board == board_t::board_unknown) { board = _default_fallback_board(); }
}
Expand Down Expand Up @@ -798,6 +812,7 @@ namespace m5
bool _probe_i2c_addr(uint8_t sda, uint8_t scl, uint8_t addr);

static void _setup_pinmap(board_t);
static int8_t _get_power_hold_pin(board_t);
static bool _speaker_enabled_cb_core2(void* args, bool enabled);
static bool _speaker_enabled_cb_cores3(void* args, bool enabled);
static bool _speaker_enabled_cb_sticks3(void* args, bool enabled);
Expand Down
33 changes: 16 additions & 17 deletions src/M5Unified.inl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ namespace m5
int8_t M5Unified::_get_pin_table[pin_name_max];

#if defined (M5UNIFIED_PC_BUILD)
int8_t M5Unified::_get_power_hold_pin(board_t) { return -1; }

void M5Unified::_setup_pinmap(board_t)
{
std::fill(_get_pin_table, _get_pin_table + pin_name_max, 255);
Expand Down Expand Up @@ -475,6 +477,13 @@ static constexpr const uint8_t _pin_table_mbus[][31] = {
{ board_t::board_unknown , 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
};

int8_t M5Unified::_get_power_hold_pin(board_t id)
{
for (const auto& row : _pin_table_other1)
{ if (row[0] == id) { return static_cast<int8_t>(row[1]); } }
return -1;
}

void M5Unified::_setup_pinmap(board_t id)
{
if (id == board_t::board_M5Tab5X) {
Expand Down Expand Up @@ -1650,30 +1659,20 @@ static constexpr const uint8_t _pin_table_mbus[][31] = {
const auto pkg = m5gfx::get_pkg_ver();
if (pkg == 6) { return board_t::board_M5AtomPsram; } // PICO-V3
if (pkg == 5) { return board_t::board_M5StampPico; } // PICO-D4
// The legacy detector defaulted D0WDQ6 to TimerCam after other probes failed.
if (pkg == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) { return board_t::board_M5TimerCam; }
return board_t::board_M5AtomLite;
// StampPico and AtomPsram have no positive detector and remain defaults.
// All D0WDQ6 members have detectors; other packages have no M5 boards.
// Do not assume a rejected member. Unknown retains the generic I2C map.
return board_t::board_unknown;
#elif defined (CONFIG_IDF_TARGET_ESP32S3)
#if defined (BOARD_ID) && BOARD_ID == 147
return board_t::board_M5DualKey;
#endif
// ESP32-S3 package 0 is QFN56 and package 1 is LGA56.
if (m5gfx::get_pkg_ver() == 1) { return board_t::board_M5StampS3Mini; }
return board_t::board_M5StampS3;
#elif defined (CONFIG_IDF_TARGET_ESP32C3)
return board_t::board_M5StampC3U;
#elif defined (CONFIG_IDF_TARGET_ESP32C6)
// Preserve legacy package/flash defaults when no detector confirms a board.
if (m5gfx::get_pkg_ver() == 1)
{
return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_4_REG, EFUSE_FLASH_CAP) == 2
? board_t::board_M5StampC6 : board_t::board_M5NanoC6;
}
#elif defined (CONFIG_IDF_TARGET_ESP32C6) || defined (CONFIG_IDF_TARGET_ESP32H2) || defined (CONFIG_IDF_TARGET_ESP32C5)
// Package-only Stamp suggestions arrive as detector candidates. Do not
// assume a Nano or Stamp after its positive detector rejects the board.
return board_t::board_unknown;
#elif defined (CONFIG_IDF_TARGET_ESP32H2)
return board_t::board_M5NanoH2;
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
return board_t::board_M5StampC5;
#elif defined (CONFIG_IDF_TARGET_ESP32P4)
// Unidentified P4 modules have no display or board-specific power contract.
esp_chip_info_t info;
Expand Down
Loading