Skip to content

Commit 54ca41e

Browse files
committed
getFlashFrequencyMHz
1 parent e8d0d31 commit 54ca41e

File tree

2 files changed

+125
-18
lines changed

2 files changed

+125
-18
lines changed

cores/esp32/chip-debug-report.cpp

Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
#include "soc/efuse_reg.h"
1010
#include "soc/rtc.h"
1111
#include "soc/spi_reg.h"
12+
#include "soc/soc.h"
1213
#if CONFIG_IDF_TARGET_ESP32S2
1314
#include "esp32s2/rom/spi_flash.h"
1415
#endif
1516
#include "esp_bit_defs.h"
1617

1718
#include "Arduino.h"
1819
#include "esp32-hal-periman.h"
20+
#include "chip-debug-report.h"
1921

2022
#define chip_report_printf log_printf
2123

@@ -138,25 +140,19 @@ static void printFlashInfo(void) {
138140
chip_report_printf(" Block Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.block_size, b2kb(g_rom_flashchip.block_size));
139141
chip_report_printf(" Sector Size : %8lu B (%6.1f KB)\n", g_rom_flashchip.sector_size, b2kb(g_rom_flashchip.sector_size));
140142
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");
159154
}
155+
160156
chip_report_printf(" Bus Mode : ");
161157
#if CONFIG_ESPTOOLPY_OCT_FLASH
162158
chip_report_printf("OPI\n");
@@ -345,3 +341,106 @@ void printAfterSetupInfo(void) {
345341
chip_report_printf("============ After Setup End =============\n");
346342
delay(20); //allow the print to finish
347343
}
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+
}

cores/esp32/chip-debug-report.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,13 @@
55
*/
66
#pragma once
77

8+
#include <stdint.h>
9+
810
void printBeforeSetupInfo(void);
911
void printAfterSetupInfo(void);
12+
13+
// Flash frequency runtime detection
14+
uint32_t getFlashFrequencyMHz(void);
15+
uint8_t getFlashSourceFrequencyMHz(void);
16+
uint8_t getFlashClockDivider(void);
17+
bool isFlashHighPerformanceModeEnabled(void);

0 commit comments

Comments
 (0)