姓名:劉偉 學號:17103223402
【嵌牛導讀】
本文介紹了測量程序運行時間的一種方法
【嵌牛鼻子】程序運行時間的測量
【嵌牛提問】利用該原理還能進行什么工作?
【嵌牛正文】
ucos-iii 源碼中,有一個功能是測量關中斷時間的功能,使用的是STM32的時間戳,即記錄程序運行的某個時刻,如果記錄下程序前后的兩個時刻點,即可以算出這段程序的運行時間。
ucos 時間戳使用的是 Cortex-M內核中的一個時鐘計數器來實現的,內核時鐘跳動一次,該計數器就加1,精度非常高,決定于內核的頻率是多少,如果是F103系列,內核時鐘是72M,那精度就是1/72M = 14ns,而程序的運行時間都是微秒級別的,所以14ns的精度是遠遠夠的。
但是有關內核寄存器的描述的資料非常少,還好在arm的官網找到一個,里面有這些內核寄存器的詳細描述,其中時間戳相關的寄存器在第10章和11章有詳細的描述。
下面的代碼是我從ucos-iii里面抽離出來的ucos 時間戳相關的功能代碼,測試完全可用,這部分代碼可以用來測量程序的運行時間,也可以用來實現us級別的延時。
這個文件是Cortex-M3內核的技術參考手冊,里面有內核寄存器的全部描述。
/*
************************************************************************************************************************
*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 時間戳相關寄存器定義
************************************************************************************************************************
*/
/*
在Cortex-M3里面有一個外設叫DWT(Data Watchpoint and Trace),該外設有一個32位的寄存器叫CYCCNT,它是一個向上的
計數器,記錄的是內核時鐘運行的個數,最長能記錄的時間為:60s=2的32次方/72000000(假設內核頻率為72M,內核跳一次的時間大概為1/72M=14ns)
當CYCCNT溢出之后,會清0重新開始向上計數。
使能CYCCNT計數的操作步驟:
1、先使能DWT外設,這個由另外內核調試寄存器DEMCR的位24控制,寫1使能
2、使能CYCCNT寄存器之前,先清0
3、使能CYCCNT寄存器,這個由DWT_CTRL(代碼上宏定義為DWT_CR)的位0控制,寫1使能
*/
#define? DWT_CR? ? ? *(uint32_t *)0xE0001000
#define? DWT_CYCCNT? *(uint32_t *)0xE0001004
#define? DEM_CR? ? ? *(uint32_t *)0xE000EDFC
#define? DEM_CR_TRCENA? ? ? ? ? ? ? ? ? (1 << 24)
#define? DWT_CR_CYCCNTENA? ? ? ? ? ? ? ? (1 <<? 0)
/* 初始化時間戳 */
void CPU_TS_TmrInit(void)
{
? ? /* 使能DWT外設 */
? ? ? ? DEM_CR |= (uint32_t)DEM_CR_TRCENA;? ? ? ? ? ? ? ?
? ? ? ? /* DWT CYCCNT寄存器計數清0 */
? ? ? ? DWT_CYCCNT = (uint32_t)0u;
? ? ? ?
? ? ? ? /* 使能Cortex-M3 DWT CYCCNT寄存器 */
? ? DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}
uint32_t OS_TS_GET(void)
{? ? ? ?
? ? ? ? return ((uint32_t)DWT_CYCCNT);
}
/* CPU相關初始化 */
void? CPU_Init (void)
{
? ? ? ? /* 初始化時間戳 */
? ? ? ? CPU_TS_TmrInit();
}
?
這里面使用的是Cortex-M 內核里面的一個 內核時鐘計數器,跟使用TIM,SysTick這些外設不一樣,這個內核時鐘計數器精度更高,它存在于內核的DWT這個外設中。
DWT的縮寫是:Data Watchpoint and Trace,是不是學了這么久STM32,這個外設根本沒有聽過?
要想使用DWT里面的CYCCNT,還要再使用一個DEMCR這個內核寄存器,DEM是不是也沒聽說過?