@ElectrodBot Write a function in C to retrieve information about the operating frequency of the selected core in the ESP32. Use ESP-IDF.
Czy wolisz polską wersję strony elektroda?
Nie, dziękuję Przekieruj mnie tamkhoam wrote:Of course, I would be happy to help you write such a function. In ESP32, to read the core frequency, you can use the `esp_clk_cpu_freq()` function available in ESP-IDF, which returns the CPU frequency in Hz.Write a function in C to retrieve information about the operating frequency of the selected core in the ESP32. Use ESP-IDF.
ElektrodaBot wrote:This is about a function that will take a core number as an argument and for this core return its operating frequency.If, however, you are working on a version of ESP32 that allows independent control of the frequency of the cores, you will need to look for other functions specific to this configuration.
khoam wrote:Understood, you would want a function that takes a core number as an argument and returns the frequency of operation for it. On the ESP32, both cores typically run at the same clock rate, and the SDK does not provide a direct API to get the frequency for each core. The clock frequency of the cores is common to both and managed by the system driver, and this configuration is global and independent of the core number.What you want is a function that will take a core number as an argument and for that core return the frequency of its operation.
ElektrodaBot wrote:This does not have to be the case at all. Consider using the esp_ipc_call() function.However, below I give an example of a function that takes a core number as an argument and returns the operating frequency, but note that the value returned will be the same for both cores.
khoam wrote:I understand you want to use `esp_ipc_call()` to run code on a specific core, which can be useful in some situations where you want to see if code running on a specific core can get different results regarding the operating frequency of that core (although in practice the frequency for both cores on the ESP32 is the same, unless a specific configuration has been put in place for some use case).This does not have to be the case at all. Consider using the esp_ipc_call() function.
ElektrodaBot wrote:The `ipc_get_core_freq()` function then reads the clock frequency for that core and writes the result to the global variable `s_core_freq`, which `get_core_frequency()` reads after waiting for the IPC operation to complete.
khoam wrote:Thanks for your comments. Actually `esp_ipc_call()` allows us to pass an argument to a function that will be called on another core. We can use this functionality to pass a pointer to a variable where we want to store the frequency of the core.Try changing this to not use a global variable. The esp_ipc_call() function can take a pointer argument to a void.
ElektrodaBot wrote:The function esp_ipc_call() is not a blocking function. There is another version of this function called esp_ipc_call_blocking(), which is a blocking function.esp_ipc_call()` waits for the execution of the function `ipc_get_core_freq()
khoam wrote:I apologise for the earlier misunderstanding and thank you for the correction. So we will use the `esp_ipc_call_blocking()` function to call a function on a specific core and wait for it to execute.The esp_ipc_call() function is not a blocking function. There is another version of this function called esp_ipc_call_blocking(), which is a blocking function.
khoam wrote:In C++20 we can use lambda expressions, which are very useful when we want to pass a block of code as a function argument without having to define a separate function. Lambdas can also capture variables from the environment, allowing us to work with the context without having to pass additional parameters.Write now an analogous function in C++20 that will use a lambda function instead of the ipc_get_core_freq() function.
khoam wrote:I apologise for the confusion about special characters in the code. This is probably due to the HTML formatting. Here is the corrected code in C++20 that uses a lambda expression to obtain the core frequency without using additional helper functions:The code is incomprehensible. Tags such as """ or ">" have appeared.
What header file is required to use the esp_clk_cpu_freq() function?
khoam wrote:The compiler does not find such a header file.khoam wrote:Sorry for misleading you - my mistake. The correct function to get the CPU core frequency in ESP-IDF is `esp_clk_cpu_freq` and it is declared in the file `esp32/clk.h` or `esp_clk.h` (depending on the ESP-IDF version). The omission regarding the missing file is due to my error.Let's go back to the last version of the function in C. Try using the function esp_clk_tree_src_get_freq_hz() instead of esp_clk_cpu_freq().
If you want to use the `esp_clk_tree_src_get_freq_hz()` function, which can provide the frequency for different clock sources in the clock tree, you need to know that it may require a different header. This function is part of the system clocks API, so make sure you have the appropriate ESP-IDF headers imported.
The following is an example of the use of the `esp_clk_tree_src_get_freq_hz()` function in C:Code: C / C++Log in, to see the code
Remember to check that your development environment is set to the correct version of ESP-IDF and that the `esp32/clk.h` file (or alternatively `esp_clk.h` depending on the ESP-IDF version) is available. It is in this header file that the `esp_clk_tree_src_get_freq_hz()` function declaration is located. If you are using the latest version of ESP-IDF, make sure that the references to the functions and header files correspond to this version.You can call me in any topic by writing @ElektrodaBot. Disclaimer: Some answers provided by the ElektrodaBot may be inaccurate. Elektroda not responsible for accuracy, reliability or completeness of the information presented. All ElektrodaBot responses should be verified by the user. OpenAI can monitor and save information entered after calling ElektrodaBot.
ElektrodaBot wrote:The following is an example of the use of the function `esp_clk_tree_src_get_freq_hz()` in C
khoam wrote:Thanks for the clarification. From this it appears that the function `esp_clk_tree_src_get_freq_hz` returns a value via the output argument and itself returns an error code of type `esp_err_t` to check if the operation succeeded. The header file you should include is `esp_clk_tree.h`. Here is an example of how the aforementioned function can be used:This is an incorrect use of this function. This function is declared as follows:
esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value)
It is available in the header file esp_clk_tree.h
ElektrodaBot wrote:The `CLK_TREE_CPU` parameter is used as an identifier of the CPU clock source.
ElektrodaBot wrote:is called with flag `CLK_TREE_SRC_FREQ_PRECISION_HIGH`
khoam wrote:Excuse me for previous misunderstandings. Now that we have all the information we need, we can move on to the correct use of the `esp_clk_tree_src_get_freq_hz()` function in the context of an inter-process function call (IPC) on the ESP32 core. Below is a revised version of the `ipc_get_core_freq` function which uses the correct `SOC_MOD_CLK_CPU` and `ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT` constants:There is no such parameter but there is SOC_MOD_CLK_CPU.
There is no such parameter. There are instead: ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT and ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID.
ElektrodaBot wrote:Below is a corrected version of the `ipc_get_core_freq` function which uses the correct `SOC_MOD_CLK_CPU` and `ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT` constants
khoam wrote:Excuse the error from the previous answer. Let's now focus on feature compatibility with the ESP32-S3. The ESP32-S3 is another chip in the ESP32 family and in many cases code written for ESP32 will be compatible with ESP32-S3. However, there may be hardware differences that require attention.This last question. Will this version of the code also work correctly for ESP32-S3 ?
TL;DR: For ESP-IDF users who need per-core CPU frequency on ESP32, use core 0 or 1 with
esp_ipc_call_blocking(). As one correction states, "not a blocking function," so plainesp_ipc_call()is unsafe for a stack variable. Read the value throughesp_clk_tree_src_get_freq_hz(..., ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &freq)in Hz. [#20881965]
Why it matters: This avoids race conditions, wrong headers, and invalid clock-tree calls when you need a frequency reading from a selected ESP32 core.
| Approach | Blocking | Result handoff | Thread verdict |
|---|---|---|---|
esp_ipc_call() + local variable |
No | Unsafe without extra sync | Rejected |
esp_ipc_call_blocking() + pointer arg |
Yes | Direct write to caller variable | Accepted |
esp_clk_cpu_freq() |
N/A | Simple global CPU read | Version-sensitive |
esp_clk_tree_src_get_freq_hz() |
N/A | esp_err_t + output pointer |
Final preferred API |
Key insight: The winning pattern is not "read frequency globally," but "run the read on the selected core and return it through a pointer." In this thread, correct API details mattered more than the basic idea.
esp_ipc_call() was explicitly corrected as non-blocking, while esp_ipc_call_blocking() was named as the blocking variant for safe completion on the target core. [#20881965]esp_err_t and writes frequency through a uint32_t * output pointer, not as a direct return value in Hz. [#20882042]esp_clk_tree_src_get_freq_hz() in the final correction is esp_clk_tree.h, not esp_clk.h. [#20882042]SOC_MOD_CLK_CPU and ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT; earlier names were rejected as undefined. [#20882077]core_id, creates a local uint32_t core_freq, and calls esp_ipc_call_blocking(core_id, ipc_get_core_freq, &core_freq). Inside the IPC callback, call esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_CPU, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, freq_ptr). Return 0 for invalid core IDs outside 0 and 1. This design reads the frequency on the selected core and returns it in Hz through the pointer. [#20882089]esp_ipc_call_blocking() is the IPC variant that waits until the function finishes on the selected core. Use it when the callback writes into a caller-owned local variable, because the caller must not continue before the write completes. In this thread, the non-blocking version was explicitly corrected as unsuitable for that pattern. Use the blocking call when you target core 0 or 1 and need the result immediately after the call returns. [#20881965]esp_ipc_call() with esp_ipc_call_blocking() for safe handoff of the frequency value in Hz. [#20881965]esp_clk_tree.h. The thread first tried esp_clk.h and chip-specific clock headers, but the final correction states that esp_clk_tree_src_get_freq_hz() is available in esp_clk_tree.h. If your compiler cannot find the symbol, start by checking that header and your ESP-IDF version. [#20882042]uint32_t * output pointer. The corrected form in the thread is esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_CPU, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, freq), where freq points to a variable that receives the value in Hz. Check the returned esp_err_t before you trust the result. [#20882089]SOC_MOD_CLK_CPU is the CPU clock-source identifier used with the clock-tree API, and ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT requests the exact precision mode named in the thread. Earlier symbols were rejected as invalid. In plain terms, these two constants tell ESP-IDF what clock to measure and how precise the reported frequency should be. [#20882077]void *arg parameter. In the callback, cast that pointer to uint32_t * and write the frequency into it. This removes the global state and keeps the result tied to one function call. It works safely only with the blocking IPC variant, because the caller must wait for the remote write to finish. [#20881970]0 and 1, and reject everything else immediately. The examples in the thread use a simple if (core_id != 0 && core_id != 1) check, log an error, and return 0. That is the cleanest validation for a dual-core ESP32 example, because it blocks invalid IPC targets before any callback runs. [#20881920]esp_clk.h, but the compiler reportedly could not find that header. Later, the discussion moved to esp_clk_tree_src_get_freq_hz() in esp_clk_tree.h, with corrected constants and a corrected function signature. That makes the older examples look too generic for the user's ESP-IDF setup. [#20882028]esp_clk_cpu_freq() is the simpler read, but it was discussed with header confusion and version mismatch. esp_clk_tree_src_get_freq_hz() is more explicit: it takes a source ID, a precision mode, and an output pointer, then returns esp_err_t. In this thread, the clock-tree call became the preferred final approach because its correct header and corrected arguments were pinned down more clearly. [#20882059]void *, and invoke it from a C-compatible callback. The thread used std::function<void()>, a wrapper callback, and esp_ipc_call_blocking(core_id, ipc_callback, &func). That preserves a C++20 lambda while satisfying the C-style IPC callback signature. The thread also showed that copied HTML entities can make such examples look broken if not cleaned up first. [#20882018]" and > appearing in the C++20 example, which made it hard to read. Fix it by replacing escaped entities with normal characters before compiling, then re-check the includes and callback syntax. This is a formatting issue, not an ESP-IDF runtime issue. [#20882011]esp_clk_tree.h. 2. Verify the exact symbol names; the accepted constants were SOC_MOD_CLK_CPU and ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT. 3. Verify the function signature; esp_clk_tree_src_get_freq_hz() returns esp_err_t and fills a uint32_t *. Those three checks fixed every symbol issue raised in the thread. [#20882077]