diff --git a/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/Kconfig b/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/Kconfig index 35b2e561b..3471f1c04 100644 --- a/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/Kconfig +++ b/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/Kconfig @@ -10,6 +10,7 @@ config BOARD_CONFIG bool default y select ENABLE_BUTTON + select ENABLE_LED select PLATFORM_FLASHSIZE_16M config UART_NUM0_TX_PIN diff --git a/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/board_com_api.c b/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/board_com_api.c index 415d5989e..997b13f7f 100644 --- a/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/board_com_api.c +++ b/boards/ESP32/WAVESHARE_ESP32C6_DEV_KIT_N16/board_com_api.c @@ -10,6 +10,7 @@ #include "tal_api.h" #include "tdd_button_gpio.h" +#include "tdd_led_esp_ws1280.h" /*********************************************************** ************************macro define************************ @@ -17,6 +18,7 @@ #define BOARD_BUTTON_PIN TUYA_GPIO_NUM_9 #define BOARD_BUTTON_ACTIVE_LV TUYA_GPIO_LEVEL_LOW +#define BOARD_LED_PIN TUYA_GPIO_NUM_8 /*********************************************************** ***********************typedef define*********************** ***********************************************************/ @@ -45,8 +47,25 @@ static OPERATE_RET __board_register_button(void) }; TUYA_CALL_ERR_RETURN(tdd_gpio_button_register(BUTTON_NAME, &button_hw_cfg)); + + return OPRT_OK; } +static OPERATE_RET __board_register_led(void) +{ + OPERATE_RET rt = OPRT_OK; + + TDD_LED_WS1280_CFG_T led_hw_cfg = { + .gpio = BOARD_LED_PIN, + .led_count = 1, + .color = 0x00001F, // 0xRRGGBB format + }; + + TUYA_CALL_ERR_RETURN(tdd_led_esp_ws1280_register(LED_NAME, &led_hw_cfg)); + + return OPRT_OK; +} + /** * @brief Registers all the hardware peripherals (audio, button, LED) on the board. * diff --git a/boards/ESP32/common/CMakeLists.txt b/boards/ESP32/common/CMakeLists.txt index f4dfd0897..4a004a14a 100755 --- a/boards/ESP32/common/CMakeLists.txt +++ b/boards/ESP32/common/CMakeLists.txt @@ -9,6 +9,9 @@ file(GLOB_RECURSE DISPLAY_SRCS "${COMMON_PATH}/display/*.c") # add lcd source files file(GLOB_RECURSE LCD_SRCS "${COMMON_PATH}/lcd/*.c") +# add led source files +file(GLOB_RECURSE LED_SRCS "${COMMON_PATH}/led/*.c") + # add io_expander source files file(GLOB_RECURSE IO_EXPANDER_SRCS "${COMMON_PATH}/io_expander/*.c") @@ -47,3 +50,13 @@ if (CONFIG_ENABLE_AUDIO) "${COMMON_PATH}/audio" ) endif() + +if (CONFIG_ENABLE_LED) + list(APPEND BOARD_SRC + "${LED_SRCS}" + ) + + list(APPEND BOARD_INC + "${COMMON_PATH}/led" + ) +endif() diff --git a/boards/ESP32/common/led/tdd_led_esp_ws1280.c b/boards/ESP32/common/led/tdd_led_esp_ws1280.c new file mode 100644 index 000000000..170736e21 --- /dev/null +++ b/boards/ESP32/common/led/tdd_led_esp_ws1280.c @@ -0,0 +1,339 @@ +/** + * @file tdd_led_esp_ws1280.c + * @brief ESP32 WS1280 LED driver implementation. + * + * + * @copyright Copyright (c) 2021-2026 Tuya Inc. All Rights Reserved. + * + */ + +#include "tuya_cloud_types.h" +#include "tal_log.h" +#include "tkl_memory.h" +#include "tdd_led_esp_ws1280.h" +#include "tdl_led_driver.h" + +#include "driver/rmt_tx.h" +#include "driver/gpio.h" +#include "esp_log.h" + +/*********************************************************** +************************macro define************************ +***********************************************************/ +#define TAG "WS1280_DRIVER" + +#define WS1280_COLOR_BYTES 3 // Number of bytes used by one LED color data (RGB) +#define WS1280_BITS_PER_LED (WS1280_COLOR_BYTES * 8) +#define WS1280_RESOLUTION 10000000 // 10MHz +#define WS1280_TIMEOUT_MS 100 // Transmission timeout in milliseconds +#define WS1280_T0H 4 +#define WS1280_T0L 9 +#define WS1280_T1H 8 +#define WS1280_T1L 5 +#define WS1280_RESET_US 50 +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ +typedef struct { + TDD_LED_WS1280_CFG_T cfg; + uint16_t symbol_count; + rmt_symbol_word_t *symbols_buf; +}TDD_LED_WS1280_INFO_T; + +/*********************************************************** +***********************variable define********************** +***********************************************************/ +static rmt_channel_handle_t sg_rmt_chan = NULL; +static rmt_encoder_handle_t sg_copy_encoder = NULL; // Generic copy encoder + +/*********************************************************** +***********************function define********************** +***********************************************************/ +/** + * @brief Encode WS1280 timing for a single bit. + * @param sym Output RMT symbol pointer. + * @param bit Input bit value (0 or 1). + * @return + */ +static void __ws1280_encode_bit(rmt_symbol_word_t *sym, uint8_t bit) +{ + if (bit) { + // Logic 1 timing + sym->level0 = 1; + sym->duration0 = WS1280_T1H; + sym->level1 = 0; + sym->duration1 = WS1280_T1L; + } else { + // Logic 0 timing + sym->level0 = 1; + sym->duration0 = WS1280_T0H; + sym->level1 = 0; + sym->duration1 = WS1280_T0L; + } +} + +/** + * @brief Encode RGB data into RMT timing symbols. + * @param symbols_buff Output symbol buffer. + * @param color LED color value. + * @param led_count Number of LEDs. + * @return + */ +static void __ws1280_encode_data(rmt_symbol_word_t *symbols_buff, uint32_t color, uint16_t led_count) +{ + uint16_t sym_idx = 0; + + if(NULL == symbols_buff || led_count == 0) { + return; + } + + for(int i = 0; i < led_count; i++) { + for (int bit = 23; bit >= 0; bit--) { + __ws1280_encode_bit(&symbols_buff[sym_idx], (color >> bit) & 0x01); + sym_idx++; + } + } + + // Add reset timing (low level) + symbols_buff[sym_idx].level0 = 0; + symbols_buff[sym_idx].duration0 = WS1280_RESET_US * 10; + symbols_buff[sym_idx].level1 = 0; + symbols_buff[sym_idx].duration1 = 0; + + return; +} + +/** + * @brief Initialize the WS1280 driver. + * @param gpio_num GPIO used for WS1280 data output. + * @return ESP_OK on success, otherwise an error code. + */ +static esp_err_t __ws1280_init(gpio_num_t gpio_num) +{ + esp_err_t err = ESP_OK; + + // 1. Create RMT TX channel + rmt_tx_channel_config_t tx_cfg = { + .gpio_num = gpio_num, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = WS1280_RESOLUTION, + .mem_block_symbols = 64, // Enough for 8 LEDs (24 bits each) plus reset timing + .trans_queue_depth = 4, + .flags.invert_out = false, // Keep output level non-inverted + .flags.with_dma = false, // DMA is unnecessary for small data payloads + }; + err = rmt_new_tx_channel(&tx_cfg, &sg_rmt_chan); + if (err != ESP_OK) { + PR_ERR("rmt_new_tx_channel failed: %s", esp_err_to_name(err)); + return err; + } + + // 2. Create generic copy encoder (required because rmt_transmit encoder arg cannot be NULL) + rmt_copy_encoder_config_t copy_encoder_cfg = {}; // No special configuration is required + err = rmt_new_copy_encoder(©_encoder_cfg, &sg_copy_encoder); + if (err != ESP_OK) { + PR_ERR("rmt_new_copy_encoder failed: %s", esp_err_to_name(err)); + rmt_del_channel(sg_rmt_chan); + sg_rmt_chan = NULL; + return err; + } + + // 3. Enable RMT channel + err = rmt_enable(sg_rmt_chan); + if (err != ESP_OK) { + PR_ERR("rmt_enable failed: %s", esp_err_to_name(err)); + rmt_del_encoder(sg_copy_encoder); + sg_copy_encoder = NULL; + rmt_del_channel(sg_rmt_chan); + sg_rmt_chan = NULL; + return err; + } + + PR_NOTICE("WS1280 driver initialized (GPIO:%d)", gpio_num); + + return ESP_OK; +} + +/** + * @brief Refresh LED output by transmitting buffered symbols. + * @param symbols Encoded symbol buffer. + * @param sym_count Number of symbols to transmit. + * @return ESP_OK on success, otherwise an error code. + */ +static esp_err_t __ws1280_show(rmt_symbol_word_t *symbols, uint16_t sym_count) +{ + esp_err_t err = ESP_OK; + + if(NULL == symbols || 0 == sym_count) { + return ESP_ERR_INVALID_ARG; + } + + if (sg_rmt_chan == NULL || sg_copy_encoder == NULL) { + return ESP_ERR_INVALID_STATE; + } + + rmt_transmit_config_t tx_cfg = { + .loop_count = 0, // Transmit once + .flags.eot_level = 0, // Keep low level after transmission ends + }; + + // New transmission API: handles timing and encoding flow + err = rmt_transmit(sg_rmt_chan, sg_copy_encoder, symbols, sym_count * sizeof(rmt_symbol_word_t), &tx_cfg); + if (err != ESP_OK) { + PR_ERR("rmt_transmit failed: %s", esp_err_to_name(err)); + return err; + } + + err = rmt_tx_wait_all_done(sg_rmt_chan, WS1280_TIMEOUT_MS); + if (err != ESP_OK) { + PR_ERR("rmt_tx_wait_all_done timeout/error: %s", esp_err_to_name(err)); + return err; + } + + PR_NOTICE("rmt send %d symbols", sym_count); + + return ESP_OK; +} + +/** + * @brief Deinitialize the RMT channel resources. + * @param + * @param + * @return + */ +static void __ws1280_deinit(void) +{ + if (sg_rmt_chan) { + rmt_disable(sg_rmt_chan); + } + + if (sg_copy_encoder) { + rmt_del_encoder(sg_copy_encoder); + sg_copy_encoder = NULL; + } + + if (sg_rmt_chan) { + rmt_del_channel(sg_rmt_chan); + sg_rmt_chan = NULL; + } +} + +/** + * @brief Open the WS1280 LED device. + * @param dev LED device handle. + * @param + * @return Operation result code. + */ +static OPERATE_RET __tdd_led_ws1280_open(TDD_LED_HANDLE_T dev) +{ + if(NULL == dev) { + return OPRT_INVALID_PARM; + } + + TDD_LED_WS1280_INFO_T *led_info = (TDD_LED_WS1280_INFO_T *)dev; + + esp_err_t err = __ws1280_init(led_info->cfg.gpio); + if (err != ESP_OK) { + return OPRT_COM_ERROR; + } + + return OPRT_OK; +} + +/** + * @brief Set WS1280 LED on/off state. + * @param dev LED device handle. + * @param is_on True to turn on, false to turn off. + * @return Operation result code. + */ +static OPERATE_RET __tdd_led_ws1280_set(TDD_LED_HANDLE_T dev, bool is_on) +{ + PR_NOTICE("Setting WS1280 LEDs %s", is_on ? "ON" : "OFF"); + + if(NULL == dev) { + return OPRT_INVALID_PARM; + } + + TDD_LED_WS1280_INFO_T *led_info = (TDD_LED_WS1280_INFO_T *)dev; + + if(is_on) { + __ws1280_encode_data(led_info->symbols_buf, led_info->cfg.color, led_info->cfg.led_count); + } else { + __ws1280_encode_data(led_info->symbols_buf, 0, led_info->cfg.led_count); + } + + esp_err_t err = __ws1280_show(led_info->symbols_buf, led_info->symbol_count); + if (err != ESP_OK) { + PR_ERR("Failed to transmit WS1280 data: %s", esp_err_to_name(err)); + return OPRT_COM_ERROR; + } + + return OPRT_OK; +} + +/** + * @brief Close the WS1280 LED device. + * @param dev LED device handle. + * @param + * @return Operation result code. + */ +static OPERATE_RET __tdd_led_ws1280_close(TDD_LED_HANDLE_T dev) +{ + if(NULL == dev) { + return OPRT_INVALID_PARM; + } + + __ws1280_deinit(); + + return OPRT_OK; +} + +/** + * @brief Register a WS1280 LED device. + * @param dev_name Device name. + * @param cfg WS1280 configuration. + * @return Operation result code. + */ +OPERATE_RET tdd_led_esp_ws1280_register(char *dev_name, TDD_LED_WS1280_CFG_T *cfg) +{ + TDD_LED_WS1280_INFO_T *led_info = NULL; + uint16_t symbol_count = 0; + uint32_t symbols_buf_size = 0; + + if (dev_name == NULL || cfg == NULL) { + return OPRT_INVALID_PARM; + } + + if(cfg->led_count > TDD_LED_WS1280_COUNT_MAX) { + PR_ERR("LED count exceeds maximum (%d)", TDD_LED_WS1280_COUNT_MAX); + return OPRT_INVALID_PARM; + } + + symbol_count = cfg->led_count * WS1280_BITS_PER_LED + 1; // 24-bit symbols per LED + reset timing + symbols_buf_size = symbol_count * sizeof(rmt_symbol_word_t); + + led_info = (TDD_LED_WS1280_INFO_T *)tkl_system_malloc(sizeof(TDD_LED_WS1280_INFO_T)+\ + symbols_buf_size); + if (led_info == NULL) { + return OPRT_MALLOC_FAILED; + } + memset(led_info, 0, sizeof(TDD_LED_WS1280_INFO_T) + symbols_buf_size); + memcpy(&led_info->cfg, cfg, sizeof(TDD_LED_WS1280_CFG_T)); + + led_info->symbols_buf = (rmt_symbol_word_t *)(led_info + 1); + led_info->symbol_count = symbol_count; + + TDD_LED_INTFS_T intfs = { + .led_open = __tdd_led_ws1280_open, + .led_set = __tdd_led_ws1280_set, + .led_close = __tdd_led_ws1280_close, + }; + + OPERATE_RET rt = tdl_led_driver_register(dev_name, (TDD_LED_HANDLE_T)led_info, &intfs); + if (rt != OPRT_OK) { + tkl_system_free(led_info); + return rt; + } + + return OPRT_OK; +} diff --git a/boards/ESP32/common/led/tdd_led_esp_ws1280.h b/boards/ESP32/common/led/tdd_led_esp_ws1280.h new file mode 100644 index 000000000..1b7f5b4a8 --- /dev/null +++ b/boards/ESP32/common/led/tdd_led_esp_ws1280.h @@ -0,0 +1,43 @@ +/** + * @file tdd_led_esp_ws1280.h + * @brief ESP32 WS1280 LED driver interface. + * + * + * @copyright Copyright (c) 2021-2026 Tuya Inc. All Rights Reserved. + * + */ + +#ifndef __TDD_LED_WS1280_H__ +#define __TDD_LED_WS1280_H__ + +#include "tuya_cloud_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************** +************************macro define************************ +***********************************************************/ +#define TDD_LED_WS1280_COUNT_MAX 8 + +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ +typedef struct { + uint16_t led_count; + uint32_t gpio; + uint32_t color; // 24-bit color rgb/grb/.. format, depends on the LED strip +}TDD_LED_WS1280_CFG_T; + +/*********************************************************** +********************function declaration******************** +***********************************************************/ + +OPERATE_RET tdd_led_esp_ws1280_register(char *dev_name, TDD_LED_WS1280_CFG_T *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* __TDD_LED_WS1280_H__ */ diff --git a/examples/peripherals/led/config/WAVESHARE_ESP32C6_DEV_KIT_N16.config b/examples/peripherals/led/config/WAVESHARE_ESP32C6_DEV_KIT_N16.config new file mode 100755 index 000000000..ef7c9a1f9 --- /dev/null +++ b/examples/peripherals/led/config/WAVESHARE_ESP32C6_DEV_KIT_N16.config @@ -0,0 +1,3 @@ +CONFIG_BOARD_CHOICE_ESP32=y +CONFIG_BOARD_CHOICE_WAVESHARE_ESP32C6_DEV_KIT_N16=y +CONFIG_ENABLE_LED=y diff --git a/examples/peripherals/led/src/example_led.c b/examples/peripherals/led/src/example_led.c index e69de29bb..8e92e6ca7 100755 --- a/examples/peripherals/led/src/example_led.c +++ b/examples/peripherals/led/src/example_led.c @@ -0,0 +1,136 @@ +/** + * @file example_led.c + * @version 0.1 + * @copyright Copyright (c) 2021-2026 Tuya Inc. All Rights Reserved. + */ + +#include "tal_api.h" +#include "tkl_output.h" + +#include "tdl_led_manage.h" +#include "board_com_api.h" +/*********************************************************** +************************macro define************************ +***********************************************************/ + + +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ + + +/*********************************************************** +***********************variable define********************** +***********************************************************/ +static TDL_LED_HANDLE_T sg_led_hdl = NULL; + +/*********************************************************** +***********************function define********************** +***********************************************************/ + +/** + * @brief user_main + * + * @param[in] param:Task parameters + * @return none + */ +void user_main(void) +{ + OPERATE_RET rt = OPRT_OK; + + /* basic init */ + tal_log_init(TAL_LOG_LEVEL_DEBUG, 1024, (TAL_LOG_OUTPUT_CB)tkl_log_output); + + PR_NOTICE("Application information:"); + PR_NOTICE("Project name: %s", PROJECT_NAME); + PR_NOTICE("App version: %s", PROJECT_VERSION); + PR_NOTICE("Compile time: %s", __DATE__); + PR_NOTICE("TuyaOpen version: %s", OPEN_VERSION); + PR_NOTICE("TuyaOpen commit-id: %s", OPEN_COMMIT); + PR_NOTICE("Platform chip: %s", PLATFORM_CHIP); + PR_NOTICE("Platform board: %s", PLATFORM_BOARD); + PR_NOTICE("Platform commit-id: %s", PLATFORM_COMMIT); + + tal_sw_timer_init(); + + /*hardware register*/ + board_register_hardware(); + + sg_led_hdl = tdl_led_find_dev(LED_NAME); + TUYA_CALL_ERR_LOG(tdl_led_open(sg_led_hdl)); + + TUYA_CALL_ERR_LOG(tdl_led_set_status(sg_led_hdl, TDL_LED_ON)); + tal_system_sleep(2000); + + TUYA_CALL_ERR_LOG(tdl_led_set_status(sg_led_hdl, TDL_LED_OFF)); + tal_system_sleep(2000); + + TDL_LED_BLINK_CFG_T blink_cfg = { + .cnt = 5, + .start_stat = TDL_LED_ON, + .first_half_cycle_time = 300, + .latter_half_cycle_time = 300, + }; + TUYA_CALL_ERR_LOG(tdl_led_blink(sg_led_hdl, &blink_cfg)); + PR_NOTICE("LED will blink for 5 times with 300ms half cycle time"); + + tal_system_sleep(6000); + + TUYA_CALL_ERR_LOG(tdl_led_flash(sg_led_hdl, 1000)); + PR_NOTICE("LED will flash with 1s half cycle time"); + + while (1) { + tal_system_sleep(2000); + } + + return; +} + +/** + * @brief main + * + * @param argc + * @param argv + * @return void + */ +#if OPERATING_SYSTEM == SYSTEM_LINUX +void main(int argc, char *argv[]) +{ + user_main(); + + while (1) { + tal_system_sleep(500); + } +} +#else + +/* Tuya thread handle */ +static THREAD_HANDLE ty_app_thread = NULL; + +/** + * @brief task thread + * + * @param[in] arg:Parameters when creating a task + * @return none + */ +static void tuya_app_thread(void *arg) +{ + user_main(); + + tal_thread_delete(ty_app_thread); + ty_app_thread = NULL; +} + +void tuya_app_main(void) +{ + THREAD_CFG_T thrd_param = {0}; + thrd_param.stackDepth = 1024 * 4; + thrd_param.priority = THREAD_PRIO_1; + thrd_param.thrdname = "tuya_app_main"; + tal_thread_create_and_start(&ty_app_thread, NULL, NULL, tuya_app_thread, NULL, &thrd_param); +} +#endif + +/*********************************************************** +***********************function define********************** +***********************************************************/ diff --git a/src/peripherals/led/tdd_led/src/tdd_led_gpio.c b/src/peripherals/led/tdd_led/src/tdd_led_gpio.c index e834da768..065ba903b 100644 --- a/src/peripherals/led/tdd_led/src/tdd_led_gpio.c +++ b/src/peripherals/led/tdd_led/src/tdd_led_gpio.c @@ -46,8 +46,6 @@ static OPERATE_RET __tdd_led_gpio_set(TDD_LED_HANDLE_T handle, bool is_on) level = (true == led_cfg->level) ? TUYA_GPIO_LEVEL_LOW : TUYA_GPIO_LEVEL_HIGH; } - PR_NOTICE("led:%d gpio write %d", is_on, level); - return tkl_gpio_write(led_cfg->pin, level); } diff --git a/src/peripherals/led/tdl_led/src/tdl_led_manage.c b/src/peripherals/led/tdl_led/src/tdl_led_manage.c index 63d9cf88f..aa46aded5 100644 --- a/src/peripherals/led/tdl_led/src/tdl_led_manage.c +++ b/src/peripherals/led/tdl_led/src/tdl_led_manage.c @@ -296,7 +296,7 @@ OPERATE_RET tdl_led_flash(TDL_LED_HANDLE_T handle, uint32_t half_cycle_time) __led_stop_blink(led_dev); - led_dev->blink_cfg.cnt = LED_BLINK_START; + led_dev->blink_cfg.cnt = TDL_BLINK_FOREVER; led_dev->blink_cfg.start_stat = TDL_LED_ON; led_dev->blink_cfg.first_half_cycle_time = half_cycle_time; led_dev->blink_cfg.latter_half_cycle_time = half_cycle_time; @@ -304,8 +304,13 @@ OPERATE_RET tdl_led_flash(TDL_LED_HANDLE_T handle, uint32_t half_cycle_time) led_dev->blink_stat = LED_BLINK_START; led_dev->blink_cnt = led_dev->blink_cfg.cnt; - TUYA_CALL_ERR_RETURN(tal_sw_timer_trigger(led_dev->led_tm)); - + rt = tal_sw_timer_start(led_dev->led_tm, 10, TAL_TIMER_ONCE); + if (rt != OPRT_OK) { + PR_ERR("Failed to trigger LED timer: %d", rt); + tal_mutex_unlock(led_dev->mutex); + return rt; + } + tal_mutex_unlock(led_dev->mutex); return OPRT_OK; @@ -343,7 +348,12 @@ OPERATE_RET tdl_led_blink(TDL_LED_HANDLE_T handle, TDL_LED_BLINK_CFG_T *cfg) led_dev->blink_stat = LED_BLINK_START; led_dev->blink_cnt = led_dev->blink_cfg.cnt; - TUYA_CALL_ERR_RETURN(tal_sw_timer_trigger(led_dev->led_tm)); + rt = tal_sw_timer_start(led_dev->led_tm, 10, TAL_TIMER_ONCE); + if (rt != OPRT_OK) { + PR_ERR("Failed to trigger LED timer: %d", rt); + tal_mutex_unlock(led_dev->mutex); + return rt; + } tal_mutex_unlock(led_dev->mutex); @@ -377,7 +387,12 @@ OPERATE_RET tdl_led_close(TDL_LED_HANDLE_T handle) __led_stop_blink(led_dev); if (led_dev->drv_intfs.led_close) { - TUYA_CALL_ERR_RETURN(led_dev->drv_intfs.led_close(led_dev->drv_hdl)); + rt = led_dev->drv_intfs.led_close(led_dev->drv_hdl); + if (rt != OPRT_OK) { + PR_ERR("Failed to close LED driver: %d", rt); + tal_mutex_unlock(led_dev->mutex); + return rt; + } } led_dev->is_open = false; diff --git a/src/tuya_ai_service/svc_ai_basic/src/tuya_ai_private.h b/src/tuya_ai_service/svc_ai_basic/src/tuya_ai_private.h index 37af7bf95..aefb64bb6 100644 --- a/src/tuya_ai_service/svc_ai_basic/src/tuya_ai_private.h +++ b/src/tuya_ai_service/svc_ai_basic/src/tuya_ai_private.h @@ -26,7 +26,8 @@ #include "tal_memory.h" #include "tal_thread.h" -#if defined(AI_HEAP_IN_PSRAM) && (AI_HEAP_IN_PSRAM == 1) +#if defined(AI_HEAP_IN_PSRAM) && (AI_HEAP_IN_PSRAM == 1) &&\ + defined(ENABLE_EXT_RAM) && (ENABLE_EXT_RAM == 1) #define OS_MALLOC(size) tal_psram_malloc(size) #define OS_FREE(ptr) tal_psram_free(ptr) #define OS_CALLOC(num, size) tal_psram_calloc(num, size)