在Linux應用程序中,常用的延時函數包括sleep()、usleep()、select()等,這幾個延時函數函數的執行機制,都是將當前線程掛起,由操作系統做延時,然后再恢復當前線程。這意味著其延時的最小間隔是兩次線程切換時間。經測試,在單一線程情況下,兩次線程的切換時間在150us左右。大多數情況下,應用程序會有多個線程在運行,這時線程恢復有可能在下一個時間片,而Linux系統缺省的線程輪片時間為10ms,這意味著只有當延時在大于10ms情況時,常規的延時函數才有意義。在工控領域,我們常常碰到需要微秒級的延時需求,例如實現某種讀寫時序等,這時Linux系統的常規延時函數難于滿足其需求。針對這樣的應用需求,我們設計了采用內存映射的方法操作主板的硬件定時器和GPIO,從而產生出具有微秒精度的脈沖波形來。下面就詳細介紹如何在用戶進程實現這樣的精確延時的操作。
以EM335x工控主板為例,用其內部的定時器來實現精確延時的功能,EM335x內部定時器的輸入時鐘為24MHz,單位時間為41.6ns,通過將Linux系統的mem設備文件和mmap()函數結合起來使用,可直接對EM335x內部定時器的寄存器進行操作,再通過同樣的方式控制GPIO,實現:(1)設置GPIO,(2)啟動定時器,當檢測到定時器計數完畢,(3)再設置GPIO,共三個步驟,就可產生精確時間間隔的脈沖。
Linux系統中的/dev/mem設備文件,是專門用來讀寫物理地址用的,里面的內容是所有物理內存的地址以及內容信息。只要我們使用mmap()函數將/dev/mem設備文件映射到進程地址空間,實現對內存物理地址的讀寫,就能夠通過這種方式快速的對GPIO和定時器進行操作,而mmap操作提供了一種機制,讓用戶程序直接訪問設備內存,這樣就相當于直接對硬件進行操作,從而避開了驅動程序,如果調用驅動就需要在用戶空間和內核空間互相拷貝數據,還會涉及到系統調度等機制,效率將會變低。
將/dev/mem/設備文件中定時器的地址映射到用戶進程空間的代碼:
void *timer_em335x_pin_config(unsigned int BASE)
{
int mem_fd;
void *base;
mem_fd = open('/dev/mem', O_RDWR|O_SYNC);
printf('mem_fd is %d\n', mem_fd);
/* mmap Timer */
base = mmap(
NULL, //起始地址
DMTIMER_DEV_SIZE, //映射的文件內容的大小
PROT_READ|PROT_WRITE,//映射區域可讀可寫
MAP_SHARED, //映射區域的寫入數據會寫回到原來的文件
mem_fd,
BASE//被映射的硬件地址
);
close(mem_fd);
return base;
}
將/dev/mem/設備文件中GPIO的地址映射到用戶進程空間的代碼:
void *GPIO_MMAP::gpio_em335x_pin_config(unsigned int BASE)
{
int mem_fd;
void *base;
mem_fd = open('/dev/mem', O_RDWR|O_SYNC);
printf('mem_fd is %d\n', mem_fd);
/* mmap GPIO */
base = mmap(
NULL,//起始地址
GPIO_DEV_SIZE, //映射的文件內容的大小
PROT_READ|PROT_WRITE,//映射區域可讀可寫
MAP_SHARED,//映射區域的寫入數據會寫回到原來的文件
mem_fd,
BASE //被映射的硬件地址
);
close(mem_fd);
return base;
}
成功執行時,mmap()函數返回被映射區的指針。普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。只需要使用返回的地址指針在對應的寄存器的偏移地址賦值,就可以完成操作。在例程中已經將函數接口引出(詳細的代碼請參考例程):
ptr=Timer_Init();//初始化,將定時器地址映射到用戶進程
Timer_Start(ptr, GPIO0, 0xfffffffa); //啟動定時器,并設置時間和哪一位GPIO
定時器是從0計數到0xffffffff,需要實現定時功能,我們就要改變定時器的初值,上面的程序中0xfffffffa為定時器的初值,前面提到過由于EM335x定時器時鐘為24MHZ,所以定時器單位時間為1/24000000=41.6ns,假設程序訪問寄存器還需要花費時間T0,在計算初值的時候,就需要加上這一部分時間才能保證準確性,因此定時器取值的計算公式為:
T=0xffffffff-(目標延時/41.6ns)+T0
經過測試,執行一次程序訪問寄存器所需花費的時間大約為T0=800ns。舉個例子,比如目標延時為2μs,那么定時器初值為:0xffffffff-(2000/41.6)+800,也就是0xffffffe2,測試的時候帶入這個值,再進行微調,即可得到想要的結果。
使用英創工控主板運行例程測試,分別測試延時1μs,1.5μs,2μs,5μs,10μs時的精度,結果如下:
目標延時 | 定時器取值 | 實際延時 | |
Min | Max | ||
1us | 0xfffffffa | 1.14us | 1.20us |
1us的測試波形
目標延時 | 定時器取值 | 實際延時 | |
Min | Max | ||
1.5us | 0xffffffee | 1.46us | 1.52us |
1.5μs的測試波形
目標延時 | 定時器取值 | 實際延時 | |
Min | Max | ||
2us | 0xffffffe2 | 1.90us | 2.08us |
2μs的測試波形
目標延時 | 定時器取值 | 實際延時 | |
Min | Max | ||
5us | 0xffffff9a | 4.92us | 5.04us |
5μs的測試波形
目標延時 | 定時器取值 | 實際延時 | |
Min | Max | ||
10us | 0xffffff22 | 9.90us | 10.10us |
10μs的測試波形
可以看到,在1μs時,誤差范圍在±200ns左右,超過1μs,其余的取值,誤差都在±100ns以內,隨著延時的增加,精確度將越來越高,在10μs的時候,誤差已經非常小了。
通過以上方案實現了在用戶進程對精確延時的操作,詳細的操作代碼請參考例程。
關于這一方法在EM9x60系列工控主板上的實現可閱讀下文:英創嵌入式主板支持精確延時操作之二
注意事項:我們推薦客戶直接使用例程中引出的接口進行操作,不推薦客戶對硬件訪問這一部分代碼進行修改,以免在操作的時候出現無法預估的錯誤。
-
Linux
+關注
關注
87文章
11329瀏覽量
209967 -
嵌入式主板
+關注
關注
7文章
6086瀏覽量
35486
發布評論請先 登錄
相關推薦
飛騰助力首屆教育信息技術應用創新大賽圓滿落幕
有方科技參編的信息技術團體標準發布
龍芯中科助力2024首屆教育信息技術應用創新大賽成功舉辦
AWTK-WEB 快速入門(2) - JS 應用程序
![AWTK-WEB 快速入門(2) - JS <b class='flag-5'>應用程序</b>](https://file.elecfans.com/web2/M00/50/DA/pYYBAGLH6TyAB71EAAAPQ7KgtYA038.png)
AWTK-WEB 快速入門(1) - C 語言應用程序
![AWTK-WEB 快速入門(1) - C 語言<b class='flag-5'>應用程序</b>](https://file.elecfans.com/web2/M00/50/DA/pYYBAGLH6TyAB71EAAAPQ7KgtYA038.png)
中科創達榮獲2024年軟件和信息技術服務優秀企業
信創國產化背景下的工控主板發展現狀
Linux網絡協議棧的實現
![<b class='flag-5'>Linux</b>網絡協議棧的<b class='flag-5'>實現</b>](https://file1.elecfans.com/web2/M00/06/C6/wKgaombfpT-AeVQcAACjr17dpiQ190.png)
梯度科技入選2023年信息技術應用創新解決方案名單
實測14us,Linux-RT實時性能及開發案例分享—基于全志T507-H國產平臺
Linux是做什么用的?
應用程序中的服務器錯誤怎么解決?
龍芯中科三項信創方案入圍工信部2023年信息技術應用創新應用示范案例名單
![龍芯中科三項信<b class='flag-5'>創</b>方案入圍工信部2023年<b class='flag-5'>信息技術</b>應用創新應用示范案例名單](https://file1.elecfans.com/web2/M00/C3/19/wKgZomXpfwWAT16RAABpz-I0EpY201.png)
RX78M組 EtherCAT ETG.5003示例程序固件信息技術
![RX78M組 EtherCAT ETG.5003示例<b class='flag-5'>程序</b>固件<b class='flag-5'>信息技術</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
通過實時加速器技術實現實時應用程序的 Windows
![通過實時加速器<b class='flag-5'>技術</b><b class='flag-5'>實現</b>實時<b class='flag-5'>應用程序</b>的 Windows](https://file1.elecfans.com/web2/M00/BF/B6/wKgaomW3THSALNnxAABcfm8u1dw971.png)
評論