图 2 线程状态切换
建立线程实例
下面介绍一下线程创建的步骤,以下发生在main.c源文件中。
01
定义线程控制块和声明线程函数
sta
tic rt_thread_t mm32_example_thread = RT_NULL; //初始化线程控制块
static void mm32_thread_entry(void *parameter); //线程函数声明
02
在main函数中创建线程
可以使用 rt_thread_create() 创建一个动态线程,或者使用 rt_thread_init() 初始化一个静态线程,动态线程与静态线程的
区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。
mm32_example_thread = //线程控制块指针
rt_thread_create("example", //线程名字
mm32_thread_entry, //线程入口函数
RT_NULL, //线程入口函数参数
512, //线程栈大小
3, //线程的优先级
20); //线程时间片(单位tick)
// 如果成功获取到线程控制块,则启动线程,开启调度
IF(mm32_example_thread != RT_NULL)
rt_thread_startup(mm32_example_thread);
else
return -1;
03
编写线程函数内容
设计一个无限循环的作为线程函数。无限循环的目的就是为了让这个线程一直被系统循环调度运行,永不删除。
作为一个优先级明确的
实时系统,如果一个线程中的程序陷入了没有释放CPU使用权的循环操作,那么比它优先级低的线程都将不能够得到执行。所以在实时操作系统中必须注意的一点就是:线程中必须要有让出 CPU使用权的动作,如在循环中调用等待事件的操作、调用延时函数或者主动挂起。
static void mm32_thread_entry(void *parameter)
{
while(1) // 无限循环,该线程不会被系统删除,
// 若无这个循环,则线程运行完毕后会被系统自动删除
{
Wait_Event(); // 操作系统在这里释放CPU去执行其它线程,当事件发生再继续执行
Do_Something(); // 对事件进行服务、进行处理
}
}
通过以上三个步骤,就能建立可运行的线程了。
线程还有其他一些操作操作函数,如:
线程删除函数
rt_thread_delete(rt_thread_t thread):
用于rt_thread_create创建的线程
线程脱离函数
rt_thread_detach(rt_thread_t thread):
用于rt_thread_init()初始化的线程
线程挂起函数
rt_thread_suspend(rt_thread_t thread);
线程恢复函数
rt_thread_resume(rt_thread_t thread);
线程启动函数
rt_thread_startup(rt_thread_t thread);
线程获取函数
rt_thread_self(void);
除了以上操作函数,另外还有使线程让出处理器资源函数、使线程睡眠函数、控制线程函数、设置和删除空闲钩子函数、设置调度器钩子函数等,用户可以根据实际的应用需求选择对应的线程调用函数。
示例代码
#define MM32_THREAD_STACK_SIZE 512 /* 线程堆栈大小 */
#define MM32_THREAD_PRIORITY 5 /* 线程优先级 */
#define MM32_THREAD_TIMESLICE 10 /* 线程轮转时间片 */
static rt_thread_t mm32_thread1 = RT_NULL;
static char mb_str[] = "Hello MM32!"; /* 邮箱内容 */
/* 线程1入口函数:实现
LED1灯的翻转和发送邮件信息 */
static void mm32_thread1_entry(void *parameter)
{
/* 初始化LED灯控制端口 */
mm32_led_init();
while(1)
{
/* LED灯翻转显示 */
mm32_led_toggle(LED1);
/* 发送mb_str地址到邮箱中 */
rt_mb_send(&mm32_mb, (rt_uint32_t)&mb_str);
/* 打印提示消息 */
rt_k
printf("
LED Toggle and Send Mailbox
");
/* 处理500毫秒,释放MCU使用权,供内核调度 */
rt_thread_mdelay(500);
}
}
ALIGN(RT_ALIGN_SIZE)
static char mm32_thread2_stack[1024];
static struct rt_thread mm32_thread2;
static struct rt_mailbox mm32_mb;
static char mm32_mb_poll[128];
/* 线程2入口函数:实现邮箱的初始化、接收邮件并打印显示在终端 */
static void mm32_thread2_entry(void *parameter)
{
char *str;
rt_err_t result;
/* 初始化邮箱 */
result = rt_mb_init(&mm32_mb,
"mm32_mb",
&mm32_mb_poll[0], sizeof(mm32_mb_poll)/4,
RT_IPC_FLAG_FIFO);
/* 判断邮箱是否初始化成功 */
if(result != RT_EOK)
{
rt_kprintf("Init Mailbox Failed!
");
return;
}
while(1)
{
/* 从邮箱中收取邮件 */
if(rt_mb_recv(&mm32_mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
{
/* 打印邮件内容 */
rt_kprintf("Mailbox Received: %s
", str);
rt_thread_mdelay(100);
}
}
}
int main(void)
{
/* 动态创建mm32_thread1线程 */
mm32_thread1 = rt_thread_create("thread1",
mm32_thread1_entry, RT_NULL,
MM32_THREAD_STACK_SIZE,
MM32_THREAD_PRIORITY,
MM32_THREAD_TIMESLICE);
/* 如果线程动态创建成功,则启动该线程 */
if(mm32_thread1 != RT_NULL)
{
rt_thread_startup(mm32_thread1);
}
/* 静态初始化mm_thread2线程 */
rt_thread_init(&mm32_thread2, "thread2",
mm32_thread2_entry, RT_NULL,
&mm32_thread2_stack[0],
sizeof(mm32_thread2_stack),
MM32_THREAD_PRIORITY - 1,
MM32_THREAD_TIMESLICE);
/* 启动静态线程 */
rt_thread_startup(&mm32_thread2);
return 0;
}
示例代码
添加上述线程管理后,参考之前“灵动MM32MCU”官方公众号的RT-Thread UART数据收发章节,将程序下载到
芯片后输出显示结果如下:
图 3 运行结果
2020灵动MM32协作大会
2020年9月10日 9:00
深圳星河丽思卡尔顿酒店
“2020灵动MM32协作大会”重磅开启!
大会内容:
新品发布 技术分享
市场分析行业专家热点剖析
合作伙伴现场秀、互动小游戏
热销“MM32 INSIDE”应用案例展演等
更多精彩等着您,欢迎扫码报名参会!
`
0