FreeRTOS xSemaphoreTake assert failed
Posted: Sat Apr 13, 2024 9:32 pm
I'm using ESP32-S3 to calculate RMS of sine wave signal input from ADC. I use ADC 1 continuous mode, trigger adc_continuous_read by GPTimer and FreeRTOS task, then pass ADC conversion result to another task by queue, store all conversion results, finally calculate root-mean-square after getting enough samples. I use binary semaphore as a flag of "it's time to calculate RMS". But when I call xSemaphoreGive(sem) in the first task then call xSemaphoreTake(sem, 0) in the second task, the FreeRTOS crashed and the board rebooted.
I want to know what's going wrong and how to fix it. Following is my code:
and backtrace:
I want to know what's going wrong and how to fix it. Following is my code:
Code: Select all
static adc_continuous_handle_t handle = NULL;
static adc_cali_handle_t cali_handle = NULL;
static SemaphoreHandle_t adc_read_call = NULL;
static SemaphoreHandle_t rms_call = NULL;
static QueueHandle_t rms_data_queue = NULL;
uint32_t frequency; // Will be edited by other tasks
typedef struct {
int channel;
int value;
} adc_output_t;
typedef struct {
uint32_t ret_num;
adc_output_t data[2048];
} adc_cali_output_t;
static bool IRAM_ATTR adc_read(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) {
xSemaphoreGiveFromISR(adc_read_call, NULL);
return true;
}
void adc_read_task(void *pvParameter) {
int freq_count = 0;
uint32_t *freq = (uint32_t*)pvParameter;
while(true) {
if(xSemaphoreTake(adc_read_call, portMAX_DELAY)) {
uint8_t results[2048] = {0};
uint32_t ret_num = 0;
adc_cali_output_t cali_output;
memset(&cali_output, 0, sizeof(adc_cali_output_t));
if(adc_continuous_read(handle, results, 2048, &ret_num, 100) == ESP_OK) {
int count = 0;
for(int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) {
adc_digi_output_data_t *data = (adc_digi_output_data_t*)&results[i];
adc_output_t output = {
.channel = data->type2.channel - 3, // ADC 1 Channel 3, 4, 5
};
int voltage = 0;
adc_cali_raw_to_voltage(cali_handle, data->type2.data, &voltage);
output.value = voltage;
cali_output.data[count] = output;
count++;
}
cali_output.ret_num = count;
freq_count++;
xQueueSend(rms_data_queue, &cali_output, portMAX_DELAY);
if(!(freq_count < *freq)) {
freq_count = 0;
xSemaphoreGive(rms_call);
}
} else {
ESP_LOGE(TAG, "ADC read failed");
}
}
}
}
uint32_t binpow(long long a, long long b) {
... // Binary Exponentiation, working fine
}
void adc_rms_task(void* pvParameter) {
static uint32_t data[3][2000] = {0};
static float sum_squares[3] = {0};
static int count[3] = {0};
adc_cali_output_t cali_output;
while(true) {
if(xQueueReceive(rms_data_queue, &cali_output, portMAX_DELAY)) {
for(int i = 0; i < cali_output.ret_num; i++) {
data[cali_output.data[i].channel][count[cali_output.data[i].channel]] = cali_output.data[i].value;
count[cali_output.data[i].channel]++;
}
if(xSemaphoreTake(rms_call, 0)) { // assert failed after xSemaphoreGive(rms_call) was called in adc_read_task
float rms[3] = {0};
for(int i = 0; i < 3; i++) {
for(int j = 0; j < count[i]; j++) {
sum_squares[i] += binpow(data[i][j], 2);
}
rms[i] = sqrt(sum_squares[i] / count[i]);
}
memset(sum_squares, 0, sizeof(sum_squares));
ESP_LOGI(TAG, "RMS: %1fmV, %1fmV, %1fmV", rms[0], rms[1], rms[2]);
memset(count, 0, sizeof(count));
memset(data, 0, sizeof(data));
}
}
}
}
esp_err_t adc_init(uint8_t *results) {
queue = xSemaphoreCreateBinary();
rms_data_queue = xQueueCreate(10, 2048 * sizeof(adc_digi_output_data_t));
rms_call = xSemaphoreCreateBinary();
xTaskCreatePinnedToCore(adc_read_task, "adc_read_task", 32768, (void*)results, 10, NULL, 1);
xTaskCreatePinnedToCore(adc_rms_task, "adc_voltage_rms_task", 32768, NULL, 10, NULL, 0);
esp_err_t ret = ESP_OK;
... // ADC initalize
ESP_ERROR_CHECK(adc_continuous_start(handle));
gptimer_handle_t gptimer = NULL;
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_event_callbacks_t callback_config = {
.on_alarm = adc_read,
};
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick=1us
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &callback_config, results));
ESP_ERROR_CHECK(gptimer_enable(gptimer));
ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
ESP_ERROR_CHECK(gptimer_start(gptimer));
return ret;
}
void app_main() {
adc_init(&frequency);
}
Code: Select all
assert failed: xQueueSemaphoreTake queue.c:1709 (( pxQueue ))
Backtrace: 0x40375b5e:0x3fccd120 0x4037b961:0x3fccd140 0x40382079:0x3fccd160 0x4037c1ce:0x3fccd280 0x42009ba5:0x3fccd2c0 0x4037c3f5:0x3fcd1320
None
Waiting for the device to reconnect0x40375b5e: panic_abort at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/panic.c:472
0x4037b961: esp_system_abort at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/port/esp_system_chip.c:93
0x40382079: __assert_func at C:/Espressif/frameworks/esp-idf-v5.2.1/components/newlib/assert.c:81
0x4037c1ce: xQueueSemaphoreTake at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/queue.c:1709 (discriminator 1)
0x42009ba5: adc_voltage_rms_task at C:/Users/littl/Workspace/ESP/measurer/main/adc.c:101
0x4037c3f5: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134
ELF file SHA256: bf510f105
Rebooting...
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375ad4
0x40375ad4: esp_restart_noos at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/port/soc/esp32s3/system_internal.c:159
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3810,len:0x178c
load:0x403c9700,len:0x4
load:0x403c9704,len:0xcbc
load:0x403cc700,len:0x2da0
entry 0x403c9914