使用STM32CubeMX生成ThreadX實時作業系統工程模板

chengyufeng發表於2023-05-12

部落格主頁:連結。轉載請註明出處!

由於需要在stm32上使用USB Host CDC-ECM,連線EC20傳送資料到伺服器,接觸到了ThreadX實時作業系統。

在調研過程中,發現stm32官方USB庫內只有Device ECM類,無法作為host連線網路卡;

電腦上經常使用的tinyusb,對stm裝置的device支援較差;

此外還有lrndis、TeenyUSB,提供了host ecm類的支援,但使用並不方便,且有的已很少有人維護(小開源專案難免如此)。

最終決定使用微軟的Azure RTOS ThreadX全家桶,利用NetX Duo+USBX實現對ECM網路卡的支援。ThreadX的效能和儲存佔用都最佳化得很好,且中介軟體齊全,免去了很多自己配置的麻煩。目前ThreadX已經開源,並加入CubeMX,直接使用視覺化介面就可完成配置,解決一些小坑之後十分方便,遂寫此隨筆以作記錄、分享。

本文使用的工具包括CubeMX、MDK,內容假設閱讀者已基本掌握這兩個軟體的使用。在學習過程中,參考了另兩篇教程,附上鍊接:

https://juejin.cn/post/7099829592713592840

https://blog.csdn.net/wallace89/article/details/114941859

一、CubeMX生成模板

1. 配置RCC、時鐘、SYS、GPIO

RCC設定外部晶振,這個根據板子情況調整,我這裡高低速都是外部晶振

使用STM32CubeMX生成ThreadX實時作業系統工程模板

時鐘配置,和平時一樣,可以輸入HCLK讓cubemx自動設定,也可手動調,48MHz時鐘一定要有

使用STM32CubeMX生成ThreadX實時作業系統工程模板

系統設定內,debug根據板子設定,我使用的是jlink的SW除錯口,所以選擇serial wire。時基源選擇任意一個沒用到的TIM。

使用STM32CubeMX生成ThreadX實時作業系統工程模板

最後配置板子上三個LED燈的GPIO,根據自己板子上情況修改。

使用STM32CubeMX生成ThreadX實時作業系統工程模板

2. 配置串列埠和USB

根據板子,配置串列埠用於除錯

使用STM32CubeMX生成ThreadX實時作業系統工程模板

配置USB FS,用於和EC20通訊

使用STM32CubeMX生成ThreadX實時作業系統工程模板

3. 重頭戲:配置Azure RTOS

首先安裝所需軟體包

使用STM32CubeMX生成ThreadX實時作業系統工程模板

我用的MCU是stm32f4系列,因此找到AZRTOS-F4。勾選Core以及需要使用的USBX-UX Host Class CDC ECM,會提示所選的包還有依賴項沒選上,根據提示補齊。如果不需要USB和網路,只選擇threadx core就行.

使用STM32CubeMX生成ThreadX實時作業系統工程模板

回到主介面,可以看到左邊X-CUBE-AZRTOS-F4變得可選,點選開啟配置。

可以根據需要修改配置,我這裡基本保持預設,後面有需求再修改。

使用STM32CubeMX生成ThreadX實時作業系統工程模板

4. 生成專案模板

常規操作,注意:1. IDE選用自己使用的;2. 增大堆疊,我均改為0x2000;3. .c/.h分開

二、Keil內編寫跑馬燈程式碼

1. 編輯app_azure_rtos.h

增加對GPIO、串列埠、printf的支援,程式碼:

/* USER CODE BEGIN Includes */
#include "main.h"
#include "stdio.h"
#include "usart.h"
#if 1
__asm__(".global __use_no_semihosting");

FILE __stdout;
//define function _sys_exit() to avoid using semi-hosting mode
void _sys_exit(int x)
{
    x = x;
}
//redefine function fputc to redirect output
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart6, (uint8_t *)&ch, 1, 0x10);
    return ch;
}
#endif
/* USER CODE END Includes */

增加執行緒函式申明

/* USER CODE BEGIN EFP */
void app1_LED123(ULONG thread_input);
/* USER CODE END EFP */

2. 編輯app_azure_rtos.h

檔案前面增加執行緒引數設定

/* USER CODE BEGIN PD */
//defination of app1
#define APP1_PRIO 15u    //優先順序,越大越不優先
#define APP1_STACKSIZE 1024u    //堆疊大小,注意大於cubemx內設定的最低大小
static TX_THREAD app1_TCB;    //執行緒控制塊
static uint8_t app1_STACK[APP1_STACKSIZE];    //堆疊
/* USER CODE END PD */

在 tx_application_define函式內,增加建立執行緒的操作,並串列埠顯示建立狀態。

/* USER CODE BEGIN  tx_application_define */
printf("tx_application_define\n");
UINT status = tx_thread_create(&app1_TCB,
                               "app1_led123",
                               app1_led123,
                               0,
                               &app1_STACK[0],
                               APP1_STACKSIZE,
                               APP1_PRIO,
                               APP1_PRIO,
                               TX_NO_TIME_SLICE,
                               TX_AUTO_START);
printf("thread create status:%d\n", status);
/* USER CODE END  tx_application_define */

 這裡遇到一個坑,我的堆疊大小起初設定得低於cubemx中指定的400B,因此執行緒建立失敗。可透過status的值判斷是否是執行緒建立失敗導致的問題。

使用STM32CubeMX生成ThreadX實時作業系統工程模板

最後,在檔案末尾編寫跑馬燈執行緒程式碼:

/* USER CODE BEGIN  0 */
void app1_led123(ULONG thread_input)
{
    printf("app1_led123 start\n");
    while(1) {
        HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
        tx_thread_sleep(10);
        HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
        tx_thread_sleep(10);
        HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
        tx_thread_sleep(10);
    }
}
/* USER CODE END  0 */

3. 設定編譯和除錯引數

在魔法棒內設定使用v6編譯器、勾選上microlib。debug選項卡內也選擇自己使用的偵錯程式。

v6編譯器的速度快了相當多,尤其是在帶RTOS的專案裡,需要選上。

使用STM32CubeMX生成ThreadX實時作業系統工程模板

設定完成,即可編譯下載,執行自己的程式!

——————THE END——————

部落格主頁:連結。轉載請註明出處!

相關文章