tinyOS  v1.00
tTask.c
Go to the documentation of this file.
1 
15 #include "tinyOS.h"
16 
23 void tTaskInit (tTask *task, void (*entry) (void *), void *param, uint32_t prio, uint32_t *stack, uint32_t size) {
24  uint32_t *stackTop;
25 
26  // 为了简化代码,tinyOS无论是在启动时切换至第一个任务,还是在运行过程中在不同间任务切换
27  // 所执行的操作都是先保存当前任务的运行环境参数(CPU寄存器值)的堆栈中(如果已经运行运行起来的话),然后再
28  // 取出从下一个任务的堆栈中取出之前的运行环境参数,然后恢复到CPU寄存器
29  // 对于切换至之前从没有运行过的任务,我们为它配置一个“虚假的”保存现场,然后使用该现场恢复。
30  task->stackBase = stack;
31  task->stackSize = size;
32  memset(stack, 0, size);
33 
34  // 注意以下两点:
35  // 1、不需要用到的寄存器,直接填了寄存器号,方便在IDE调试时查看效果;
36  // 2、顺序不能变,要结合PendSV_Handler以及CPU对异常的处理流程来理解
37  stackTop = stack + size / sizeof(tTaskStack);
38  *(--stackTop) = (unsigned long) (1 << 24); // XPSR, 设置了Thumb模式,恢复到Thumb状态而非ARM状态运行
39  *(--stackTop) = (unsigned long) entry; // 程序的入口地址
40  *(--stackTop) = (unsigned long) 0x14; // R14(LR), 任务不会通过return xxx结束自己,所以未用
41  *(--stackTop) = (unsigned long) 0x12; // R12, 未用
42  *(--stackTop) = (unsigned long) 0x3; // R3, 未用
43  *(--stackTop) = (unsigned long) 0x2; // R2, 未用
44  *(--stackTop) = (unsigned long) 0x1; // R1, 未用
45  *(--stackTop) = (unsigned long) param; // R0 = param, 传给任务的入口函数
46  *(--stackTop) = (unsigned long) 0x11; // R11, 未用
47  *(--stackTop) = (unsigned long) 0x10; // R10, 未用
48  *(--stackTop) = (unsigned long) 0x9; // R9, 未用
49  *(--stackTop) = (unsigned long) 0x8; // R8, 未用
50  *(--stackTop) = (unsigned long) 0x7; // R7, 未用
51  *(--stackTop) = (unsigned long) 0x6; // R6, 未用
52  *(--stackTop) = (unsigned long) 0x5; // R5, 未用
53  *(--stackTop) = (unsigned long) 0x4; // R4, 未用
54 
55  task->slice = TINYOS_SLICE_MAX; // 初始化任务的时间片计数
56  task->stack = stackTop; // 保存最终的值
57  task->prio = prio; // 设置任务的优先级
58  task->state = TINYOS_TASK_STATE_RDY; // 设置任务为就绪状态
59  task->suspendCount = 0; // 初始挂起次数为0
60  task->clean = (void (*) (void *)) 0; // 设置清理函数
61  task->cleanParam = (void *) 0; // 设置传递给清理函数的参数
62  task->requestDeleteFlag = 0; // 请求删除标记
63 
64  task->waitEvent = (tEvent *) 0; // 没有等待事件
65  task->eventMsg = (void *) 0; // 没有等待事件
66  task->waitEventResult = tErrorNoError; // 没有等待事件错误
67 
68  tNodeInit(&(task->delayNode)); // 初始化延时结点
69 
70  tNodeInit(&(task->linkNode)); // 初始化链接结点
71 
72  tTaskSchedRdy(task); // 将任务插入就绪队列
73 
74 #if TINYOS_ENABLE_HOOKS == 1
75  tHooksTaskInit(task);
76 #endif
77 }
78 
83 void tTaskSuspend (tTask *task) {
84  // 进入临界区
85  uint32_t status = tTaskEnterCritical();
86 
87  // 不允许对已经进入延时状态的任务挂起
88  if (!(task->state & TINYOS_TASK_STATE_DELAYED)) {
89  // 增加挂起计数,仅当该任务被执行第一次挂起操作时,才考虑是否
90  // 要执行任务切换操作
91  if (++task->suspendCount <= 1) {
92  // 设置挂起标志
94 
95  // 挂起方式很简单,就是将其从就绪队列中移除,这样调度器就不会发现他
96  // 也就没法切换到该任务运行
97  tTaskSchedUnRdy(task);
98 
99  // 当然,这个任务可能是自己,那么就切换到其它任务
100  if (task == currentTask) {
101  tTaskSched();
102  }
103  }
104  }
105 
106  // 退出临界区
107  tTaskExitCritical(status);
108 }
109 
114 void tTaskWakeUp (tTask *task) {
115  // 进入临界区
116  uint32_t status = tTaskEnterCritical();
117 
118  // 检查任务是否处于挂起状态
119  if (task->state & TINYOS_TASK_STATE_SUSPEND) {
120  // 递减挂起计数,如果为0了,则清除挂起标志,同时设置进入就绪状态
121  if (--task->suspendCount == 0) {
122  // 清除挂起标志
124 
125  // 同时将任务放回就绪队列中
126  tTaskSchedRdy(task);
127 
128  // 唤醒过程中,可能有更高优先级的任务就绪,执行一次任务调度
129  tTaskSched();
130  }
131  }
132 
133  // 退出临界区
134  tTaskExitCritical(status);
135 }
136 
143 void tTaskSetCleanCallFunc (tTask *task, void (*clean) (void *param), void *param) {
144  task->clean = clean;
145  task->cleanParam = param;
146 }
147 
152 void tTaskForceDelete (tTask *task) {
153  // 进入临界区
154  uint32_t status = tTaskEnterCritical();
155 
156  // 如果任务处于延时状态,则从延时队列中删除
157  if (task->state & TINYOS_TASK_STATE_DELAYED) {
158  tTimeTaskRemove(task);
159  }
160  // 如果任务不处于挂起状态,那么就是就绪态,从就绪表中删除
161  else if (!(task->state & TINYOS_TASK_STATE_SUSPEND)) {
162  tTaskSchedRemove(task);
163  }
164 
165 
166  // 删除时,如果有设置清理函数,则调用清理函数
167  if (task->clean) {
168  task->clean(task->cleanParam);
169  }
170 
171  // 如果删除的是自己,那么需要切换至另一个任务,所以执行一次任务调度
172  if (currentTask == task) {
173  tTaskSched();
174  }
175 
176  // 退出临界区
177  tTaskExitCritical(status);
178 }
179 
183 void tTaskRequestDelete (tTask *task) {
184  // 进入临界区
185  uint32_t status = tTaskEnterCritical();
186 
187  // 设置清除删除标记
188  task->requestDeleteFlag = 1;
189 
190  // 退出临界区
191  tTaskExitCritical(status);
192 }
193 
199 uint8_t tTaskIsRequestedDelete (void) {
200  uint8_t delete;
201 
202  // 进入临界区
203  uint32_t status = tTaskEnterCritical();
204 
205  // 获取请求删除标记
206  delete = currentTask->requestDeleteFlag;
207 
208  // 退出临界区
209  tTaskExitCritical(status);
210 
211  return delete;
212 }
213 
217 void tTaskDeleteSelf (void) {
218  // 进入临界区
219  uint32_t status = tTaskEnterCritical();
220 
221  // 任务在调用该函数时,必须是处于就绪状态,不可能处于延时或挂起等其它状态
222  // 所以,只需要从就绪队列中移除即可
224 
225  // 删除时,如果有设置清理函数,则调用清理函数
226  if (currentTask->clean) {
228  }
229 
230  // 接下来,肯定是切换到其它任务去运行
231  tTaskSched();
232 
233  // 退出临界区
234  tTaskExitCritical(status);
235 }
236 
242 void tTaskGetInfo (tTask *task, tTaskInfo *info) {
243  uint32_t *stackEnd;
244 
245  // 进入临界区
246  uint32_t status = tTaskEnterCritical();
247 
248  info->delayTicks = task->delayTicks; // 延时信息
249  info->prio = task->prio; // 任务优先级
250  info->state = task->state; // 任务状态
251  info->slice = task->slice; // 剩余时间片
252  info->suspendCount = task->suspendCount; // 被挂起的次数
253  info->stackSize = task->stackSize;
254 
255  // 计算堆栈使用量
256  info->stackFree = 0;
257  stackEnd = task->stackBase;
258  while ((*stackEnd++ == 0) && (stackEnd <= task->stackBase + task->stackSize / sizeof(tTaskStack))) {
259  info->stackFree++;
260  }
261 
262  // 转换成字节数
263  info->stackFree *= sizeof(tTaskStack);
264 
265  // 退出临界区
266  tTaskExitCritical(status);
267 }
268 
uint32_t stackSize
Definition: tTask.h:71
void tTimeTaskRemove(tTask *task)
将延时的任务从延时队列中移除
Definition: tCore.c:189
uint32_t * stack
Definition: tTask.h:36
#define TINYOS_TASK_STATE_DELAYED
Definition: tTask.h:19
Definition: tTask.h:31
uint32_t tTaskStack
Definition: tTask.h:25
void * eventMsg
Definition: tTask.h:58
void tTaskSchedRemove(tTask *task)
将任务从就绪列表中移除
Definition: tCore.c:115
void tTaskSetCleanCallFunc(tTask *task, void(*clean)(void *param), void *param)
Definition: tTask.c:143
void tTaskDeleteSelf(void)
Definition: tTask.c:217
tTaskCritical_t tTaskEnterCritical(void)
Definition: tSwitch.c:36
void tNodeInit(tNode *node)
Definition: tList.c:19
void tTaskSuspend(tTask *task)
Definition: tTask.c:83
struct _tEvent * waitEvent
Definition: tTask.h:57
uint32_t prio
Definition: tTask.h:67
void tTaskSched(void)
任务调度接口。通过它来选择下一个具体的任务,然后切换至该任务运行。
Definition: tCore.c:126
void * cleanParam
Definition: tTask.h:53
uint32_t suspendCount
Definition: tTask.h:70
uint8_t requestDeleteFlag
Definition: tTask.h:54
void tTaskInit(tTask *task, void(*entry)(void *), void *param, uint32_t prio, uint32_t *stack, uint32_t size)
Definition: tTask.c:23
#define TINYOS_TASK_STATE_SUSPEND
Definition: tTask.h:20
Definition: tEvent.h:32
uint32_t suspendCount
Definition: tTask.h:50
void tTaskRequestDelete(tTask *task)
Definition: tTask.c:183
void tHooksTaskInit(tTask *task)
void(* clean)(void *param)
Definition: tTask.h:52
uint32_t slice
Definition: tTask.h:48
tNode delayNode
Definition: tTask.h:43
void tTaskExitCritical(tTaskCritical_t status)
Definition: tSwitch.c:47
uint32_t prio
Definition: tTask.h:45
uint32_t * stackBase
Definition: tTask.h:37
#define TINYOS_TASK_STATE_RDY
Definition: tTask.h:17
uint32_t delayTicks
Definition: tTask.h:66
void tTaskGetInfo(tTask *task, tTaskInfo *info)
Definition: tTask.c:242
void tTaskSchedRdy(tTask *task)
将任务设置为就绪状态
Definition: tCore.c:93
void tTaskForceDelete(tTask *task)
Definition: tTask.c:152
uint32_t state
Definition: tTask.h:47
tNode linkNode
Definition: tTask.h:40
tTask * currentTask
当前任务:记录当前是哪个任务正在运行
Definition: tCore.c:17
uint32_t slice
Definition: tTask.h:69
void tTaskWakeUp(tTask *task)
Definition: tTask.c:114
uint32_t delayTicks
Definition: tTask.h:42
void tTaskSchedUnRdy(tTask *task)
将任务从就绪列表中移除
Definition: tCore.c:102
uint32_t stackFree
Definition: tTask.h:72
uint32_t stackSize
Definition: tTask.h:39
uint8_t tTaskIsRequestedDelete(void)
Definition: tTask.c:199
uint32_t state
Definition: tTask.h:68
uint32_t waitEventResult
Definition: tTask.h:59