From bdeb4b1bfaf09c698b624af9034e9d8629cb92a1 Mon Sep 17 00:00:00 2001 From: wbz <1664546556@qq.com> Date: Thu, 9 Apr 2026 14:05:48 +0800 Subject: [PATCH] =?UTF-8?q?bugfix:=20=E4=BF=AE=E5=A4=8D=20ISR=20=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E3=80=81Wi-Fi=20=E4=BA=8B=E4=BB=B6=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E3=80=81I2C=20=E6=80=BB=E7=BA=BF=E9=80=89=E6=8B=A9=E4=B8=8E?= =?UTF-8?q?=E9=97=B9=E9=92=9F=E9=87=8D=E5=A4=8D=E8=A7=A6=E5=8F=91=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将充电 GPIO ISR 改为仅发送任务通知,避免在 ISR 中直接调用非 ISR-safe 逻辑(电机/风扇控制) - Wi-Fi 事件处理增加 event_base 判断,防止在共用 handler 中误解析 event_data 类型 - I2C 封装按设备句柄选择对应总线(RTC/IMU=port0,Touch=port1),并在错误时对正确总线执行 reset - 闹钟触发增加分钟槽位去重,避免 100ms 定时器在同一秒内重复触发 影响范围: - main/main.cpp - components/esp_wifi_bsp/esp_wifi_bsp.c - components/i2c_bsp/i2c_bsp.c - components/i2c_bsp/i2c_bsp.h - main/page.cpp --- .../components/esp_wifi_bsp/esp_wifi_bsp.c | 7 +-- .../components/i2c_bsp/i2c_bsp.c | 53 +++++++++++++++---- .../components/i2c_bsp/i2c_bsp.h | 9 ++-- Code/PhoneBed_code/main/main.cpp | 24 ++++++++- Code/PhoneBed_code/main/page.cpp | 12 +++-- 5 files changed, 82 insertions(+), 23 deletions(-) diff --git a/Code/PhoneBed_code/components/esp_wifi_bsp/esp_wifi_bsp.c b/Code/PhoneBed_code/components/esp_wifi_bsp/esp_wifi_bsp.c index 843764c..92efdb8 100644 --- a/Code/PhoneBed_code/components/esp_wifi_bsp/esp_wifi_bsp.c +++ b/Code/PhoneBed_code/components/esp_wifi_bsp/esp_wifi_bsp.c @@ -51,20 +51,21 @@ void espwifi_Init(void) static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - if (event_id == WIFI_EVENT_STA_START) + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); // 连接到 Wi-Fi // esp_wifi_scan_u(); } - else if (event_id == IP_EVENT_STA_GOT_IP) + else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; char ip[25]; uint32_t pxip = event->ip_info.ip.addr; + wifi_retry_num = 0; sprintf(ip, "%d.%d.%d.%d", (uint8_t)(pxip), (uint8_t)(pxip >> 8), (uint8_t)(pxip >> 16), (uint8_t)(pxip >> 24)); printf("IP: %s\n", ip); } - else if (event_id == WIFI_EVENT_STA_DISCONNECTED) + else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { wifi_retry_num++; if (wifi_retry_num > MAXIMUM_RETRY_NUM) diff --git a/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.c b/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.c index 4b0cc57..5ec0319 100644 --- a/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.c +++ b/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.c @@ -24,6 +24,19 @@ static uint32_t i2c_done_pdMS_TICKS = 0; esp_io_expander_handle_t io_expander = NULL; +static i2c_master_bus_handle_t get_bus_handle_by_device(i2c_master_dev_handle_t dev_handle) +{ + if (dev_handle == rtc_dev_handle || dev_handle == imu_dev_handle) + { + return user_i2c_port0_handle; + } + if (dev_handle == disp_touch_dev_handle) + { + return user_i2c_port1_handle; + } + return NULL; +} + static void tca9554_init(void) { i2c_master_bus_handle_t tca9554_i2c_bus_ = NULL; @@ -86,11 +99,17 @@ void i2c_master_init(void) tca9554_init(); } -uint8_t i2c_writr_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf, uint8_t len) +esp_err_t i2c_writr_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf, uint8_t len) { - uint8_t ret; + esp_err_t ret; uint8_t *pbuf = NULL; - ret = i2c_master_bus_wait_all_done(user_i2c_port1_handle, i2c_done_pdMS_TICKS); + i2c_master_bus_handle_t bus_handle = get_bus_handle_by_device(dev_handle); + if (bus_handle == NULL) + { + ESP_LOGE("i2c.master", "Unknown device handle in write path"); + return ESP_ERR_INVALID_ARG; + } + ret = i2c_master_bus_wait_all_done(bus_handle, i2c_done_pdMS_TICKS); if (ret != ESP_OK) return ret; if (reg == -1) @@ -111,10 +130,16 @@ uint8_t i2c_writr_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf } return ret; } -uint8_t i2c_master_write_read_dev(i2c_master_dev_handle_t dev_handle, uint8_t *writeBuf, uint8_t writeLen, uint8_t *readBuf, uint8_t readLen) +esp_err_t i2c_master_write_read_dev(i2c_master_dev_handle_t dev_handle, uint8_t *writeBuf, uint8_t writeLen, uint8_t *readBuf, uint8_t readLen) { - uint8_t ret; - ret = i2c_master_bus_wait_all_done(user_i2c_port1_handle, i2c_done_pdMS_TICKS); + esp_err_t ret; + i2c_master_bus_handle_t bus_handle = get_bus_handle_by_device(dev_handle); + if (bus_handle == NULL) + { + ESP_LOGE("i2c.master", "Unknown device handle in write-read path"); + return ESP_ERR_INVALID_ARG; + } + ret = i2c_master_bus_wait_all_done(bus_handle, i2c_done_pdMS_TICKS); if (ret != ESP_OK) { ESP_LOGE("i2c.master", "wait_all_done failed: %s", esp_err_to_name(ret)); @@ -123,15 +148,21 @@ uint8_t i2c_master_write_read_dev(i2c_master_dev_handle_t dev_handle, uint8_t *w ret = i2c_master_transmit_receive(dev_handle, writeBuf, writeLen, readBuf, readLen, i2c_data_pdMS_TICKS); if (ret != ESP_OK) { ESP_LOGE("i2c.master", "transmit_receive failed: %s", esp_err_to_name(ret)); - (void)i2c_master_bus_reset(user_i2c_port1_handle); + (void)i2c_master_bus_reset(bus_handle); } return ret; } -uint8_t i2c_read_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf, uint8_t len) +esp_err_t i2c_read_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf, uint8_t len) { - uint8_t ret; + esp_err_t ret; uint8_t addr = 0; - ret = i2c_master_bus_wait_all_done(user_i2c_port1_handle, i2c_done_pdMS_TICKS); + i2c_master_bus_handle_t bus_handle = get_bus_handle_by_device(dev_handle); + if (bus_handle == NULL) + { + ESP_LOGE("i2c.master", "Unknown device handle in read path"); + return ESP_ERR_INVALID_ARG; + } + ret = i2c_master_bus_wait_all_done(bus_handle, i2c_done_pdMS_TICKS); if (ret != ESP_OK) return ret; if (reg == -1) @@ -145,7 +176,7 @@ uint8_t i2c_read_buff(i2c_master_dev_handle_t dev_handle, int reg, uint8_t *buf, } if (ret != ESP_OK) { ESP_LOGE("i2c.master", "read failed: %s", esp_err_to_name(ret)); - (void)i2c_master_bus_reset(user_i2c_port1_handle); + (void)i2c_master_bus_reset(bus_handle); } return ret; } diff --git a/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.h b/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.h index d20c9b2..87ae6cd 100644 --- a/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.h +++ b/Code/PhoneBed_code/components/i2c_bsp/i2c_bsp.h @@ -9,6 +9,7 @@ #ifndef I2C_BSP_H #define I2C_BSP_H #include "driver/i2c_master.h" +#include "esp_err.h" extern i2c_master_dev_handle_t rtc_dev_handle; extern i2c_master_dev_handle_t imu_dev_handle; @@ -22,12 +23,12 @@ extern "C" { void i2c_master_init(void); void touch_i2c_master_Init(void); -uint8_t i2c_writr_buff(i2c_master_dev_handle_t dev_handle,int reg,uint8_t *buf,uint8_t len); -uint8_t i2c_master_write_read_dev(i2c_master_dev_handle_t dev_handle,uint8_t *writeBuf,uint8_t writeLen,uint8_t *readBuf,uint8_t readLen); -uint8_t i2c_read_buff(i2c_master_dev_handle_t dev_handle,int reg,uint8_t *buf,uint8_t len); +esp_err_t i2c_writr_buff(i2c_master_dev_handle_t dev_handle,int reg,uint8_t *buf,uint8_t len); +esp_err_t i2c_master_write_read_dev(i2c_master_dev_handle_t dev_handle,uint8_t *writeBuf,uint8_t writeLen,uint8_t *readBuf,uint8_t readLen); +esp_err_t i2c_read_buff(i2c_master_dev_handle_t dev_handle,int reg,uint8_t *buf,uint8_t len); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/Code/PhoneBed_code/main/main.cpp b/Code/PhoneBed_code/main/main.cpp index 584ace0..b7cdb45 100644 --- a/Code/PhoneBed_code/main/main.cpp +++ b/Code/PhoneBed_code/main/main.cpp @@ -33,6 +33,7 @@ static const char *TAG = "PhoneBed_main"; TaskHandle_t audio_task_handle = NULL; // 音频任务句柄 TaskHandle_t onboard_button_task_handle = NULL; // 板载按钮任务句柄 +static TaskHandle_t charge_action_task_handle = NULL; // 充电事件处理任务句柄 static SemaphoreHandle_t lvgl_mux = NULL; // LVGL 互斥体 static SemaphoreHandle_t flush_done_semaphore = NULL; // 刷新完成信号量 @@ -219,11 +220,29 @@ static void example_lvgl_port_task(void *arg) } } +// 充电GPIO中断的后处理任务,在任务态执行非ISR安全的逻辑 +static void charge_action_task(void *arg) +{ + for (;;) + { + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + quilt_close(); // 先把被子盖上 + fan_set_speed(FAN_SPEED_GRADE3); // 拉高风扇转速,防止温度过高 + } +} + // 手机放上去充上电后,会进这个中断服务程序 static void IRAM_ATTR charge_isr_handler(void *arg) { - quilt_close(); // 先把被子盖上 - fan_set_speed(FAN_SPEED_GRADE3); // 拉高风扇转速,防止温度过高 + BaseType_t high_task_awoken = pdFALSE; + if (charge_action_task_handle != NULL) + { + vTaskNotifyGiveFromISR(charge_action_task_handle, &high_task_awoken); + } + if (high_task_awoken == pdTRUE) + { + portYIELD_FROM_ISR(); + } } extern "C" void app_main(void) @@ -368,6 +387,7 @@ extern "C" void app_main(void) // =============================== 按键相关初始化 =============================== xTaskCreatePinnedToCore(onboard_button_task, "onboard_button_task", 8 * 1024, NULL, 2, &onboard_button_task_handle, 1); // 按钮事件 + xTaskCreate(charge_action_task, "charge_action_task", 2048, NULL, 3, &charge_action_task_handle); // 充电事件后处理 // =============================== 风扇相关初始化 =============================== fan_init(); // 初始化风扇控制 diff --git a/Code/PhoneBed_code/main/page.cpp b/Code/PhoneBed_code/main/page.cpp index 13c3b26..956e00f 100644 --- a/Code/PhoneBed_code/main/page.cpp +++ b/Code/PhoneBed_code/main/page.cpp @@ -49,6 +49,7 @@ static bool alarm_clock_flag = false; // 闹钟是否开启标志 static int alarm_clock_index = 0; // 闹钟当前修改索引 0表示未修改 1表示修改小时 2表示修改分钟 static lv_obj_t *alarm_page = NULL; // 闹钟页面对象 static uint8_t alarm_clock[2] = {0, 0}; // 闹钟时间结构体 +static uint32_t last_alarm_trigger_slot = 0; // 记录最近一次触发的分钟槽位,避免同一秒重复触发 static lv_obj_t *alarm_switch_default; // 闹钟默认开关对象 static lv_obj_t *alarm_switch; // 闹钟开关对象 static lv_obj_t *alarm_roller_hour; // 闹钟设置小时滚轮 @@ -153,6 +154,7 @@ void page_time_refresh(lv_timer_t *timer) datetime = i2c_rtc_get(); // 获取当前时间 char time_str[32]; // 时间字符串缓冲区 sprintf(time_str, "%02d:%02d:%02d", datetime.hour, datetime.minute, datetime.second); // 格式化时间字符串 + uint32_t current_alarm_slot = (((((uint32_t)datetime.year * 12U) + datetime.month) * 32U + datetime.day) * 24U + datetime.hour) * 60U + datetime.minute; if (label_time != NULL) { @@ -160,9 +162,13 @@ void page_time_refresh(lv_timer_t *timer) } if (alarm_clock_flag && (datetime.hour == alarm_clock[0]) && (datetime.minute == alarm_clock[1]) && (datetime.second == 0)) // 如果闹钟开启且时间到了 { - // 触发闹钟事件 - ESP_LOGI("ALARM", "Alarm Triggered at %02d:%02d:%02d", datetime.hour, datetime.minute, datetime.second); - alarm_start(); // 启动闹钟,开始吵,吵,吵 + if (last_alarm_trigger_slot != current_alarm_slot) + { + // 触发闹钟事件 + ESP_LOGI("ALARM", "Alarm Triggered at %02d:%02d:%02d", datetime.hour, datetime.minute, datetime.second); + last_alarm_trigger_slot = current_alarm_slot; + alarm_start(); // 启动闹钟,开始吵,吵,吵 + } } }