【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

Wi-Fi 设备、蜂窝设备、WuKongAI、开发板、TuyaOS 移植等


Gzz_lin
Posts: 30

1.png
2.png

Tags:
User avatar
一线长天
Posts: 110

Re: 【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

有完整的日志么?上电开始的。目前代码如何使用player的完整逻辑看不到,无法判断是否触发了未知场景。
wukong player是单线程的,因此如果有多线程访问,可能触发未测试到的问题。

Gzz_lin
Posts: 30

Re: 【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

测试比较久才能复现问题,基本都是需要挂机一晚上,第二天唤醒就会出bug,我们是10pcs样品一起测试,出问题可能就一两台,日志没有办法记录那么多。
产品确实是多线程在操作player,但是都有加锁,除非是在一些wokong的代码里面又异步操作了player。

而且现在明显队列满了,处理消息的线程卡死了,这个才是根本原因,处理消息的线程跟我们变更player的状态没有关系,为什么会卡死,我深挖底层代码,在tkl_audio.c里面发现了一段可能的死循环:

Code: Select all

OPERATE_RET tkl_ao_put_frame(INT32_T card, TKL_AO_CHN_E chn, VOID *handle,
                             TKL_AUDIO_FRAME_INFO_T *pframe)
{
    OPERATE_RET ret;
    if (pframe == NULL) {
        return OPRT_INVALID_PARM;
    }
    if (!s_audio_init.audio_init || !s_audio_init.audio_start) {
        return OPRT_RESOURCE_NOT_READY;
    }
    int offset = 0; // 偏移量
    int remaining_size = pframe->used_size; // 剩余数据大小
    int chunk_size = 0;

if (remaining_size < 0) {
    return -1;
}

int spk_ringbuf_size = FRAME_SIZE_PER_20MS(s_audio_mic.samp_rate) * DRIVER_SPEAK_FIFO_FRAME_NUM;
                                        //
// bk_printf("rate: %d, spk_ringbuf_size: %d, output size:%d\r\n",
//         s_audio_mic.samp_rate, spk_ringbuf_size, remaining_size);

// 分段调用 bk_aud_intf_write_spk_data
while (remaining_size > 0) {
    // 计算当前要写入的数据大小
    chunk_size = (remaining_size > spk_ringbuf_size) ? spk_ringbuf_size : remaining_size;

write_spk_retry:
        ret = bk_voice_write_frame_data(g_voice_write_handle, (char *)(pframe->pbuf + offset), chunk_size);
        // ret = bk_voice_write_spk_data(g_voice_handle, (char *)(pframe->pbuf + offset), chunk_size);
        if (ret == 0) {
            tkl_system_sleep(20);
            goto write_spk_retry;
        }

    if (ret < 0) {
        os_printf("audio intf spk semaphore wait fail, ret:%d \r\n", ret);
        return ret;
    }
    // 更新偏移量和剩余大小
    offset += chunk_size;
    remaining_size -= chunk_size;
}

return OPRT_OK;
}

这里有个goto write_spk_retry;是否有风险?

以下是产品当前使用player的完整代码。

Code: Select all

#include "hly_ai.h"
#include "wukong_ai_agent.h"
#include "tal_memory.h"
#include "tal_log.h"
#include "wukong_kws.h"
#include "tal_sw_timer.h"
#include "wukong_audio_player.h"
#include "wukong_audio_input.h"
#include "wukong_audio_aec_vad.h"
#include "skill_emotion.h"
#include <string.h>
#include "ty_cJSON.h"
#include "hly_fs.h"
#include "tal_mutex.h"
#include "base_event.h"
#include "base_event_info.h"
#include "tal_semaphore.h"
#include "tal_queue.h"

#define AI_AGENT_SCODE_DEFAULT ""
#define AI_AUDIO_SLICE_TIME 50

#define AI_TTS_TIME 10



typedef struct
{
    const char* name;
    HLY_AI_EMOJI_E emoji;
}_HLY_AI_EMOJI_T;


STATIC hly_ai_config_t* _hly_ai_config;//ai配置
STATIC hly_ai_stat_e _ai_stat=AI_STAT_INIT;//ai状态
STATIC BOOL_T ai_start=FALSE;
STATIC TIMER_ID _re_idel_timer;
STATIC BOOL_T wake_up_flag=false;
STATIC BOOL_T paly_alart=false;
STATIC BOOL_T free_chat=true;
STATIC MUTEX_HANDLE _ai_mutex;
STATIC MUTEX_HANDLE _timer_mutex;
STATIC MUTEX_HANDLE _alert_mutex;
STATIC THREAD_HANDLE _hly_ai_sem_task;
STATIC SEM_HANDLE _hly_ai_sem;
STATIC THREAD_HANDLE _hly_ai_stat_task;
STATIC QUEUE_HANDLE _hly_ai_stat_queue;
STATIC THREAD_HANDLE _hly_ai_debug_task;
STATIC uint16_t debug_step_a=0;
STATIC uint16_t debug_step_b=0;
STATIC uint16_t debug_step_c=0;
STATIC uint16_t debug_step_d=0;
STATIC uint16_t debug_step_e=0;

STATIC _HLY_AI_EMOJI_T _ai_emoji_list[]={
    {"NEUTRAL",HLY_AI_EMOJI_NEUTRAL},
    {"HAPPY",HLY_AI_EMOJI_HAPPY},
    {"LAUGHING",HLY_AI_EMOJI_LAUGHING},
    {"FUNNY",HLY_AI_EMOJI_FUNNY},
    {"SAD",HLY_AI_EMOJI_SAD},
    {"ANGRY",HLY_AI_EMOJI_ANGRY},
    {"CRYING",HLY_AI_EMOJI_CRYING},
    {"LOVING",HLY_AI_EMOJI_LOVING},
    {"EMBARRASSED",HLY_AI_EMOJI_EMBARRASSED},
    {"SURPRISE",HLY_AI_EMOJI_SURPRISE},
    {"SHOCKED",HLY_AI_EMOJI_SHOCKED},
    {"THINKING",HLY_AI_EMOJI_THINKING},
    {"WINKING",HLY_AI_EMOJI_WINKING},
    {"COOL",HLY_AI_EMOJI_COOL},
    {"RELAXED",HLY_AI_EMOJI_RELAXED},
    {"DELICIOUS",HLY_AI_EMOJI_DELICIOUS},
    {"KISSY",HLY_AI_EMOJI_KISSY},
    {"CONFIDENT",HLY_AI_EMOJI_CONFIDENT},
    {"SLEEPY",HLY_AI_EMOJI_SLEEPY},
    {"SILLY",HLY_AI_EMOJI_SILLY},
    {"CONFUSED",HLY_AI_EMOJI_CONFUSED},

};
/** 停止恢复待机定时器*/
STATIC VOID _hly_ai_re_idel_stop()
{

if(tal_sw_timer_is_running(_re_idel_timer))
{
    tal_sw_timer_stop(_re_idel_timer);
}

}
/** 启动恢复待机定时器*/
STATIC VOID _hly_ai_re_idel_start(uint16_t time_s)
{
    
tal_mutex_lock(_timer_mutex); TAL_PR_DEBUG("======ai re idel time:%d======",time_s); _hly_ai_re_idel_stop(); if(time_s==0) { tal_mutex_unlock(_timer_mutex); return; } tal_sw_timer_start(_re_idel_timer,time_s*1000,TAL_TIMER_ONCE); tal_mutex_unlock(_timer_mutex); } STATIC VOID _hly_ai_stat_task_cb(PVOID_T args) { hly_ai_stat_e stat; while(1) { debug_step_a=1; tal_queue_fetch(_hly_ai_stat_queue, &stat, SEM_WAIT_FOREVER); debug_step_a=2; tal_mutex_lock(_ai_mutex); debug_step_a=3; if (_ai_stat != stat) { TAL_PR_DEBUG("=============ai stat:%d=============", stat); _ai_stat = stat; debug_step_a=4; ty_publish_event(AI_STAT_EVENT, &_ai_stat); } debug_step_a=5; if (_ai_stat == AI_STAT_IDEL) { debug_step_a=6; _hly_ai_re_idel_start(0); wukong_vad_set_threshold(WUKONG_AUDIO_VAD_LOW); wake_up_flag = false; wukong_audio_input_wakeup_set(FALSE); debug_step_a=7; } else { debug_step_a=8; wukong_audio_input_wakeup_set(true); debug_step_a=9; } debug_step_a=10; if (_ai_stat == AI_STAT_LISTEN) { debug_step_a=11; _hly_ai_re_idel_start(_hly_ai_config->wake_time); wukong_vad_set_threshold(WUKONG_AUDIO_VAD_LOW); debug_step_a=12; } else if(_ai_stat==AI_STAT_THINK) { debug_step_a=13; _hly_ai_re_idel_start(_hly_ai_config->wake_time); debug_step_a=14; } else if (_ai_stat == AI_STAT_SPEAK) { debug_step_a=15; _hly_ai_re_idel_start(AI_TTS_TIME); wukong_vad_set_threshold(WUKONG_AUDIO_VAD_HIGH); debug_step_a=16; } debug_step_a=17; tal_mutex_unlock(_ai_mutex); debug_step_a=18; } } STATIC VOID _hly_ai_set_stat(hly_ai_stat_e stat) { hly_ai_stat_e msg; msg = stat; tal_queue_post(_hly_ai_stat_queue, &msg, 10); } /**ai表情 */ // STATIC VOID _hly_ai_skill_emoji(void* data) // { // WUKONG_AI_EMO_T *emo = (WUKONG_AI_EMO_T *)data; // TAL_PR_NOTICE("======ai emoji:%s,%s", emo->name,emo->emoji); // int count = sizeof(_ai_emoji_list)/sizeof(_HLY_AI_EMOJI_T); // for(int i = 0;i<count;i++) // { // if(strcasecmp(emo->name,_ai_emoji_list[i].name)==0) // { // _hly_ai_config->hly_ai_emoji_cb(_ai_emoji_list[i].emoji); // return; // } // _hly_ai_config->hly_ai_emoji_cb(HLY_AI_EMOJI_UNKNOWN); // } // } /**ai技能 */ STATIC int _hly_ai_skill(ty_cJSON* data) { // ty_cJSON *node = NULL; // CHAR_T *code = NULL; // ty_cJSON *skillContent = NULL; // ty_cJSON *emotions = NULL; // ty_cJSON *emo = NULL;
// node = ty_cJSON_GetObjectItem(data, "code"); // code = ty_cJSON_GetStringValue(node); // if(code!=NULL && strcmp(code,"emo")==0) // { // TAL_PR_DEBUG("=====emo======="); // skillContent=ty_cJSON_GetObjectItem(data,"skillContent"); // if(skillContent!=NULL) // { // TAL_PR_DEBUG("skillContent:%s",ty_cJSON_Print(skillContent)); // emotions=ty_cJSON_GetObjectItem(skillContent,"emotion"); // if(emotions!=NULL) // { // TAL_PR_DEBUG("emotions:%s",ty_cJSON_Print(emotions)); // emo=ty_cJSON_GetArrayItem(emotions,0); // if(emo!=NULL) // { // TAL_PR_DEBUG("emo:%s",ty_cJSON_Print(emo)); // code = ty_cJSON_GetStringValue(emo); // if(code!=NULL) // { // TAL_PR_DEBUG("emo str:%s",code); // } // } // } // } // } // char* str=ty_cJSON_PrintUnformatted(data); // if(strstr(str,"101")) // { // wake_up_flag=FALSE; // return 0; // } return 0; } /**ai事件 */ STATIC VOID _hly_ai_event(WUKONG_AI_EVENT_T *event) { // wukong_ai_handle_event(event, 0); TUYA_CHECK_NULL_RETURN(event, OPRT_INVALID_PARM); TAL_PR_DEBUG("======wukong ai event type: %d", event->type); switch (event->type) { case WUKONG_AI_EVENT_ASR_EMPTY: case WUKONG_AI_EVENT_ASR_ERROR: { tal_mutex_lock(_ai_mutex); debug_step_d=9; if (_ai_stat == AI_STAT_THINK) { _hly_ai_set_stat(AI_STAT_LISTEN); } tal_mutex_unlock(_ai_mutex); debug_step_d=10; } break; case WUKONG_AI_EVENT_ASR_OK: { } break; case WUKONG_AI_EVENT_TTS_PRE: { _hly_ai_set_stat(AI_STAT_SPEAK); } break; case WUKONG_AI_EVENT_TTS_START: case WUKONG_AI_EVENT_TTS_DATA: { _hly_ai_re_idel_start(AI_TTS_TIME); } break; case WUKONG_AI_EVENT_TTS_STOP: case WUKONG_AI_EVENT_TTS_ABORT: case WUKONG_AI_EVENT_TTS_ERROR: { _hly_ai_re_idel_start(AI_TTS_TIME); } break; case WUKONG_AI_EVENT_VAD_TIMEOUT: { } break; case WUKONG_AI_EVENT_TEXT_STREAM_START: case WUKONG_AI_EVENT_TEXT_STREAM_DATA: case WUKONG_AI_EVENT_TEXT_STREAM_STOP: case WUKONG_AI_EVENT_TEXT_STREAM_ABORT: { // __ai_wakeup_text_stream(event->type, event->data); } break; case WUKONG_AI_EVENT_EMOTION: case WUKONG_AI_EVENT_LLM_EMOTION: { // _hly_ai_skill_emoji(event->data); // __ai_wakeup_emition(event->type, event->data); } break; case WUKONG_AI_EVENT_SKILL: { _hly_ai_skill(event->data); } break; case WUKONG_AI_EVENT_CHAT_BREAK: case WUKONG_AI_EVENT_SERVER_VAD: { } break; case WUKONG_AI_EVENT_EXIT: _hly_ai_set_stat(AI_STAT_IDEL); break; case WUKONG_AI_EVENT_PLAY_CTL_PLAY: case WUKONG_AI_EVENT_PLAY_CTL_RESUME: { wukong_audio_player_set_resume(TRUE); } break; case WUKONG_AI_EVENT_PLAY_CTL_PAUSE: { wukong_audio_player_stop(AI_PLAYER_BG); } break; case WUKONG_AI_EVENT_PLAY_CTL_REPLAY: { wukong_audio_player_set_replay(TRUE); } break; case WUKONG_AI_EVENT_PLAY_CTL_END: case WUKONG_AI_EVENT_PLAY_END: { tal_mutex_lock(_ai_mutex); debug_step_d=11; if(paly_alart) { paly_alart=FALSE; } if(wake_up_flag) { _hly_ai_set_stat(AI_STAT_LISTEN); } else { _hly_ai_set_stat(AI_STAT_IDEL); } tal_mutex_unlock(_ai_mutex); debug_step_d=12; } break; case WUKONG_AI_EVENT_PLAY_ALERT: { //wukong_audio_player_alert((TY_AI_TOY_ALERT_TYPE_E)event->data, TRUE); } break; case WUKONG_AI_EVENT_PLAY_CTL_PREV: case WUKONG_AI_EVENT_PLAY_CTL_NEXT: case WUKONG_AI_EVENT_PLAY_CTL_SEQUENTIAL: case WUKONG_AI_EVENT_PLAY_CTL_SEQUENTIAL_LOOP: case WUKONG_AI_EVENT_PLAY_CTL_SINGLE_LOOP: { } break; default: break; } return OPRT_OK; } /** 麦克风输入*/ STATIC INT_T _hly_ai_mic_data(UINT8_T *data, UINT16_T datalen) { OPERATE_RET rt = OPRT_OK; UINT64_T pts = 0; UINT64_T timestamp = 0; TAL_PR_NOTICE("hly ai -> recv wukong mic data: %d", datalen); tal_mutex_lock(_ai_mutex); if (!tuya_ai_agent_is_ready()) { TAL_PR_DEBUG("ai agent is not ready, ignore audio input"); tal_mutex_unlock(_ai_mutex); return OPRT_OK; } if((_ai_stat == AI_STAT_SPEAK) && (!free_chat)) { TAL_PR_DEBUG("========off free speak!!========"); tal_mutex_unlock(_ai_mutex); return OPRT_OK; } tal_mutex_unlock(_ai_mutex); timestamp = pts = tal_system_get_millisecond(); TUYA_CALL_ERR_LOG(tuya_ai_audio_input(timestamp, pts, (UINT8_T *)data, datalen, datalen)); return rt; } STATIC OPERATE_RET _hly_ai_agent_init() { OPERATE_RET rt = OPRT_OK; /* Register downlink event callback and init player. */ TUYA_CALL_ERR_LOG(wukong_ai_agent_init(_hly_ai_event)); TUYA_CALL_ERR_LOG(wukong_audio_player_init()); /* Audio input: board (16k, mono, 80 ms slice, VAD by trigger mode) or UART. */ WUKONG_AUDIO_INPUT_CFG_T audio_cfg = {0}; // #if defined(USING_BOARD_AUDIO_INPUT) && (USING_BOARD_AUDIO_INPUT == 1) audio_cfg.type = WUKONG_AUDIO_USING_BOARD; audio_cfg.board.sample_rate = TKL_AUDIO_SAMPLE_16K; audio_cfg.board.sample_bits = TKL_AUDIO_DATABITS_16; audio_cfg.board.channel = TKL_AUDIO_CHANNEL_MONO; audio_cfg.board.slice_ms = AI_AUDIO_SLICE_TIME; /* HOLD trigger -> manual VAD; otherwise auto VAD (e.g. one-shot, free talk). */ audio_cfg.board.vad_mode = WUKONG_AUDIO_VAD_MANIAL;//WUKONG_AUDIO_VAD_AUTO;//是否由按键触发vad audio_cfg.board.vad_off_ms = 1000; audio_cfg.board.vad_active_ms = 200; audio_cfg.board.spk_io = _hly_ai_config->spk_en_pin; audio_cfg.board.spk_io_level = TUYA_GPIO_LEVEL_LOW; audio_cfg.board.output_cb = _hly_ai_mic_data; // #elif defined(USING_UART_AUDIO_INPUT) && (USING_UART_AUDIO_INPUT == 1) // audio_cfg.type = WUKONG_AUDIO_USING_UART; // audio_cfg.uart.mic_upload = __on_ai_toy_mic_data; // #endif TUYA_CALL_ERR_LOG(wukong_audio_input_init(&audio_cfg)); hly_ai_set_vol(_hly_ai_config->volume); TUYA_CALL_ERR_LOG(wukong_kws_default_init()); wukong_audio_input_wakeup_mode_set(WUKONG_AUDIO_VAD_AUTO); // wukong_kws_enable(); return rt; } //ai客户端运行事件 STATIC OPERATE_RET _hly_ai_client_run_cb(VOID_T *data) { TAL_PR_NOTICE("hly ai -> connected to server"); // wukong_ai_handle_client(NULL, 0); return OPRT_OK; } /** ai唤醒词事件. */ STATIC OPERATE_RET _hly_ai_audio_kws_cb(VOID_T *data) { OPERATE_RET rt = OPRT_OK; tal_mutex_lock(_ai_mutex); if(_ai_stat != AI_STAT_IDEL) { tal_mutex_unlock(_ai_mutex); return rt; } tal_mutex_unlock(_ai_mutex); if (data) { INT_T idx = (INT_T)data; TAL_PR_DEBUG("==========hly wakeup : %d===========", idx); if (idx) { hly_ai_wakeup(); } }
return rt; // return wukong_ai_handle_wakeup(NULL, 0); } /** VAD 人声检测*/ STATIC OPERATE_RET _hly_ai_vad_change(VOID *data) { TUYA_CHECK_NULL_RETURN(data, OPRT_INVALID_PARM); // wukong_ai_handle_vad(data, 0); tal_mutex_lock(_ai_mutex); if (_ai_stat == AI_STAT_IDEL || _ai_stat==AI_STAT_INIT || !ai_start || !wake_up_flag) { tal_mutex_unlock(_ai_mutex); return OPRT_OK; } _hly_ai_re_idel_start(_hly_ai_config->wake_time); WUKONG_AUDIO_VAD_FLAG_E vad_flag = (WUKONG_AUDIO_VAD_FLAG_E)data; TAL_PR_DEBUG("[====ai_wakeup] vad: [%d]", vad_flag); if (WUKONG_AUDIO_VAD_START == vad_flag) { if (!tuya_ai_agent_is_ready()) { TAL_PR_DEBUG("ai agent is not ready, ignore audio input"); tal_mutex_unlock(_ai_mutex); return OPRT_RESOURCE_NOT_READY; } tuya_ai_agent_set_scode(AI_AGENT_SCODE_DEFAULT); tuya_ai_input_start(FALSE); } else { tuya_ai_input_stop(); if(_ai_stat!=AI_STAT_SPEAK) { _hly_ai_set_stat(AI_STAT_THINK); } } tal_mutex_unlock(_ai_mutex); return OPRT_OK; } //恢复待机定时器 STATIC VOID_T _hly_ai_re_idel_timer_cb (TIMER_ID timer_id, VOID_T *arg) { TAL_PR_DEBUG("===hly ai time out==="); hly_ai_shutup(); } STATIC VOID _hly_ai_sem_task_cb(PVOID_T args) { while (true) { debug_step_c=1; tal_semaphore_wait(_hly_ai_sem, SEM_WAIT_FOREVER); debug_step_c=2; tal_mutex_lock(_ai_mutex); debug_step_c=3; wukong_audio_player_stop(AI_PLAYER_FG); debug_step_c=5; tuya_ai_agent_event(AI_EVENT_CHAT_BREAK, 0); debug_step_c=6; paly_alart=TRUE; _hly_ai_set_stat(AI_STAT_IDEL); debug_step_c=7; tal_mutex_unlock(_ai_mutex); hly_ai_play_alert(HLY_AI_ALERT_EXIT); debug_step_c=8; }
} STATIC VOID _hly_ai_debug_task_cb(PVOID_T args) { while(1) { TAL_PR_DEBUG("====*******ai debug A:%d B:%d C:%d D:%d E:%d********====",debug_step_a,debug_step_b,debug_step_c,debug_step_d,debug_step_e); tal_system_sleep(1000); } } OPERATE_RET hly_ai_init(hly_ai_config_t* config) { OPERATE_RET rt = OPRT_OK; tal_sw_timer_create(_hly_ai_re_idel_timer_cb,NULL,&_re_idel_timer); TAL_PR_DEBUG("=======_hli_ai_re_idel_timer_cb timer id:%08X========",_re_idel_timer); tal_mutex_create_init(&_ai_mutex); tal_mutex_create_init(&_timer_mutex); tal_mutex_create_init(&_alert_mutex);
_hly_ai_config = tal_psram_malloc(sizeof(hly_ai_config_t)); if(_hly_ai_config==NULL) { TAL_PR_ERR("hly ai init malloc fail."); return OPRT_MALLOC_FAILED; } memset(_hly_ai_config,0,sizeof(hly_ai_config_t)); memcpy(_hly_ai_config,config,sizeof(hly_ai_config_t)); ty_subscribe_event(EVENT_AI_CLIENT_RUN, "hly_ai", _hly_ai_client_run_cb, SUBSCRIBE_TYPE_NORMAL); ty_subscribe_event(EVENT_WUKONG_KWS_WAKEUP, "hly_ai", _hly_ai_audio_kws_cb, SUBSCRIBE_TYPE_NORMAL); ty_subscribe_event(EVENT_AUDIO_VAD, "hly_ai", _hly_ai_vad_change, SUBSCRIBE_TYPE_NORMAL); ty_subscribe_event(AI_STAT_EVENT, "hly_ai", _hly_ai_config->hly_ai_stat_cb, SUBSCRIBE_TYPE_NORMAL); TUYA_CALL_ERR_GOTO( _hly_ai_agent_init(), __error); tal_queue_create_init(&_hly_ai_stat_queue,sizeof(hly_ai_stat_e),10); THREAD_CFG_T stat_task_cfg={ .priority=0, .stackDepth=4096, .thrdname="hly_ai_stat_task", .psram_mode=1 }; tal_thread_create_and_start(&_hly_ai_stat_task,NULL,NULL,_hly_ai_stat_task_cb,NULL,&stat_task_cfg); tal_semaphore_create_init(&_hly_ai_sem,0,1); THREAD_CFG_T cfg={ .priority=0, .stackDepth=2048, .thrdname="hly_ai_sem_task", .psram_mode=1 }; tal_thread_create_and_start(&_hly_ai_sem_task,NULL,NULL,_hly_ai_sem_task_cb,NULL,&cfg); THREAD_CFG_T debug_cfg={ .priority=0, .stackDepth=2048, .thrdname="hly_ai_debug_task", .psram_mode=1 }; tal_thread_create_and_start(&_hly_ai_debug_task,NULL,NULL,_hly_ai_debug_task_cb,NULL,&debug_cfg); return rt; __error: return rt; } // OPERATE_RET hly_ai_deinit();//取消初始化 OPERATE_RET hly_ai_start(void) { TAL_PR_DEBUG("================ai start============"); tal_mutex_lock(_ai_mutex); debug_step_d=7; ai_start=TRUE; _hly_ai_set_stat(AI_STAT_IDEL); tal_mutex_unlock(_ai_mutex); debug_step_d=8; } //停止运行ai OPERATE_RET hly_ai_stop(void) { tal_mutex_lock(_ai_mutex); debug_step_d=5; ai_start=FALSE; hly_ai_shutup(); tal_mutex_unlock(_ai_mutex); debug_step_d=6; } // OPERATE_RET hly_ai_nw_stat_change(GW_WIFI_NW_STAT_E stat);//设置网络状态变化 //唤醒进入聆听模式 OPERATE_RET hly_ai_wakeup(void) { debug_step_b=1; tal_mutex_lock(_ai_mutex); if(!ai_start) { tal_mutex_unlock(_ai_mutex); debug_step_b=2; return 0; } debug_step_b = 3; wukong_audio_player_stop(AI_PLAYER_ALL); debug_step_b = 4; wukong_audio_input_reset(); debug_step_b = 5; tuya_ai_agent_event(AI_EVENT_CHAT_BREAK, 0); debug_step_b = 6; wake_up_flag = TRUE; paly_alart = TRUE; // wukong_audio_player_alert(AI_TOY_ALERT_TYPE_WAKEUP, FALSE); _hly_ai_set_stat(AI_STAT_LISTEN); debug_step_b=7; tal_mutex_unlock(_ai_mutex); tal_mutex_lock(_alert_mutex); wukong_audio_player_alert(AI_TOY_ALERT_TYPE_WAKEUP, FALSE); tal_mutex_unlock(_alert_mutex); debug_step_b=8; return 0; } //立刻停止说话 OPERATE_RET hly_ai_shutup(void) { TAL_PR_DEBUG("==============hly_ai_shutup publish=============="); tal_semaphore_post(_hly_ai_sem); } //结束对话 OPERATE_RET hly_ai_chat_over(void) {
tal_mutex_lock(_ai_mutex); debug_step_d=3; wake_up_flag = FALSE; paly_alart=TRUE; tal_mutex_unlock(_ai_mutex); debug_step_d=4; hly_ai_play_alert(HLY_AI_ALERT_EXIT); return 0; } //自由对话 OPERATE_RET hly_ai_free_chat(BOOL_T value) { tal_mutex_lock(_ai_mutex); debug_step_d=1; free_chat=value; tal_mutex_unlock(_ai_mutex); debug_step_d=2; return 0; } OPERATE_RET hly_ai_set_vol(uint8_t vol) { float f; f=vol/100.0f; f=f*70; return wukong_audio_player_set_vol((int)f); // return wukong_audio_player_set_vol(vol); } OPERATE_RET hly_ai_set_asr(BOOL_T enable) { if(enable) { wukong_kws_enable(); } else { wukong_kws_disable(); } return 0; } OPERATE_RET hly_ai_play_alert(HLY_AI_ALERT_E alert) { static HLY_AI_ALERT_E curr_alert=HLY_AI_ALERT_MAX; static uint8_t* data=NULL; static uint32_t len; uint8_t str[32]={0}; tal_mutex_lock(_alert_mutex); debug_step_e=1; // wukong_audio_player_stop(AI_PLAYER_ALL); debug_step_e=2; TAL_PR_DEBUG("=====hly ai play alert:%d", alert); if (curr_alert != alert) { curr_alert = alert; if (data != NULL) { hly_free_psram(data); } switch (curr_alert) { case HLY_AI_ALERT_ALARM: sprintf(&str, "/mp3/%s.mp3", "alarm"); break; case HLY_AI_ALERT_CLOCK: sprintf(&str, "/mp3/%s.mp3", "clock"); break; case HLY_AI_ALERT_ERROR: sprintf(&str, "/mp3/%s.mp3", "error"); break; case HLY_AI_ALERT_EXIT: sprintf(&str, "/mp3/%s.mp3", "exit"); break; case HLY_AI_ALERT_START: sprintf(&str, "/mp3/%s.mp3", "start"); break; case HLY_AI_ALERT_STOP: sprintf(&str, "/mp3/%s.mp3", "stop"); break; case HLY_AI_ALERT_WAKEUP: sprintf(&str, "/mp3/%s.mp3", "wakeup"); break; default: tal_mutex_unlock(_alert_mutex); debug_step_e=8; return -1; break; } TAL_PR_DEBUG("=====hly ai load alert:%s", &str); if (hly_fs_load_psram(&str, &data, &len) != 0) { tal_mutex_unlock(_alert_mutex); debug_step_e=7; return -3; } } if (data == NULL) { debug_step_e=6; tal_mutex_unlock(_alert_mutex); return -1; } debug_step_e=3; int rt = wukong_audio_play_data(AI_AUDIO_CODEC_MP3, data, len); debug_step_e=4; tal_mutex_unlock(_alert_mutex); debug_step_e=5; return rt; } OPERATE_RET hly_ai_set_weke_time(uint8_t wake_time) { _hly_ai_config->wake_time=wake_time; return 0; }
Gzz_lin
Posts: 30

Re: 【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

包括之前的stop死循环事件,都说明了处理队列消息的线程就是会卡死,不然不会死循环的。

User avatar
一线长天
Posts: 110

Re: 【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

可以按照这个先处理再挂机看看。

  1. 给 tkl_ao_put_frame 的重试加上累计超时——例如 ret==0 连续重试超过 X ms(比如 200500ms)就 return OPRT_TIMEOUT 并丢帧,绝不 goto 死循环。(同时增加超时的日志)
  2. 兜底(应用/播放器层):
    • 把播放消息队列深度从 2 调大(比如10),减少瞬时 -26369;
    • tuya_ai_player_stop/start 的 tal_queue_post 给个小超时而非 0;
    • 配合方案1(播放线程内不忙等),避免重入。
User avatar
一线长天
Posts: 110

Re: 【求助】T5 tuya_os_sdk3.13.3播放提示音或停止时卡死

附件是完整的分析报告,可以参考(包括代码重构)

Attachments
tuyaos-audio-deadlock-bundle.zip
(46.85 KiB) Downloaded 2 times
Post Reply