热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

嵌入式框架ZorbFramework搭建七:任务的实现

我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。嵌入式框架ZorbFramework搭建过程嵌入式框架ZorbFramework搭建

我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。

嵌入式框架Zorb Framework搭建过程

嵌入式框架Zorb Framework搭建一:嵌入式环境搭建、调试输出和建立时间系统

嵌入式框架Zorb Framework搭建二:环形缓冲区的实现

嵌入式框架Zorb Framework搭建三:列表的实现

嵌入式框架Zorb Framework搭建四:状态机的实现

嵌入式框架Zorb Framework搭建五:事件的实现

嵌入式框架Zorb Framework搭建六:定时器的实现

嵌入式框架Zorb Framework搭建七:任务的实现

 

一、前言

  在开发程序时,有时候会发现单线程程序开发起来比较吃力,要是可以多线程那该多好。本篇要为Zorb Framework提供多线程功能,也就是多任务功能。

 

二、任务功能设计

  我们先来看看要实现的任务提供什么功能:

  初步要提供的功能如下:

  1、可以开始和停止任务

  2、任务有优先级区分

  3、可以进行系统延时

  4、可以知道任务的运行时间

  5、可以动态创建和销毁任务

  因此,初步设计的数据结构如下:

1 /* 任务状态 */
2 typedef enum _TaskState
3 {
4 TASK_STATE_STOP = 0, /* 停止 */
5 TASK_STATE_RUNNING /* 运行 */
6 } TaskState;
7
8 /* 任务结构 */
9 typedef struct _Task
10 {
11 uint32_t *pStkPtr; /* 堆栈指针 */
12 uint32_t *pStkBase; /* 堆栈基地址 */
13 uint32_t StkSize; /* 堆栈大小 */
14 uint32_t DelayTime; /* 任务延时时间(系统周期) */
15 uint8_t Priority; /* 任务优先级 */
16 uint8_t State; /* 任务状态 */
17 uint32_t RunTime; /* 任务总运行时间(系统周期) */
18
19 /* 开始任务 */
20 bool (*Start)(struct _Task * const pTask);
21
22 /* 停止任务 */
23 bool (*Stop)(struct _Task * const pTask);
24
25 /* 销毁任务 */
26 void (*Dispose)(struct _Task * const pTask);
27
28 /* 延时任务 */
29 bool (*Delay)(struct _Task * const pTask, uint32_t tick);
30 } Task;

  为Zorb Framework提供的任务功能比较简单,状态也只有运行和关闭两种状态。任务功能实现的关键在于任务调度,而任务调度的核心又在于任务堆栈的保存和恢复。这部分需要根据使用的芯片进行修改,在STM32中,通过触发PendSV异常进行任务切换:

1 /******************************************************************************
2 * 描述 :PendSV异常处理
3 * 参数 :无
4 * 返回 :无
5 ******************************************************************************/
6 __asm void PendSV_Handler(void)
7 {
8 IMPORT pCurrentTask
9 IMPORT pTopPriorityTask
10
11 /* 任务的保存,即把CPU寄存器的值存储到任务的堆栈中 */
12 /* 关中断,NMI和HardFault除外 */
13 CPSID I
14
15 /* 判断是否第一次运行 */
16 MRS R0, PSP
17 CBZ R0, PendSVHandler_NotSave
18
19 /**
20 在进入PendSV异常的时候,当前CPU的xPSR,PC(任务入口地址),
21 R14,R12,R3,R2,R1,R0会自动存储到当前任务堆栈,同时递减PSP的值
22 **/
23 /* 手动存储CPU寄存器R4-R11的值到当前任务的堆栈 */
24 STMDB R0!, {R4-R11}
25
26 /* R0指向pCurrentTask的堆栈指针(指向空闲位置的顶部) */
27 LDR R1, = pCurrentTask
28 LDR R1, [R1]
29 STR R0, [R1]
30 NOP
31
32 /* 任务的切换,即把下一个要运行的任务的堆栈内容加载到CPU寄存器中 */
33 PendSVHandler_NotSave
34
35 /* 等效操作pCurrentTask = pTopPriorityTask; */
36 LDR R0, = pCurrentTask
37 LDR R1, = pTopPriorityTask
38 LDR R2, [R1]
39 STR R2, [R0]
40
41 /* pTopPriorityTask的信息出栈 */
42 LDR R0, [R2]
43 LDMIA R0!, {R4-R11}
44
45 /* 设置PSP指向下一个要执行的任务的堆栈的栈底(已弹出了寄存器信息) */
46 MSR PSP, R0
47 /* 确保异常返回使用的堆栈指针是PSP */
48 ORR LR, LR, #0x04 /* 设置LR寄存器的位2为1 */
49 CPSIE I /* 开中断 */
50
51 /**
52 函数返回,这个时候任务堆栈中的剩下内容将会自动加载到
53 xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)
54 同时PSP的值也将更新,即指向任务堆栈的栈顶。
55 在STM32中,堆栈是由高地址向低地址生长的
56 **/
57 BX LR
58 NOP
59 }

  具体实现请看附件代码或在文末的github地址拉框架源码。

 

三、任务结果测试

  简单的测试代码如下:

1 /**
2 *****************************************************************************
3 * @file app_task.c
4 * @author Zorb
5 * @version V1.0.0
6 * @date 2018-06-28
7 * @brief 任务测试的实现
8 *****************************************************************************
9 * @history
10 *
11 * 1. Date:2018-06-28
12 * Author:Zorb
13 * Modification:建立文件
14 *
15 *****************************************************************************
16 */
17
18 #include "app_task.h"
19 #include "zf_includes.h"
20
21 static Task *pTask1; /* 任务1 */
22 static Task *pTask2; /* 任务2 */
23 static Task *pTask3; /* 任务3 */
24
25 static void Process1(void *pArg); /* 任务1程序定义 */
26 static void Process2(void *pArg); /* 任务2程序定义 */
27 static void Process3(void *pArg); /* 任务3程序定义 */
28
29 /******************************************************************************
30 * 描述 :任务1程序
31 * 参数 :(in)-pArg 参数指针
32 * 返回 :无
33 ******************************************************************************/
34 static void Process1(void *pArg)
35 {
36 ZF_DEBUG(LOG_D, "\r\n");
37 ZF_DEBUG(LOG_D, "system time is %dms\r\n", ZF_SYSTIME_MS());
38 ZF_DEBUG(LOG_D, "I am %s\r\n", (char *)pArg);
39 ZF_DEBUG(LOG_D, "task count is %d\r\n", TASK_GET_TASK_COUNT());
40
41 ZF_DEBUG(LOG_D, "I will create task3\r\n");
42
43 /* 创建任务3 */
44 Task_create(&pTask3, Process3, "task3", 3, 256);
45
46 ZF_DEBUG(LOG_D, "task count is %d\r\n", TASK_GET_TASK_COUNT());
47
48 ZF_DEBUG(LOG_D, "I will dispose myself\r\n");
49
50 pTask1->Dispose(pTask1);
51 }
52
53 /******************************************************************************
54 * 描述 :任务2程序
55 * 参数 :(in)-pArg 参数指针
56 * 返回 :无
57 ******************************************************************************/
58 static void Process2(void *pArg)
59 {
60 while(1)
61 {
62 ZF_DEBUG(LOG_D, "\r\n");
63 ZF_DEBUG(LOG_D, "system time is %dms\r\n", ZF_SYSTIME_MS());
64 ZF_DEBUG(LOG_D, "I am %s\r\n", (char *)pArg);
65 ZF_DEBUG(LOG_D, "task count is %d\r\n", TASK_GET_TASK_COUNT());
66 ZF_DEBUG(LOG_D, "I will sleep 1000ms\r\n");
67 ZF_DEBUG(LOG_D, "wake up time is %dms\r\n", ZF_SYSTIME_MS() + 1000);
68 ZF_DELAY_MS(1000);
69 }
70 }
71
72 /******************************************************************************
73 * 描述 :任务3程序
74 * 参数 :(in)-pArg 参数指针
75 * 返回 :无
76 ******************************************************************************/
77 static void Process3(void *pArg)
78 {
79 while(1)
80 {
81 ZF_DEBUG(LOG_D, "\r\n");
82 ZF_DEBUG(LOG_D, "system time is %dms\r\n", ZF_SYSTIME_MS());
83 ZF_DEBUG(LOG_D, "I am %s\r\n", (char *)pArg);
84 ZF_DEBUG(LOG_D, "task count is %d\r\n", TASK_GET_TASK_COUNT());
85 ZF_DEBUG(LOG_D, "I will sleep 1000ms\r\n");
86 ZF_DEBUG(LOG_D, "wake up time is %dms\r\n", ZF_SYSTIME_MS() + 1000);
87 ZF_DELAY_MS(1000);
88 }
89 }
90
91 /******************************************************************************
92 * 描述 :任务初始化
93 * 参数 :无
94 * 返回 :无
95 ******************************************************************************/
96 void App_Task_init(void)
97 {
98 /* 创建任务1 */
99 Task_create(&pTask1, Process1, "task1", 1, 512);
100 /* 创建任务1 */
101 Task_create(&pTask2, Process2, "task2", 2, 512);
102 /* 运行任务系统 */
103 Task_run();
104
105 /* 程序不会到这 */
106 }
107
108 /******************************** END OF FILE ********************************/

  结果:

system time is 3ms
I am task1
task count
is 3
I will create task3
task count
is 4
I will dispose myselfsystem time
is 13ms
I am task2
task count
is 3
I will sleep 1000ms
wake up time
is 1019mssystem time is 21ms
I am task3
task count
is 3
I will sleep 1000ms
wake up time
is 1028mssystem time is 1021ms
I am task2
task count
is 3
I will sleep 1000ms
wake up time
is 2027mssystem time is 1030ms
I am task3
task count
is 3
I will sleep 1000ms
wake up time
is 2036mssystem time is 2029ms
I am task2
task count
is 3
I will sleep 1000ms
wake up time
is 3035mssystem time is 2038ms
I am task3
task count
is 3
I will sleep 1000ms
wake up time
is 3044ms省略...

 

四、最后

  本篇为Zorb Framework提供了任务功能。使用多任务功能进行开发是方便了许多,但同时任务间的协作和资源调用加大了调试和排错的难度。在享受多任务带来的快乐的同时,要做好排错时痛苦的准备。

 

  Zorb Framework github:https://github.com/54zorb/Zorb-Framework

  版权所有,转载请打赏哟

 

如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟

转:https://www.cnblogs.com/54zorb/p/9337754.html



推荐阅读
author-avatar
心梦飞扬-吕
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有