printf crashes within critical section

ukrsms
Posts: 24
Joined: Tue Aug 20, 2019 11:30 am

printf crashes within critical section

Postby ukrsms » Fri Jul 10, 2020 1:54 pm

Several times I faced an issues when my program crases within a critical_section. Each time the cause is linked to printf() function.
Recently I found that the program paniced when printf() was called within a critical section and the last case happened when trying to call gpio_config() which yet has printf inside.

Briefly, the code called is:

Code: Select all

portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&mutex);
gpio_config_t GPIO_Struct;
...
err=gpio_config(&GPIO_Struct);
...
portEXIT_CRITICAL(&mutex);
According to the backtrace panic is invoked on calling printf:

Code: Select all

0x40088091: invoke_abort at C:/esp-idf/components/esp32/panic.c:157
0x40088421: abort at C:/esp-idf/components/esp32/panic.c:174
0x40083646: lock_acquire_generic at C:/esp-idf/components/newlib/locks.c:143
0x40083769: _lock_acquire_recursive at C:/esp-idf/components/newlib/locks.c:171
0x40172186: _vfprintf_r at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdio/vfprintf.c:853 (discriminator 2)
0x401751b5: vprintf at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdio/vprintf.c:34
0x400933a1: esp_log_write at C:/esp-idf/components/log/log.c:190
0x400eaf45: gpio_config at C:/esp-idf/components/driver/gpio.c:364 (discriminator 9)
And it is found that this happened when printf() function was called within

I am wandering whether it is incorrect to call any function internally invoking printf() within critical section or it is just a coincidence and the problem is caused by other thing?

chegewara
Posts: 2362
Joined: Wed Jun 14, 2017 9:00 pm

Re: printf crashes within critical section

Postby chegewara » Fri Jul 10, 2020 2:08 pm

Try to use

Code: Select all

ets_printf();

ESP_Sprite
Posts: 9711
Joined: Thu Nov 26, 2015 4:08 am

Re: printf crashes within critical section

Postby ESP_Sprite » Fri Jul 10, 2020 6:36 pm

Chegewara is right. Additionally, code run within a critical section more-or-less has the same restrictions as code running in an IRQ, that is, it should not (directly or indirectly) call any blocking functions.

ukrsms
Posts: 24
Joined: Tue Aug 20, 2019 11:30 am

Re: printf crashes within critical section

Postby ukrsms » Tue Jul 14, 2020 8:49 am

Thank you,
ets_printf() is the function I usually use to avoid problems within a critical section but is not convenient each time to predict whether the current procedure will or not be used within a critical section.
I was hoping some more convenient practice exists. Nevertheless, is it possible to define whether a piece of code (say a function) is called within a critical section (ISR) or not)?

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: printf crashes within critical section

Postby ESP_Angus » Wed Jul 15, 2020 4:31 am

Hi ukrsms,

The driver functions themselves should be thread-safe at minimum, so you shouldn't need critical sections for calling functions like gpio_config(). Can you fill us in on the big picture of what this critical section is protecting?

If the resources you're controlling access to are bigger in granularity (ie more than a few hundred instructions) then it may make more sense to use a FreeRTOS mutex semaphore or similar. These have more overhead but don't implement critical sections, and if a task if blocked on one then the CPU is freed up to run another task (unlike the critical sections which are implemented with spinlocks, so the blocked task will spin.)

ukrsms
Posts: 24
Joined: Tue Aug 20, 2019 11:30 am

Re: printf crashes within critical section

Postby ukrsms » Wed Jul 15, 2020 3:33 pm

@esp_angus, thank you for the explanation.
Can you fill us in on the big picture of what this critical section is protecting?
I use the critical section as an alternative for mutex in order to decrease overhead. In the case described I use it inside a function that read ADC value which additionally needs to switch GPIO pin to enable an external sensor.
My decision is based on the following consideration: if I use a critical section everything will execute anyway, but if I use RTOS mutex an execution could be skipped if the mutex occupied in another place.

I tried to find a detailed description of portENTER_CRITICAL function but I didn't.

Could you clarify for me if I use portENTER_CRITICAL does the system scheduler is stopped until portEXIT_CRITICAL or it continues? In other words, if protect function with critical section does it mean that only this function wouldn't be repeatedly called or no other function wouldn't be called as well?

Who is online

Users browsing this forum: No registered users and 95 guests