HEXIWEAR---FreeRTOS之任務

創建第一個任務

系統主函數如下:

void main()
{
  /** initialize the hardware */
  PE_low_level_init();

  /** disable write buffering end enable ARM exceptions */
  HEXIWEAR_EnableExceptions();

  /** initialize the startup task */
  HEXIWEAR_Init();

  /** start RTOS scheduler */
  HEXIWEAR_Start();

  while (1) {}
}

函數HEXIWEAR_Init初始化啓動任務HEXIWEAR_startup



任務創建完成後,靜態變量指針pxCurrentTCB(見《FreeRTOS高級篇2—FreeRTOS任務創建分析》第7節內容)指向優先級最高的就緒任務。但此時任務並不能運行,因爲接下來還有關鍵的一步:啓動FreeRTOS調度器


開啓內核運行,調度便由此開始

調度器是FreeRTOS操作系統的核心,主要負責任務切換,即找出最高優先級的就緒任務,並使之獲得CPU運行權。調度器並非自動運行的,需要人爲啓動它
API函數vTaskStartScheduler()用於啓動調度器,它會:

  • 創建一個空閒任務;
  • 初始化一些靜態變量;
  • 最主要的,它會初始化系統節拍定時器並設置好相應的中斷;
  • 然後啓動第一個任務。

http://blog.csdn.net/zhzht19861011/article/details/51331638


執行第一個任務,也就是啓動任務HEXIWEAR_startup

code/HEXIWEAR/src/HEXIWEAR_driver.c

HEXIWEAR_startup分析:

  1. output GPIO configuration
  2. input GPIO configuration
  3. intern flash initialization
  4. create basic tasks
    Notification_Init – HostInterface_Init(HostInterface_TxInit,HostInterface_RxInit) – sensor_Init – GuiDriver_Init
  5. check for settings in flash at startup
  6. CLOCK_SYS_Init POWER_SYS_Init
  7. turn on regular battery readings

搜索OSA_TaskCreate
這裏寫圖片描述

分析上圖可知,啓動任務HEXIWEAR_startup,開啓了
power_Task
sensor_GetData
HostInterface_TxTask
HostInterface_RxTask
watch_TimeUpdateTask
watch_GetPacketsTask
watch_GuiUpdateTask
七個任務,執行完成後自動Destroy自己。

這裏寫圖片描述
注:上圖註釋有誤,其實不止四個Tasks,加上Watch的三個,應該是七個。

watch_TimeUpdateTask
watch_GetPacketsTask
watch_GuiUpdateTask
這三個任務,HEXIWEAR_startup—>GuiDriver_Init—>進入開機畫面—>進入watch畫面,後創建的。

power_Task
功耗管理任務,主要是負責HEXIWEAR的自動睡眠

HostInterface_TxTask
HostInterface_RxTask
與K40 的MCU接口接受任務,主要負責處理接受到的數據包

sensor_GetData
Sensor數據讀取任務,負責循環讀取各個sensor的數據



從上圖中可以看出,除了上面的後四個任務,其餘任務基本上都和GUI的各個界面一一對應。那這些其餘的任務,肯定是跟着界面的跳動動態創建和銷燬。參考我博客的GUI 篇,你可以知道界面如何跳轉的。


開機默認界面Watch

也就是找watch_CreateTasks這個任務何時被創建。
HEXIWEAR_startup—>
GuiDriver_Init—>
GuiDriver_Navigation( GUI_NAVIGATION_SPLASH, NULL ); (直接開機畫面)
GuiDriver_Navigation( GUI_NAVIGATION_WATCH, NULL ); (進入Watch界面)
—>

gui_status_t GuiDriver_Navigation(guiNavigationDir_t navigationDir, void *param)
{
    const guiScreen_t* ptrNewScreen;
    oled_transition_t transition;
    void *destroyParam = NULL;
    void *initParam = NULL;
    void *createParam = NULL;

    const guiNavigation_t* navigation = &guiDriver_display.guiItem->navigation;

    switch(navigationDir)
    {
        /**
         * splash screen (啓動畫面)
         */
        case GUI_NAVIGATION_SPLASH:
        {
            ptrNewScreen = &splashScreen;
            transition = OLED_TRANSITION_NONE;
            break;
        }

        /**
         * goto watch directly(直接進入watch 界面)
         */

         case GUI_NAVIGATION_WATCH:
         {
             ptrNewScreen = &watchScreen;
             transition = OLED_TRANSITION_NONE;
             break;
         }

......
    // update the current gui item
    guiDriver_display.guiItem = (guiScreen_t*)ptrNewScreen;

    // starting action for the new screen
    if( NULL != ptrNewScreen->initFunction )
    {
        ptrNewScreen->initFunction(initParam);
    }

    while (1)
    {
        statusOLED = OLED_DrawScreen(
                                        guiDriver_display.image,
                                        xCrd,
                                        yCrd,
                                        width,
                                        height,
                                        transition
                                    );
        if ( OLED_STATUS_SUCCESS == statusOLED )
        {
            break;
        }
    }

    if(haptic_CurrentStateGet() == hapticState_enable)
    {
        //OSA_TimeDelay(50);
        haptic_MutexUnlock();
    }

    if( OLED_STATUS_SUCCESS == statusOLED )
    {
      // post-load action for the new screen (就在這裏創建了Watch的任務)
      if( NULL != ptrNewScreen->createTaskFunction )
      {
        ptrNewScreen->createTaskFunction(createParam);
      }

      return GUI_STATUS_SUCCESS;
    }

    else
    {
      return GUI_STATUS_ERROR;
    }
......

ptrNewScreen = &watchScreen;

// update the current gui item
guiDriver_display.guiItem = (guiScreen_t*)ptrNewScreen;

ptrNewScreen->initFunction(initParam);

ptrNewScreen->createTaskFunction(createParam);


如何快速的知道一個系統到底會創建多少個任務?

其實,每個任務的創建我們都會給其定義一個優先級,作爲參數傳進去。所以,只要找一下各個任務的的優先級的宏定義就好了。
HEXIWEAR的任務優先級定義在HEXIWEAR_info.h中。

/** tasks' priorities */
#define HEXIWEAR_STARTUP_PRIO ( 1 )
#define HEXIWEAR_KW40_INTF_TASK_OK_PRIO ( gHostInterfaceOkPriority_c )
#define HEXIWEAR_KW40_INTF_TASK_Tx_PRIO ( gHostInterfaceTxPriority_c )
#define HEXIWEAR_KW40_INTF_TASK_Rx_PRIO ( gHostInterfaceRxPriority_c )
#define HEXIWEAR_GUI_PRIO     ( 5 )
#define HEXIWEAR_APP_PRIO     ( 6 )
#define HEXIWEAR_SENSOR_PRIO  ( 7 )
#define HEXIWEAR_USB_TASK     ( USB_PRIO )

#define HEXIWEAR_TASK_SENSOR_TAG_PRIO     ( SENSOR_GET_DATA_PRIO )
#define HEXIWEAR_APP_WATCH_DATA_PRIO      ( WATCH_PRIO )
發佈了51 篇原創文章 · 獲贊 26 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章