娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

ALSA聲卡_從零編寫之數據傳輸(基于優龍FS2410開發板,UDA1341聲卡)

發布者:清新微笑最新更新時間:2024-07-11 來源: elecfans關鍵字:數據傳輸  FS2410開發板 手機看文章 掃描二維碼
隨時隨地手機看文章

一、實驗環境

1.1 虛擬機環境

    a) Vmware版本:Vmware Workstation 12.5.7

    b) Ubuntu版本:9.10

    c) 內核版本:2.6.31.14

    d) toolchain版本:arm-linux-gcc 4.3.2

1.2 開發板

    優龍FS2410開發板,UDA1341聲卡

    內核版本:3.4.2

二、聲卡數據傳輸的原理(以播放為例)

image

(1) 驅動程序分配一個buffer:s2c2440_dma_new

(2) app不斷寫一個個period數據到buffer(appl_ptr以frame為單位) 。一個period包含多個frame,一個frame就是一個采樣數據

(3) 驅動不斷從buffer里取出一個period:load_dma_period,啟動DMA傳輸:s3c2440_dma_start,發送給聲卡

(4)傳輸完畢,產生中斷):s3c2440_dma2_irq ,更新狀態(hw_ptr,以frame為單位)

三、具體實現(s3c2440_dma.c)

注:內核中關于s3c24xx的DMA操作的代碼框架非常復雜,暫時未仔細研究(可參考:李蘭溪  S3C24XX DMA框架源碼分析)。而我們自制的驅動,則簡化了很多,但基本思想和流程是和內核一致的。     

準備工作

1. 定義好DMA操作相關的寄存器,并進行ioremap,以便后續的訪問

#define DMA0_BASE_ADDR  0x4B000000

#define DMA1_BASE_ADDR  0x4B000040

#define DMA2_BASE_ADDR  0x4B000080

#define DMA3_BASE_ADDR  0x4B0000C0


struct s3c_dma_regs {

unsigned long disrc;

unsigned long disrcc;

unsigned long didst;

unsigned long didstc;

unsigned long dcon;

unsigned long dstat;

unsigned long dcsrc;

unsigned long dcdst;

unsigned long dmasktrig;

};

static volatile struct s3c_dma_regs *dma_regs;


static int s3c2440_dma_init(void)

 {

dma_regs = ioremap(DMA2_BASE_ADDR, sizeof(struct s3c_dma_regs));

platform_device_register(&s3c2440_dma_dev);

platform_driver_register(&s3c2440_dma_drv);

return 0;

 }

 static void s3c2440_dma_exit(void)

 {

platform_device_unregister(&s3c2440_dma_dev);

platform_driver_unregister(&s3c2440_dma_drv);

iounmap(dma_regs);

 }


2. 實現幾個基礎函數,供后續s3c2440_dma_prepare、s3c2440_dma2_irq和s3c2440_dma_trigger調用


/* 數據傳輸: 源,目的,長度 */

static void load_dma_period(void)

{

    /* 把源,目的,長度告訴DMA */

    dma_regs->disrc      = playback_dma_info.phy_addr + playback_dma_info.dma_ofs;  /* 源的物理地址 */

    dma_regs->disrcc     = (0<<1) | (0<<0); /* 源位于AHB總線, 源地址遞增 */

    dma_regs->didst      = 0x55000010;        /* 目的的物理地址 IIS fifo entry*/

    dma_regs->didstc     = (0<<2) | (1<<1) | (1<<0); /* 目的位于APB總線, 目的地址不變 */

    /*

handshake mode

DACK and DREQ are synchronized to PCLK

Enable/Disable the interrupt setting for CURR_TC

A unit transfer

single service mode

select I2SSDO of DCON2 as DMA request source

hardware trigger DMA request

datasize to be transfered: half word

2(bytes)*1(unit)*initial transfer_count = len

==>transfer_count=len/2

    */

    /* bit22: 1-noreload */

    //傳輸的長度(datasize是half word即2個字節):playback_dma_info.period_size/2

    dma_regs->dcon = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(playback_dma_info.period_size/2);

    /* 使能中斷,單個傳輸,硬件觸發 */

}

static void s3c2440_dma_start(void)

{

/* 啟動DMA */

dma_regs->dmasktrig  = (1<<1);

}

static void s3c2440_dma_stop(void)

{

/* 停止DMA */

dma_regs->dmasktrig  &= ~(1<<1);

}


3.1 實現s3c2440_dma_platform.pcm_new(即s3c2440_dma_new)


(參考 soundsocsamsungdma.c 的 dma_new)


static int s3c2440_dma_new(struct snd_soc_pcm_runtime *rtd)

{

struct snd_card *card = rtd->card->snd_card;

struct snd_pcm *pcm = rtd->pcm;

struct snd_pcm_substream *substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;

struct snd_dma_buffer *buf = &substream->dma_buffer;

  /* 

           snd_dma_buffer的作用:

           在hw_params階段,snd_soc_platform_driver的ops->hw_params會被調用,通常會使用snd_pcm_set_runtime_buffer()

           把substream->dma_buffer的值拷貝到substream->runtime的相關字段中(.dma_area, .dma_addr, .dma_bytes),

           這樣以后就可以通過substream->runtime獲得這些地址和大小信息了。因為有播放和錄音兩個substream,而runtime始終指向當前使用的substream,

           所以便于跟蹤substream。

        */

int ret = 0;


/* 1. 分配DMA BUFFER */

if (!card->dev->dma_mask)  //這段代碼,是后來調試時發現,必須要加的

card->dev->dma_mask = &dma_mask;

if (!card->dev->coherent_dma_mask)

card->dev->coherent_dma_mask = DMA_BIT_MASK(32);


if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {

playback_dma_info.virt_addr = (unsigned int)dma_alloc_writecombine(pcm->card->dev, s3c2440_dma_hardware.buffer_bytes_max,

&playback_dma_info.phy_addr, GFP_KERNEL);

if (!playback_dma_info.virt_addr)

{

return -ENOMEM;

}

playback_dma_info.buf_max_size = s3c2440_dma_hardware.buffer_bytes_max;


buf->dev.type = SNDRV_DMA_TYPE_DEV;

buf->dev.dev = pcm->card->dev;

buf->private_data = NULL;

buf->area = (unsigned char *)playback_dma_info.virt_addr; //這句話是后來調試時,才發現需要加的

buf->bytes = playback_dma_info.buf_max_size;

buf->addr = playback_dma_info.phy_addr;

}


return ret;


        //為了簡化,先去掉錄音功能 

}


3.2 實現s3c2440_dma_platform.ops.open(即s3c2440_dma_open)

(參考 soundsocsamsungdma.c 的 dma_open)


static const struct snd_pcm_hardware s3c2440_dma_hardware = {

.info = SNDRV_PCM_INFO_INTERLEAVED |

SNDRV_PCM_INFO_BLOCK_TRANSFER |

SNDRV_PCM_INFO_MMAP |

SNDRV_PCM_INFO_MMAP_VALID |

SNDRV_PCM_INFO_PAUSE |

SNDRV_PCM_INFO_RESUME,

.formats = SNDRV_PCM_FMTBIT_S16_LE |

SNDRV_PCM_FMTBIT_U16_LE |

SNDRV_PCM_FMTBIT_U8 |

SNDRV_PCM_FMTBIT_S8,

.channels_min = 2,

.channels_max = 2,

.buffer_bytes_max = 128*1024, //在s3c2440_dma_new里被用于指定dma_alloc_writecombine的size參數

.period_bytes_min = PAGE_SIZE,

.period_bytes_max = PAGE_SIZE*2,

.periods_min = 2,

.periods_max = 128,

.fifo_size = 32,

};

//目前只支持播放 

static int s3c2440_dma_open(struct snd_pcm_substream *substream)

{

    struct snd_pcm_runtime *runtime = substream->runtime;

    int ret;

    /* 設置屬性 */

    snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); //約束:periods必須是整數

    snd_soc_set_runtime_hwparams(substream, &s3c2440_dma_hardware);

    /*

        snd_soc_set_runtime_hwparams的作用: 把s3c2440_dma_hardware的各個屬性賦給substream->runtime->hw,

        后續在snd_pcm_open_file==>snd_pcm_open_substream==>snd_pcm_hw_constraints_complete==>

        snd_pcm_hw_constraint_minmax里會調用諸如snd_pcm_hw_constraint_minmax(runtime, 

        SNDRV_PCM_HW_PARAM_CHANNELS, hw->channels_min, hw->channels_max);

    */

/* 注冊中斷 */

    ret = request_irq(IRQ_DMA2, s3c2440_dma2_irq, IRQF_DISABLED, 'myalsa for playback', substream);

    if (ret)

    {

        printk('request_irq error!n');

        return -EIO;

    }

return 0;

}

static int s3c2440_dma_close(struct snd_pcm_substream *substream)

{

    free_irq(IRQ_DMA2, substream);

    return 0;

}


3.3 實現s3c2440_dma_platform.ops. hw_params(即s3c2440_dma_hw_params)


(參考 soundsocsamsungdma.c 的 dma_hw_params)


static int s3c2440_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)

{

    struct snd_pcm_runtime *runtime = substream->runtime;

    unsigned long totbytes = params_buffer_bytes(params);


    /* 根據params設置DMA */

    /* 關于snd_pcm_set_runtime_buffer的作用,可看上文s3c2440_dma_new 關于snd_dma_buffer的注釋*/

    snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);


    /* 

       s3c2440_dma_new分配了很大的DMA BUFFER,而dma_bytes表明app決定使用多大

       runtime->dma_bytes被snd_pcm_lib_readv_transfer和snd_pcm_lib_writev_transfer用來和App之間傳輸數據

     */

    runtime->dma_bytes            = totbytes;

    playback_dma_info.buffer_size = totbytes;

    playback_dma_info.period_size = params_period_bytes(params); //記錄了app在每個period里傳輸的數據大小(單位:byte),一個period里包含多個frame 

    return 0;

}


3.4 實現s3c2440_dma_prepare


(參考 soundsocsamsungdma.c 的 dma_prepare)


static int s3c2440_dma_prepare(struct snd_pcm_substream *substream)

{

    /* 準備DMA傳輸 */

    /* 復位各種狀態信息 */

    playback_dma_info.dma_ofs = 0;

    playback_dma_info.be_running = 0;

    /* 加載第1個period */

    load_dma_period(); //仿照裸板程序的dma_init()

return 0;

}


3.5 實現s3c2440_dma_trigger


(參考 soundsocsamsungdma.c 的 dma_trigger)


static int s3c2440_dma_trigger(struct snd_pcm_substream *substream, int cmd)

{

int ret = 0;

    /* 根據cmd啟動或停止DMA傳輸 */

switch (cmd) {

case SNDRV_PCM_TRIGGER_START:

case SNDRV_PCM_TRIGGER_RESUME:

case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:

        /* 啟動DMA傳輸 */

        playback_dma_info.be_running = 1;

        s3c2440_dma_start();

break;

case SNDRV_PCM_TRIGGER_STOP:

case SNDRV_PCM_TRIGGER_SUSPEND:

case SNDRV_PCM_TRIGGER_PAUSE_PUSH:

        /* 停止DMA傳輸 */

        playback_dma_info.be_running = 0;

        s3c2440_dma_stop();

break;

default:

ret = -EINVAL;

break;

}

return ret;

}


3.6 實現s3c2440_dma2_irq


(參考 soundsocsamsungdma.c 的 audio_buffdone)


static irqreturn_t s3c2440_dma2_irq(int irq, void *devid)

{

    struct snd_pcm_substream *substream = devid;

    /* 更新狀態信息 */

    playback_dma_info.dma_ofs += playback_dma_info.period_size;

    if (playback_dma_info.dma_ofs >= playback_dma_info.buffer_size) // buffer_size來自于params_buffer_bytes(params),即App需要使用的緩沖區大小

        playback_dma_info.dma_ofs = 0; //如果當前DMA緩沖區中已傳輸的位置,超出了playback_dma_info.buffer_size,那么回零

    /* 更新hw_ptr等信息,

     * 并且判斷:如果buffer里沒有數據了,則調用trigger來停止DMA

     */

     snd_pcm_period_elapsed(substream);

     /*

        snd_pcm_period_elapsed為了查詢當前已傳輸的DMA數據在ring_buffer中的位置,會調用snd_pcm_update_hw_ptr0==>substream->ops->pointer(即soc_pcm_pointer) ==>

[1] [2]
關鍵字:數據傳輸  FS2410開發板 引用地址:ALSA聲卡_從零編寫之數據傳輸(基于優龍FS2410開發板,UDA1341聲卡)

上一篇:U-Boot移植
下一篇:ALSA聲卡_從零編寫之調試(基于優龍FS2410開發板,UDA1341聲卡)

推薦閱讀最新更新時間:2025-05-01 08:51

迅為恩智浦IMX6Q開發板Buildroot 文件系統 alsa 聲卡工具測試
耳機設置常用命令如下: 設置音量(最大為 127):amixer sset Headphone 101,101 左聲道開啟設置:amixer sset 'Left Output Mixer PCM' on 右聲道開啟設置:amixer sset 'Right Output Mixer PCM' on 使用命令“aplay -l”查看當前查看播放音頻設備: 如下圖所示,使用命令 amixer sset Headphone 101,101 設置音量大小。 如下圖所示,使用命令 amixer sset 'Left Output Mixer PCM' on 開啟左聲道。 如下圖所示,使
[單片機]
迅為恩智浦IMX6Q<font color='red'>開發板</font>Buildroot 文件系統 <font color='red'>alsa</font> <font color='red'>聲卡</font>工具測試
專利文件說明 未來MagSafe可能變成無線數據傳輸系統
4月15日上午消息,蘋果公司的MagSafe目前只是無線磁力充電裝置,但在未來,它可能才是無線數據傳輸的關鍵。 蘋果公司一直在研究如何讓MagSafe像現在的Lightning一樣傳輸數據,以及如何識別和驗證配件。   蘋果表示,目前MagSafe的工作方式存在“一些短板”近期的“與電子設備通信的附件設備”是一項新披露的蘋果專利申請,其中提出了問題,并提供了使MagSafe更智能的解決方案。 發熱是最主要的問題,蘋果提到,一些附件設備由于在電子設備上的位置而無意中形成了一個‘熱阱’,   此外,處理器技術的進步為電子設備提供了更快的處理速度,但在運行過程中會產生更多的熱量。” 蘋果公司建議電子設備,如iPhone,包含“
[手機便攜]
專利文件說明 未來MagSafe可能變成無線<font color='red'>數據傳輸</font>系統
ST 推出全新汽車智能網關平臺,讓數據傳輸更高效
意法半導體智能網關平臺(SGP)為汽車智能網關及域控制器應用原型開發提供了一個非常有用的開發工具。 隨著汽車架構逐漸集成高吞吐量車載網絡和高數據速率車云連接,汽車市場對高性能智能網關和域控制器電控單元(ECU)的需求日漸提高。 基于安全的ASIL-B Telemaco3P微處理器(MPU)與ASIL-D SPC58/Chorus微控制器(MCU)之間的千兆以太網通信,意法半導體的模塊化智能網關平臺(SGP)具有強大的處理能力,可以執行防火墻、預測性維護、固件無線升級(OTA)功能,以及ECU之間和車云之間的高數據速率通信。 Chorus 微控制器的多個CAN-FD接口提供低功耗的實時安全車載連接功能,而Telem
[汽車電子]
ST 推出全新汽車智能網關平臺,讓<font color='red'>數據傳輸</font>更高效
汽車記錄儀無線數據傳輸設計方案
  摘 要:提出并實現了無線傳輸在汽車行駛記錄中的使用方法。將無線模塊添加到汽車行駛記錄儀中,并設計了無線傳輸協議,用于快速檢測記錄儀中的數據,如超時、超速等。試驗測試結果表明,該方法能夠移動,遠程、快速、準確地獲取信息,具有較好的性價比以及推廣價值。   0 引 言   隨著道路交通的快速發展,道路交通事故率也在不斷地攀升,超時駕駛、超速駕駛成為交通事故的主要誘因。汽車行駛記錄儀(以下簡稱:記錄儀)是對車輛行駛速度、時間、里程、以及有關車輛行駛的其他狀態信息進行記錄、存儲并通過接口實現數據傳輸的數字式電子記錄裝置。汽車行駛記錄儀的使用,對遏制疲勞駕駛、車輛超速等交通違章、約束駕駛人的不良行為、保障車輛行駛安全以及道路交通事
[單片機]
汽車記錄儀無線<font color='red'>數據傳輸</font>設計方案
基于CDMA技術的遠程數據傳輸系統
  引 言   大型油田的油井、大型煤礦的礦井、水文監測點等監控設備具有分布地域廣,工作時間長,不宜長期值守等缺點,通常采用人工抄取數據的方式,條件較好的地方則采用專線或數傳電臺的方式把監測點的數據傳輸到信息中心。然而,這些方法都存在很大的不足:人工抄取方式既不方便,也浪費人力物力;數傳電臺需要向專門的管理部門申請傳輸頻率,并且受天氣和地理條件的影響很大。鑒于此,本文設計一種基于碼分多址 (Code Division Multipie Access,CDMA)技術與MECA128L的遠程數據傳輸系統。   CDMA是近年來被應用于商業的一種數字接口技術,與GSM相比具有以下優勢:發射功率小;采用先進的軟切換技術,使得其通話可與固定
[單片機]
基于CDMA技術的遠程<font color='red'>數據傳輸</font>系統
e2v利用全新ESIstream? 協議簡化串行數據傳輸
領先的高可靠性半導體供應商 e2v 日前發布了全新開放串行化協議的方案。高效串行接口 (ESIstream?) 將極高的數據速率效率和簡化的硬件實施結合在一起,用于實現串行數據傳輸。 數據速率效率對于減少數據傳輸通道數量至關重要。e2v 的全新 ESIstream? 僅有 12.5% 的開銷數據,而其他形式的串行化標準(例如 JESD204b)具有高達 30% 的開銷數據。 由于應用范圍非常廣泛,通用標準變得日益復雜。這導致設計人員必須付出很大努力來了解協議復雜性,進而確定適用于其應用的最佳實施方式。與其他協議相比,ESIstream? 將邏輯門數量減少了至少一半,從而保持了簡單性。這樣可以縮短設計時間和產品上市時間。
[嵌入式]
單片機數據通信之單總線數據傳輸
純單片機干不了大事,必須得配上各種外設,那么了解單片機與傳感器之間的數據通信就顯得必不可少了。常見的單片機數據通信方式有SPI,IIC,RS232,單總線等等。每種通信方式都有相應的時序圖,分析時序圖并完成代碼的編寫是單片機學習者的必修課。本文以DS18B20為例分析一下單總線數據傳輸。 DS18B20是單總線數據傳輸,因此對于時序的要求就非常的高,學會分析其時序圖是非常有必要的。 1.初始化時序圖分析: 首先是由總線控制器拉低總線,維持480us。在480us后釋放總線,由上拉電阻講總線拉高。等待5-60us后,DS18B20開始響應,會將數據總線拉低60-240us.之后便釋放總線,由上拉電阻拉高總線。轉換為代碼如下
[單片機]
單片機數據通信之單總線<font color='red'>數據傳輸</font>
拋棄式海水溫度測量儀數據傳輸系統設計
0 引言 溫度、鹽度等海洋水文環境參數的獲取日益重要。拋棄式溫探測系統是快速獲取大面積海域溫度剖面資料的儀器,為海洋調查、科學研究、軍事應用提供了先進的測量手段。國外發達國家自20世紀60年代開始,研制了機載可拋棄式海洋水文探測系統,其系列產品(已有溫、鹽、深、流)主要應用于美國海軍,能夠在一次任務航線上,利用同一種探測平臺快速獲取遠海目標海域的多要素實時數據,是至今機動性最好的遠海現場探測手段。其優點是:海洋水文要素獲取的機動性強;遠海探測成本、信息獲取的機動性、實時性均顯著優于船載系統。美國海軍使用的機載投棄式溫度計利用熱敏傳感器測量海水剖面溫度,溫度準確度達0.5℃。我國國家海洋局海洋技術研究所于1998年自主研制了機載
[單片機]
拋棄式海水溫度測量儀<font color='red'>數據傳輸</font>系統設計
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 剑河县| 泗阳县| 三台县| 景洪市| 德州市| 昌图县| 西峡县| 治多县| 普安县| 剑阁县| 南通市| 江西省| 九寨沟县| 霍邱县| 茌平县| 扶沟县| 呼伦贝尔市| 友谊县| 伊吾县| 大关县| 濮阳县| 大冶市| 开封市| 吉安县| 通化县| 黄骅市| 平凉市| 阿坝县| 湖南省| 中牟县| 丰宁| 隆子县| 津市市| 焉耆| 屏边| 和田县| 洞头县| 翼城县| 平顶山市| 安国市| 松滋市|