diff --git a/CMakeLists.txt b/CMakeLists.txt index ff444683..5f925aef 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -set(PROJECT_VER "1.9.1") +set(PROJECT_VER "1.9.2") # Add this line to disable the specific warning add_compile_options(-Wno-missing-field-initializers) diff --git a/main/application.cc b/main/application.cc index 3d619def..59530acb 100644 --- a/main/application.cc +++ b/main/application.cc @@ -532,9 +532,6 @@ void Application::Schedule(std::function callback) { // If other tasks need to access the websocket or chat state, // they should use Schedule to call this function void Application::MainEventLoop() { - // Raise the priority of the main event loop to avoid being interrupted by background tasks (which has priority 2) - vTaskPrioritySet(NULL, 3); - while (true) { auto bits = xEventGroupWaitBits(event_group_, MAIN_EVENT_SCHEDULE | MAIN_EVENT_SEND_AUDIO | @@ -746,11 +743,20 @@ bool Application::CanEnterSleepMode() { } void Application::SendMcpMessage(const std::string& payload) { - Schedule([this, payload]() { - if (protocol_) { + if (protocol_ == nullptr) { + return; + } + + // Make sure you are using main thread to send MCP message + if (xTaskGetCurrentTaskHandle() == main_event_loop_task_handle_) { + ESP_LOGI(TAG, "Send MCP message in main thread"); + protocol_->SendMcpMessage(payload); + } else { + ESP_LOGI(TAG, "Send MCP message in sub thread"); + Schedule([this, payload = std::move(payload)]() { protocol_->SendMcpMessage(payload); - } - }); + }); + } } void Application::SetAecMode(AecMode mode) { diff --git a/main/application.h b/main/application.h index f5659d6b..655b18b7 100644 --- a/main/application.h +++ b/main/application.h @@ -82,6 +82,7 @@ private: bool aborted_ = false; int clock_ticks_ = 0; TaskHandle_t check_new_version_task_handle_ = nullptr; + TaskHandle_t main_event_loop_task_handle_ = nullptr; void OnWakeWordDetected(); void CheckNewVersion(Ota& ota); @@ -89,4 +90,19 @@ private: void SetListeningMode(ListeningMode mode); }; + +class TaskPriorityReset { +public: + TaskPriorityReset(BaseType_t priority) { + original_priority_ = uxTaskPriorityGet(NULL); + vTaskPrioritySet(NULL, priority); + } + ~TaskPriorityReset() { + vTaskPrioritySet(NULL, original_priority_); + } + +private: + BaseType_t original_priority_; +}; + #endif // _APPLICATION_H_ diff --git a/main/audio/audio_service.cc b/main/audio/audio_service.cc index 3081e6ad..8a87208b 100644 --- a/main/audio/audio_service.cc +++ b/main/audio/audio_service.cc @@ -100,11 +100,11 @@ void AudioService::Start() { #if CONFIG_USE_AUDIO_PROCESSOR /* Start the audio input task */ - xTaskCreatePinnedToCore([](void* arg) { + xTaskCreate([](void* arg) { AudioService* audio_service = (AudioService*)arg; audio_service->AudioInputTask(); vTaskDelete(NULL); - }, "audio_input", 2048 * 3, this, 8, &audio_input_task_handle_, 1); + }, "audio_input", 2048 * 3, this, 8, &audio_input_task_handle_); /* Start the audio output task */ xTaskCreate([](void* arg) { diff --git a/main/display/lcd_display.cc b/main/display/lcd_display.cc index ce028a4b..e069d7ff 100644 --- a/main/display/lcd_display.cc +++ b/main/display/lcd_display.cc @@ -117,6 +117,9 @@ SpiLcdDisplay::SpiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_h ESP_LOGI(TAG, "Initialize LVGL port"); lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); port_cfg.task_priority = 1; +#if CONFIG_SOC_CPU_CORES_NUM > 1 + port_cfg.task_affinity = 1; +#endif lvgl_port_init(&port_cfg); ESP_LOGI(TAG, "Adding LCD display"); @@ -178,7 +181,9 @@ RgbLcdDisplay::RgbLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_h ESP_LOGI(TAG, "Initialize LVGL port"); lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); port_cfg.task_priority = 1; - port_cfg.timer_period_ms = 50; +#if CONFIG_SOC_CPU_CORES_NUM > 1 + port_cfg.task_affinity = 1; +#endif lvgl_port_init(&port_cfg); ESP_LOGI(TAG, "Adding LCD display"); @@ -237,6 +242,10 @@ MipiLcdDisplay::MipiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel ESP_LOGI(TAG, "Initialize LVGL port"); lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); + port_cfg.task_priority = 1; +#if CONFIG_SOC_CPU_CORES_NUM > 1 + port_cfg.task_affinity = 1; +#endif lvgl_port_init(&port_cfg); ESP_LOGI(TAG, "Adding LCD display"); diff --git a/main/display/oled_display.cc b/main/display/oled_display.cc index d3fb3aaf..08d22517 100644 --- a/main/display/oled_display.cc +++ b/main/display/oled_display.cc @@ -23,6 +23,9 @@ OledDisplay::OledDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handl lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); port_cfg.task_priority = 1; port_cfg.task_stack = 6144; +#if CONFIG_SOC_CPU_CORES_NUM > 1 + port_cfg.task_affinity = 1; +#endif lvgl_port_init(&port_cfg); ESP_LOGI(TAG, "Adding OLED display"); diff --git a/main/idf_component.yml b/main/idf_component.yml index 85fe8701..ddc06909 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,7 +15,7 @@ dependencies: 78/esp_lcd_nv3023: ~1.0.0 78/esp-wifi-connect: ~2.5.2 78/esp-opus-encoder: ~2.4.1 - 78/esp-ml307: ~3.3.1 + 78/esp-ml307: ~3.3.5 78/xiaozhi-fonts: ~1.5.2 espressif/led_strip: ~3.0.1 espressif/esp_codec_dev: ~1.4.0 diff --git a/main/main.cc b/main/main.cc index c4bce23d..62477d27 100755 --- a/main/main.cc +++ b/main/main.cc @@ -27,5 +27,4 @@ extern "C" void app_main(void) // Launch the application auto& app = Application::GetInstance(); app.Start(); - app.MainEventLoop(); } diff --git a/main/mcp_server.cc b/main/mcp_server.cc index 2d86e212..bd617db0 100644 --- a/main/mcp_server.cc +++ b/main/mcp_server.cc @@ -16,8 +16,6 @@ #define TAG "MCP" -#define DEFAULT_TOOLCALL_STACK_SIZE 6144 - McpServer::McpServer() { } @@ -100,6 +98,9 @@ void McpServer::AddCommonTools() { Property("question", kPropertyTypeString) }), [camera](const PropertyList& properties) -> ReturnValue { + // Lower the priority to do the camera capture + TaskPriorityReset priority_reset(1); + if (!camera->Capture()) { return "{\"success\": false, \"message\": \"Failed to capture photo\"}"; } @@ -235,13 +236,7 @@ void McpServer::ParseMessage(const cJSON* json) { ReplyError(id_int, "Invalid arguments"); return; } - auto stack_size = cJSON_GetObjectItem(params, "stackSize"); - if (stack_size != nullptr && !cJSON_IsNumber(stack_size)) { - ESP_LOGE(TAG, "tools/call: Invalid stackSize"); - ReplyError(id_int, "Invalid stackSize"); - return; - } - DoToolCall(id_int, std::string(tool_name->valuestring), tool_arguments, stack_size ? stack_size->valueint : DEFAULT_TOOLCALL_STACK_SIZE); + DoToolCall(id_int, std::string(tool_name->valuestring), tool_arguments); } else { ESP_LOGE(TAG, "Method not implemented: %s", method_str.c_str()); ReplyError(id_int, "Method not implemented: " + method_str); @@ -316,7 +311,7 @@ void McpServer::GetToolsList(int id, const std::string& cursor) { ReplyResult(id, json); } -void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments, int stack_size) { +void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments) { auto tool_iter = std::find_if(tools_.begin(), tools_.end(), [&tool_name](const McpTool* tool) { return tool->name() == tool_name; @@ -358,15 +353,9 @@ void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* to return; } - // Start a task to receive data with stack size - esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); - cfg.thread_name = "tool_call"; - cfg.stack_size = stack_size; - cfg.prio = 1; - esp_pthread_set_cfg(&cfg); - - // Use a thread to call the tool to avoid blocking the main thread - tool_call_thread_ = std::thread([this, id, tool_iter, arguments = std::move(arguments)]() { + // Use main thread to call the tool + auto& app = Application::GetInstance(); + app.Schedule([this, id, tool_iter, arguments = std::move(arguments)]() { try { ReplyResult(id, (*tool_iter)->Call(arguments)); } catch (const std::exception& e) { @@ -374,5 +363,4 @@ void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* to ReplyError(id, e.what()); } }); - tool_call_thread_.detach(); } \ No newline at end of file diff --git a/main/mcp_server.h b/main/mcp_server.h index ac2b936f..bb610d99 100644 --- a/main/mcp_server.h +++ b/main/mcp_server.h @@ -285,10 +285,9 @@ private: void ReplyError(int id, const std::string& message); void GetToolsList(int id, const std::string& cursor); - void DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments, int stack_size); + void DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments); std::vector tools_; - std::thread tool_call_thread_; }; #endif // MCP_SERVER_H