|
9 | 9 | #include "soc/efuse_reg.h"
|
10 | 10 | #include "soc/rtc.h"
|
11 | 11 | #include "soc/spi_reg.h"
|
| 12 | +#include "soc/soc.h" |
12 | 13 | #if CONFIG_IDF_TARGET_ESP32S2
|
13 | 14 | #include "esp32s2/rom/spi_flash.h"
|
14 | 15 | #endif
|
15 | 16 | #include "esp_bit_defs.h"
|
16 | 17 |
|
17 | 18 | #include "Arduino.h"
|
18 | 19 | #include "esp32-hal-periman.h"
|
| 20 | +#include "chip-debug-report.h" |
19 | 21 |
|
20 | 22 | #define chip_report_printf log_printf
|
21 | 23 |
|
@@ -138,25 +140,19 @@ static void printFlashInfo(void) {
|
138 | 140 | chip_report_printf(" Block Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.block_size, b2kb(g_rom_flashchip.block_size));
|
139 | 141 | chip_report_printf(" Sector Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.sector_size, b2kb(g_rom_flashchip.sector_size));
|
140 | 142 | chip_report_printf(" Page Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.page_size, b2kb(g_rom_flashchip.page_size));
|
141 |
| - esp_image_header_t fhdr; |
142 |
| - esp_flash_read(esp_flash_default_chip, (void *)&fhdr, ESP_FLASH_IMAGE_BASE, sizeof(esp_image_header_t)); |
143 |
| - if (fhdr.magic == ESP_IMAGE_HEADER_MAGIC) { |
144 |
| - uint32_t f_freq = 0; |
145 |
| - switch (fhdr.spi_speed) { |
146 |
| -#if CONFIG_IDF_TARGET_ESP32H2 |
147 |
| - case 0x0: f_freq = 32; break; |
148 |
| - case 0x2: f_freq = 16; break; |
149 |
| - case 0xf: f_freq = 64; break; |
150 |
| -#else |
151 |
| - case 0x0: f_freq = 40; break; |
152 |
| - case 0x1: f_freq = 26; break; |
153 |
| - case 0x2: f_freq = 20; break; |
154 |
| - case 0xf: f_freq = 80; break; |
155 |
| -#endif |
156 |
| - default: f_freq = fhdr.spi_speed; break; |
157 |
| - } |
158 |
| - chip_report_printf(" Bus Speed : %lu MHz\n", f_freq); |
| 143 | + |
| 144 | + // Runtime flash frequency detection from hardware registers |
| 145 | + uint32_t actual_freq = getFlashFrequencyMHz(); |
| 146 | + uint8_t source_freq = getFlashSourceFrequencyMHz(); |
| 147 | + uint8_t divider = getFlashClockDivider(); |
| 148 | + |
| 149 | + chip_report_printf(" Bus Speed : %lu MHz\n", actual_freq); |
| 150 | + chip_report_printf(" Flash Frequency : %lu MHz (source: %u MHz, divider: %u)\n", actual_freq, source_freq, divider); |
| 151 | + |
| 152 | + if (isFlashHighPerformanceModeEnabled()) { |
| 153 | + chip_report_printf(" HPM Mode : Enabled (> 80 MHz)\n"); |
159 | 154 | }
|
| 155 | + |
160 | 156 | chip_report_printf(" Bus Mode : ");
|
161 | 157 | #if CONFIG_ESPTOOLPY_OCT_FLASH
|
162 | 158 | chip_report_printf("OPI\n");
|
@@ -345,3 +341,106 @@ void printAfterSetupInfo(void) {
|
345 | 341 | chip_report_printf("============ After Setup End =============\n");
|
346 | 342 | delay(20); //allow the print to finish
|
347 | 343 | }
|
| 344 | + |
| 345 | +// ============================================================================ |
| 346 | +// Flash Frequency Runtime Detection |
| 347 | +// ============================================================================ |
| 348 | + |
| 349 | +// Define SPI0 base addresses for different chips |
| 350 | +#if CONFIG_IDF_TARGET_ESP32S3 |
| 351 | + #define FLASH_SPI0_BASE 0x60003000 |
| 352 | +#elif CONFIG_IDF_TARGET_ESP32S2 |
| 353 | + #define FLASH_SPI0_BASE 0x3f402000 |
| 354 | +#elif CONFIG_IDF_TARGET_ESP32C3 |
| 355 | + #define FLASH_SPI0_BASE 0x60002000 |
| 356 | +#elif CONFIG_IDF_TARGET_ESP32C2 |
| 357 | + #define FLASH_SPI0_BASE 0x60002000 |
| 358 | +#elif CONFIG_IDF_TARGET_ESP32C6 |
| 359 | + #define FLASH_SPI0_BASE 0x60003000 |
| 360 | +#elif CONFIG_IDF_TARGET_ESP32H2 |
| 361 | + #define FLASH_SPI0_BASE 0x60003000 |
| 362 | +#elif CONFIG_IDF_TARGET_ESP32 |
| 363 | + #define FLASH_SPI0_BASE 0x3ff42000 |
| 364 | +#else |
| 365 | + #define FLASH_SPI0_BASE 0x60003000 // Default for new chips |
| 366 | +#endif |
| 367 | + |
| 368 | +// Register offsets |
| 369 | +#define FLASH_CORE_CLK_SEL_OFFSET 0x80 |
| 370 | +#define FLASH_CLOCK_OFFSET 0x14 |
| 371 | + |
| 372 | +/** |
| 373 | + * @brief Read the source clock frequency from hardware registers |
| 374 | + * @return Source clock frequency in MHz (80, 120, 160, or 240) |
| 375 | + */ |
| 376 | +uint8_t getFlashSourceFrequencyMHz(void) { |
| 377 | + volatile uint32_t* core_clk_reg = (volatile uint32_t*)(FLASH_SPI0_BASE + FLASH_CORE_CLK_SEL_OFFSET); |
| 378 | + uint32_t core_clk_sel = (*core_clk_reg) & 0x3; // Bits 0-1 |
| 379 | + |
| 380 | + uint8_t source_freq = 80; // Default |
| 381 | + |
| 382 | +#if CONFIG_IDF_TARGET_ESP32S3 |
| 383 | + switch (core_clk_sel) { |
| 384 | + case 0: source_freq = 80; break; |
| 385 | + case 1: source_freq = 120; break; |
| 386 | + case 2: source_freq = 160; break; |
| 387 | + case 3: source_freq = 240; break; |
| 388 | + } |
| 389 | +#elif CONFIG_IDF_TARGET_ESP32S2 |
| 390 | + switch (core_clk_sel) { |
| 391 | + case 0: source_freq = 80; break; |
| 392 | + case 1: source_freq = 120; break; |
| 393 | + case 2: source_freq = 160; break; |
| 394 | + } |
| 395 | +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || \ |
| 396 | + CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 |
| 397 | + switch (core_clk_sel) { |
| 398 | + case 0: source_freq = 80; break; |
| 399 | + case 1: source_freq = 120; break; |
| 400 | + } |
| 401 | +#elif CONFIG_IDF_TARGET_ESP32 |
| 402 | + // ESP32 classic - simplified |
| 403 | + source_freq = 80; |
| 404 | +#endif |
| 405 | + |
| 406 | + return source_freq; |
| 407 | +} |
| 408 | + |
| 409 | +/** |
| 410 | + * @brief Read the clock divider from hardware registers |
| 411 | + * @return Clock divider value (1 = no division, 2 = divide by 2, etc.) |
| 412 | + */ |
| 413 | +uint8_t getFlashClockDivider(void) { |
| 414 | + volatile uint32_t* clock_reg = (volatile uint32_t*)(FLASH_SPI0_BASE + FLASH_CLOCK_OFFSET); |
| 415 | + uint32_t clock_val = *clock_reg; |
| 416 | + |
| 417 | + // Bit 31: if set, clock is 1:1 (no divider) |
| 418 | + if (clock_val & (1 << 31)) { |
| 419 | + return 1; |
| 420 | + } |
| 421 | + |
| 422 | + // Bits 16-23: clkdiv_pre |
| 423 | + uint8_t clkdiv_pre = (clock_val >> 16) & 0xFF; |
| 424 | + return clkdiv_pre + 1; |
| 425 | +} |
| 426 | + |
| 427 | +/** |
| 428 | + * @brief Get the actual flash frequency in MHz |
| 429 | + * @return Flash frequency in MHz |
| 430 | + */ |
| 431 | +uint32_t getFlashFrequencyMHz(void) { |
| 432 | + uint8_t source = getFlashSourceFrequencyMHz(); |
| 433 | + uint8_t divider = getFlashClockDivider(); |
| 434 | + |
| 435 | + if (divider == 0) divider = 1; // Safety check |
| 436 | + |
| 437 | + return source / divider; |
| 438 | +} |
| 439 | + |
| 440 | +/** |
| 441 | + * @brief Check if High Performance Mode is enabled |
| 442 | + * @return true if flash runs > 80 MHz, false otherwise |
| 443 | + */ |
| 444 | +bool isFlashHighPerformanceModeEnabled(void) { |
| 445 | + return getFlashFrequencyMHz() > 80; |
| 446 | +} |
0 commit comments