2012-11-15 19 views
9

我們有一個使用3.2內核的ARM9 - 一切似乎都很好。最近我被要求添加一些代碼在啓動時在一些GPIO線上添加50ms脈衝。脈衝碼很好;正如預期的那樣,我可以看到這些線條不斷上升。不按我期望的方式工作的是udelay()函數。閱讀文檔使我認爲單位是微秒,但在邏輯分析儀中測得的結果太短。所以我最終添加了這個代碼來獲得50ms。如何證明__udelay()在我的ARM嵌入式系統上正常工作?

// wait 50ms to be sure PCIE reset takes 
for (i=0;i<6100;i++) // measured on logic analyzer - seems wrong to me!! 
{ 
    __udelay(2000); // 2000 is max 
} 

我不喜歡它,但它工作正常。在udelay代碼中有一些奇怪的常量和指令。有人能告訴我這是如何工作的嗎?這個代碼在所有的時鐘初始化之後被調用,所以其他的一切似乎都沒問題。

回答

4

根據萊納斯在this thread

如果是約1%的折扣,這一切都很好。如果有人選擇延遲值 ,它對延遲中的小錯誤非常敏感,並且他們注意到 - 或者甚至注意到了5% - 然後他們也選擇了延遲時間過短的 。

udelay()從來沒有真正意味着某種精度 儀器。尤其是在CPU運行頻率不同的情況下,我們歷史上有一些相當大的波動。傳統的 繁忙循環最終不僅受到中斷的影響,而且還受到緩存對齊(我們曾經將其內聯)等事情的影響,然後後來基於TSC的一個顯然依賴於TSC的穩定性(它們是 均不穩定暫時沒有)。

所以在歷史上,我們已經看到udelay的()是真的關閉(即50折 等),我就不會擔心在1%範圍內的事情。

萊納斯

所以它不會是完美的。它會關閉。多少依賴於很多因素。不要使用for循環,而應考慮使用mdelay。這可能會更精確一點。從O'Reilly Linux Device Drivers書:

udelay的調用只能調用對短時間流失,因爲 的loops_per_second精度只有8位,並計算長時間的延遲時明顯 誤差累積。即使最大允許延遲時間接近一秒(因爲計算 溢出了較長的延遲),建議的最大值udelay是 1000微秒(一毫秒)。功能mdelay有助於 延遲時間必須長於1毫秒的情況。

同樣重要的是要記住,udelay的是忙等待功能 (因此mdelay過);其他任務在 失效時間內無法運行。因此,您必須非常小心,尤其是mdelay和 應避免使用它,除非沒有其他方法可以實現您的目標。

目前,支持超過幾微秒的延遲和比計時器計時器更短的延遲是非常低效的。這通常不是 問題,因爲延遲需要足夠長的時間才能被人類或硬件發現。對於與人相關的時間間隔,百分之一秒是合適的精度,而對於硬件活動而言,一毫秒是足夠長的延遲。

具體行「udelay的建議的最大值爲1000毫秒(一毫秒)」我伸出因爲你指出2000是最大。從this document上插入延遲:

mdelay是圍繞udelay的宏觀包裝,傳遞大爭論時udelay的

所以這是可能的,你正在運行到溢出錯誤來解釋可能 溢出。雖然我通常不會認爲2000年是一個「大論點」。但是如果你需要真正的準確性,你需要像你一樣處理偏移量,推出你自己的或者使用不同的內核。有關如何使用匯編器或使用硬實時內核來編譯自己的延遲函數的信息,請參見High-resolution timing上的這篇文章。

參見:Linux Kernel: udelay() returns too early?

+0

在現代內核hrtimer_nanosleep應該足夠輕便。 – cdleonard

+0

@cdleonard'''nanosleep'可能會在繁忙的循環中使用'udelay',具體取決於調度器模式和延遲長度。請參閱我在[高分辨率時機]上提供的鏈接(http://tldp.org/HOWTO/IO-Port-Programming-4.html)。 –

+0

@ embedded.kyle - 非常感謝您的回答,但我不滿意。 mdelay只是在for循環中調用udelay,所以沒有任何幫助。而且udelay的數量已經不在1%或者50%的範圍之內了 - 如果一切正常(每個循環2ms),我預計會有25的循環計數器。如果它是50%折扣 - 比我的循環將是50.但6100?這太遙遠了,它讓我困惑不已。再次感謝,但我仍然在追求:) – Jeff

相關問題