23、STM 32上のシステムの正確な遅延とmicro時間関数の取得の実現(FreeRTOSでも移植可能)

2535 ワード

プログラミングでは、正確な遅延が必要になることがよくあります.あるいは、コードの実行時間を正確に統計する必要があります.あるいは、コードが正確に保証される必要があります.
呼び出しの頻度.例えば、ある関数の実行時間を統計してオーバーヘッドを判断する必要があり、例えば、フライング制御では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などの関数はそのままでよい