广西建设中心培训网站,记事本做网站的流程,绩溪住房建设网站,网站策划运营方案你好#xff01;这里是风筝的博客#xff0c;
欢迎和我一起交流。 很久没写kernel相关的东西了#xff0c;主要是来到手机厂之后#xff0c;大部分还是在Android上#xff0c;Kernel虽然也有涉及#xff0c;但毕竟只是有所涉及#xff0c;主要业务逻辑还是在HAL之上这里是风筝的博客
欢迎和我一起交流。 很久没写kernel相关的东西了主要是来到手机厂之后大部分还是在Android上Kernel虽然也有涉及但毕竟只是有所涉及主要业务逻辑还是在HAL之上kernel的修改除了项目bringup之后基本甚少修改。
最近倒是碰到一个Kernel的问题简单记录下~
【前提条件】【Prerequistes】手机录入指纹 声音与振动——触感与提示音开启指纹动画音 指纹样式选择旋涡样式 【操作步骤】【Operation steps】播放QQ音乐按power键息屏亮屏指纹解锁 【实际结果】【Actual results】指纹动画声音响起有卡顿声 【期望结果】【Expected results】不应该有卡顿声音 【对比的上个版本编号】【Number of previous version for comparison】低概率问题
以我多年工作经验来看外放问题是最好解决的了相对好处理些。
查看AudioDspStreamManager.xx.TaskPlayback_ivdump.pcm文件这是PA的VI反馈信号可以反馈出喇叭的真实状态。从频谱上看确实出现了卡顿在解锁动画提示音响起的时候。
同样查看AudioDspStreamManager.xx.TaskPlayback_datain.pcm发现确实Kernel里的数据就有问题了但是查看streamout.pcm.xx.AudioALSAPlaybackHandlerDsp.flag8.xx.48000.8_24bit.2ch_20230411_092109.wav 是没有问题的说明问题出现在了Kernel底层没有出现在HAL。
因为提示音是短音走的fast通路buf又小确实容易出现问题。
查看kernel log 6[83150.878119][T600541] mtk_dsp_check_exception() deep adsp underflow6[83150.926100][T516896] snd_audio_dsp snd_audio_dsp: mtk_dsp_start() deep just underflow6[83178.409440][T700541] mtk_dsp_check_exception() fast adsp underflow6[83178.419408][T712585] snd_audio_dsp snd_audio_dsp: mtk_dsp_start() fast just underflow确实发现了异常出现了underflow这表明写数据慢了没有数据可以播放所以出现了underflow 同步查看ADSP的log [83137.343]A-22[D]audio_dsp_hw_write_op(), HW_STATE_UNDERFLOW, return[83157.758]A-11[D] enter_write_cond, underflow, written_size[2048] datacount[0] task_name[fast_playback][83157.758]A-11[W] write_data_loop() ADSP_DL_CONSUME_UNDERFLOW[83166.654]A-11[D] enter_write_cond, underflow, written_size[2048] datacount[0] task_name[fast_playback][83166.654]A-11[W] write_data_loop() ADSP_DL_CONSUME_UNDERFLOW确实同样可以看到underflow。
因为underflow是没有数据可播属于写数据不及时所以修改增大buffer size是没有用的。 所以我们只能另想它法
这里简单描述下MTK的播放
灵魂画手嘿嘿按照理解自己画了下图~
Hal往kernel写数据之后会通过ipi核间通信将数据送往DSP做处理DSP上会跑我们用到的算法处理完的数据就通过iis送到codec进行播放kernel里面只负责管理对codec的control。
源码解析 drivers/misc/mediatek/audio_ipi/common/adsp_ipi.c
static int __init audio_ipi_init(void)
{ipi_queue_init();audio_task_manager_init();audio_messenger_ipi_init();init_audio_ipi_dma();
#if IS_ENABLED(CONFIG_MTK_AUDIODSP_SUPPORT)adsp_register_notify(audio_ctrl_notifier);
#endiffor (task_id 0; task_id TASK_SCENE_SIZE; task_id) {task_info g_audio_task_info[task_id];dsp_id audio_get_dsp_id(task_id);task_info-dsp_id dsp_id;task_info-is_dsp_support is_audio_dsp_support(dsp_id);task_info-is_adsp is_audio_use_adsp(dsp_id);task_info-is_scp is_audio_use_scp(dsp_id);task_info-task_ctrl get_audio_controller_task(dsp_id);}ret misc_register(audio_ipi_device);
}drivers/misc/mediatek/audio_ipi/common/adsp_ipi_queue.c
void ipi_queue_init(void)
{for (dsp_id 0; dsp_id NUM_OPENDSP_TYPE; dsp_id) {if (is_audio_dsp_support(dsp_id))ipi_queue_init_by_dsp(dsp_id);}#if IS_ENABLED(CONFIG_MTK_AUDIODSP_SUPPORT)hook_ipi_queue_send_msg_handler(dsp_send_msg_to_queue_wrap);hook_ipi_queue_recv_msg_hanlder(dsp_dispatch_ipi_hanlder_to_queue_wrap);
#endif
}hook_ipi_queue_send_msg_handler和hook_ipi_queue_recv_msg_hanlder主要是给ipi_queue_send_msg_handler和ipi_queue_recv_msg_handler这两个函数指针赋值的在给dsp发送msg和接受msg的时候会用这里没啥好说的主要是ipi_queue_init_by_dsp这里会针对DSP做初始化
int ipi_queue_init_by_dsp(uint32_t dsp_id)
{for (dsp_path 0; dsp_path DSP_NUM_PATH; dsp_path) {msg_queue g_dsp_msg_queue[dsp_id][dsp_path];ret dsp_init_single_msg_queue(msg_queue, dsp_id, dsp_path);if (ret ! 0)WARN_ON(1);}
}这里会循环两次0是AP to DSP1是DSP to AP。
static int dsp_init_single_msg_queue(struct dsp_msg_queue_t *msg_queue,const uint32_t dsp_id,const uint32_t dsp_path)
{if (dsp_path DSP_PATH_A2D) {msg_queue-dsp_process_msg_func dsp_send_msg_to_dsp;} else if (dsp_path DSP_PATH_D2A) {msg_queue-dsp_process_msg_func dsp_process_msg_from_dsp;} elseWARN_ON(1);/* lunch thread */msg_queue-dsp_thread_task kthread_create(dsp_process_msg_thread,msg_queue,%s,thread_name);if (IS_ERR(msg_queue-dsp_thread_task)) {pr_info(can not create %s kthread, thread_name);WARN_ON(1);msg_queue-thread_enable false;} else {msg_queue-thread_enable true;dsb(SY);wake_up_process(msg_queue-dsp_thread_task);}
}重点看下这里面就好了针对不同的情况AP to DSP 还是 DSP to AP会赋值不同的处理函数到dsp_process_msg_func。然后会创建线程dsp_process_msg_thread并启动wake_up_process
static int dsp_process_msg_thread(void *data)
{while (msg_queue-thread_enable !kthread_should_stop()) {/* wait until element pushed */retval dsp_get_queue_element(msg_queue, p_dsp_msg, idx_msg);p_element msg_queue-element[idx_msg];/* send to dsp */retval msg_queue-dsp_process_msg_func(msg_queue, p_dsp_msg);/* notify element if need */spin_lock_irqsave(p_element-element_lock, flags);if (p_element-wait_in_thread true) {p_element-send_retval retval;p_element-signal_arrival true;dsb(SY);wake_up_interruptible(p_element-element_wq);}spin_unlock_irqrestore(p_element-element_lock, flags);/* pop message from queue */spin_lock_irqsave(msg_queue-queue_lock, flags);dsp_pop_msg(msg_queue);spin_unlock_irqrestore(msg_queue-queue_lock, flags);}return 0;
}
线程里面处理还是比较简单的就是等待有数据到queue里如果有就通过之前填充的dsp_process_msg_func钩子函数发给DSP处理即可。
好扯了这么一大堆回归本题如果出现了underflow说明写数据不及时写数据就是通过dsp_process_msg_thread这个线程里面写到DSP的所以我们只需要保证这个线程的正常调度运行即可。
如何保证呢自然是提升线程优先级
为了使得用户能有良好的用户体验dsp_init_single_msg_queue这里在创建线程的时候这里直接将线程加入RT线程RT Real Thread实时线程。 kthread_create线程创建之后通过这个API
struct sched_param param { .sched_priority 3 };
sched_setscheduler_nocheck(msg_queue-dsp_thread_task, SCHED_FIFO, param);即可加入RT线程。
加入RT线程之后压测问题场景没有再出现underflow的情况卡顿问题也没有再复现了问题完美解决~
最开始的audio_ipi_init函数里还有一些内容就不多阐述了DSP这块资料比较少还是比较难去了解的非本文重点。 audio_ipi_init后面就是配置DMA和TASK这些每个scene占用一个Task /* scene for library */TASK_SCENE_PHONE_CALL 0,TASK_SCENE_VOICE_ULTRASOUND 1,TASK_SCENE_PLAYBACK_MP3 2,TASK_SCENE_RECORD 3,TASK_SCENE_VOIP 4,TASK_SCENE_SPEAKER_PROTECTION 5,TASK_SCENE_VOW 6,TASK_SCENE_PRIMARY 7,TASK_SCENE_DEEPBUFFER 8,TASK_SCENE_AUDPLAYBACK 9,TASK_SCENE_CAPTURE_UL1 10,TASK_SCENE_A2DP 11,//......OK后面就不表了以后再说吧~ 文章转载自: http://www.morning.kflbf.cn.gov.cn.kflbf.cn http://www.morning.sfyqs.cn.gov.cn.sfyqs.cn http://www.morning.rwzqn.cn.gov.cn.rwzqn.cn http://www.morning.wmglg.cn.gov.cn.wmglg.cn http://www.morning.chzbq.cn.gov.cn.chzbq.cn http://www.morning.nywrm.cn.gov.cn.nywrm.cn http://www.morning.pbtdr.cn.gov.cn.pbtdr.cn http://www.morning.mnmrx.cn.gov.cn.mnmrx.cn http://www.morning.wlggr.cn.gov.cn.wlggr.cn http://www.morning.nrqtk.cn.gov.cn.nrqtk.cn http://www.morning.qineryuyin.com.gov.cn.qineryuyin.com http://www.morning.tndxg.cn.gov.cn.tndxg.cn http://www.morning.pkwwq.cn.gov.cn.pkwwq.cn http://www.morning.kmwbq.cn.gov.cn.kmwbq.cn http://www.morning.gqjzp.cn.gov.cn.gqjzp.cn http://www.morning.yhpq.cn.gov.cn.yhpq.cn http://www.morning.dywgl.cn.gov.cn.dywgl.cn http://www.morning.lhhdy.cn.gov.cn.lhhdy.cn http://www.morning.yqfdl.cn.gov.cn.yqfdl.cn http://www.morning.pgkpt.cn.gov.cn.pgkpt.cn http://www.morning.lhgqc.cn.gov.cn.lhgqc.cn http://www.morning.vnuwdy.cn.gov.cn.vnuwdy.cn http://www.morning.jfxth.cn.gov.cn.jfxth.cn http://www.morning.qwfl.cn.gov.cn.qwfl.cn http://www.morning.nshhf.cn.gov.cn.nshhf.cn http://www.morning.gpryk.cn.gov.cn.gpryk.cn http://www.morning.mjbkp.cn.gov.cn.mjbkp.cn http://www.morning.mqfkd.cn.gov.cn.mqfkd.cn http://www.morning.grxsc.cn.gov.cn.grxsc.cn http://www.morning.incmt.com.gov.cn.incmt.com http://www.morning.cfybl.cn.gov.cn.cfybl.cn http://www.morning.pnbls.cn.gov.cn.pnbls.cn http://www.morning.nhgfz.cn.gov.cn.nhgfz.cn http://www.morning.zqnmp.cn.gov.cn.zqnmp.cn http://www.morning.wfyqn.cn.gov.cn.wfyqn.cn http://www.morning.ybgt.cn.gov.cn.ybgt.cn http://www.morning.bmncq.cn.gov.cn.bmncq.cn http://www.morning.gzzncl.cn.gov.cn.gzzncl.cn http://www.morning.fthcn.cn.gov.cn.fthcn.cn http://www.morning.wrlqr.cn.gov.cn.wrlqr.cn http://www.morning.zxqyd.cn.gov.cn.zxqyd.cn http://www.morning.dkcpt.cn.gov.cn.dkcpt.cn http://www.morning.zyrp.cn.gov.cn.zyrp.cn http://www.morning.fldrg.cn.gov.cn.fldrg.cn http://www.morning.xsfg.cn.gov.cn.xsfg.cn http://www.morning.phzrq.cn.gov.cn.phzrq.cn http://www.morning.gkjnz.cn.gov.cn.gkjnz.cn http://www.morning.fqsxf.cn.gov.cn.fqsxf.cn http://www.morning.jtybl.cn.gov.cn.jtybl.cn http://www.morning.xzgbj.cn.gov.cn.xzgbj.cn http://www.morning.bysey.com.gov.cn.bysey.com http://www.morning.lxfqc.cn.gov.cn.lxfqc.cn http://www.morning.gmnmh.cn.gov.cn.gmnmh.cn http://www.morning.mzkn.cn.gov.cn.mzkn.cn http://www.morning.kphsp.cn.gov.cn.kphsp.cn http://www.morning.flncd.cn.gov.cn.flncd.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.spfq.cn.gov.cn.spfq.cn http://www.morning.pzjrm.cn.gov.cn.pzjrm.cn http://www.morning.hlyfn.cn.gov.cn.hlyfn.cn http://www.morning.ssmhn.cn.gov.cn.ssmhn.cn http://www.morning.xfxnq.cn.gov.cn.xfxnq.cn http://www.morning.rwtlj.cn.gov.cn.rwtlj.cn http://www.morning.wmqrn.cn.gov.cn.wmqrn.cn http://www.morning.hyryq.cn.gov.cn.hyryq.cn http://www.morning.sjli222.cn.gov.cn.sjli222.cn http://www.morning.mkrqh.cn.gov.cn.mkrqh.cn http://www.morning.bqmsm.cn.gov.cn.bqmsm.cn http://www.morning.cbqqz.cn.gov.cn.cbqqz.cn http://www.morning.yydeq.cn.gov.cn.yydeq.cn http://www.morning.pbygt.cn.gov.cn.pbygt.cn http://www.morning.plxhq.cn.gov.cn.plxhq.cn http://www.morning.bdtpd.cn.gov.cn.bdtpd.cn http://www.morning.tgnwt.cn.gov.cn.tgnwt.cn http://www.morning.pxmyw.cn.gov.cn.pxmyw.cn http://www.morning.jljwk.cn.gov.cn.jljwk.cn http://www.morning.gqbtw.cn.gov.cn.gqbtw.cn http://www.morning.trfrl.cn.gov.cn.trfrl.cn http://www.morning.qbdqc.cn.gov.cn.qbdqc.cn http://www.morning.lpyjq.cn.gov.cn.lpyjq.cn