日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]一,要使用DMA先要初始化一個結(jié)構(gòu)體這個結(jié)構(gòu)體就只有一個字段name,在DMA中斷請求時這個name將傳遞個dev_name。intrequest_irq( , , ,const char *dev_name,);。struct s3c2410_dma_client {char *name;};還得知道要

一,

要使用DMA先要初始化一個結(jié)構(gòu)體這個結(jié)構(gòu)體就只有一個字段name,在DMA中斷請求時這個name

將傳遞個dev_name。intrequest_irq( , , ,const char *dev_name,);。

struct s3c2410_dma_client {
char *name;
};

還得知道要使用的DMA源。然后就可以調(diào)用下面函數(shù)來請求該DMA源對應(yīng)的DMA通道了。

int s3c2410_dma_request(unsigned int channel,struct s3c2410_dma_client *client,void *dev)

在上面請求函數(shù)中做了兩項重要工作:

(1)

調(diào)用函數(shù)chan = s3c2410_dma_map_channel(channel); 根據(jù)DMA源在 源-----通道 管理結(jié)構(gòu)體

dma_sel.map(該結(jié)構(gòu)體在《DMA原理》中講過)中找出一個該DMA源所能請求并且空閑的通道,再根據(jù)

該通道號在數(shù)組s3c2410_chans[ch]中獲取一個被部分初始化過的DMA通道管理結(jié)構(gòu)體s3c2410_dma_chan。

然后將這個結(jié)構(gòu)體指針放到數(shù)組dma_chan_map[channel] 中,該數(shù)組中存放的都是在使用的DMA通道的管理結(jié)構(gòu)體

指針,獲取DMA通道管理結(jié)構(gòu)體用下面函數(shù)來實現(xiàn):

static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
{

。。。。。。
return dma_chan_map[channel];
}

下面是函數(shù)s3c2410_dma_map_channel()中的主要工作。

ch_map = dma_sel.map + channel;

。。。。。。

dmach = &s3c2410_chans[ch];
dmach->map = ch_map;
dma_chan_map[channel] = dmach;

(2)

獲取DMA通道之后注冊該通道的中斷,并關(guān)聯(lián)中斷函數(shù)s3c2410_dma_irq(),該函數(shù)在后面講解。

request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,client->name, (void *)chan);

二,

int s3c2410_dma_devconfig(int channel,enum s3c2410_dmasrc source,int hwcfg,unsigned long devaddr)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);

。。。。。

chan->source = source;
chan->dev_addr = devaddr;
chan->hw_cfg = hwcfg;

switch (source) {
case S3C2410_DMASRC_HW://源在外設(shè),既是從外設(shè)讀數(shù)據(jù)到內(nèi)存,源的地址是確定的。
dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);//初始化源控制寄存器
dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);//將源地址寫入初始源寄存器
dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));//目的地址在系統(tǒng)總線AHB上

chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);//將目的初始寄存器地址存于chan->addr_reg。

//外設(shè)的地址是確定的,內(nèi)存地址不確定,chan->addr_reg上存的地址或是初始源寄存器,初始目的寄存器

//根據(jù)從外設(shè)讀寫數(shù)據(jù)的不同而不同,但內(nèi)存的地址始終是寫到chan->addr_reg所指向的寄存器中。
break;

case S3C2410_DMASRC_MEM:////源在內(nèi)存,既是將內(nèi)存數(shù)據(jù)寫到外設(shè),目的地址是確定的。
dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);

chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
break;

default:

return -EINVAL;
}

return 0;
}

三,

int s3c2410_dma_config(unsigned int channel, int xferunit,int dcon)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);//找出源channel對應(yīng)的DMA通道管理結(jié)構(gòu)體。

dcon |= chan->dcon & dma_sel.dcon_mask;//設(shè)定DMA源選擇位

switch (xferunit) {//數(shù)據(jù)傳輸?shù)膯挝淮笮?br/>case 1:
dcon |= S3C2410_DCON_BYTE;
break;

case 2:
dcon |= S3C2410_DCON_HALFWORD;
break;

case 4:
dcon |= S3C2410_DCON_WORD;
break;

default:
return -EINVAL;
}

dcon |= S3C2410_DCON_HWTRIG;//源觸發(fā),不是軟件觸發(fā)
dcon |= S3C2410_DCON_INTREQ;//中斷使能

//將DMA通道控制寄存器的配置存于chan->dcon,到現(xiàn)在DMA通道控制寄存器中還有傳輸計數(shù)的值沒有配置了,

//當(dāng)內(nèi)存加載到初始源寄存器或是初始目的寄存器時再配置該值,并將chan->dcon中的值一并寫入DMA控制寄存器。

chan->dcon = dcon;
chan->xfer_unit = xferunit;

return 0;
}

四,

int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);

。。。。。。

//設(shè)置回調(diào)函數(shù)。待傳輸數(shù)據(jù)的內(nèi)存空間可能是不連續(xù)的,有很多段,當(dāng)一段內(nèi)存用完后

//調(diào)用該回調(diào)函數(shù)進(jìn)行處理。

chan->callback_fn = rtn;

return 0;
}

五,

int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);

chan->flags = flags;//設(shè)定flags的值比如S3C2410_DMAF_AUTOSTART,這個值在后面會用到。

return 0;
}

六,

s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);//下面講解

//函數(shù)s3c2410_dma_ctrl()的原型如下:

int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);

switch (op) {
case S3C2410_DMAOP_START:
return s3c2410_dma_start(chan);

case S3C2410_DMAOP_STOP:
return s3c2410_dma_dostop(chan);

case S3C2410_DMAOP_PAUSE:
case S3C2410_DMAOP_RESUME:
return -ENOENT;

case S3C2410_DMAOP_FLUSH:
return s3c2410_dma_flush(chan);

case S3C2410_DMAOP_STARTED:
return s3c2410_dma_started(chan);

case S3C2410_DMAOP_TIMEOUT:
return 0;

}

return -ENOENT; /* unknown, don't bother */
}

此處我們傳輸?shù)闹凳荢3C2410_DMAOP_FLUSH,應(yīng)該執(zhí)行函數(shù)s3c2410_dma_flush(chan);。

static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
{
。。。。。。

chan->curr = chan->next = chan->end = NULL; ////

。。。。。。

s3c2410_dma_waitforstop(chan);//循環(huán)等待屏蔽觸發(fā)寄存器中的DMA通道開關(guān)位的關(guān)閉。

return 0;
}

七,

//先將各內(nèi)存段掛到sg連上,調(diào)用函數(shù)dma_map_sg()映射一個發(fā)散/匯聚 DMA 操作,返回合并后的內(nèi)存段數(shù)。

dma_len =dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction)

for (i = 0; i < dma_len; i++) {

//分配一個數(shù)據(jù)段管理結(jié)構(gòu)體,并將各數(shù)據(jù)段穿成單向鏈表,以及加載一個數(shù)據(jù)段到DMA通道

//并開啟DMA數(shù)據(jù)傳輸s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,S3C2410_DMAOP_START);

res = s3c2410_dma_enqueue(unsigned int channel, void *id,dma_addr_t data, int size)
}

int s3c2410_dma_enqueue(unsigned int channel, void *id,
dma_addr_t data, int size)
{
struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
struct s3c2410_dma_buf *buf;
unsigned long flags;

//從內(nèi)存池dma_kmem為內(nèi)存管理結(jié)構(gòu)體s3c2410_dma_buf分配內(nèi)存。

buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);

buf->next = NULL;
buf->data = buf->ptr = data;//該段內(nèi)存的物理地址
buf->size = size;//該段內(nèi)存的大小
buf->id = id;
buf->magic = BUF_MAGIC;

local_irq_save(flags);

if (chan->curr == NULL) {//該函數(shù)第一次被調(diào)用也就是加載該通道的第一段內(nèi)存會進(jìn)入下面分支。

//在多段內(nèi)存工作過程中chan->curr指向當(dāng)前 目的/源 寄存器中加載的內(nèi)存段,也表示內(nèi)存段鏈表

//中的第一個內(nèi)存段。chan->next指向初始 目的/源 寄存器中加載的內(nèi)存段。也表示內(nèi)存段鏈表

//中的第二個內(nèi)存段。chan->end表示內(nèi)存段鏈表中最后一個內(nèi)存段。

chan->curr = buf;
chan->end = buf;//此時只有一段內(nèi)存。
chan->next = NULL;
} else {

chan->end->next = buf;//以后內(nèi)存段都是從鏈表尾插入鏈表的。
chan->end = buf;
}

//第一個內(nèi)存段加入chan->next指向第一個內(nèi)存段,第二個內(nèi)存段加入chan->next指向第二個內(nèi)存段,

////第三個內(nèi)存段加入chan->next還是指向第二個內(nèi)存段,
if (chan->next == NULL)
chan->next = buf;

//只有函數(shù)s3c2410_dma_ctrl()中調(diào)用的各函數(shù)可以改變chan->state的值,該值代表DMA通道的工作狀態(tài)。

//chan->load_state表示內(nèi)存段的在DMA寄存器中的加載情況,一般在存儲段加載函數(shù)中改變

//該值。在第一次調(diào)用該函數(shù)時是不會進(jìn)入下面分支的,第一次調(diào)用本函數(shù)會在下面調(diào)用函數(shù)

//s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,S3C2410_DMAOP_START);開啟DMA數(shù)據(jù)傳輸,

//第二次調(diào)用該函數(shù)可能就會進(jìn)入下面分支了。
if (chan->state == S3C2410_DMA_RUNNING) {
if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {

//如果開啟了DMA數(shù)據(jù)傳輸有一段內(nèi)存加載到了初始 目的/源 地址寄存器,但DMA當(dāng)前 目的/源 地址寄存器中還沒有

//加載內(nèi)存地址,則等待初始 目的/源 地址寄存器中的內(nèi)存地址加載到當(dāng)前 目的/源 地址寄存器中。
if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
。。。。。。
}
}

while (s3c2410_dma_canload(chan) && chan->next != NULL) {

//如果DMA當(dāng)前 目的/源 地址寄存器 或 DMA初始 目的/源 地址寄存器中沒有加載內(nèi)存地址則,加載一段內(nèi)存

/*

函數(shù)s3c2410_dma_loadbuf

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉