void HAL_Delay(__IO uint32_t Delay) 函式溢位的問題
阿新 • • 發佈:2018-12-31
計數器的更新
計數器uwTick
是在每次Systick中斷中加一更新,此處配置Systick中斷為每1ms中斷一次。uwTick
為uint32_t
型別,那麼uwTick
的最長計時為0xFFFFFFFF毫秒(約為49.7天),也就是說 uwTick 會在系統持續執行49天后溢位清零。
函式的實現
void HAL_Delay(__IO uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
while((HAL_GetTick() - tickstart) < Delay)
{
}
}
函式中計時的實現是通過迴圈讀取uwTick 變數,比較差值來實現延遲,那麼當計數器溢位時,此函式是否繼續有效呢?
無符號整數的特性
我們知道:1 - (-1) = 2
,
將其轉換為32位補碼形式為:0x00000001 - 0xFFFFFFFF = 0x00000002
,
當HAL_GetTick()
為0xFFFFFFFF
時,正好將tickstart
賦值。而當計數器溢位重新開始比較的時候,可以發現,上面的比較方式任然成立
此處需要注意HAL_GetTick()
返回的無符號型別要與當前CPU的位數一致。
uint16_t a = 0xffff
,在32位系統中參與運算,賦值到32位的暫存器變數中變為0x0000FFFF,運算的結果顯然不正確。
linux 的解決方法
在linux中,jiffies溢位是通過time_after和time_before巨集來解決
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(b) - (long)(a) < 0))
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long , b) && \
((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b) time_after_eq(b,a)
#define time_in_range(a,b,c) \
(time_after_eq(a,b) && \
time_before_eq(a,c))
/* Same as above, but does so with platform independent 64bit types.
* These must be used when utilizing jiffies_64 (i.e. return value of
* get_jiffies_64() */
#define time_after64(a,b) \
(typecheck(__u64, a) && \
typecheck(__u64, b) && \
((__s64)(b) - (__s64)(a) < 0))
#define time_before64(a,b) time_after64(b,a)
#define time_after_eq64(a,b) \
(typecheck(__u64, a) && \
typecheck(__u64, b) && \
((__s64)(a) - (__s64)(b) >= 0))
#define time_before_eq64(a,b) time_after_eq64(b,a)
其中需要保證a
和b
均為無符號整數