日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

s3c2450下AC97驱动研究

發(fā)布時(shí)間:2024/3/24 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 s3c2450下AC97驱动研究 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/alien75/article/details/4656922

?

AC97驅(qū)動(dòng)分析

總體而言,AC97驅(qū)動(dòng)是wavedev結(jié)構(gòu)的驅(qū)動(dòng),上層應(yīng)用通過(guò)調(diào)用WAVEAPI函數(shù),和驅(qū)動(dòng)接口HandleWaveMessage進(jìn)行交互,驅(qū)動(dòng)根據(jù)傳遞的WIDM_XXX系列值進(jìn)行操作。現(xiàn)在以Wince5自帶的waverec例程進(jìn)行分析

一、流程
1、初始化過(guò)程
這個(gè)是設(shè)備啟動(dòng)時(shí),由設(shè)備管理器加載驅(qū)動(dòng)。調(diào)用了WAV_Init、WAV_OPEN、WAV_CLOSE三個(gè)函數(shù);傳遞WIDM_GETNUMDEVS、WODM_GETNUMDEVS、WODM_GETEXTDEVCAPS、WODM_OPEN、WODM_SETVOLUME共五個(gè)控制碼,如果系統(tǒng)設(shè)置為有開(kāi)機(jī)聲音還會(huì)傳遞WODM_WRITE、WODM_UNPREPARE、WODM_CLOSE。
在WAV_INIT中會(huì)調(diào)用CreateHWContext創(chuàng)建全局硬件上下文,完成初始化GPIO、分配DMA內(nèi)存、初始化AC97控制器和外部codec、創(chuàng)建輸入/輸出IST

2、錄音過(guò)程
(1)WIDM_OPEN
(a)獲取設(shè)備上下文:DeviceContext *pDeviceContext = g_pHWContext->GetInputDeviceContext(uDeviceId);?===> InputDeviceContext對(duì)象

(b)打開(kāi)輸入流:pDeviceContext->OpenStream;?
第一步:創(chuàng)建輸入流
pStreamContext = CreateStream(lpWOD);?===> InputStreamContext對(duì)象
父類(lèi)DeviceContext的CreateStream為純虛函數(shù),它派生的的兩個(gè)子類(lèi)InputDeviceContext和OutputDeviceContext重載了此函數(shù)
InputDeviceContext的CreateStream只是創(chuàng)建了一個(gè)對(duì)象InputStreamContext
OutputDeviceContext的處理要復(fù)雜一點(diǎn),它有CMidiStream、OutputStreamContextM8、OutputStreamContextM16、OutputStreamContextS8、OutputStreamContextS16五個(gè)子類(lèi),針對(duì)輸入格式、聲道、采樣位數(shù)創(chuàng)建不同的子類(lèi)
第二步:打開(kāi)輸入流
Result = pStreamContext->Open(this,lpWOD,dwFlags);
根據(jù)派生關(guān)系先隱式調(diào)用WaveStreamContext的Open,再顯式調(diào)用StreamContext的Open。到這一步,錄音的初始化基本完成。

(2)WIDM_PREPARE
無(wú)操作

(3)WIDM_ADDBUFFER
pStreamContext->QueueBuffer((LPWAVEHDR)dwParam1);
dwParam1對(duì)應(yīng)的就是應(yīng)用程序傳遞的參數(shù)(因不在同一地址空間,所以其地址是不一樣的),將它加入到一個(gè)單鏈表中(具體說(shuō)明見(jiàn)相關(guān)數(shù)據(jù)結(jié)構(gòu)的第4點(diǎn))

(4)WIDM_START
啟動(dòng)DMA輸入:pStreamContext->Run();
m_pDeviceContext->StreamReadyToRender(this);?===> InputDeviceContext對(duì)象
g_pHWContext->StartInputDMA();???===> 初次調(diào)用,在IST中每次TransferInputBuffers中會(huì)調(diào)用此函數(shù)(如果BytesTransferred為0則StopImputDMA)
第一步:DMA通道狀態(tài)設(shè)置(開(kāi)/關(guān))
Codec_channel()
第二步:
m_InputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;?
第三步:配置DMA輸入通道
InitInputDMA()
第四步:打開(kāi)輸入音量
AudioMute(DMA_CH_MIC, FALSE);
第五步:開(kāi)始DMA輸入
AUDIO_RESET_RECORD_POINTER();
SELECT_AUDIO_DMA_INPUT_BUFFER_A();?===> 選擇BUFFER_A做為DMA輸入緩沖
Codec_channel();
AUDIO_IN_DMA_ENABLE();???===> 設(shè)置DMA控制器使能DMA傳輸
SELECT_AUDIO_DMA_INPUT_BUFFER_B();?===> 選擇BUFFER_B做為DMA輸入緩沖??? ===> A為下次傳輸做準(zhǔn)備,不讓DMA空置停機(jī)
到這一步,DMA傳輸就緒,接下來(lái)就由IST等待中斷事件并進(jìn)行數(shù)據(jù)處理。

(5)WIDM_UNPREPARE
無(wú)操作

(6)WIDM_CLOSE
釋放輸入流:pStreamContext->Release();
m_pDeviceContext->DeleteStream(this);?//引用計(jì)數(shù)為0才真正釋放

3、HardwareContext的IST流程
(1)等待DMA中斷事件產(chǎn)生
(2)根據(jù)m_InputDMAStatus判斷是BUFFER_A還是BUFFER_B完成DMA傳輸,并切換到另一個(gè)緩沖做DMA傳輸
(3)AUDIO_IN_DMA_ENABLE();?===> 發(fā)出新的DMA請(qǐng)求
(4)InputTransferred = TransferInputBuffers(m_InputDMAStatus); ===>這是個(gè)很重要的函數(shù),將DMA收到的數(shù)據(jù)進(jìn)行Render(插值運(yùn)算轉(zhuǎn)換采樣率,AC97源采樣率44100)
a)HardwareContext::TransferInputBuffer
b)DeviceContext::TransferBuffer
c)StreamContext::Render??===> 純虛函數(shù),實(shí)際調(diào)用WaveStreamContext::Render
d)StreamContext::GetNextBuffer?===> 子類(lèi)都要調(diào)用此函數(shù),目的是提高代碼復(fù)用性
從StreamContext的單鏈表(具體說(shuō)明見(jiàn)相關(guān)數(shù)據(jù)結(jié)構(gòu)的第4點(diǎn))取出一個(gè)LPWAVEHEAD(由QueueBuffer加入鏈表)獲得成員lpData賦值給m_lpCurrData(具體說(shuō)明見(jiàn)相關(guān)數(shù)據(jù)結(jié)構(gòu)),并返回。
e)WaveStreamContext::Render2?===> 純虛函數(shù),實(shí)際調(diào)用派生子類(lèi)(詳見(jiàn)相關(guān)數(shù)據(jù)結(jié)構(gòu)中的說(shuō)明)的函數(shù)。具體算法參見(jiàn)各子類(lèi)的Render2(待深入研究)
將DMA中的數(shù)據(jù)render后放到m_lpCurrData中(LPWAVEHEADER),應(yīng)用程序通過(guò)MM_WIN_DATA應(yīng)該能從WAVEHEADER中獲得此數(shù)據(jù)
(5)重復(fù)第(1)步

二、相關(guān)數(shù)據(jù)結(jié)構(gòu)
1、全局硬件上下文
HardwareContext *g_pHWContext

2、設(shè)備上下文
派生關(guān)系:
InputDeviceContext <-- DeviceContext
OutputDeviceContext <-- DeviceContext

3、數(shù)據(jù)流上下文
派生關(guān)系:
InputStreamContext <-- WaveStreamContext <-- StreamContext
CMidiStream <-- StreamContext
OutputStreamContextM8(M16/S8/S16) <-- OutputStreamContext <-- WaveStreamContext <-- StreamContext

4、StreamContext的WAVEHDR單鏈表
LPWAVEHDR??? m_lpWaveHdrHead;
LPWAVEHDR??? m_lpWaveHdrCurrent;
LPWAVEHDR??? m_lpWaveHdrTail;

5、StreamContext的數(shù)據(jù)緩沖區(qū)指針
PBYTE??? m_lpCurrData;??????????? // position in current buffer
PBYTE??? m_lpCurrDataEnd;???????? // end of current buffer
在調(diào)用QueueBuffer(WIDM_ADDBUFFER)的時(shí)候進(jìn)行賦值,m_lpCurrData賦值是LPWAVEHDR中的lpData,也就是應(yīng)用程序接收緩沖區(qū)首地址;m_lpCurrDataEnd賦值是應(yīng)用程序接收緩沖區(qū)未地址

6、DeviceContext的linklist雙向鏈表,管理流上下文對(duì)象
LIST_ENTRY? m_StreamList;???????? // List of streams rendering to/from this device
根據(jù)其成員Flink查找相應(yīng)StreamContext對(duì)象(Flink對(duì)應(yīng)StreamContext成員m_Link)

7、DMA通道狀態(tài)設(shè)置
BOOL?m_InputDMARunning;
BOOL?m_OutputDMARunning;

8、DMA控制器狀態(tài)記錄
//----- Used to track DMA controllers status -----
#define DMA_CLEAR???0x00000000
#define DMA_DONEA???0x00000008
#define DMA_STRTA???0x00000010
#define DMA_DONEB???0x00000020
#define DMA_STRTB???0x00000040
#define DMA_BIU????0x00000080?// Determines which buffer is in use: (A=0, B=1)
DWORD? m_InputDMAStatus;????// Input DMA channel's status

9、DMA緩沖區(qū)頁(yè)面大小(輸入/輸出都有兩個(gè)緩沖區(qū)A和B進(jìn)行雙緩沖操作)
#define AUDIO_DMA_PAGE_SIZE?(4096)

10、DMA緩沖區(qū)接收數(shù)據(jù)大小數(shù)組
m_InBytes[IN_BUFFER_A];
m_InBytes[IN_BUFFER_B];

11、DMA接收緩沖區(qū)A/B首地址
PBYTE m_Input_pbDMA_PAGES[2];

12、IST中斷事件
HANDLE m_hAudioInterruptInput;

三、容易混淆的概念
1、WIDM_XXX/WODM_XXX、WOM_XXX/WIM_XXX、MM_WOM_XXX/MM_WIM_XXX的區(qū)別
(1)在waveapi通過(guò)DeviceIoControl調(diào)用驅(qū)動(dòng)的WAV_IOControl時(shí)傳遞的參數(shù)
(2)傳遞給回調(diào)函數(shù)waveInProc或waveOutProc的消息,回調(diào)函數(shù)是waveInOpen或waveOutOpen的參數(shù)
(3)傳遞給窗口的消息。就是說(shuō)要基于窗口類(lèi)的程序才有用,可以認(rèn)此種情況不能用于控制臺(tái)程序,第二種情況則可以

?

總結(jié)

以上是生活随笔為你收集整理的s3c2450下AC97驱动研究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。