目录
等待互斥信号量
信号量未被占用
信号量被自己占用
信号量被高优先级任务占用
信号量被低优先级任务占用
释放互斥信号量
未发生优先级继承
发生优先级继承
等待互斥信号量
信号量未被占用
- 标记为已经被占用
- 锁定计数+1
信号量被自己占用
- 锁定计数+1
信号量被高优先级任务占用
- 低优先级任务插入事件控制块的等待队列中
信号量被低优先级任务占用
- 高优先级任务插入到等待队列中
- 低优先级任务设置成高优先级任务一样的优先级
释放互斥信号量
未发生优先级继承
- 释放信号量
- 从等待队列中唤醒一个任务占用信号量
发生优先级继承
- 低优先级任务从信号量中释放,不再占用信号量,同时低优先级任务优先级改为原有的优先级
- 从等待队列中唤醒一个任务占用信号量
tMutex.c
#include "tinyOS.h"/* 互斥信号量初始化函数 */
void tMutexInit(tMutex *mutex)
{tEventInit(&mutex->event, tEventTypeMutex);mutex->lockedCount = 0;mutex->owner = (tTask *)0;mutex->ownerOriginalPrio = TINYOS_PRO_COUNT;//初始设为无效值
}/* 等待互斥信号量函数 */
//参数:互斥信号量,超时时间
uint32_t tMutexWait(tMutex *mutex, uint32_t waitTicks)
{uint32_t status = tTaskEnterCritical();//互斥信号量是否被锁定if(mutex->lockedCount <= 0){//未锁定:当前任务可以占用互斥信号量mutex->owner = currentTask;mutex->ownerOriginalPrio = currentTask->prio;mutex->lockedCount++;tTaskExitCritical(status);return tErrorNoError;}else{//已锁定://判断是否是当前任务锁定的if(mutex->owner == currentTask){mutex->lockedCount++;tTaskExitCritical(status);return tErrorNoError;}else{//不是当前任务锁定://判断当前任务优先级和互斥信号量占有者优先级哪个高if(currentTask->prio < mutex->owner->prio){//当前任务优先级高://任务优先级继承机制tTask *owner = mutex->owner;//判断当前任务是否为就绪状态if(owner->state == TINYOS_TASK_STATE_RDY){//当前任务为就绪状态:tTaskSchedUnRdy(owner);//从原有就绪队列中移出owner->prio = currentTask->prio;//更改所有者优先级tTaskSchedRdy(owner);//插入新的队列}else{owner->prio = currentTask->prio;}}tEventWait(&mutex->event, currentTask, (void *)0, tEventTypeMutex, waitTicks);//当前任务插入事件控制块中tTaskExitCritical(status);tTaskSched();return currentTask->waitEventResult;}}
}/* 无等待获取互斥信号量函数 */
//仅需检查互斥信号量能否被当前任务获取到
uint32_t tMutexNoWaitGet(tMutex *mutex)
{uint32_t status = tTaskEnterCritical();//判断互斥信号量是否被锁定if(mutex->lockedCount <= 0){//没有被锁定:由当前任务锁定mutex->owner = currentTask;mutex->ownerOriginalPrio = currentTask->prio;mutex->lockedCount++;tTaskExitCritical(status);return tErrorNoError;}else{//被锁定://判断互斥信号量所有者是否是当前任务if(mutex->owner == currentTask){mutex->lockedCount++;tTaskExitCritical(status);return tErrorNoError;}tTaskExitCritical(status);return tErrorResourceUnavailable;}
}/* 释放互斥信号量函数 */
uint32_t tMutexNotify(tMutex *mutex)
{uint32_t status = tTaskEnterCritical();//判断信号量是否被锁定if(mutex->lockedCount <= 0){tTaskExitCritical(status);return tErrorNoError;}//判断信号量所有者if(mutex->owner != currentTask){tTaskExitCritical(status);return tErrorOwner;}//对锁定计数--仍大于0:没有到最终释放任务的过程if(--mutex->lockedCount > 0){tTaskExitCritical(status);return tErrorNoError;}//判断是否发生优先级继承if(mutex->ownerOriginalPrio != mutex->owner->prio){//发生优先级继承://判断任务是否在就绪状态if(mutex->owner->state == TINYOS_TASK_STATE_RDY){//更改任务所在就绪列表位置及优先级tTaskSchedUnRdy(mutex->owner);currentTask->prio = mutex->ownerOriginalPrio;tTaskSchedUnRdy(mutex->owner);}else{currentTask->prio = mutex->ownerOriginalPrio;}}//判断当前等待队列中是否有任务if(tEventWaitCount(&mutex->event) > 0){tTask *task = tEventWakeUp(&mutex->event, (void *)0, tErrorNoError);//取出一个任务//信号量的所有者设置为新任务mutex->owner = task;mutex->ownerOriginalPrio = task->prio;mutex->lockedCount++;//判断任务的优先级是否比当前任务的优先级高if(task->prio < currentTask->prio){tTaskSched();}}tTaskExitCritical(status);return tErrorNoError;
}
tMutex.h
#ifndef __TMUTEX_H
#define __TMUTEX_H#include "tEvent.h"/* 互斥信号量结构 */
typedef struct _tMutex
{tEvent event; //事件控制块uint32_t lockedCount; //锁定计数器tTask *owner; //当前互斥信号量所有者uint32_t ownerOriginalPrio; //所有者原始优先级
}tMutex;void tMutexInit(tMutex *mutex);
uint32_t tMutexWait(tMutex *mutex, uint32_t waitTicks);
uint32_t tMutexNoWaitGet(tMutex *mutex);
uint32_t tMutexNotify(tMutex *mutex);#endif
tintOS.h
#ifndef __TINYOS_H
#define __TINYOS_H#include <stdint.h>
#include "tLib.h"
#include "tConfig.h"
#include "tTask.h"
#include "tEvent.h"
#include "tSem.h"
#include "tMbox.h"
#include "tMemBlock.h"
#include "tFlagGroup.h"
#include "tMutex.h"/* 错误码 */
typedef enum _tError{tErrorNoError = 0, //没有错误发生tErrorTimeout, //超时tErrorResourceUnavailable,//资源不可用tErrorDel, //被删除tErrorResourceFull, //资源已满tErrorOwner, //拥有者错误
}tError;extern tTask *currentTask;
extern tTask *nextTask; uint32_t tTaskEnterCritical(void);
void tTaskExitCritical(uint32_t status);void tTaskSwitch(void); //和CPU相关,写在switch.c
void tTaskRunFirst(void);void tTaskSchedInit(void);
void tTaskSchedDisable(void);
void tTaskSchedEnable(void);
void tTaskSchedRdy(tTask *task);
void tTaskSchedUnRdy(tTask *task);
void tTaskSchedRemove(tTask *task);
void tTaskSched(void);
void tTimeTaskWait(tTask *task, uint32_t ticks);
void tTimeTaskWakeUp(tTask *task);
void tTimeTaskRemove(tTask *task);
void tTaskSystemTickHandler(void);
void tTaskDelay(uint32_t delay);void tSetSysTickPeriod(uint32_t ms);
void tInitApp(void);#endif
tEvent.c
#include "tinyOS.h"/* 事件控制块初始化函数 */
void tEventInit(tEvent *event, tEventType type)
{event->type = tEventTypeUnknow;tListInit(&event->waitList);
}/* 事件控制块等待函数 */
//参数:事件控制块,任务,消息(传入消息来源,在事件发生以后存放具体的消息),等待的状态,超时时间
void tEventWait(tEvent *event, tTask *task, void *msg, uint32_t state, uint32_t timeout)
{uint32_t status = tTaskEnterCritical();task->state |= state << 16;task->waitEvent = event;task->eventMsg = msg;task->waitEventResult = tErrorNoError;tTaskSchedUnRdy(task);//移出就绪队列tListAddLast(&event->waitList, &task->linkNode);//插入事件控制块等待队列的尾部if(timeout){tTimeTaskWait(task, timeout);//设置了超时事件,插入延时队列}tTaskExitCritical(status);
}/* 事件控制块通知函数(将任务从事件控制块中唤醒,唤醒队列首部任务) */
//参数:事件控制块,消息,唤醒结果
tTask *tEventWakeUp(tEvent *event, void *msg, uint32_t result)
{tNode *node;tTask *task = (tTask *)0;uint32_t status = tTaskEnterCritical();if((node = tListRemoveFirst(&event->waitList)) != (tNode *)0){task = (tTask *)tNodeParent(node, tTask, linkNode);//插入到事件控制块是用linknodetask->waitEvent = (tEvent *)0;//不等待任何事件task->eventMsg = msg;task->waitEventResult = result;task->state &= ~TINYOS_TASK_WAIT_MASK;if(task->delayTicks != 0)//有延时{tTimeTaskWakeUp(task);//强制将任务从延时队列中移除}tTaskSchedRdy(task);//插入就绪队列}tTaskExitCritical(status);return task;
}/* 事件控制块通知函数(将任务从事件控制块中唤醒,唤醒队列中的指定任务) */
//参数:事件控制块,指定唤醒的任务,消息,唤醒结果
tTask *tEventWakeUpTask(tEvent *event, tTask *task, void *msg, uint32_t result)
{uint32_t status = tTaskEnterCritical();tListRemove(&event->waitList, &task->linkNode);//直接将任务移出队列task->waitEvent = (tEvent *)0;//不等待任何事件task->eventMsg = msg;task->waitEventResult = result;task->state &= ~TINYOS_TASK_WAIT_MASK;if(task->delayTicks != 0)//有延时{tTimeTaskWakeUp(task);//强制将任务从延时队列中移除}tTaskSchedRdy(task);//插入就绪队列tTaskExitCritical(status);return task;
}/* 事件控制块移除函数 */
void tEventRemoveTask(tTask *task, void *msg, uint32_t result)
{uint32_t status = tTaskEnterCritical();tListRemove(&task->waitEvent->waitList, &task->linkNode);task->waitEvent = (tEvent *)0;task->eventMsg = msg;task->waitEventResult = result;task->state &= ~TINYOS_TASK_WAIT_MASK;tTaskExitCritical(status);
}/* 事件控制块清空函数 */
//返回值:事件任务块被清空时,它的等待队列中有多少任务
uint32_t tEventRemoveAll(tEvent *event, void *msg, uint32_t result)
{tNode *node;uint32_t count = 0;uint32_t status = tTaskEnterCritical();count = tListCount(&event->waitList);//等待队列中有多少任务while((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)//移除等待队列头部任务{tTask *task = (tTask *)tNodeParent(node, tTask, linkNode);//获取task结构task->waitEvent = (tEvent *)0;//不再等待事件task->eventMsg = msg;task->waitEventResult = result;task->state &= ~TINYOS_TASK_WAIT_MASK;if(task->delayTicks != 0)//任务有延时{tTimeTaskWakeUp(task);//移出延时队列}tTaskSchedRdy(task);}tTaskExitCritical(status);return count;
}/* 获取事件控制块中等待任务函数 */
uint32_t tEventWaitCount(tEvent *event)
{uint32_t count = 0;uint32_t status = tTaskEnterCritical();count = tListCount(&event->waitList);tTaskExitCritical(status);return count;
}
app.c
#include "tinyOS.h"
#include "string.h"//定义任务,分别为它们配备独立的堆栈空间
tTask tTask1;
tTask tTask2;
tTask tTask3;
tTask tTask4;
tTaskStack task1Env[1024];
tTaskStack task2Env[1024];
tTaskStack task3Env[1024];
tTaskStack task4Env[1024];tMutex mutex;//定义任务要执行的功能
int task1Flag;
void task1Entry(void *param)
{tSetSysTickPeriod(10);//初始化tMutexInit(&mutex);for(;;)//任务里是for的死循环{//嵌套的申请互斥信号量再释放tMutexWait(&mutex, 0);tMutexWait(&mutex, 0);task1Flag = 0; tTaskDelay(1);task1Flag = 1;tTaskDelay(1);tMutexNotify(&mutex);tMutexNotify(&mutex);}
}int task2Flag;
void task2Entry(void *param)
{for(;;){tMutexWait(&mutex, 0);tMutexWait(&mutex, 0);task2Flag = 0;tTaskDelay(1);task2Flag = 1;tTaskDelay(1);tMutexNotify(&mutex);tMutexNotify(&mutex);}
}
int task3Flag;
void task3Entry(void *param)
{for(;;){task3Flag = 0;tTaskDelay(1);task3Flag = 1;tTaskDelay(1);}
}
int task4Flag;
void task4Entry(void *param)
{for(;;){task4Flag = 0;tTaskDelay(1);task4Flag = 1;tTaskDelay(1);}
}/* 应用任务初始化函数 */
void tInitApp(void)
{//最后一个参数:传堆栈末端地址,因为堆栈是向下生长的,初始堆栈地址是堆栈空间最后一个单元地址的末端tTaskInit(&tTask1, task1Entry, (void *)0x11111111, 0, &task1Env[1024]);tTaskInit(&tTask2, task2Entry, (void *)0x22222222, 1, &task2Env[1024]);tTaskInit(&tTask3, task3Entry, (void *)0x22222222, 1, &task3Env[1024]);tTaskInit(&tTask4, task4Entry, (void *)0x22222222, 1, &task4Env[1024]);
}