自己写的一个基于AVR单片机(Meag16)、编译器WINAVR20070122的调度程序,基于时间片轮转法,定时器0计时,轮流让8个任务运行,切换任务时保存全部寄存器R0-R31、SREG到当前任务的堆栽,然后恢复下一个任务的现场,用中断返回指令作任务切换。设置让编译器在中断程序不保存任何寄存器,由自己保存寄存器。 8个任务可以轮流运行,但是任务内部定义的局部在任务每次重新执行时都变为0。请教大家,谢谢了!程序代码如下:
(1)头文件:任务控制块TCB定义、保存任务环境的入栽宏、恢复任务现场的出栽宏。 typedef struct { unsigned char* task_stk_top; //保存任务的栽顶 unsigned char task_stack[100];//任务堆栽 }OS_TASK_TCB;
//保存所有寄存器的宏 #define pushall() __asm__ __volatile__ ("push r1" "
"); __asm__ __volatile__ ("push r0" "
"); __asm__ __volatile__ ("in r0, 0x3f" "
");保存CPU状态寄存器 __asm__ __volatile__ ("push r0" "
"); __asm__ __volatile__ ("eor r1, r1" "
");WINAVR要求R1等于0 __asm__ __volatile__ ("push r2" "
"); __asm__ __volatile__ ("push r3" "
"); __asm__ __volatile__ ("push r4" "
"); __asm__ __volatile__ ("push r5" "
"); __asm__ __volatile__ ("push r6" "
"); __asm__ __volatile__ ("push r7" "
"); __asm__ __volatile__ ("push r8" "
"); __asm__ __volatile__ ("push r9" "
"); __asm__ __volatile__ ("push r10" "
"); __asm__ __volatile__ ("push r11" "
"); __asm__ __volatile__ ("push r12" "
"); __asm__ __volatile__ ("push r13" "
"); __asm__ __volatile__ ("push r14" "
"); __asm__ __volatile__ ("push r15" "
"); __asm__ __volatile__ ("push r16" "
"); __asm__ __volatile__ ("push r17" "
"); __asm__ __volatile__ ("push r18" "
"); __asm__ __volatile__ ("push r19" "
"); __asm__ __volatile__ ("push r20" "
"); __asm__ __volatile__ ("push r21" "
"); __asm__ __volatile__ ("push r22" "
"); __asm__ __volatile__ ("push r23" "
"); __asm__ __volatile__ ("push r24" "
"); __asm__ __volatile__ ("push r25" "
"); __asm__ __volatile__ ("push r26" "
"); __asm__ __volatile__ ("push r27" "
"); __asm__ __volatile__ ("push r28" "
"); __asm__ __volatile__ ("push r29" "
"); __asm__ __volatile__ ("push r30" "
"); __asm__ __volatile__ ("push r31" "
");
//恢复任务现场时弹出所有寄存器的宏 #define popall() __asm__ __volatile__ ("pop r31" "
"); __asm__ __volatile__ ("pop r30" "
"); __asm__ __volatile__ ("pop r29" "
"); __asm__ __volatile__ ("pop r28" "
"); __asm__ __volatile__ ("pop r27" "
"); __asm__ __volatile__ ("pop r26" "
"); __asm__ __volatile__ ("pop r25" "
"); __asm__ __volatile__ ("pop r24" "
"); __asm__ __volatile__ ("pop r23" "
"); __asm__ __volatile__ ("pop r22" "
"); __asm__ __volatile__ ("pop r21" "
"); __asm__ __volatile__ ("pop r20" "
"); __asm__ __volatile__ ("pop r19" "
"); __asm__ __volatile__ ("pop r18" "
"); __asm__ __volatile__ ("pop r17" "
"); __asm__ __volatile__ ("pop r16" "
"); __asm__ __volatile__ ("pop r15" "
"); __asm__ __volatile__ ("pop r14" "
"); __asm__ __volatile__ ("pop r13" "
"); __asm__ __volatile__ ("pop r12" "
"); __asm__ __volatile__ ("pop r11" "
"); __asm__ __volatile__ ("pop r10" "
"); __asm__ __volatile__ ("pop r9" "
"); __asm__ __volatile__ ("pop r8" "
"); __asm__ __volatile__ ("pop r7" "
"); __asm__ __volatile__ ("pop r6" "
"); __asm__ __volatile__ ("pop r5" "
"); __asm__ __volatile__ ("pop r4" "
"); __asm__ __volatile__ ("pop r3" "
"); __asm__ __volatile__ ("pop r2" "
"); __asm__ __volatile__ ("pop r0" "
"); __asm__ __volatile__ ("out 0x3f, r0" "
");恢复CPU状态寄存器 __asm__ __volatile__ ("pop r0" "
"); __asm__ __volatile__ ("pop r1" "
"); __asm__ __volatile__ ("RETI" "
"); //******************************************************************
(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的局部变量 TCCR0 = 0X05;//定时器0初始化 TIMSK = 0X01; TCNT0 = 0x00; sei(); //打开全局中断 while(1) { //任务1每次重新执行temp都会变为0,就是这里请教大家为什么? 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
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 ); }//****************************************************************
我的问题就是任务1内部定义的局部变量temp为什么每次在任务1重新执行都为从0开始。这个时自己学习RTOS写的,请大家多指教!我想不断的进步,谢谢了! 祝大家中秋快乐,工作顺心,呵呵! |