赞
踩
开源代码用来学习是可以的,但是如果要商用,则需要获取到开源代码所有者的商业许可。
void YourTask (void *pdata) {
for (;;) {
/* USER CODE
Call one of uC/OS-II's services:
OSFlagPend();
OSMboxPend();
OSMutexPend();
OSQPend();
OSSemPend();
OSTaskSuspend(OS_PRIO_SELF);
OSTimeDly();
OSTimeDlyHMSM();
/* USER CODE */
}
}
// 或者是
void YourTask (void *pdata) {
/* USER CODE */
OSTaskDel(OS_PRIO_SELF);
}
typedef struct os_tcb
{
//栈指针;
//INT16U OSTCBId; /*任务的ID*/
//链表指针;
//OS_EVENT *OSTCBEventPtr; /*事件指针*/
//void *OSTCBMsg; /*消息指针*/
//INT8U OSTCBStat; /*任务的状态*/
//INT8U OSTCBPrio; /*任务的优先级*/
//其他……
} OS_TCB;
OSRdyGrp |= 0x02
OSRdyTbl[1] |= 0x10
OSRdyGrp |= 0x04
OSRdyTbl[2] |= 0x20
OSRdyTbl[]
的值与
2
n
2^n
2n相或。uC/OS中,把
2
n
2^n
2n的n=0-7的8个值先计算好存在数组OSMapTbl[7]
中,也就是:
OSRdyGrp |= OSMapTbl[prio>>3]
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07]
OSRdyGrp |= OSMapTbl[12>>3](0x02)
OSRdyTbl[1] |= 0x10
if((OSRdyTbl[prio>>3] &= ~OSMapTbl[prio&0x07]) == 0) OSRdyGrp &= ~OSMapTbl[prio>>3];
void OSSched (void){
INT8U y;
OS_ENTER_CRITICAL();
// 检查是否中断调⽤和允许任务调⽤
if ((OSLockNesting | OSIntNesting) == 0) {
y = OSUnMapTbl[OSRdyGrp];
// 找到优先级最⾼的任务
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
// 该任务是否正在运行
if (OSPrioHighRdy != OSPrioCur) {
OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OS_TASK_SW();
}
}
OS_EXIT_CRITICAL();
}
Y = OSUnMapTbl[OSRdyGrp]
X = OSUnMapTbl[OSRdyTbl[Y]]
Prio = (Y<<3) + X;
static void OS_SchedNew (void)
{
#if OS_LOWEST_PRIO <= 63//μC/OS-II v2.7之前⽅式
INT8U y;
y = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
#else
INT8U y;
INT16U *ptbl;
//OSRdyGrp为16位
if ((OSRdyGrp & 0xFF) != 0) {
y = OSUnMapTbl[OSRdyGrp & 0xFF];
} else {
y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8;//矩形组号y>=8
}
ptbl = &OSRdyTbl[y];//取出x方向的16bit数据
if ((*ptbl & 0xFF) != 0) {
OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]);//*16
}
else {
OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8);
}
#endif
}
调用OS_TASK_SW()前的数据结构 | 保存当前CPU寄存器的值 | 重新装入要运行的任务 |
---|---|---|
Void OSCtxSw(void)
{
//将R1,R2,R3及R4推⼊当前堆栈;
OSTCBCur->OSTCBStkPtr = SP;
OSTCBCur = OSTCBHighRdy;
SP = OSTCBHighRdy->OSTCBSTKPtr;
//将R4,R3,R2及R1从新堆栈中弹出;
//执⾏中断返回指令;
}
INT8U OSTaskCreate (
void (*task)(void *pd), //任务代码指针
void *pdata, //任务参数指针
OS_STK *ptos, //任务栈的栈顶指针
INT8U prio //任务的优先级
);
INT8U OSTaskCreateExt(
//前四个参数与OSTaskCreate相同,
INT16U id, //任务的ID
OS_STK *pbos, //指向任务栈底的指针
INT32U stk_size, //栈能容纳的成员数⽬
void *pext,//指向⽤户附加数据域的指针
INT16U opt //⼀些选项信息
);
static OS_STK MyTaskStack[stack_size];
、OS_STK MyTaskStack[stack_size];
OS_STK *pstk;
pstk = (OS_STK *)malloc(stack_size);
/* 确认malloc()能得到⾜够的内存空间 */
if (pstk != (OS_STK *)0)
{
// Create the task;
}
OS_STK TaskStack[TASK_STACK_SIZE]
;OSTaskCreate(task, pdata,&TaskStack[TASK_STACK_SIZE-1],prio)
;void MyTask (void *pdata)
{
...... /* ⽤户代码 */
OSTaskDel(OS_PRIO_SELF);
}
INT8U OSTaskChangePrio(INT8U oldprio, INT8U newprio)
/* 在调⽤本函数之前必须先将中断关闭 */
void OSIntEnter (void){
if (OSRunning == TRUE) {
if (OSIntNesting < 255) {
OSIntNesting++;
}
}
}
void OSIntExit (void)
{
OS_ENTER_CRITICAL(); //关中断
if ((--OSIntNesting|OSLockNesting) == 0) //判断嵌套是否为零
{ //把⾼优先级任务装⼊
OSIntExitY = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy=(INT8U)((OSIntExitY<< 3) +
OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
if (OSPrioHighRdy != OSPrioCur) {
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OSIntCtxSw();
}
}
OS_EXIT_CRITICAL(); //开中断返回
}
void OSTickISR(void){
//(1)保存处理器寄存器的值;
//(2)调⽤OSIntEnter()或将OSIntNesting加1;
//(3)调⽤OSTimeTick(); /*检查每个任务的时间延时*/
//(4)调⽤OSIntExit();
//(5)恢复处理器寄存器的值;
//(6)执⾏中断返回指令;
}
void OSTimeDly (INT16U ticks){
if (ticks > 0){
OS_ENTER_CRITICAL();
if ((OSRdyTbl[OSTCBCur->OSTCBY] &=
~OSTCBCur->OSTCBBitX) == 0){
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly = ticks;
OS_EXIT_CRITICAL();
OSSched();
}
}
这个问题是指,对于一个OSTimeDly()操作而言,其实我们是不能严格延迟一个时间周期的,因为可能出现高优先级的事务,最好是OSTimeDLY(2),同样对于OSRTimeDly(1)而言,其实严格意义上的dly时间是不确定的(抖动)。
INT8U OSTimeDlyHMSM(
INT8U hours, // ⼩时
INT8U minutes, // 分钟
INT8U seconds, // 秒
INT16U milli // 毫秒
);
void main(void)
{
OSInit(); /* 初始化uC/OS-II*/
/* 应⽤程序初始化代码... */
/* 调⽤OSTaskCreate()创建⾄少⼀个任务*/
//允许时钟节拍中断; /* 错误!可能crash!*/
OSStart(); /* 开始多任务调度 */
}
void main (void)
{
OSInit(); /* 初始化uC/OS-II */
...
通过调⽤OSTaskCreate()或OSTaskCreateExt()
创建⾄少⼀个任务;
...
OSStart(); /*开始多任务调度! 永不返回*/
}
void OSStart (void)
{
INT8U Y;
INT8U X;
if (OSRunning == FALSE) {
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy = (INT8U)((Y<<3) + X);
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSTCBCur = OSTCBHighRdy;
OSStartHighRdy();
}
}
void OSStatInit (void){
OSTimeDly(2);
OS_ENTER_CRITICAL();
OSIdleCtr = 0L;
OS_EXIT_CRITICAL();
OSTimeDly(OS_TICKS_PER_SEC);
OS_ENTER_CRITICAL();
OSIdleCtrMax = OSIdleCtr;
OSStatRdy = TRUE;
OS_EXIT_CRITICAL();
}
// ECB数据结构
typedef struct {
void *OSEventPtr; /*指向消息或消息队列列的指针*/
INT8U OSEventTbl[OS_EVENT_TBL_SIZE];//等待任务列列表
INT16U OSEventCnt; /*计数器器(当事件是信号量量时)*/
INT8U OSEventType; /*事件类型:信号量量、邮箱等*/
INT8U OSEventGrp; /*等待任务组*/
} OS_EVENT;
pevent->OSEventGrp |= OSMapTbl[prio >> 3];
pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) {
pevent->OSEventGrp &= ~OSMapTbl[prio >> 3];
}
y = OSUnMapTbl[pevent->OSEventGrp];
x = OSUnMapTbl[pevent->OSEventTbl[y]];
prio = (y << 3) + x;
OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err);
typedef struct os_q {
struct os_q *OSQPtr;//空闲队列控制块指针
void **OSQStart; //指向消息队列的起始地址
void **OSQEnd; //指向消息队列的结束地址
void **OSQIn; //指向消息队列中下⼀个插⼊消息的位置
void **OSQOut;//指向消息队列中下⼀个取出消息的位置
INT16U OSQSize; //消息队列中总的单元数
INT16U OSQEntries; //消息队列中当前的消息数量
} OS_EVENT;
typedef struct {
void *OSMemAddr; /*分区起始地址*/
void *OSMemFreeList;//下⼀个空闲内存块
INT32U OSMemBlkSize; /*内存块的⼤⼩*/
INT32U OSMemNBlks; /*内存块数量*/
INT32U OSMemNFree; /*空闲内存块数量*/
} OS_MEM;
OS_MEM *OSMemCreate (
void *addr, // 内存分区的起始地址
INT32U nblks, // 分区内的内存块数
INT32U blksize,// 每个内存块的字节数
INT8U *err); // 指向错误码的指针
OS_MEM *CommTxBuf;
INT8U CommTxPart[100][32];
CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err);
void *OSMemGet(OS_MEM *pmem, INT8U *err);
OS_EVENT *SemaphorePtr;
OS_MEM *PartitionPtr;
INT8U Partition[100][32];
OS_STK TaskStk[1000];
void main(void){
INT8U err;
OSInit();
...
SemaphorePtr = OSSemCreate(100);
PartitionPtr = OSMemCreate(Partition, 100, 32, &err);
OSTaskCreate(Task, (void *)0, &TaskStk[999], &err);
OSStart();
}
void Task (void *pdata){
INT8U err;
INT8U *pblock;
for (;;) {
OSSemPend(SemaphorePtr, 0, &err);
pblock = OSMemGet(PartitionPtr, &err);
/* 使⽤内存块 */
...
OSMemPut(PartitionPtr, pblock);
OSSemPost(SemaphorePtr);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。