1. 程式人生 > >CMSIS-RTOS 時間管理之時間延遲Time Delay

CMSIS-RTOS 時間管理之時間延遲Time Delay

生命周期 分享圖片 oar ros eid 返回 define over lan

時間管理 Time Management

此RTOS除了可以把你的應用代碼作為線程運行,它還可以提供一些時間服務功能,使用這些功能你就可以訪問RTOS的一些系統調用。

時間延遲Time Delay

在所有的時間服務功能中,最基本的一個就是延時函數。它可以在你的應用中提供非常簡單易用的延時功能。也許你會覺得CMSIS-RTOS已經占用了5k字節的代碼量,但是在非RTOS的應用中,我們也常會用到一些延時循環、簡單的調度循環等,這些循環功能同樣會占用一些字節,而我們的RTOS在這方面可能會占用更少的代碼量。

void osDelay(uint32_t millisec)

上面這個調用會導致當前線程進入等待延時狀態(WAIT_DELAY),延時時間由用戶指定。與此同時調度器將會執行下一個處於準備狀態(READY)的線程。

技術分享圖片

註:在線程的生命周期中,它會進入多種狀態。這裏一個處於運行狀態(RUN)的線程被osDelay阻塞,然後它就會進入等待狀態(WAIT)。當延時時間結束時,它就會進入準備狀態(READY),調度器就會把它置於運行狀態(RUN)。如果它的時間片結束了,它就會返回準備狀態(READY)。

當定時時間結束時,線程會離開等待延時狀態,進入READY狀態。當調度器把線程移入RUNNING狀態時,它就會繼續運行。如果線程在以後的執行過程中沒有任何阻塞調用,在它的時間片結束時就會被置於READY狀態,同時另外一個同優先級的線程就會進入運行狀態。

等待事件

除了單純的時間延遲,同樣可以使用事件等待讓線程暫停並進入等待狀態,當有另外一個RTOS事件出現時,就會觸發線程繼續運行。RTOS事件可以是一個信號,消息或者郵件。如果沒有事件出現,就可以osWait()這個API,它有一個毫秒級別的超時機制,可以允許線程的喚醒和繼續執行。

osStatus osWait(uint32_t millisec)//RTX不支持此函數

當設定的時間結束,線程就會由WAIT狀態進入到READY狀態,隨後被調度器置於RUN狀態。osWait在CMSIS RTOS裏面是一個可選API。如果你打算使用這個函數,必須先確定你使用的RTOS是支持的。需要註意的是,CMSIS RTOS目前封裝的keil RTX 是不支持這個API的。

通過STM32的simulaiton,我發現他的執行順序是這樣的:首先進入main函數,一系列初始化後,完成osKernelStart (); 後,馬上進入led_Thread2,執行到osSemaphoreRelease(sem1);,轉到led_Thread1,LED_On(1); osDelay(500);還沒開始delay就又轉到led_Thread2。恰好線程2又是delay,程序中沒什麽可執行,索性線程1和線程2就delay了500ms,然後又回到線程1執行led關,等待semaphore。

/*----------------------------------------------------------------------------
    
    Designers Guide to the Cortex-M Family
    Semaphore Example
*----------------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "cmsis_os.h"
 
#include "Board_LED.h"
 
void led_Thread1 (void const *argument);
void led_Thread2 (void const *argument);
osThreadDef(led_Thread1, osPriorityAboveNormal, 1, 0);            //note the raised priority for led_thread 1
osThreadDef(led_Thread2, osPriorityNormal, 1, 0);
 
osThreadId T_ledOn;
osThreadId T_ledOff;
/*----------------------------------------------------------------------------
  Define the semaphore
 *---------------------------------------------------------------------------*/    
osSemaphoreId sem1;                                    
osSemaphoreDef(sem1);
/*----------------------------------------------------------------------------
  Wait to acquire a semaphore token from sem1 then flash LED 1
 *---------------------------------------------------------------------------*/
void led_Thread1 (void const *argument) 
{
    for (;;) 
    {
        osSemaphoreWait(sem1, osWaitForever);
        LED_On(1);                          
        osDelay(500);
        LED_Off(1);
    }
}
/*----------------------------------------------------------------------------
  Flash LED 2 and ‘release‘ a semaphore token to sem1
 *---------------------------------------------------------------------------*/
void led_Thread2 (void const *argument) 
{
    for (;;) 
    {
        LED_On(2);        
        osSemaphoreRelease(sem1);
        osDelay(500);
        LED_Off(2);
        osDelay(500);
    }
}
 
/*----------------------------------------------------------------------------
  Initilise the LED‘s, Create the semaphore and start the threads
 *---------------------------------------------------------------------------*/
int main (void) 
{
    osKernelInitialize ();                    // initialize CMSIS-RTOS
 
    LED_Initialize ();
    sem1 = osSemaphoreCreate(osSemaphore(sem1), 0);    
    T_ledOff = osThreadCreate(osThread(led_Thread2), NULL);
    T_ledOn = osThreadCreate(osThread(led_Thread1), NULL);
    
    osKernelStart ();                         // start thread execution 
}

CMSIS-RTOS 時間管理之時間延遲Time Delay