2. 多线程协作
任务目标
在ThreadX实时操作系统中创建两个线程,分别控制LED闪烁与蜂鸣器鸣响,通过时间片轮转调度使两个任务交替执行,演示RTOS多线程协作的基本机制。
硬件与依赖
- MCU:STM32F103系列(或其他Cortex-M3/M4内核MCU)
- ThreadX内核源码(已移植至目标平台)
- 开发板自带LED(接PA1)与有源蜂鸣器(接PA2),低电平有效
核心实现
#include "tx_api.h"
/* 线程控制块与栈 */
TX_THREAD led_thread;
TX_THREAD buzzer_thread;
static uint8_t led_stack[512];
static uint8_t buzzer_stack[512];
/* GPIO初始化(寄存器方式,适配STM32F103) */
static void gpio_init(void)
{
/* 使能GPIOA时钟 */
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
/* PA1、PA2推挽输出,50MHz */
GPIOA->CRL = (GPIOA->CRL & ~(0xFF << 4)) | (0x33 << 4);
/* 初始关闭LED与蜂鸣器 */
GPIOA->BRR = (1 << 1) | (1 << 2);
}
/* LED线程:每200ms翻转一次 */
static void led_thread_entry(ULONG arg)
{
(void)arg;
while (1) {
GPIOA->ODR ^= (1 << 1); /* 翻转PA1 */
tx_thread_sleep(20); /* 延时200ms(1 tick=10ms) */
}
}
/* 蜂鸣器线程:每500ms翻转一次 */
static void buzzer_thread_entry(ULONG arg)
{
(void)arg;
while (1) {
GPIOA->ODR ^= (1 << 2); /* 翻转PA2 */
tx_thread_sleep(50); /* 延时500ms */
}
}
/* 应用初始化 */
void app_main(void)
{
/* 创建两个线程,优先级相同,时间片各5个tick */
tx_kernel_enter();
}
void tx_application_define(void *first_unused_memory)
{
(void)first_unused_memory;
gpio_init();
tx_thread_create(&led_thread, "LED", led_thread_entry, 0,
led_stack, sizeof(led_stack),
15, 15, 5, TX_AUTO_START);
tx_thread_create(&buzzer_thread, "BUZZER", buzzer_thread_entry, 0,
buzzer_stack, sizeof(buzzer_stack),
15, 15, 5, TX_AUTO_START);
}
编译与运行
- 将上述代码加入ThreadX BSP工程,确保
tx_api.h与内核库已正确链接。 - 配置系统时钟节拍为10ms(
TX_TIMER_TICKS_PER_SECOND设为100)。 - 编译烧录后,复位运行。
验证方法
- 现象观察:LED以约200ms间隔闪烁,蜂鸣器以约500ms间隔鸣响,两者互不阻塞。
- 调度验证:两个线程优先级相同(均为15),时间片为5个tick(50ms)。在调试器中暂停内核,查看
tx_thread_current_ptr指向的线程会交替变化,证明时间片轮转调度生效。 - 通过条件:LED与蜂鸣器按各自周期独立工作,且任一线程进入死循环(如删除延时)不影响另一线程运行,即证明多线程协作成功。
关键说明
两个线程优先级相同,ThreadX将以时间片轮转方式调度:每个线程运行5个tick(50ms)后自动切换到另一个就绪线程。若将优先级设为不同值,则高优先级线程将抢占低优先级线程,时间片仅在相同优先级间生效。本案例使用寄存器直接操作GPIO以保持代码最小化,实际工程中可替换为HAL库函数。