Code: Select all
rmt: rmt_receive(411): channel not in enable state
Looking at the RMT driver's state machine, it made me wonder whether I'm allowed to call rmt_receive from the ISR context at all. Here's my ISR for reference:
Code: Select all
IRAM_ATTR bool RMTReceiverTask::rxDoneCallback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t* edata, void* user_data) {
auto* self = static_cast<RMTReceiverTask*>(user_data);
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
bool isFull = false;
for (auto i = 0; i < edata->num_symbols; i++) {
if (!isFull) {
if (!self->symbol_queue.push_ISR(edata->received_symbols[i], higherPriorityTaskWoken)) {
self->dropped_symbols_count += (edata->num_symbols - i);
isFull = true;
}
}
if (edata->received_symbols[i].duration0 == 0 || edata->received_symbols[i].duration1 == 0) {
self->startReceive();
}
}
if (higherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
return true;
}
Is this a potential problem or do you have an idea what else could be wrong? Note that this way works fine for hours without having the SysInfo stuff in parallel. For reference, here's what I'm doing in the low priority (1) task:
Code: Select all
esp_err_t SystemInfo::updateStats(TickType_t probeIntervalInMs) {
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
TaskStatus_t *start_array = NULL, *end_array = NULL;
UBaseType_t start_array_size, end_array_size;
uint32_t start_run_time, end_run_time;
// Allocate array to store current task states
start_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
start_array = static_cast<TaskStatus_t*>(malloc(sizeof(TaskStatus_t) * start_array_size));
if (start_array == NULL) { return ESP_ERR_NO_MEM; }
// Get current task states
start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time);
if (start_array_size == 0) {
free(start_array);
return ESP_ERR_INVALID_SIZE;
}
vTaskDelay(pdMS_TO_TICKS(probeIntervalInMs));
// Allocate array to store tasks states post delay
end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
end_array = static_cast<TaskStatus_t*>(malloc(sizeof(TaskStatus_t) * end_array_size));
if (end_array == NULL) {
free(start_array);
return ESP_ERR_NO_MEM;
}
// Get post delay task states
end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time);
if (end_array_size == 0) {
free(start_array);
free(end_array);
return ESP_ERR_INVALID_SIZE;
}
// Calculate total_elapsed_time in units of run time stats clock period.
uint32_t total_elapsed_time = (end_run_time - start_run_time);
if (total_elapsed_time == 0) {
free(start_array);
free(end_array);
return ESP_ERR_INVALID_STATE;
}
#ifdef CONFIG_SYSINFO_OUTPUT
ESP_LOGD(LOG, "+----------------------+-----+-----------+-------+-------+");
ESP_LOGD(LOG, "| %-20s | %-3s | %-9s | %-5s | %-5s |", "Task", "PRI", "Run Time", "Load", "Stack");
ESP_LOGD(LOG, "+----------------------+-----+-----------+-------+-------+");
#endif
uint32_t accumulatedIdlePercentage = 0;
// Match each task in start_array to those in the end_array
for (int i = 0; i < start_array_size; i++) {
int k = -1;
for (int j = 0; j < end_array_size; j++) {
if (start_array[i].xHandle == end_array[j].xHandle) {
k = j;
//Mark that task have been matched by overwriting their handles
start_array[i].xHandle = NULL;
end_array[j].xHandle = NULL;
break;
}
}
// Check if matching task found
if (k >= 0) {
uint32_t task_elapsed_time = end_array[k].ulRunTimeCounter - start_array[i].ulRunTimeCounter;
uint32_t percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * portNUM_PROCESSORS);
#ifdef CONFIG_SYSINFO_OUTPUT
ESP_LOGD(LOG, "| %-20s | %3" PRIu8 " | %9" PRIu32 " | %4" PRIu32 "%% | %5" PRIu32 " |",
start_array[i].pcTaskName,
start_array[i].uxCurrentPriority,
task_elapsed_time,
percentage_time,
start_array[i].usStackHighWaterMark
);
#endif
// Store "IDLE" load
if (strncmp(start_array[i].pcTaskName, "IDLE", 4) == 0) {
accumulatedIdlePercentage += percentage_time;
}
}
}
#ifdef CONFIG_SYSINFO_OUTPUT
// Print unmatched tasks
for (int i = 0; i < start_array_size; i++) {
if (start_array[i].xHandle != NULL) {
ESP_LOGD(LOG, "| %-20s | Deleted", start_array[i].pcTaskName);
}
}
for (int i = 0; i < end_array_size; i++) {
if (end_array[i].xHandle != NULL) {
ESP_LOGD(LOG, "| %-20s | Created", end_array[i].pcTaskName);
}
}
ESP_LOGD(LOG, "+----------------------+-----+-----------+-------+-------+");
#endif
// Compute accumulated CPU load and memory pressure
cpuConsumption = 100 - accumulatedIdlePercentage;
if (cpuConsumption > maxCpuConsumption) {
maxCpuConsumption = cpuConsumption;
}
// Free resources
free(start_array);
free(end_array);
#else
ESP_LOGD(LOG, "CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS not enabled. Task Statistics are not available.");
#endif
return ESP_OK;
}