任务调度器代码:
任务调度器代码:
(1)头文件:任务控制块TCB定义、保存任务环境的入栽宏、恢复任务现场的出栽宏。
typedef struct
{
unsigned char* task_stk_top; //保存任务的栽顶
unsigned char task_stack[100];//任务堆栽
}OS_TASK_TCB;
//任务现场保护,保存所有寄存器的宏
#define pushall() \
__asm__ __volatile__ ("push r1" "\n\t");\
__asm__ __volatile__ ("push r0" "\n\t");\
__asm__ __volatile__ ("in r0, 0x3f"
"\n\t");\保存CPU状态寄存器
__asm__ __volatile__ ("push r0" "\n\t");\
__asm__ __volatile__ ("eor r1, r1"
"\n\t");\WINAVR要求R1等于0
__asm__ __volatile__ ("push r2" "\n\t");\
__asm__ __volatile__ ("push r3" "\n\t");\
__asm__ __volatile__ ("push r4" "\n\t");\
__asm__ __volatile__ ("push r5" "\n\t");\
__asm__ __volatile__ ("push r6" "\n\t");\
__asm__ __volatile__ ("push r7" "\n\t");\
__asm__ __volatile__ ("push r8" "\n\t");\
__asm__ __volatile__ ("push r9" "\n\t");\
__asm__ __volatile__ ("push r10" "\n\t");\
__asm__ __volatile__ ("push r11" "\n\t");\
__asm__ __volatile__ ("push r12" "\n\t");\
__asm__ __volatile__ ("push r13" "\n\t");\
__asm__ __volatile__ ("push r14" "\n\t");\
__asm__ __volatile__ ("push r15" "\n\t");\
__asm__ __volatile__ ("push r16" "\n\t");\
__asm__ __volatile__ ("push r17" "\n\t");\
__asm__ __volatile__ ("push r18" "\n\t");\
__asm__ __volatile__ ("push r19" "\n\t");\
__asm__ __volatile__ ("push r20" "\n\t");\
__asm__ __volatile__ ("push r21" "\n\t");\
__asm__ __volatile__ ("push r22" "\n\t");\
__asm__ __volatile__ ("push r23" "\n\t");\
__asm__ __volatile__ ("push r24" "\n\t");\
__asm__ __volatile__ ("push r25" "\n\t");\
__asm__ __volatile__ ("push r26" "\n\t");\
__asm__ __volatile__ ("push r27" "\n\t");\
__asm__ __volatile__ ("push r28" "\n\t");\
__asm__ __volatile__ ("push r29" "\n\t");\
__asm__ __volatile__ ("push r30" "\n\t");\
__asm__ __volatile__ ("push r31" "\n\t");\
//恢复任务现场,弹出所有寄存器的宏
#define popall() \
__asm__ __volatile__ ("pop r31" "\n\t");\
__asm__ __volatile__ ("pop r30" "\n\t");\
__asm__ __volatile__ ("pop r29" "\n\t");\
__asm__ __volatile__ ("pop r28" "\n\t");\
__asm__ __volatile__ ("pop r27" "\n\t");\
__asm__ __volatile__ ("pop r26" "\n\t");\
__asm__ __volatile__ ("pop r25" "\n\t");\
__asm__ __volatile__ ("pop r24" "\n\t");\
__asm__ __volatile__ ("pop r23" "\n\t");\
__asm__ __volatile__ ("pop r22" "\n\t");\
__asm__ __volatile__ ("pop r21" "\n\t");\
__asm__ __volatile__ ("pop r20" "\n\t");\
__asm__ __volatile__ ("pop r19" "\n\t");\
__asm__ __volatile__ ("pop r18" "\n\t");\
__asm__ __volatile__ ("pop r17" "\n\t");\
__asm__ __volatile__ ("pop r16" "\n\t");\
__asm__ __volatile__ ("pop r15" "\n\t");\
__asm__ __volatile__ ("pop r14" "\n\t");\
__asm__ __volatile__ ("pop r13" "\n\t");\
__asm__ __volatile__ ("pop r12" "\n\t");\
__asm__ __volatile__ ("pop r11" "\n\t");\
__asm__ __volatile__ ("pop r10" "\n\t");\
__asm__ __volatile__ ("pop r9" "\n\t");\
__asm__ __volatile__ ("pop r8" "\n\t");\
__asm__ __volatile__ ("pop r7" "\n\t");\
__asm__ __volatile__ ("pop r6" "\n\t");\
__asm__ __volatile__ ("pop r5" "\n\t");\
__asm__ __volatile__ ("pop r4" "\n\t");\
__asm__ __volatile__ ("pop r3" "\n\t");\
__asm__ __volatile__ ("pop r2" "\n\t");\
__asm__ __volatile__ ("pop r0" "\n\t");\
__asm__ __volatile__ ("out 0x3f, r0" "\n\t");\恢复CPU状态寄存器
__asm__ __volatile__ ("pop r0" "\n\t");\
__asm__ __volatile__ ("pop r1" "\n\t");\
__asm__ __volatile__ ("RETI" "\n\t");\
//******************************************************************
(2)主函数main()代码,包括8个任务,调度程序,定义8个任务,每个任务对应一个LED灯的闪烁:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "RTOS.h"
#define LED_PORT PORTA //LED端口定义
#define LED_DDR DDRA
#define LED_PIN PINA
//第1个任务定义
void task1( void )
{
unsigned char temp ;//任务1的局部变量
//在任务1启动节拍定时器
TCCR0 = 0X05;//定时器0初始化
TIMSK = 0X01;
TCNT0 = 0x00;
sei();//打开全局中断
while(1)
{
temp++;
LED_PORT ^=0X01;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第2个任务定义
void task2(void)
{
while(1)
{
LED_PORT ^=0X02;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第3个任务定义
void task3(void)
{
while(1)
{
LED_PORT ^=0X04;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第4个任务定义
void task4(void)
{
while(1)
{
LED_PORT ^=0X08;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第5个任务定义
void task5(void)
{
while(1)
{
LED_PORT ^=0X10;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第6个任务定义
void task6(void)
{
while(1)
{
LED_PORT ^=0X20;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第7个任务定义
void task7(void)
{
while(1)
{
LED_PORT ^=0X40;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//第8个任务定义
void task8(void)
{
while(1)
{
LED_PORT ^=0X80;
for( unsigned char i=0; i<250; i++)
_delay_ms(10);
}
}
//*******************************************************************
volatile unsigned char next_task = 0;//用来指出下一个运行的任务
//计数变量,在定时器0中断函数里加1,用来控制任务切换频率
volatile unsigned char count = 0;
volatile OS_TASK_TCB task_tcb[ 8 ];//定义8个任务的任务控制块TCB数组
//任务堆栽初始化函数,参数为:任务入口地址、任务序号(1-8)
unsigned char* stackinit( void (*task)( void ), unsigned char task_id )
{
unsigned char* stk;
unsigned int temp;
temp = (unsigned int)task;//任务入口地址
stk = &( task_tcb[task_id].task_stack[99] );//取得任务栽顶指针
*stk-- = (unsigned char)(temp&0xff);//将任务入口地址入栽
*stk-- = (unsigned char)(temp>>8);
//以下是CPU所有寄存器初始化,为0值,
*stk-- = (unsigned char)0x00;
/* R0 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R1 = 0x00 */
*stk-- = (unsigned char)0x80;
/* R2 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R3 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R4 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R5 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R6 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R7 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R8 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R9 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R10 = */
*stk-- = (unsigned char)0x00;
/* R11 = */
*stk-- = (unsigned char)0x00;
/* R12 = */
*stk-- = (unsigned char)0x00;
/* R13 = */
*stk-- = (unsigned char)0x00;
/* R14 = */
*stk-- = (unsigned char)0x00;
/* R15 = */
*stk-- = (unsigned char)0x00;
/* R16 = */
*stk-- = (unsigned char)0x00;
/* R17 = */
*stk-- = (unsigned char)0x00;
/* R18 = */
*stk-- = (unsigned char)0x00;
/* R19 = */
*stk-- = (unsigned char)0x00;
/* R20 = */
*stk-- = (unsigned char)0x00;
/* R21 = */
*stk-- = (unsigned char)0x00;
/* R22 = */
*stk-- = (unsigned char)0x00;
/* R23 = */
*stk-- = (unsigned char)0x00;
/* R24 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R25 = 0x00 */
*stk-- = (unsigned char)0x00;
/* R26 = */
*stk-- = (unsigned char)0x00;
/* R27 = */
*stk-- = (unsigned char)0x00;
/* R28 = */
*stk-- = (unsigned char)0x00;
/* R29 = */
*stk-- = (unsigned char)0x00;
/* R30 = */
*stk-- = (unsigned char)0x00;
/* R31 = */
*stk-- = (unsigned char)0x00;
/* SREG = */
return ( (unsigned char*)stk );//返回当前堆栈指针
}
//任务创建函数:
void taskcreat( void (*task)( void ), unsigned char task_id )
{
unsigned char *temp;
temp = stackinit( task, task_id );//堆栽初始化,并返回栽顶指针
//初始化之后将堆栽栽顶指针保存在任务的TCB里,这个变量一直指向栽顶
task_tcb[task_id].task_stk_top = temp;
}
//调度器启动函数,用于运行第一个任务
void OS_Start( void )
{
SP = task_tcb[0].task_stk_top + 33;//堆栽指针指向第一个任务
//用中断返回指令将入口地址弹出到PC指针,运行第一个任务
asm("RETI");
}
//定时器0的中断函数:作周期中断,每次中断,表示当前任务的时间片用完,将结束当前任务,调用下一个任务
//加上下面这句,WINAVR将不保存任何寄存器
void SIG_OVERFLOW0( void ) __attribute__ ( ( signal, naked ) );
SIGNAL( SIG_OVERFLOW0 )
{
pushall( );//自己人工保存所有寄存器
count++; //每次中断加1
if(count>100)//100时任务切换,count值可以调整任务切换频率
{
count = 0;//重新清0
task_tcb[ next_task % 8 ].task_stk_top
=SP;//保存当前任务的栽顶SP指针到当前任务的控制块TCB
next_task++;指向下一个任务
//堆栽指针指向下一个任务栽顶
SP = task_tcb[ next_task % 8
].task_stk_top;
}
popall( );//人工恢复所有寄存器
}
//main()函数
int main( void )
{
//LED灯控制端口设置
LED_PORT=0Xff;
LED_DDR =0Xff;
//创建并初始化8个任务
taskcreat( task1, 0 );
taskcreat( task2, 1 );
taskcreat( task3, 2 );
taskcreat( task4, 3 );
taskcreat( task5, 4 );
taskcreat( task6, 5 );
taskcreat( task7, 6 );
taskcreat( task8, 7 );
OS_Start( );//开始运行任务
while( 1 );
}//****************************************************************