23、STM 32上のシステムの正確な遅延とmicro時間関数の取得の実現(FreeRTOSでも移植可能)
2535 ワード
プログラミングでは、正確な遅延が必要になることがよくあります.あるいは、コードの実行時間を正確に統計する必要があります.あるいは、コードが正確に保証される必要があります.
呼び出しの頻度.例えば、ある関数の実行時間を統計してオーバーヘッドを判断する必要があり、例えば、フライング制御では2 mおきに1を呼び出すことを正確に保証する必要がある.
二次読取センサの関数は,タイマを用いて実現できる.STM 32プラットフォームでは、systickを活用して実現できます.
使用方法:
main関数でsystick_を呼び出すInit()を初期化する
呼び出しdelay_us関数はus級遅延を実現する
呼び出しdelay_ms関数によるmsレベル遅延の実現
計算コードの実行時間:
last = micro();
... /* 統計が必要なコード/関数*/
cur = micro();
usetime = cur - last;
FreeRTOSでの移植
FreeRTOSではsystickがシステムによって占有されるため,この方式を直接使用して実現することはできず,少し修正する必要がある.
A、元のsysTickMillis変数をグローバル変数として宣言し、他の場所で呼び出すことができるようにする
B、systick_check_underflow();関数は外部として宣言され、port.cで呼び出すことができます.
C、元のSystick割込み処理関数を削除し、その関数の処理コードをport.cのxPortSysTickHandlerに追加する
関数から削除
systick_check_underflow();
sysTickMillis++;
D、systick_の削除init関数
E、Microsoftおよびdelay_msなどの関数はそのままでよい
呼び出しの頻度.例えば、ある関数の実行時間を統計してオーバーヘッドを判断する必要があり、例えば、フライング制御では2 mおきに1を呼び出すことを正確に保証する必要がある.
二次読取センサの関数は,タイマを用いて実現できる.STM 32プラットフォームでは、systickを活用して実現できます.
static volatile uint32_t sysTickMillis = 0;
static const uint32_t sysTickPerUs = 72; /* - 72MHz */
/* */
static int systick_check_underflow(void)
{
return SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk;
}
/* systick */
void SysTick_Handler(void)
{
__disable_irq();
systick_check_underflow();
sysTickMillis++;
__enable_irq();
}
/* systick */
void systick_init(void)
{
sysTickPerUs = SystemCoreClock / 1000000;
SysTick_Config(SystemCoreClock / 1000);
}
/* micro */
uint32_t micros(void)
{
uint32_t cycle, timeMs;
do
{
timeMs = sysTickMillis;
cycle = SysTick->VAL;
__ASM volatile("nop");
}while (timeMs != sysTickMillis);
if (systick_check_underflow())
{
timeMs++;
cycle = SysTick->VAL;
}
return (timeMs * 1000) + (SysTick->LOAD + 1 - cycle) / sysTickPerUs;
}
uint32_t millis(void)
{
return sysTickMillis;
}
/* */
void delay_us(u32 us)
{
staticint currentTime, lastTime = 0;
lastTime= micros();
while(1)
{
currentTime= micros();
if ( currentTime - lastTime >= us )
{
break;
}
}
}
/* */
void delay_ms(u32 ms)
{
staticint currentTime, lastTime = 0;
lastTime= millis();
while(1)
{
currentTime= millis();
if( currentTime - lastTime >= ms )
{
break;
}
}
}
使用方法:
main関数でsystick_を呼び出すInit()を初期化する
呼び出しdelay_us関数はus級遅延を実現する
呼び出しdelay_ms関数によるmsレベル遅延の実現
計算コードの実行時間:
last = micro();
... /* 統計が必要なコード/関数*/
cur = micro();
usetime = cur - last;
FreeRTOSでの移植
FreeRTOSではsystickがシステムによって占有されるため,この方式を直接使用して実現することはできず,少し修正する必要がある.
A、元のsysTickMillis変数をグローバル変数として宣言し、他の場所で呼び出すことができるようにする
B、systick_check_underflow();関数は外部として宣言され、port.cで呼び出すことができます.
C、元のSystick割込み処理関数を削除し、その関数の処理コードをport.cのxPortSysTickHandlerに追加する
関数から削除
systick_check_underflow();
sysTickMillis++;
D、systick_の削除init関数
E、Microsoftおよびdelay_msなどの関数はそのままでよい