<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 嵌入式Linux下ARM處理器與DSP的數據通信

嵌入式Linux下ARM處理器與DSP的數據通信

作者: 時(shí)間:2006-02-15 來(lái)源:網(wǎng)絡(luò ) 收藏

摘要:本文通過(guò)一個(gè)開(kāi)發(fā)實(shí)例詳細說(shuō)明如何通過(guò)的HPI接口與運行操作系統的架構進(jìn)行。給出接口部分的實(shí)際電路和-下驅動(dòng)程序的開(kāi)發(fā)過(guò)程。

關(guān)鍵詞:設備驅動(dòng)程序 HPI

1 引言

基于A(yíng)RM核心系統以其自身資源豐富、功耗低、價(jià)格低廉、支持廠(chǎng)商眾多的緣故,越來(lái)越多地應用在各種需要復雜控制和通信功能的系統中。

內核源碼開(kāi)放的Linux與ARM體系相結合,可以發(fā)揮Linux系統支持各種協(xié)議及存在多進(jìn)程調度機制的優(yōu)點(diǎn),從而使開(kāi)發(fā)周期縮短,擴展性增強。作為數字處理專(zhuān)用電路,的數字信號處理能力十分強大,但對諸如任務(wù)管理、通信、人機交互等功能的實(shí)現較為困難。

如果將這三者結合起來(lái),即由DSP結合采樣電路采集并處理信號,由ARM處理器作為平臺,運行Linux操作系統,將經(jīng)過(guò)DSP運算的結果發(fā)送給用戶(hù)程序進(jìn)行進(jìn)一步處理,然后提供給圖形化友好的人機交互環(huán)境完成數據分析和網(wǎng)絡(luò )傳輸等功能,就會(huì )最大限度的發(fā)揮三者所長(cháng)。

2 系統結構

該系統硬件由二部分組成,其中一部分為若干塊DSP板,各自獨立承接數據采集和信號處理。另一部分為以ARM為核心處理器的CPU板。系統硬件框圖如圖1所示(僅接口部分)。

3 接口硬件部分設計

3.1 HPI接口簡(jiǎn)介

HPI接口是TI公司新一代、高性能DSP上用以完成與主機或其他DSP之間數據交換的接口,這里主要介紹實(shí)際電路中使用的控制引腳和時(shí)序。

HCNTL0和HCNTL1為訪(fǎng)問(wèn)控制選擇。用來(lái)確定主機(ARM)究竟對TMS320C6711中的哪一個(gè)HPI寄存器進(jìn)行處理。具體功能如表1所列。

表1 HCNTL0和HCNTL1的功能

HCNTL0HCNTL1

功 能

00主機對HPI控制寄存器(HPIC)進(jìn)行讀寫(xiě)
01主機對HPI地址寄存器(HPIA)進(jìn)行讀寫(xiě)
10主機對HPI數據寄存器(HPID)地址自動(dòng)增加模式(Auto increment mode)進(jìn)行讀寫(xiě),對HPID讀寫(xiě)后,地址寄存器(HPIA)自動(dòng)增加一個(gè)字地址(4字節地址)
11主機對HPI數據寄存器(HPID)地址固定模式(Fixed mode)進(jìn)行讀寫(xiě)。對HPID讀寫(xiě)后,地址寄存器(HPIA)保持不變

HR/W:讀寫(xiě)選擇控制。為“1”表示是從DSP中讀,反之則為寫(xiě)。

HHWIL:半字節定義選擇,與HPIC寄存器中的HWOB位進(jìn)行配合可以選擇當前傳輸的是高半字還是低半字。低電平是第一個(gè)半字,高電平是第二個(gè)半字。

HCS:選通脈沖(Strobe),與HDS1、HDS2相互配合完成內部信號HSTROBE的生成。邏輯關(guān)系如圖2所示。

將HDS1、HDS2分別固定為高電平和低電平,這樣HCS就和HSTROBE完全一致。

HSTROBE讀時(shí)序如圖3所示。

3.2 接口電路

ARM處理器通過(guò)DSP的HPI接口與DSP進(jìn)行連接的硬件原理如圖4所示(以單板DSP為例)。其中SN74LVTH16245為16位(二個(gè)8位)雙向三態(tài)總線(xiàn)收發(fā)器,主要起總線(xiàn)驅動(dòng)和方向控制的作用同時(shí)也保證在不對HPI口進(jìn)行操作時(shí)數據總線(xiàn)鎖閉。AT91RM9200為Atmel公司生產(chǎn)的ARM9為核心的處理器,其中引腳D0-D15為數據總線(xiàn),A2-A8為地址總線(xiàn)的一部分,CS3為片選信號線(xiàn),當ARM對總線(xiàn)地址范圍為0x40000 0000~0x4FFF FFFF的外部設備進(jìn)行操作時(shí),會(huì )在該引腳產(chǎn)生一個(gè)片選信號。同時(shí)該信號控制SN74LVTH16245的使能端,避免在讀寫(xiě)其他地址時(shí)對HPI端口造成影響。TMS320C6711D是TI公司生產(chǎn)的DSP,每秒可以完成15億次浮點(diǎn)運算,數據處理功能十分強大。引腳D0-D15為數據總線(xiàn)。其余端口是HPI接口的控制引腳。

4 驅動(dòng)程序設計

4.1 Linux驅動(dòng)程序簡(jiǎn)介

在Linux操作系統下有二種方式將驅動(dòng)程序裝入操作系統內核:一種是直接將驅動(dòng)程序編譯進(jìn)內核,另外一種是將驅動(dòng)程序構建為驅動(dòng)程序模塊后采用insmod/rmmod命令將模塊加載內核中。由于是在嵌入式系統中進(jìn)行程序開(kāi),所以筆者選用了模塊加載方式。這樣,在整個(gè)程序的調試過(guò)程中不必因為修改某處而反復編譯整個(gè)內核,只需編譯驅動(dòng)程序模塊并重新加載。

本例中Linux下的驅動(dòng)程序主要用來(lái)完成文件(Linux把外部設備也認為是文件)的打開(kāi)、關(guān)閉、讀、寫(xiě)等操作。也就是對如下結合的填充。

Static struct file_operations fops=

{open:hpi_open,

release:hpi_release,

mmap:hpi_mmap,

};

其中,open和release完成設備的打開(kāi)和關(guān)閉。mmap為內存地址映射操作。因為采用的是模塊加載方式,所以還應該加上int init_module(void)和void cleanup_module(void)函數,以完成模塊的注冊和卸載。

4.2 驅動(dòng)程序中映射的實(shí)現

由于驅動(dòng)程序的內存空間是在內核空間中,因此首先應解決內核空間與用戶(hù)空間的交互問(wèn)題。這里采用最直接的方式將內核空間和用戶(hù)空間聯(lián)系起來(lái)實(shí)現映射,即利用remap_page_range內核函數(通過(guò)mmap系統調用實(shí)現)。

函數原形如下:

int remap_page_range(unsigned long virt_add,unsigned long phys_add,unsigned long size,pgprot_tprot);

函數的功能是構造用于映射一段物理地址的新頁(yè)表。函數返回的值通常是0或者一個(gè)負的錯誤碼。函數參數的確切含義如下:

virt_add:重映射起始處的用戶(hù)虛擬地址。phys_add:虛擬地址所映射的物理地址。Size:被重映射的區域的大小。Prot:新VMA(virtual memory area)的“保證(protection)”標志。具體定義在源泉文件/include/linux/mm.h中。系統調用MMAP的程序代碼如下:

static int hpi_mmap(struct file *f,struct vm_area_struct *vma)

vma->vm_flags|=VM_WRITE;

if(remap_page_range(vma->vm_start,((0x40000000)),

vma->vm_end-vma->vm_start,(_pgprot (pgprot_val(pgprot_noncached(vma->vm_page_prot))|

(L_PTE_WRITE|L_PTE_DIRTY))))) //進(jìn)行映射

{return -1;} //映射失敗

return 0;

}

結合硬件結構可對函數remap_page_range()分別填充如下參數:

remap_page_range(vma->vm_start,((0x40000000)),vma->vm_end-vma->vm_start,(__pgprot(pgprot_val(pgprot_noncached(vma->vm_page_prot)) |(L_PTE_WRITE|L_PTE_DIRTY)))))

其中vma為結合vm_area_struct,在linux/mm.h>中定義。

應用中需要注意以下字段:unsigned long vm_flags應該使用標志VM_RESERVED,以避免內存管理系統將該VMA交換出去。因為要對DSP寫(xiě)入數據,所以必須使用標志VM_WRITE說(shuō)明對這一段VMA是允許寫(xiě)入的。pgport_t vm_page_prot指明了對VMA的保護權限。由于利用CS3對DSP的HPI接口進(jìn)行控制,所以應用pgprot_noncached禁止高速緩沖。

通過(guò)mmap的構建就能夠將內核空間的數據映射到用戶(hù)空間去,也就是說(shuō)可以在用戶(hù)空間內直接對地址為0x4000_0000的內存空間進(jìn)行操作,而該段空間正是DSP的HPI接口所對應的地址。

在實(shí)際應用中,應對CS3的低電平脈寬加以控制,方法是在初始化模塊時(shí)對ARM的控制寄存器CSR[3]進(jìn)行調節。該寄存器的D0-D6確定了ARM外部總線(xiàn)的時(shí)鐘延時(shí)周期,D7為等待周期的使能,D12-D14為數據寬度。具體定義如下:AT91_SYS->EBI_SMC2_CSR[3]=0x00003083,即使用16bit數據寬度,等待周期為3個(gè)。當ARM主頻為180MHz時(shí),CS3低電平脈寬約為150ns。

4.3 驅動(dòng)程序的系統調用接口

為對處于總線(xiàn)地址0x4000_0000的DSP板進(jìn)行操作,首先應用open打開(kāi)設備,該設備可以通過(guò)mknod建立(本例建立的是/dev/hpi)。然后mmap完成映射。

Int dev_hpi_open(str_HPI *ss)

{size_t length=1024;

int i;

if((*ss).hpi_number==0)

{

(*ss).hpi_fd=open("/dev/hpi",O_RDWR);

}

if((*ss).hpi_fd==-1)return -1;

(*ss).hpi_mmap_start =mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,((*ss).hpi_fd),0); //獲得映射區內存的起始地址

return 0;

} //dev_hpi_open

mmap的作用是將文件內容映射到內存中。函數的原形及各參數定義如下:

*mmap(void *start,size_length,int prot,int flags,intfd,off_t offset)

start指向欲對應的內存地址,size-length的含義是要映射的量;prot代表映射區域的保護方式;flag會(huì )影響映射區域的各種特性;fd為文件描述符;offtoffset代表文件的偏移量,通常設置為零。

示例程序中的結構體變量ss用來(lái)總知各種變量。通過(guò)mmap可以獲得映射后的內存地址,用(*ss).hpi_mmap_start表示。

一旦獲得了這個(gè)起始地址,就能對0x4000_0000起始的總線(xiàn)地址進(jìn)行操作,因為映射已經(jīng)完成,對(*ss).hpi_mmap_start的操作就是對0x4000_0000起始的總線(xiàn)地址進(jìn)行操作,而DSP板HPI接口的控制線(xiàn)正是在這個(gè)位置。這樣就實(shí)現了物理地址和用戶(hù)空間的轉換。

4.4 用戶(hù)程序接口部分

下面以HPI接口讀寫(xiě)中最復雜的自增讀方式用戶(hù)程序為例說(shuō)明用戶(hù)接口程序的設計過(guò)程。要完成自增讀的操作,對于HPI一側,假設采用軟件握手的方式。要完成的工作如下:

首先讀HPIC以查詢(xún)其中的HRDY位是否為1,如果為1則表示DSP中數據已經(jīng)備妥。然后寫(xiě)HPIA以告訴DSP從什么位置開(kāi)始進(jìn)行自增讀。接著(zhù)將HPIC的FETCH位置1以刷新寫(xiě)入。再讀HPIC以查詢(xún)其中的HRDY位是否為1,如果為1則表示DSP中數據已經(jīng)備妥。最后從HPID中讀取數據。

對于A(yíng)RM一側,要對HPIC、HPID、HPIA寄存器進(jìn)行讀寫(xiě)必須滿(mǎn)足HPI接口的定義,具體如下(以自增讀為例):

讀前半字節(高16位)時(shí),HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0。

讀后半字節(低16位)時(shí),HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0。

從硬件的原理圖可知,這些HPI的控制口線(xiàn)分別與ARM的一部分地址總線(xiàn)連接。具體為HCNTL0----A2、HCNTL1----A3、HR/W------A4、HHWIL-----A5。

宏定義過(guò)程如下:

#define HPIC_R_F(HPI_VA_BASE)*((unsigned long*)((HPI_VA_BASE)+0x00000004+DSPNUMBER))

//讀HPIC第一半字

#define HPIC_R_S(HPI_VA_BASE)*((unsigned long*)((HPI_VA_BASE)+0x0000000C+DSPNUMBER))

//讀HPIC第二半字

等等,只要改變在HPI_BA_BASE基礎上增加的數字就可以獲取對控制口線(xiàn)的操作。

在這里HPI_VA_BASE將由映射得到的用戶(hù)空間虛擬地址代替,所以如果“自增模式讀HPID第一半字”那么就可求滿(mǎn)足前文提到的HCNTL0=0、HCNTL1=1、HR/W=1、HHWRL=0,也就是要滿(mǎn)足地址位A2=0、A3=1、A4=1、A5=0,所以只要在HPI_VA_BASE的基礎上加0x0000_0006就可以了。要注意的是ARM處理器的地址是32位。所以是加上0x0000_0006而不是0x0000_0018。

另外,還有二點(diǎn)需要說(shuō)明:

通過(guò)改變宏定義中的DSPNUMBER常量可以控制地址總線(xiàn)A6、A7、A8。通過(guò)這3個(gè)總線(xiàn)組合并通過(guò)簡(jiǎn)單地址譯碼電路就可以完成對多塊DSP板的讀寫(xiě)。在硬件電路中可以定義為0。

A4(HR/W)同時(shí)還用做SN74LVTH16245的方向控制。讀的時(shí)候A4=1,此時(shí)SN74LVTH16245的數據從A-->B;反之,則從B-->A。

下面給出程序中的自增讀和注釋部分:

int dev_hpi_auto1(str_HPI *ss)

{volatile unsigned long dsp_addr_hign_read_auto;//定義各種中間變量

volatile unsigned long dsp_addr_low_read_auto;

volatile unsigned long dsp_data_hign_read_auto;

volatile unsigned long dsp_data_low_read_auto;

volatile unsigned long dsp_add_temp;

int i;

volatile unsigned long data_length;

//---read hpic----the host polls the HPIC for HRDY=1

volatile unsigned long polltest;

polltest=HPIC_R_F((*ss).hpi_mmap_start);

while((polltest0x00000008)!=0x00000008)

{polltest=HPIC_R_F((*ss).hpi_mmap_start);

}

dsp_add_temp=((*ss).hpi_dsp_add);//從應用程序傳過(guò)來(lái)的參數,指明希望從DSP的哪一個(gè)地址讀起

dsp_addr_low_read_auto=((dsp_add_temp)0x0000ffff)+((dsp_add_temp)16); //完成數據轉換

dsp_addr_hign_read_auto=((dsp_add_temp)0xffff0000)+((dsp_add_temp)>>16);

//---write dsp s addr to HPIA

HPIA_W_F ((*ss).hpi_mmap_start)=(dsp_addr_hign_read_auto);

HPIA_W_S((*ss).hpi_mmap_start)=(dsp_addr_low_read_auto);

//--------write hpic----------to FETCH bit

HPIC_W_F((*ss).hpi_mmap_start)=0xfff8fff8;

HPIC_W_S((*ss).hpi_mmap_start)=0xfff8fff8;

//---read dsp s data from HPID,autoincrement mode

data_length=(*ss).hpi_dsp_data_length;//從應用程序傳過(guò)來(lái)的參數,指明期望讀取多少個(gè)字

for(i=0;i=data_length;i++)

{//---read hpic----the host polls the HPIC for HRDY=1 again

polltest=HPIC_R_F((*ss).hpi_mmap_start);

while((polltest0x00000008)!=0x00000008)

{polltest=HPIC_R_F((*ss).hpi_mmap_start);

}

dsp_data_hign_read_auto =HPID_R_F_A((*ss).hpi_mmap_start); //讀第一個(gè)半字。

dsp_data_low_read_auto =HPID_R_S_A((*ss).hpi_mmap_start); //第二個(gè)個(gè)半字

{(*ss).buffer [(i)]=(dsp_data_hign_read_autooxffff0000)+(dsp_data_low_read_auto0x0000ffff);

//數據拼接,放入結構體,回傳給調用的用戶(hù)程序。

}

}

} //dev_hpi_read_auto(str_HPI *ss)

5 結束語(yǔ)

本文通過(guò)一個(gè)實(shí)例說(shuō)明了如何實(shí)現在Linux操作系統下ARM體系結構的處理器與DSP的。給出了接口部分的硬件處理和部分驅動(dòng)程序。

在某款智能儀表的研發(fā)過(guò)程中,給出一個(gè)簡(jiǎn)單的地址譯碼電路對二塊(或更多)DSP板進(jìn)行交替讀寫(xiě),并以自增讀方式進(jìn)行操作,當ARM主頻為180MHz,DSP主頻為125MHz時(shí),對DSP數據的讀寫(xiě)速度可以達到每毫秒1k的32位字。

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)


評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>