精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何將ThreadX移植到STM32平臺

CHANBAEK ? 來源:木南創智 ? 作者:尹家軍 ? 2022-12-14 14:38 ? 次閱讀

現在一些小型系統中也往往有多任務處理的需求,這就為實時操作系統提供了用武之地。事實上國內外各種各樣的RTOS有很多,而且基本都在走開源的路線,ThreadX也不例外,在這一篇中我們就來學習ThreadX初步應用并將其移植到STM32平臺中。

1 、前期準備

在開始將ThreadX一直到STM32平臺之間我們需要做一些前期準備。首先我們需要準備一個硬件平臺,這次我們采用STM32F407IG控制單元來作為目標平臺。其次我們需要準備一個該硬件平臺下可以正常運行的裸機項目。這兩點其實我們都已經具備了。

最主要的我們需要獲得ThreadX的源碼,這是我們移植它的基礎。ThreadX的源碼已經開源到Github上,其地址為:https://github.com/azure-rtos/threadx,直接下載源碼就可以了。目前發布的最新版本是6.0.1,在我們的移植中我們使用6.0.0的版本來實現。

2 、系統移植

首先我們先來了解一下獲得的ThreadX源碼。解壓下載下來的壓縮包,其包含有以下文件及文件夾,我們先來具體看一看都有哪些文件,如下圖

上圖中一目了然,無需做太多解釋。我們需要用到的文件主要存放在common文件夾和ports文件夾。其中common文件夾存放的是內核源碼,ports文件夾存放的是不同平臺的接口文件。我們的硬件采用的是STM32F407IG,軟件開發環境用的是IAR EWARM,所以我們選擇ports文件夾下cortex_m4下的IAR文件夾中的接口文件。

接下來我們需要在項目中添加ThreadX的相關源碼文件。所以我們在項目下添加ThreadX組、并在ThreadX組下添加Source和Ports兩個組用于添加文件。并將common文件夾和ports文件夾中的文件添加到對應的分組。如下所示:

然后要在項目屬性中為編譯器指定頭文件的引用路徑,主要是內核函數的頭文件以及接口文件的頭文件兩個路徑,在我們這個項目中配置如下:

PROJ_DIR....\\ThreadX\\common\\inc

PROJ_DIR....\\ThreadX\\ports\\cortex_m4\\iar\\inc

事實上到這了,我們已經完成了對ThreadX內核文件以及接口文件的移植,但現在ThreadX不會運行,我們還需要做一些工作。我們要將內核與主函數聯系起來,首先我們要在調用內核的地方添加頭文件“tx_api.h”,我們這里將其添加到主函數文件中。

然后有兩個函數我們需要處理,分別是:tx_kernel_enter和tx_application_define,這兩個函數在頭文件“tx_api.h”中被聲明。tx_kernel_enter實際是一個宏,真正的函數是_tx_initialize_kernel_enter,用于啟動內核,這個函數需要我們在主函數中調用。而tx_application_define函數只有聲明沒有實現,在_tx_initialize_kernel_enter函數中被調用,用于任務的創建。這個函數的實現是我們的主要工作,后續將詳細說明。

3 、任務實現

我們已經說過了tx_application_define用于任務的創建,它的具體內容需要我們來實現,接下來我們就來實現tx_application_define這個函數。

我們先來規劃一下我們將要實現的內容。我們計劃實現5個任務,包括啟動任務、紅燈閃爍任務、綠燈閃爍任務、空閑任務及統計任務。其中為啟動任務用于初始化一些配置并執行一些如系統心跳、看門狗之類的工作;用于紅燈閃爍任務和綠燈閃爍任務用于實現我們要操作的指示燈控制;空閑任務在其他任務不運行時其運行,優先級最低。統計任務再次我們實現系統空閑率的統計。接下來我們就按此思路來實現之。

/*tx_application_define函數實現*/
void tx_application_define(void *first_unused_memory)
{
 /**************創建啟動任務*********************/
 tx_thread_create(&AppTaskStartTCB,              /* 任務控制塊地址 */  
               "App Task Start",             /* 任務名 */
               AppTaskStart,                  /* 啟動任務函數地址 */
               0,                             /* 傳遞給任務的參數 */
               &AppTaskStartStk[0],           /* 堆棧基地址 */
               APP_CFG_TASK_START_STK_SIZE,  /* 堆棧空間大小 */ 
               APP_CFG_TASK_START_PRIO,      /* 任務優先級*/
               APP_CFG_TASK_START_PRIO,      /* 任務搶占閥值 */
               TX_NO_TIME_SLICE,              /* 不開啟時間片 */
               TX_AUTO_START);                /* 創建后立即啟動 */
 
 /**************創建紅燈閃爍任務*********************/
 tx_thread_create(&AppTaskRedLedTCB,           /* 任務控制塊地址 */
               "App Msp Pro",                /* 任務名 */
               AppTaskRedLED,              /* 啟動任務函數地址 */
               0,                           /* 傳遞給任務的參數 */
               &AppTaskMsgProStk[0],       /* 堆棧基地址 */
               APP_CFG_TASK_RedLED_STK_SIZE,  /* 堆棧空間大小 */
               APP_CFG_TASK_REDLED_PRIO,      /* 任務優先級*/
               APP_CFG_TASK_REDLED_PRIO,     /* 任務搶占閥值 */
               TX_NO_TIME_SLICE,               /*不開啟時間片 */
               TX_AUTO_START);                /* 創建后立即啟動 */
 
 /**************創建綠燈閃爍任務*********************/
 tx_thread_create(&AppTaskGreenLEDTCB,        /* 任務控制塊地址 */
               "App Task UserIF",             /* 任務名 */
               AppTaskGreenLED,             /* 啟動任務函數地址 */
               0,                         /* 傳遞給任務的參數 */
               &AppTaskUserIFStk[0],        /* 堆棧基地址 */
               APP_CFG_TASK_GreenLED_STK_SIZE, /* 堆棧空間大小 */
               APP_CFG_TASK_GREENLED_PRIO,     /* 任務優先級*/
               APP_CFG_TASK_GREENLED_PRIO,   /* 任務搶占閥值 */
               TX_NO_TIME_SLICE,               /*不開啟時間片 */
               TX_AUTO_START);             /* 創建后立即啟動 */
 
 /**************創建統計任務*********************/
 tx_thread_create(&AppTaskStatTCB,               /* 任務控制塊地址 */   
                  "App Task STAT",             /* 任務名 */
                  AppTaskStat,                  /* 啟動任務函數地址 */
                  0,                           /* 傳遞給任務的參數 */
                  &AppTaskStatStk[0],          /* 堆棧基地址 */
                  APP_CFG_TASK_STAT_STK_SIZE,  /* 堆棧空間大小 */ 
                  APP_CFG_TASK_STAT_PRIO,      /* 任務優先級*/
                  APP_CFG_TASK_STAT_PRIO,     /* 任務搶占閥值 */
                  TX_NO_TIME_SLICE,            /* 不開啟時間片 */
                  TX_AUTO_START);             /* 創建后立即啟動 */
 
 /**************創建空閑任務*********************/
 tx_thread_create(&AppTaskIdleTCB,               /* 任務控制塊地址 */   
                  "App Task IDLE",             /* 任務名 */
                  AppTaskIDLE,               /* 啟動任務函數地址 */
                  0,                          /* 傳遞給任務的參數 */
                  &AppTaskIdleStk[0],         /* 堆棧基地址 */
                  APP_CFG_TASK_IDLE_STK_SIZE,  /* 堆棧空間大小 */
                  APP_CFG_TASK_IDLE_PRIO,       /* 任務優先級*/
                  APP_CFG_TASK_IDLE_PRIO,     /* 任務搶占閥值 */
                  TX_NO_TIME_SLICE,           /* 不開啟時間片 */
                  TX_AUTO_START);            /* 創建后立即啟動 */
}

我們實現了tx_application_define函數,在其中創建了任務,理所當然我們還需要實現相應的任務函數。

/*系統啟動任務*/
static void  AppTaskStart (ULONGthread_input)
{
 (void)thread_input;
 
  /* 任務統計前先掛起其它任務 */
 tx_thread_suspend(&AppTaskRedLedTCB);
 tx_thread_suspend(&AppTaskGreenLEDTCB);
 
 OSStatInit();
 
  /* 任務統計完畢后,恢復其它任務 */      
 tx_thread_resume(&AppTaskRedLedTCB);
 tx_thread_resume(&AppTaskGreenLEDTCB);
 
  /* 內核開啟后,恢復HAL里的時間基準 */
 HAL_ResumeTick();
 
  while (1)
  { 
   sysHeartBeat++;
   tx_thread_sleep(1000);
  }
}
 
/*紅燈閃爍控制*/
static void AppTaskRedLED(ULONG thread_input)
{
 (void)thread_input;
 
  while(1)
  {
   HAL_GPIO_TogglePin(GPIOI,GPIO_PIN_8);
   tx_thread_sleep(500);
  }  
}
 
/*綠燈閃爍控制*/
static void AppTaskGreenLED(ULONG thread_input)
{
 (void)thread_input;
 
  while(1)
  {       
   
   HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
   tx_thread_sleep(2000);
  }
}
 
/*統計任務函數*/
static void AppTaskStat(ULONG thread_input)
{
 (void)thread_input;
 
  while(OSStatRdy == false)
  {
   tx_thread_sleep(200);     /* 等待統計任務就緒 */
  }
 
 OSIdleCtrMax /= 100uL;
  if(OSIdleCtrMax == 0uL)
  {
   OSCPUUsage = 0u;
  }
 
  OSIdleCtr= OSIdleCtrMax * 100uL;  /* 設置初始CPU利用率 0% */
 
  for (;;)
  {
   OSIdleCtrRun = OSIdleCtr;    /* 獲得100ms內空閑計數 */
   OSIdleCtr    = 0uL;          /* 復位空閑計數 */
   OSCPUUsage   = (100uL -(float)OSIdleCtrRun / OSIdleCtrMax);
   tx_thread_sleep(100);        /* 每100ms統計一次 */
  }
}
 
/*空閑任務函數*/
static void AppTaskIDLE(ULONG thread_input)
{    
 TX_INTERRUPT_SAVE_AREA
   
   (void)thread_input;
 
  while(1)
  {
   TX_DISABLE
     OSIdleCtr++;
   TX_RESTORE
  }                                                                                                                
}

實現了上面這些函數后,我們一個基于ThreadX的最基礎的系統就建立起來了,對于更復雜的系統也沒有問題,其實現的基本思路也是與此相同的。

4 、最后測試

完成前述的全部內容后,我們編譯下載到目標平臺,兩個指示燈按照我們的預期正常閃爍,說明的們的移植是成功的。

事實上ThreadX的移植相對簡單,接下來我們總結一下移植ThreadX的步驟。我們覺得大體可分為如下過程進行:

首先,將ThreadX的文件及引用,包括內核文件和接口文件,添加到我們的項目中,并做好相關的項目配置。

其次,將 tx_api.h 文件包含于所有使用 ThreadX 服務和數據結構的應用程序。如前面我們將其包含在主函數文件中。

然后,在主函數中調用 tx_kernel_enter函數以達到啟動ThreadX內核的目的。如果沒有經過ThreadX特定的初始化,可以通過增加其優先權而進入到內核中。

再其次,建立 tx_application_define 函數。這是初始系統資源創建的地方。這些資源包括線程、隊列、內存緩沖池、事件標志組以及信號

最后,編譯下載到目標平臺測試。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • threadx
    +關注

    關注

    0

    文章

    15

    瀏覽量

    13820
  • STM32
    +關注

    關注

    2266

    文章

    10876

    瀏覽量

    354922
  • 移植
    +關注

    關注

    1

    文章

    377

    瀏覽量

    28111
收藏 人收藏

    評論

    相關推薦

    如何將ThreadX移植STM32H7平臺

    前面我們ThreadX成功移植到了STM32F4平臺,但這只是我們的部分應用。我們希望
    的頭像 發表于 12-14 14:40 ?1998次閱讀
    <b class='flag-5'>如何將</b><b class='flag-5'>ThreadX</b><b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>STM32</b>H7<b class='flag-5'>平臺</b>

    如何將FreeRTOS移植STM32F411平臺

    最近打算做一個智能家居嵌入式開發平臺,選用ST的STM32F411加Qualcomm的QCA4002. 由于QCA4002功能比較復雜,打算用FreeRTOS來驅動它。 不知道有高手做過FreeRTOS
    發表于 05-17 06:05

    如何將coremark程序移植STM32

    本帖最后由 lee_st 于 2018-1-24 17:42 編輯 如何將coremark程序移植STM32
    發表于 01-24 17:40

    如何將ffmpeg移植ARM平臺

    ffmpeg移植ARM平臺。開發板使用迅為i.MX6ULL終結者和USB免驅攝像頭,交叉編譯工具為arm-linux-gnueabihf,yocto Qt5文件系統。
    發表于 12-28 06:24

    如何將Linux操作系統移植目標平臺上?

    如何將Linux操作系統移植目標平臺上?Linux交叉編譯環境的建立及內核配置和編譯Linux移植中實際指令集小于標準MIPS指令集的問題
    發表于 04-22 07:04

    ThreadX GUIX是如何移植STM32H7

    第10章 ThreadX GUIX移植STM32H7(GCC)本章節將為大家介紹ThreadX GUIX的GCC方式
    發表于 08-06 08:29

    如何將freemodbus移植stm32平臺

    modbus是一個非常好的串口協議(當然也能用在網口上),它簡潔、規范、強大。可以滿足大部分的工業、嵌入式需求。這里詳細說下如何將freemodbus移植stm32
    發表于 08-16 06:59

    學習ThreadX初步應用并將其移植STM32平臺

    ThreadX初步應用并將其移植STM32平臺中。1、前期準備在開始
    發表于 08-24 06:05

    如何將STM32移植GD32芯片上

    GD32芯片內部flash同STM32有哪些區別?如何將STM32移植GD32芯片上?
    發表于 09-23 09:31

    怎樣ThreadX GUIX移植STM32F429(MDK AC6)上去

    怎樣ThreadX GUIX移植STM32F429(MDK AC6)上去?有哪些注意事項?
    發表于 11-08 07:56

    怎樣ThreadX GUIX移植STM32F429(MDK AC5)上去呢

    怎樣ThreadX GUIX移植STM32F429(MDK AC5)上去呢?移植過程是怎樣的
    發表于 11-08 08:27

    如何將FreeModbus移植STM32平臺上去

    modbus是什么?如何將FreeModbus移植STM32平臺上?
    發表于 11-17 07:44

    如何將uCOS-III實時操作系統移植目標平臺上并運行?

    如何將uCOS-III實時操作系統移植目標平臺上并運行?
    發表于 11-29 06:11

    GD32移植STM32開發平臺

    GD32移植STM32開發平臺
    發表于 12-02 14:51 ?28次下載
    GD32<b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>STM32</b>開發<b class='flag-5'>平臺</b>

    STM32CubeIDE 中針對 STM32F407 移植 ThreadX

    STM32CubeIDE 中針對 STM32F407 移植 ThreadX,不依賴盜版破解的Keil MDK、IAR等軟件。
    發表于 12-04 13:36 ?17次下載
    在 <b class='flag-5'>STM32</b>CubeIDE 中針對 <b class='flag-5'>STM32</b>F407 <b class='flag-5'>移植</b> <b class='flag-5'>ThreadX</b>