<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應用程序訪(fǎng)問(wèn)物理地址的實(shí)例

嵌入式Linux應用程序訪(fǎng)問(wèn)物理地址的實(shí)例

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

前言
  按照分層思想,外設與主機控制器的不相關(guān),主機控制器的驅動(dòng)不關(guān)心外設,而外設驅動(dòng)也不關(guān)心主機,外設訪(fǎng)問(wèn)核心層的通用應用程序進(jìn)行數據傳輸,主機和外設之間可以進(jìn)行任意的組合。這樣思想要求應用程序不應當直接訪(fǎng)問(wèn)物理地址,而是應當通過(guò)驅動(dòng)程序的調用來(lái)實(shí)現,以便保持應用程序的性,操作訪(fǎng)問(wèn)的統一性,應用程序利用系統的統一調用訪(fǎng)問(wèn)外設,如使用write(),read()等函數進(jìn)行實(shí)際的外設讀寫(xiě)控制。應用程序通過(guò)調用進(jìn)入內核函數后,內核利用copy_from_user()獲得應用層數據,內核驅動(dòng)程序也通過(guò)分層最終執行物理訪(fǎng)問(wèn),之后把獲得的數據用copy_to_user()回傳給應用程序的調用者。由于驅動(dòng)對外需要有個(gè)統一接口,所以定義了一些結構體,鏈表等機制,以便讓?xiě)贸绦虿僮骱?jiǎn)單化,數據在內核一應用之間的復制,填充結構體等都需要時(shí)間開(kāi)銷(xiāo),有時(shí)按這種標準調用方式,因為操作時(shí)間過(guò)長(cháng),無(wú)法完成設計目的。

操作效率評估
  我們的一個(gè)項目中,系統由FPGA和ARM11結合為核心控制器,其中FPGA連接外部高速ADC、DAC和RF器件在A(yíng)RM11的控制下,實(shí)現GB18000-6C標準的UHF RFID讀寫(xiě)控制狀態(tài)機。FPGA與ARM11的接口采用SPI,其中ARM11選用三星S3C6410,作為SPI的主機,FPGA作為SPI的從機,受S3C6410的控制。在本系統中,SPI接口充當ARM11和FPGA交互的橋梁,ARM11的命令和動(dòng)作參數傳給FPGA并啟動(dòng)FPGA處理狀態(tài)機,FPGA動(dòng)作的結果也通過(guò)SPI回傳給ARM11,兩者之間的通訊效率在系統中需要重點(diǎn)關(guān)注。

  評估通訊接口時(shí),利用三星提供的SPI驅動(dòng)函數,系統運行在533MHz,SPI時(shí)鐘配置為16MHz,程序在linux3.0環(huán)境下通過(guò)read/write進(jìn)行操作,為了評估效率,另外采用一個(gè)GPIO輸出脈沖指示操作過(guò)程,試驗結果顯示效率非常低下,從應用層執行write代碼開(kāi)始到SPI端口輸出時(shí)鐘,延時(shí)長(cháng)達72μs,SPI操作之后,再回到應用層的下一個(gè)語(yǔ)句也延時(shí)42μs,對于比較少的數據傳輸情況,附加的額外等待時(shí)間遠遠長(cháng)于實(shí)際傳輸有效時(shí)間,從前面數據看出,通過(guò)標準庫調用嚴重影響系統性能,沒(méi)法滿(mǎn)足系統需求。通過(guò)查看驅動(dòng)程序的源代碼,可以發(fā)現因為驅動(dòng)程序層層封裝,并且包含應用層到內核的copy_from_user()和內核到應用層的copy_to_user()兩次數據搬移,導致執行效率很低。為了提高數據交互效率,就要設法繞開(kāi)數據搬移等時(shí)間開(kāi)銷(xiāo),最好能直接操作寄存器,雖然這種想法與分層驅動(dòng)思想不相符合,但是在嵌入式系統中,有時(shí)需要高的執行效率,如果利用系統一些特定函數,實(shí)現高效率的數據交互從而完成設計目標是有必要和可能的。

  linux存在名為mmap的函數,能把物理地址映射為虛擬地址,并且這個(gè)函數能直接在應用程序中直接調用而不是僅僅屬于內核調用的函數,這樣在應用層直接操作S3C6410的物理外設成為可能??紤]到在特定的嵌入式系統中,特定外設的使用可以由程序控制,這樣可以簡(jiǎn)化共享設備的互斥保護,進(jìn)一步減少代碼量,提高了訪(fǎng)問(wèn)效率。

mmap函數調用實(shí)例
  mmap函數作用是將物理地址映射至用戶(hù)空間。下面是函數的參數簡(jiǎn)單說(shuō)明
void* mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset);
addr: 指定文件應被映射到進(jìn)程空間的起始地址
len: 映射到用戶(hù)空間的字節數
prot: 指定被映射空間的訪(fǎng)問(wèn)權限,
flags: 由以下幾個(gè)常值指定:
fd: 映射到用戶(hù)空間的文件的描述符
offset: 被映射內存區在文件中的偏移值該函數映射文件描述符

  通過(guò)這個(gè)函數,我們可以在應用層訪(fǎng)問(wèn)對應物理地址正確映射后的虛擬地址,這個(gè)函數使我們在應用層也具有對任意物理地址的操作權限,下面代碼配置S3C6410的SPI0,因為使用mmap映射,所以不論內核是否帶有SPI驅動(dòng)都不影響我們使用SPI0,但是因為本程序需要對比研究標準驅動(dòng)方式與直接存儲器訪(fǎng)問(wèn)方式的執行差異,所以在內核中編譯了標準SPI的驅動(dòng)程序。由于S3C6410多數腳都有復用功能,為了使SPI0正確工作,還需要配置相關(guān)對應的GPIO為SPI功能(實(shí)際上因為我們編譯的內核帶有SPI0的驅動(dòng),內核程序已經(jīng)完成了SPI的初始化,有的內核沒(méi)有編譯SPI,所以下面還是完整配置了SPI,供參考),同時(shí)為了觀(guān)察研究SPI的執行效率,我們程序還對其他GPIO做了配置以便輸出脈沖,通過(guò)示波器來(lái)評估觀(guān)察。另外我們還使用若干時(shí)間標志來(lái)記錄操作過(guò)程時(shí)間,對于在沒(méi)有示波器的情況下也能評估執行時(shí)間。

  下面是測試程序代碼以及測試過(guò)程的示波器記錄抓圖。

#include "test.h"
void Init_FPGA_SPI(){//配置SPI端口
int fbb;
fbb=open("/dev/mem",O_RDWR | O_SYNC);
map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f00b000);
*(volatile unsigned int *)(map_base+0x04)=0x00000101;//CLK=16.625MHz
*(volatile unsigned int *)(map_base+0x08)=0x00000000;
*(volatile unsigned int *)(map_base+0x0c)=0x00000002;
*(volatile unsigned int *)(map_base)=0x00000003;
FPGA_RUN=map_base+0x18;
map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f008000);
GPC=map_base+0x40;//配置端口復用功能為SPI
map_GPC=*(volatile unsigned int *)(GPC+4);
*(volatile unsigned int *)(GPC)=0x12201222;
GPC+=4;
virt_addr2=map_base+0x824;//配置觀(guān)察IO
GLEDstate=*(volatile unsigned int *)(virt_addr2);
}
void Init_Timer(){//添加加配置1微秒時(shí)基定時(shí)器
int fbb;
unsigned int temp;
fbb=open("/dev/mem",O_RDWR | O_SYNC);
map_base=(char *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fbb,0x7f006000);
…………………… 篇幅原因略去部分次要代碼
MYSYSTICK=map_base+0x14;
}
void SPI_init(){
bits=8;
speed = 16625000;
trr.len =20;
trr.delay_usecs = 0;
trr.speed_hz = speed;
trr.bits_per_word = bits;
fspi = open("/dev/spidev0.0", O_RDWR);
ioctl(fspi, SPI_IOC_RD_MODE, mode);
ioctl(fspi, SPI_IOC_WR_MODE, mode);
}
__inline unsigned int GETSYSCLK(){
return(*(volatile unsigned int *)(MYSYSTICK));
}
__inline void CSFPGAL(){
map_GPC=0xfffffff7;
*(volatile unsigned int *)(GPC)=map_GPC;
}
__inline void CSFPGAH(){
map_GPC|=0x00000008;
*(volatile unsigned int *)(GPC)=map_GPC;
}
void test(){
GLEDstate=0xfffffffe;
*(volatile unsigned int *)(virt_addr2)=GLEDstate;//產(chǎn)生GPIO負跳變
starttime2=GETSYSCLK();
*(volatile unsigned int *)(FPGA_RUN-0x0c)=0x00;
*(volatile unsigned int *)(FPGA_RUN-0x18)=0x23;
*(volatile unsigned int *)(FPGA_RUN-0x18)=0x03;
CSFPGAL();
*(volatile unsigned int *)(FPGA_RUN)=tx[0];
*(volatile unsigned int *)(FPGA_RUN)=tx[1];
*(volatile unsigned int *)(FPGA_RUN)=tx[2];
*(volatile unsigned int *)(FPGA_RUN)=tx[3];
*(volatile unsigned int *)(FPGA_RUN)=tx[4];
while (((*(volatile unsigned int *)(FPGA_RUN-4)0xfe000)>>13)5){};
CSFPGAH();
stoptime2=GETSYSCLK();
GLEDstate|=0x00000001;
*(volatile unsigned int *)(virt_addr2)=GLEDstate;
GLEDstate=0xfffffffe;
*(volatile unsigned int *)(virt_addr2)=GLEDstate;
starttime1=GETSYSCLK();//產(chǎn)生GPIO一個(gè)正脈沖
write(fspi,tx,5);
stoptime1=GETSYSCLK();
GLEDstate|=0x00000001;
*(volatile unsigned int *)(virt_addr2)=GLEDstate; //產(chǎn)生GPIO正跳變
printf("DRVtime=%d REGtime=%d ",starttime1-stoptime1,starttime2-stoptime2);
}
int main(void){
SPI_init();Init_FPGA_SPI();Init_Timer();
waittime=GETSYSCLK();
while(1){
if ((waittime-GETSYSCLK())>2000000){//2000ms測試一次
waittime=GETSYSCLK();
test();
}
}
}

  圖1示波器截圖添加了一些時(shí)間信息以便對應代碼注釋說(shuō)明,對應于代碼mmap方式和標準驅動(dòng)調用方式產(chǎn)生了兩組SCK時(shí)鐘,GPIO觀(guān)察腳顯示第一次SPI訪(fǎng)問(wèn)消耗5μs,第二次訪(fǎng)問(wèn)消耗114μs,其中真正操作SPI的時(shí)間也就4μs不到,其它時(shí)間消耗在系統應用層到內核兩次雙向的數據拷貝以及為了統一對外接口所做的數據結構配置等方面,由此對比可以看出兩種方式訪(fǎng)問(wèn)效率上的巨大差異。

圖 1


結語(yǔ)
  通過(guò)mmap方式應用程序在下操作硬件寄存器,適合于關(guān)注高效率的訪(fǎng)問(wèn)場(chǎng)合,在嵌入式應用中,我們既能夠獲得使用操作系統管理任務(wù)和豐富開(kāi)源驅動(dòng)庫的好處,同時(shí)又能在局部提升處理效率,提高處理數據的實(shí)時(shí)性。

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

linux相關(guān)文章:linux教程




關(guān)鍵詞: Linux 驅動(dòng) 可移植 接口

評論


相關(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>