|
楼主 |
发表于 2006-8-31 11:12:43
|
显示全部楼层
学习1:
运行原理:task0任务和task1任务分别通过createTask() 创建任务函数将task0任务和task1任务的地址压入人工堆栈的不同位置。开启定时器0,将SP指针设为task0人工堆栈栈底的位置,弹出运行task0任务。当定时器0溢出发生中断后,先保存当前task0的下一条指令执行地址和相关的寄存器(这一部中断会自己保存),再将SP的指针设为task1人工堆栈栈底的位置,弹出运行task1任务。就这样循环运行。从而能够使两个任务在中断后能够接着原来的指令再次运行。
源程序如下:
/*UT03.C*/
/*
操作系统学习------堆栈的使用 真正的时间片轮转
ATMega16L 1MH WinAVR
作者:zhb2000
2006.08.30 写到2006.08.31 0:15 才写成
*/
#include "ut03.h"
uchar Stack[STACK_LENGHT];
uchar TASKNUMB=0; //当前要create的任务
struct _ZS_TASK
{
uchar ready; //0 not ready, 1 ready 已执行过一次,2 ready未执行
uint taskBottomPoint; //任务栈底指针
}zsTask[MAXTASK];
SIGNAL(SIG_OVERFLOW0)
{ //计时器0溢出中断
static uchar n=0;
zsTask[n].taskBottomPoint=SP;
if(zsTask[n+1].ready!=0)
{ //下一个任务
n++;
SP=zsTask[n].taskBottomPoint;
if(zsTask[n].ready==2)
{
zsTask[n].ready=1;
popAll();
_asm("reti");
}
}
else
{ //第一个任务或只有一个任务
n=0;
SP=zsTask[0].taskBottomPoint;
}
//_asm("reti"); //现在此句不能要了
}
void init(void);
void task0(void);
void task1(void);
void createTask(void (*proc)(void));
void startTask(void);
int main(void)
{
init();
createTask(task0);
createTask(task1);
startTask();
return 0;
}
void init()
{
PORTA=0xff;
DDRA=0xff;
PORTB=0xff;
DDRB=0xff;
PORTC=0xff;
DDRC=0xff;
PORTD=0xff;
DDRD=0xff;
TASKNUMB=0;
}
void createTask(void (*proc)(void))
{ //创建任务
uchar *_sp;
uint old_sp;
_sp=(uchar*)(&Stack[STACK_LENGHT-1-TASKNUMB*30]);
*_sp--=(uint)proc;
*_sp--=(uint)proc>>8;
old_sp=SP;
SP=(uint)_sp;
pushAll();
zsTask[TASKNUMB].taskBottomPoint=SP;
zsTask[TASKNUMB].ready=2;
TASKNUMB++; //当前任务数加1
SP=old_sp;
}
void startTask()
{ //开始任务调度
if(zsTask[0].ready==0) return; //无任务返回
TIMSK=(1<<TOIE0);
TCNT0=0;
TCCR0=0x2; //8分频
sei();
SP=zsTask[0].taskBottomPoint;
zsTask[0].ready=1;
popAll();
_asm("ret"); //这句不能去掉
}
void task0()
{
while(1) PORTA++;
}
void task1()
{
while(1) PORTB++;
}
////////////////////////////////////////////////////
/* UT03.H */
#ifndef _ZS_UT03
#define _ZS_UT03
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#define uchar unsigned char
#define uint unsigned int
#define _asm asm volatile
#define _reg register unsigned char
//防止被编译器占用
_reg tempR2 asm("r2");
_reg tempR3 asm("r3");
_reg tempR4 asm("r4");
_reg tempR5 asm("r5");
_reg tempR6 asm("r6");
_reg tempR7 asm("r7");
_reg tempR8 asm("r8");
_reg tempR9 asm("r9");
_reg tempR10 asm("r10");
_reg tempR11 asm("r11");
_reg tempR12 asm("r12");
_reg tempR13 asm("r13");
_reg tempR14 asm("r14");
_reg tempR15 asm("r15");
_reg tempR16 asm("r16");
_reg tempR17 asm("r17");
#define STACK_LENGHT 300 //人工堆栈长度
#define MAXTASK 6 //最大任务数
#define pushAll() \
{ \
_asm("push r0" "
\t" \
"push r1" "
\t" \
"push r18" "
\t" \
"push r19" "
\t" \
"push r20" "
\t" \
"push r21" "
\t" \
"push r22" "
\t" \
"push r23" "
\t" \
"push r24" "
\t" \
"push r25" "
\t" \
"push r26" "
\t" \
"push r27" "
\t" \
"push r28" "
\t" \
"push r29" "
\t" \
"push r30" "
\t" \
"push r31" "
\t" \
); \
}
#define popAll() \
{ \
_asm("pop r31" "
\t" \
"pop r30" "
\t" \
"pop r29" "
\t" \
"pop r28" "
\t" \
"pop r27" "
\t" \
"pop r26" "
\t" \
"pop r25" "
\t" \
"pop r24" "
\t" \
"pop r23" "
\t" \
"pop r22" "
\t" \
"pop r21" "
\t" \
"pop r20" "
\t" \
"pop r19" "
\t" \
"pop r18" "
\t" \
"pop r1" "
\t" \
"pop r0" "
\t" \
); \
}
#endif
-----此内容被zhb2000于2006-08-31,12:02:45编辑过 |
|