1. 最小系统启动

任务目标

在STM32F103(以STM32F103C8T6蓝丸板为例)上完成ThreadX内核的移植与最小系统搭建:初始化内核、创建并启动一个控制LED闪烁的线程。通过观察板载LED以约1Hz频率翻转,验证ThreadX调度器正常运行。

环境与依赖

  • 硬件:STM32F103C8T6最小系统板(板载LED接PC13,低电平点亮)
  • IDE:STM32CubeIDE 1.15+ 或 Keil MDK-ARM 5.30+
  • ThreadX源码:Azure RTOS 6.x(本案例使用6.2.0,从GitHub获取后放入工程)
  • 时钟配置:使用HSE 8MHz外部晶振,经PLL倍频至72MHz系统主频

工程配置要点

在STM32CubeMX中完成以下配置后生成工程:

  • RCC:HSE使能,时钟树配置为72MHz主频
  • PC13设为GPIO输出,初始电平为高(LED灭)
  • 调试接口:SWD(保持默认即可)

ThreadX源码需添加至工程:将tx_api.h、tx_port.h所在目录加入头文件路径,将tx_initialize_low_level.s(汇编启动文件)及tx_thread_schedule.s加入工程源文件。若使用CubeIDE,还需在链接器选项中增加--specs=nano.specs以减小体积。

关键完整代码

/* main.c - 最小系统启动与LED线程 */
#include "tx_api.h"
#include "main.h"

/* 线程栈与控制块 */
static TX_THREAD led_thread;
static uint8_t led_thread_stack[512];

/* 线程入口函数 */
static void led_thread_entry(ULONG arg)
{
    (void)arg;
    while (1)
    {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        tx_thread_sleep(500);  /* 延时500个时钟节拍(1秒) */
    }
}

/* 用户初始化入口(CubeMX生成的main函数中调用) */
void user_threadx_init(void)
{
    /* 初始化ThreadX内核 */
    tx_kernel_enter();
}

/* ThreadX内核初始化完成后回调 */
void tx_application_define(void *first_unused_memory)
{
    (void)first_unused_memory;
    
    /* 创建LED控制线程 */
    UINT status = tx_thread_create(
        &led_thread,              /* 线程控制块 */
        "led_thread",             /* 线程名称 */
        led_thread_entry,         /* 入口函数 */
        0,                        /* 入口参数 */
        led_thread_stack,         /* 栈起始地址 */
        sizeof(led_thread_stack), /* 栈大小(字节) */
        1,                        /* 优先级:0最高,31最低 */
        1,                        /* 时间片(仅同优先级轮询时有效) */
        TX_AUTO_START);           /* 创建后自动启动 */
    
    if (status != TX_SUCCESS)
    {
        /* 创建失败处理:可在此处加入错误陷阱 */
        while (1) { }
    }
}

/* main函数(CubeMX生成,此处仅保留关键调用) */
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    
    /* 进入ThreadX内核(不会返回) */
    user_threadx_init();
    
    /* 不会执行到这里 */
    while (1) { }
}

运行与验证

  1. 编译工程并烧录至STM32F103C8T6。
  2. 复位开发板,观察板载LED(PC13)。
  3. 通过标准:LED以约1Hz频率持续闪烁(亮500ms,灭500ms)。若LED常亮或常灭,检查PC13电平逻辑(低电平点亮)及GPIO初始化;若系统无反应,检查时钟配置与ThreadX汇编启动文件是否正确加入工程。

常见问题

  • 编译报错找不到tx_api.h:确认ThreadX源码路径已加入头文件搜索目录。
  • 链接错误Undefined symbol tx_thread_schedule:未将tx_thread_schedule.s加入工程。
  • 进入HardFault:检查系统时钟是否确实为72MHz,ThreadX节拍定时器(SysTick)配置依赖正确的时钟频率;同时确认线程栈大小足够(512字节在本案例中足够)。
ThreadX最小系统启动流程 main() 初始化 tx_kernel_enter() tx_application_define() LED线程运行(1Hz闪烁) 关键说明 • 硬件初始化(时钟/GPIO) • 进入ThreadX调度器 • 内核初始化完成后回调 • 在此创建用户线程 • 调度器开始运行 • 线程内循环翻转LED • tx_thread_sleep(500) • 释放CPU,节拍延时

以上流程展示了从系统上电到LED线程被调度的完整路径。核心要点在于tx_kernel_enter()不会返回,所有用户线程的创建必须在tx_application_define()回调中完成,该回调由内核在初始化完成后自动调用。