上一帖子中rt-thread適配移植主要介紹了ok1052的板卡支持,但只測試了部分驅(qū)動(串口、網(wǎng)卡),之后測試音頻的時候發(fā)現(xiàn)音頻部分只實現(xiàn)了播放,錄音沒有實現(xiàn)。分析了下音頻驅(qū)動部分,發(fā)現(xiàn)框架是完整的。本篇先從框架入手,分析一下音頻驅(qū)動的工作流程。注:本章內(nèi)容不只局限ok1052板卡,而是針對rt-thread系統(tǒng)的分析
一、首先整體框架還是比較簡單的,具體見下圖:
1、從上圖可以看到audio.c是音頻設(shè)備的核心部分,起到承上啟下的作用,向上為應(yīng)用提供通用接口(open、read、write、control等),向下為底層驅(qū)動提供了函數(shù)(rt_audio_tx_complete、rt_audio_rx_done)及需要實現(xiàn)的接口(ops)
2、再來看drv_codec.c和fsl_wm8960.c,這是主控imx rt1050和音頻芯片wm8960的芯片具體的驅(qū)動部分,不同板卡音頻驅(qū)動主要是實現(xiàn)這一部分。
a、其中drv_codec.c中實現(xiàn)了ops的相關(guān)函數(shù)接口,并通過rt_audio_register函數(shù)注冊到audio.c,相關(guān)代碼如下:
const struct rt_audio_ops _g_audio_ops =
{
.getcaps = icodec_getcaps,
.configure = icodec_configure,
.init = icodec_init,
.shutdown = icodec_shutdown,
.start = icodec_start,
.stop = icodec_stop,
.suspend = icodec_suspend,
.resume = icodec_resume,
.control = icodec_control,
.transmit = icodec_transmit,
};
int rt_hw_codec_init(void)
{
...
...
audio->ops = (struct rt_audio_ops*)&_g_audio_ops;
...
result = rt_audio_register(audio,"sound0", RT_DEVICE_FLAG_RDWR, &_g_imxcodec);
...
...
}
b、上面的icodec_xxx(xxx代指init、shutdown等)函數(shù)通過調(diào)用fsl_sai.c、fsl_sai_edma.c、wm8960.c中的函數(shù)實現(xiàn)相關(guān)操作。如:icodec_init(主要實現(xiàn)了rt1052音頻外設(shè)及wm8960的初始化)
static rt_err_t icodec_init(struct rt_audio_device *audio)
{
...
SAI_TxInit(DEMO_SAI, &config);
...
DMAMUX_Init(DMAMUX0);
...
WM8960_Init(&icodec->codecHandle, NULL);
...
}