Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPIFFS use core1/CPU1 and blocks the thread (hangs forever) (IDFGH-10593) #11830

Closed
3 tasks done
creatormir opened this issue Jul 7, 2023 · 8 comments
Closed
3 tasks done
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@creatormir
Copy link

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

v5.1

Operating System used.

Windows

How did you build your project?

Command line with CMake

If you are using Windows, please specify command line type.

CMD

Development Kit.

WROOM32E

Power Supply used.

USB

What is the expected behavior?

I expect SPIFFS will not use core1/CPU1

What is the actual behavior?

Looks like SPIFFS uses interrupts on core1/CPU1 invisibly and this blocks the thread (hangs forever)

Steps to reproduce.

  1. Use the standard example http_server/file_serving

  2. Add this code:

 void Core1_1( void* p) {
    portDISABLE_INTERRUPTS();   
    while (1)
    {
        /* code */
    }
    
}
// In app_main
    TaskHandle_t Task_1;  
    xTaskCreatePinnedToCore(
        Core1_1,       // Function that implements the task.
        "Core1_1",          // Text name for the task.
        STACK_SIZE *1,      // Stack size in bytes, not words.
        ( void * ) 1,    // Parameter passed into the task.
        25 -1, // tskIDLE_PRIORITY+2,
        // tskIDLE_PRIORITY +2, // tskIDLE_PRIORITY+2,
        // configMAX_PRIORITIES -1, // tskIDLE_PRIORITY+2,
        &Task_1,
        1 // Core 1
    );
  1. After connecting to wifi-ap and trying to load a web page, the system will hang on this line
    stat(filepath, &file_stat)

Debug Logs.

No response

More Information.

No response

@creatormir creatormir added the Type: Bug bugs in IDF label Jul 7, 2023
@espressif-bot espressif-bot added the Status: Opened Issue is new label Jul 7, 2023
@github-actions github-actions bot changed the title SPIFFS use core1/CPU1 and blocks the thread (hangs forever) SPIFFS use core1/CPU1 and blocks the thread (hangs forever) (IDFGH-10593) Jul 7, 2023
@igrr
Copy link
Member

igrr commented Jul 7, 2023

Due to the fact that access to main SPI flash requires disabling the cache, the code running on the other core has to be preempted during flash operations. This mechanism relies on interrupts and IPC. Your code disables interrupts on the CPU1, therefore IPC never completes.
This is described in more detail in https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_flash/spi_flash_concurrency.html#concurrency-constraints-for-flash-on-spi1.

@creatormir
Copy link
Author

How can I selectively disable cache on CPU1?
spi_flash_disable_cache is not defined in cache_utils.h for some reason is there some nuance?

My function requires constant execution, it reads pins and pulls them. This func can be placed in IRAM.
But most of all I am interested in the example of how to run my loop function on CPU1 while everything is running on CPU0 (with CONFIG_FREERTOS_UNICORE=y)

@igrr
Copy link
Member

igrr commented Jul 7, 2023

How can I selectively disable cache on CPU1?

At least on the ESP32 (which you are using) it is not possible. Cache can be enabled or disabled only for both CPUs.

But most of all I am interested in the example of how to run my loop function on CPU1 while everything is running on CPU0 (with CONFIG_FREERTOS_UNICORE=y)

There is no support for this use case in ESP-IDF. Please see #10410 as well.

That said, you might be able to avoid CPU1 suspension if you use external SPI flash (over SPI2 or 3) for Spiffs and NVS. This way flash operations won't require the cache to be disabled, and CPU1 won't get interrupted.

@creatormir
Copy link
Author

creatormir commented Jul 7, 2023

On which ESP32 is this possible?
Another SPI is difficult to use we plan to use WROOM modules

What is your opinion on the ESP32-Bare-Metal-AppCPU project?
A strange decision to make esp-hal not in C...

@igrr
Copy link
Member

igrr commented Jul 7, 2023

On which ESP32 is this possible?

For example, on ESP32-C6 there is an LP core which is completely independent from the main core and doesn't run an RTOS. It still has access to the same peripherals and memory as the main core.

Another SPI is difficult to use we plan to use WROOM modules.

This should be possible with WROOM. You can connect 2nd SPI flash and use it for data storage, while the main flash will be used for code execution. You can try this using storage/ext_flash_fatfs example provided in IDF. Although the example is for FAT filesystem, SPIFFS and NVS can be used in a similar fashion.

What is your opinion on the ESP32-Bare-Metal-AppCPU project?

Thanks for linking to it, I haven't seen it. I can't say whether that approach will work and if there would be any issue with it, sorry. When single core mode is used in IDF, various memory regions normally allocated to the 2nd CPU (for example, stack region used by the boot ROM) are released and used as part of the heap. It looks like this can cause heap corruption, if the 2nd CPU boots up after the heap is initialized. I am not sure how that projects deals with this issue.

A strange decision to make esp-hal not in C...

There's a growing amount of examples and documentation for esp-hal which should help you get started, even though the code might not be written in C. If you find any particular pain points, please let us know and we'll try to improve it!

@creatormir
Copy link
Author

Thanks for the quick replies!
In my application, I found a solution to disable my task while the server is running.
The only question is: is it possible to somehow enable CPU1 interrupts from the CPU0 context?
portENABLE_INTERRUPTS() unfortunately only disables interrupts in the kernel in which context it is invoked.

@igrr
Copy link
Member

igrr commented Jul 7, 2023

The only question is: is it possible to somehow enable CPU1 interrupts from the CPU0 context?

CPU interrupts are masked using registers which are internal to the CPU, and aren't accessible from the other CPU. You might be able to disable some specific peripheral interrupts on the peripheral side, but disabling them on the CPU side requires the code to run on the CPU itself, unfortunately.

@creatormir
Copy link
Author

Understood thanks!
Later I will study ESP32-C6

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Opened Issue is new labels Jul 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

3 participants