zhudlmax 发表于 2006-12-5 20:01:35

简洁实用的时间片调度法操作系统,献给大家

在OURAVR潜水有段时间了,学到不少东西,参考一些资料,我写了一个简洁实用的时间片调度法操作系统,在我的一些产品中已经应用,非常稳定,在再献给大家



// RTOS HEAD FILE



#ifndef _RTOS_T0_H

#define _RTOS_T0_H



// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间

register unsigned char tempR4asm("r4");

register unsigned char tempR5asm("r5");

register unsigned char tempR6asm("r6");

register unsigned char tempR7asm("r7");

register unsigned char tempR8asm("r8");

register unsigned char tempR9asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");





#define PUSH_ALL()                                        \

asm volatile(                                        \

"PUSH        R2"        "
\t"                                \

"PUSH        R3"        "
\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        POP_ALL()                                        \

asm volatile(                                        \

"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        R3"                "
\t"                        \

"POP        R2"                "
\t"                        \

"POP        R0"                "
\t"                        \

"OUT        0x3F,R0"                "
\t"                        \

"POP        R0"                "
\t"                        \

"POP        R1"                "
\t"                        \

)                                                \





#define Total_Task_Num        8

#define Task_Stack_Size        50

#define Total_Stack_Size        Total_Task_Num * Task_Stack_Size



unsigned char uTaskStack;

unsigned char uCurrentTaskID;

unsigned char uTotalTaskNum;

unsigned char uCurrentProperty;



unsigned int uTaskEntry;                        // 任务入口



void OS_Start(void);                                // 开启系统:0号任务开始

void OS_ScheduleTask(void);                        // 任务调度:处理任务调用属性

void OS_CreateTask( void (*pTaskEntry)(void), unsigned char *pTaskStack);

void OS_Timer0Init(void);                        // 定时中断:调度任务

void OS_CallNext(void);



#endif









// RTOS.C



#include <avr/io.h>

#include <avr/interrupt.h>

#include "RTOS_T0.h"



void OS_Timer0Init(void)

{

        TCNT0 = 0x00;

        OCR0 = 95;



        TCCR0 = (1<<CS01);                // ti = F_CPU(15360000) / OCR0(95+1) / n(8) / 2= 0.1ms



        TIMSK |= (1<<OCIE0);

}



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



void OS_CreateTask( void (*pTaskEntry)(void), unsigned char *pTaskStack)

{

        *pTaskStack-- = (unsigned int)pTaskEntry;

        *pTaskStack-- = (unsigned int)pTaskEntry>>8;



        uTaskEntry = (unsigned int)pTaskStack;

}



void OS_Start(void)

{

        SP = uTaskEntry;



        TCNT0 = 0x00;

        asm("reti");

}



// 提前调度下一任务,节约时间片资源

void OS_CallNext(void)

{

        TCNT0 = OCR0-1;

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");       

}



// 优化设置:-0s,其他形式下需要改变入栈与出栈代码



void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry = SP+19;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =uTaskEntry-19;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}

zhudlmax 发表于 2006-12-5 20:12:51

应用如下,程序仅参考,我的系统功能如下:



芯片:mega16-16AU



A:采用PS/2键盘输入,设置设备参数

B:采用20X02LCD显示

C:扩展了32路数字输入32路数字输出(DC24V)

D:控制一套伺服

E:制三个交流感应电机

F:温度控制







#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/eeprom.h>

#include <avr/pgmspace.h>



#include "RTOS_T0.h"







void Task_ScanExPort(void)

{

        ......



TaskStart:



        ......

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Keyboard(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}





void Task_System(void)

{



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_Load(void)

{

        ......



TaskStart:



        ......       

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Unload(void)

{

        ......



TaskStart:       



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_LED(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_CamDisc(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_Miss_Extra(void)

{

        ......



TaskStart:



        delay_ms(100);



        OS_CallNext();



        goto TaskStart;

}





int main(void)

{

        uTotalTaskNum = 0;

        uCurrentTaskID = 0;       

        OS_Timer0Init();

       

        OS_CreateTask(Task_ScanExPort, &uTaskStack);



        OS_CreateTask(Task_Keyboard, &uTaskStack);



        OS_CreateTask(Task_System, &uTaskStack);



        OS_CreateTask(Task_Load, &uTaskStack);



        OS_CreateTask(Task_Unload, &uTaskStack);



        OS_CreateTask(Task_LED, &uTaskStack);



        OS_CreateTask(Task_CamDisc, &uTaskStack);



        OS_CreateTask(Task_Miss_Extra, &uTaskStack);



        OS_Start();



        return(0);

}

zhudlmax 发表于 2006-12-5 20:14:39

OS_CallNext(); 可以根据实际需要而删除不用

my_avr 发表于 2006-12-5 21:03:26

好!顶一下,可以试试!

my_avr 发表于 2006-12-5 21:59:11

楼主用什么编译器?用Winavr好象不能编译过去!

tywood 发表于 2006-12-5 22:35:15

楼主厉害啊:)

AVR_AFA 发表于 2006-12-5 22:46:49

好利害,我都是用的“时间触发调度系统”方式,感觉也挺好的。

zhudlmax 发表于 2006-12-6 09:30:25

AVR Studio 4.12 SP2 Build 472 + WinAVR 2006-0421,开发很方便,直接在AVR Studio中利用WinAVR的GCC进行开发

biansf2001 发表于 2006-12-6 11:00:37

register unsigned char tempR16 asm("r17");



这里应该是

register unsigned char tempR17 asm("r17");

huangdongle 发表于 2006-12-6 11:13:20

多谢楼主的贡献精神!

zhudlmax 发表于 2006-12-6 12:05:34

输入贻误,谢谢指正

my_avr 发表于 2006-12-6 17:13:19

菜鸟请楼主指点一下:

   uTaskEntry = SP+19;

   if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

   SP =uTaskEntry-19;

是什么意思啊,为什么要加19,后面又要减19呢?

zhudlmax 发表于 2006-12-6 17:58:31

在-0s优化中,GCC将Timer0的比较中断汇编为:



@000000EE: __vector_19

22:       {

+000000EE:   921F      PUSH    R1               Push register on stack

+000000EF:   920F      PUSH    R0               Push register on stack

+000000F0:   B60F      IN      R0,0x3F          In from I/O location

+000000F1:   920F      PUSH    R0               Push register on stack

+000000F2:   2411      CLR   R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000000F3:   940C0124    JMP   0x00000124       Jump

+000000F5:   900F      POP   R0               Pop register from stack

+000000F6:   BE0F      OUT   0x3F,R0          Out to I/O location

+000000F7:   900F      POP   R0               Pop register from stack

+000000F8:   901F      POP   R1               Pop register from stack

+000000F9:   9518      RETI                     Interrupt return



执行asm("JMP OS_ScheduleTask");后进入函数OS_ScheduleTask,汇编为:

@00000124: OS_ScheduleTask

57:       {

+00000124:   922F      PUSH    R2               Push register on stack

+00000125:   923F      PUSH    R3               Push register on stack

+00000126:   932F      PUSH    R18            Push register on stack

+00000127:   933F      PUSH    R19            Push register on stack

+00000128:   934F      PUSH    R20            Push register on stack

+00000129:   935F      PUSH    R21            Push register on stack

+0000012A:   936F      PUSH    R22            Push register on stack

+0000012B:   937F      PUSH    R23            Push register on stack

+0000012C:   938F      PUSH    R24            Push register on stack

+0000012D:   939F      PUSH    R25            Push register on stack

+0000012E:   93AF      PUSH    R26            Push register on stack

+0000012F:   93BF      PUSH    R27            Push register on stack

+00000130:   93CF      PUSH    R28            Push register on stack

+00000131:   93DF      PUSH    R29            Push register on stack

+00000132:   93EF      PUSH    R30            Push register on stack

+00000133:   93FF      PUSH    R31            Push register on stack

60:               uTaskEntry = SP+19;

+00000134:   91200106    LDS   R18,0x0106       Load direct from data space

+00000136:   2FE2      MOV   R30,R18          Copy register

+00000137:   27FF      CLR   R31            Clear Register

+00000138:   0FEE      LSL   R30            Logical Shift Left

+00000139:   1FFF      ROL   R31            Rotate Left Through Carry

+0000013A:   50E0      SUBI    R30,0x00         Subtract immediate

+0000013B:   4FFF      SBCI    R31,0xFF         Subtract immediate with carry

+0000013C:   B78D      IN      R24,0x3D         In from I/O location

+0000013D:   B79E      IN      R25,0x3E         In from I/O location

+0000013E:   9643      ADIW    R24,0x13         Add immediate to word

+0000013F:   8391      STD   Z+1,R25          Store indirect with displacement

+00000140:   8380      STD   Z+0,R24          Store indirect with displacement

+00000141:   5F2F      SUBI    R18,0xFF         Subtract immediate

+00000142:   93200106    STS   0x0106,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000144:   91800107    LDS   R24,0x0107       Load direct from data space

+00000146:   1728      CP      R18,R24          Compare

+00000147:   F010      BRCS    PC+0x03          Branch if carry set

+00000148:   92100106    STS   0x0106,R1      Store direct to data space

62:               SP =uTaskEntry-19;

+0000014A:   91800106    LDS   R24,0x0106       Load direct from data space

+0000014C:   2FE8      MOV   R30,R24          Copy register

+0000014D:   27FF      CLR   R31            Clear Register

+0000014E:   0FEE      LSL   R30            Logical Shift Left

+0000014F:   1FFF      ROL   R31            Rotate Left Through Carry

+00000150:   50E0      SUBI    R30,0x00         Subtract immediate

+00000151:   4FFF      SBCI    R31,0xFF         Subtract immediate with carry

+00000152:   8180      LDD   R24,Z+0          Load indirect with displacement

+00000153:   8191      LDD   R25,Z+1          Load indirect with displacement

+00000154:   9743      SBIW    R24,0x13         Subtract immediate from word

+00000155:   BF9E      OUT   0x3E,R25         Out to I/O location

+00000156:   BF8D      OUT   0x3D,R24         Out to I/O location

64:               POP_ALL();

+00000157:   91FF      POP   R31            Pop register from stack

+00000158:   91EF      POP   R30            Pop register from stack

+00000159:   91DF      POP   R29            Pop register from stack

+0000015A:   91CF      POP   R28            Pop register from stack

+0000015B:   91BF      POP   R27            Pop register from stack

+0000015C:   91AF      POP   R26            Pop register from stack

+0000015D:   919F      POP   R25            Pop register from stack

+0000015E:   918F      POP   R24            Pop register from stack

+0000015F:   917F      POP   R23            Pop register from stack

+00000160:   916F      POP   R22            Pop register from stack

+00000161:   915F      POP   R21            Pop register from stack

+00000162:   914F      POP   R20            Pop register from stack

+00000163:   913F      POP   R19            Pop register from stack

+00000164:   912F      POP   R18            Pop register from stack

+00000165:   903F      POP   R3               Pop register from stack

+00000166:   902F      POP   R2               Pop register from stack

+00000167:   900F      POP   R0               Pop register from stack

+00000168:   BE0F      OUT   0x3F,R0          Out to I/O location

+00000169:   900F      POP   R0               Pop register from stack

+0000016A:   901F      POP   R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000016B:   BE12      OUT   0x32,R1          Out to I/O location

67:               asm("reti");

+0000016C:   9518      RETI                     Interrupt return

+0000016D:   9508      RET                      Subroutine return



中断函数出口处,需要将入栈的寄存器出栈,在出栈前更改堆栈指针SP,出栈后运行至asm("reti");后不会返回至Timer0的比较中断函数,而是直接运行至SP所指的位置,也就是每个任务在释放CPU控制权后保存的SP

zhudlmax 发表于 2006-12-6 18:15:02

uTaskEntry = SP+19;

保存中断前一个任务的SP



if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

如果每个任务已经执行了,重新从0号任务开始执行



SP =uTaskEntry-19;

获取即将执行的任务的SP



因为每个任务所处的环境不同,所以实际就是在进行任务切换前先保存刚刚执行过的任务环境,再取得已保存的下一个任务的环境,形成一个循环,这样的好处是很多的,比如说本任务处于一个等待状态,因为定时器的中断,将不会阻碍其他任务的执行,在工业控制中非常实用,而且工业控制中的实时性要求并不是很高,比如说I/O信号处理,间隔1ms采集一次远远足够。



各任务间的数据共享可以定义成全局变量如: volatile unsigned char ucCount;

volatile 不可少,至于作用,可以参考本站的许多帖子。



AVR系列在此的优势非常明显:大容量的RAM,这关系到任务数量

my_avr 发表于 2006-12-6 19:40:12

多谢楼主指点,不过我在#define PUSH_ALL() 和#define POP_ALL() 这两个宏的编译不能通过,语法错误,不知道什么问题。

zhudlmax 发表于 2006-12-6 20:15:25

什么错误?有可能是你在“\”后有空格符号,我遇到这样的情况

my_avr 发表于 2006-12-6 20:21:57

果然是空格多了,谢谢楼主,楼主大好人啊!

gdf78 发表于 2006-12-7 01:14:41

支持好贴!

morris 发表于 2006-12-7 02:49:04

樓主您好!想問問Inter Process Communication/Synchronization 在您的應用中怎樣實現?

yjbin 发表于 2006-12-7 10:25:58

盼望搂住给一个完整的应用程序啊,谢谢啊1

zhudlmax 发表于 2006-12-7 11:23:21

下面是我一台设备的程序(第二版本,第一台已经用于生产),程序完成量80%

功能:PS/2键盘输入,键F1设置设备的几个参数(需要密码,密码可以更改),键F2设备生产中需要改变的数据,有操作人员修改,其他的就是一些I/O信号的处理



// main



#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/eeprom.h>

#include <avr/pgmspace.h>



#include "RTOS_T0.h"

#include "1602LCD.h"

#include "Head.h"



void Task_ScanExPort(void)

{

        DDR_CS = 0x3F;

        PORT_CS = 0x00;       



        DisplayString(0,0,9, ucMachineInfo0);

        DisplayString(15,1,4, ucMachineInfo1);       

        delay_ms(500);



        LCD_Clean_Screen();

        DisplayString(0,0,10, ucMasterInfo0);

        DisplayString(10,1,10, ucMasterInfo1);

        delay_ms(500);



        sbi(PORT_CS, EP_LE);



        sbi(ucSystemFlag, SF_BE_LOG);



        unsigned char ucExPort_Temp;

        unsigned char ucExPort_Index;

        unsigned char ucExPort_PortValue;



TaskStart:



        for(ucExPort_Index = 0; ucExPort_Index < 8; ucExPort_Index++)

        {

                PORT_CS &= 0xF0;

                PORT_CS |= ucExPort_Index;



                if(ucExPort_Index >= 4)

                {

                        DDR_EP = 0xFF;               

                        PORT_EP = ucEP_OUT;               

                }       



                sbi(PORT_CS, CS_OE);

                asm("nop");                                // can not be ignore



                if(ucExPort_Index < 4)

                {

                        DDR_EP = 0x00;

                        PORT_EP = 0xFF;

                        asm("nop");



                        ucExPort_PortValue =~PIN_EP;



                        ucExPort_Temp = ucExPort_PortValue ^ ucEP_IN.ucPV;



                        ucEP_IN.ucBD        = ucExPort_Temp & ucEP_IN.ucPV;

                        ucEP_IN.ucBA        = ucExPort_Temp & ucExPort_PortValue;

                        ucEP_IN.ucPV        = ucExPort_PortValue;

                }

        }

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Keyboard(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



        DDRD &= 0xF3;

        PORTD |= 0x0C;



        MCUCR = (1<<ISC01);                                                                // INT0 下降沿触发

        GICR |= (1<<INT0);



        ucKeyPulse = 10;



TaskStart:



        if( ucKeyCode == F2 )                                                        // Menu Select

        {

                if( ucCurrentMenu == MENU_PROD )                        // Prod

                {       

                        sbi(ucSystemFlag, SF_BE_SET);

                        delay_ms(10);



                        LCD_Clean_Screen();

                        DisplayString(0,0,12, ucProdMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiProdQty);

                        ucCurrentMenu = MENU_TAIL;



                        MenuUpdate(MENU_PROD);                       

                }

                else if( ucCurrentMenu == MENU_TAIL )                // Tail

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucTailMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiTailQty);

                        ucCurrentMenu = MENU_LEAD;

                                               

                        MenuUpdate(MENU_TAIL);                       

                }

                else if( ucCurrentMenu == MENU_LEAD )                // Lead

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucLeadMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiLeadQty);                       

                        ucCurrentMenu = MENU_USET;



                        MenuUpdate(MENU_LEAD);                       

                }

                else if( ucCurrentMenu == MENU_USET )                // Return

                {                       

                        ucKeyCode = 0;

                        ucCurrentMenu = 0;

                        PrimalScreen();



                        cbi(ucSystemFlag, SF_BE_SET);

                }

        }

        else if(ucKeyCode == F1)

        {

                if( ucCurrentMenu == MENU_PW )                                // Password

                {

                        sbi(ucSystemFlag, SF_BE_SET);

                        delay_ms(10);



                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucPassword);

                        DisplayString(0,1,5, ucSetFlag);

                        DisplayString(16,1,4, ucPWS);

                        ucCurrentMenu = MENU_HD;                       



                        SetParameters(MENU_PW);

                }

                else if( ucCurrentMenu == MENU_HD )                        // Heat delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,14, ucHeat);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiHeatDly);                       

                        ucCurrentMenu = MENU_LD;



                        SetParameters(MENU_HD);                       

                }

                else if( ucCurrentMenu == MENU_LD )                        // load delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,14, ucLoad);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiLoadDly);

                        ucCurrentMenu = MENU_UD;



                        SetParameters(MENU_LD);                       

                }

                else if( ucCurrentMenu == MENU_UD )                        // unload delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,15, ucUnload);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiUnloadDly);                       

                        ucCurrentMenu = MENU_NP;



                        SetParameters(MENU_UD);                       

                }

                else if( ucCurrentMenu == MENU_NP )                        // New password

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,13, ucNewPWD);

                        DisplayString(0,1,5, ucSetFlag);

                        DisplayString(16,1,4, ucPWS);

                        ucCurrentMenu = MENU_USET;



                        SetParameters(MENU_NP);                       

                }

                else if( ucCurrentMenu == MENU_USET )                // Return

                {                       

                        ucKeyCode = 0;

                        ucCurrentMenu = 0;

                        PrimalScreen();



                        cbi(ucSystemFlag, SF_BE_SET);

                }

        }

        else if(ucKeyCode == F3 && ucErrorCode == 0)

        {

                if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) )

                {

                        ucKeyCode = 0;

                        sbi(ucSystemFlag, SF_BE_LEAD);

                        delay_ms(10);



                        ShowLead();

                       

                        while(true)

                        {

                                DisplayString(16,1,4, ucSpace);

                                LCD_DisplayNum(16,1, uiLeadResidual);

                               

                                delay_ms(2500);

                               

                                                               



                                if(ucKeyCode == ESC || uiLeadResidual == 0)

                                {

                                        ucKeyCode = 0;

                                        uiLeadResidual = uiLeadQty;

                                        break;

                                }



                                if(ucErrorCode)        break;



                                uiLeadResidual -= 3;

                        }



                        cbi(ucSystemFlag, SF_BE_LEAD);                       

                        PrimalScreen();

                        delay_ms(10);

                        cbi(ucSystemFlag, SF_BE_ERR);                       

                }

        }



        OS_CallNext();



        goto TaskStart;

}





void Task_System(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        if( bit_is_set(ucEP_IN.ucPV, IN_UNLOAD) )        sbi(ucEP_OUT, OUT_ENABLE_UNLOAD_MOTOR);

       

        if( bit_is_set(ucEP_IN.ucPV, IN_LOAD) )                sbi(ucEP_OUT, OUT_ENABLE_LOAD_MOTOR);       





        OS_CallNext();



        goto TaskStart;

}



void Task_Load(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        if( bit_is_clear(ucEP_IN.ucPV, IN_LOAD) )

        {

                if( bit_is_set(ucEP_OUT, OUT_ENABLE_LOAD_MOTOR) )

                {

                        delay_ms(uiLoadDly);

                        cbi(ucEP_OUT, OUT_ENABLE_LOAD_MOTOR);

                }

        }       

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Unload(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:       



        if( bit_is_clear(ucEP_IN.ucPV, IN_UNLOAD) )

        {

                if( bit_is_set(ucEP_OUT, OUT_ENABLE_UNLOAD_MOTOR) )

                {

                        delay_ms(uiUnloadDly);

                        cbi(ucEP_OUT, OUT_ENABLE_UNLOAD_MOTOR);

                }

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_SystemStatus(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



        unsigned char ucIndex;



TaskStart:



        if( bit_is_clear(ucEP_IN.ucPV, IN_SVO_IS_ON) )                        sbi(ucErrorCode, EC_SVO); else {cbi(ucErrorCode, EC_SVO);cbi(ucErrorFlag, EC_SVO);}



        if( bit_is_clear(ucEP_IN.ucPV, IN_HOST_READY) )                        sbi(ucErrorCode, EC_HRD); else {cbi(ucErrorCode, EC_HRD);cbi(ucErrorFlag, EC_HRD);}



        if( bit_is_set(ucEP_IN.ucPV, IN_NOT_AT_T_ALARM) )                 sbi(ucErrorCode, EC_NAT); else {cbi(ucErrorCode, EC_NAT);cbi(ucErrorFlag, EC_NAT);}



        if( bit_is_set(ucEP_IN.ucPV, IN_LOW_COVER_TAPE_ALARM) )         sbi(ucErrorCode, EC_LCT); else {cbi(ucErrorCode, EC_LCT);cbi(ucErrorFlag, EC_LCT);}

       

        if( bit_is_set(ucEP_IN.ucPV, IN_PART_UP_IN_TAPE_ALARM) )        sbi(ucErrorCode, EC_PIT); else {cbi(ucErrorCode, EC_PIT);cbi(ucErrorFlag, EC_PIT);}



        if( ucErrorCode )

        {

                if( bit_is_set(ucErrorCode, EC_MIS) )                        // Missing

                {

                        ucEP_OUT &= 0xF8;

                        ucEP_OUT |= 0x01;

                }

                else if( bit_is_set(ucErrorCode, EC_EXT) )                // Extra

                {

                        ucEP_OUT &= 0xF8;

                        ucEP_OUT |= 0x02;

                }

                else if( bit_is_set(ucErrorCode, EC_PIT) )                // Part up

                {

                        ucEP_OUT &= 0xF8;

                        ucEP_OUT |= 0x03;

                }

                else if( bit_is_set(ucErrorCode, EC_LCT) )                // Low cover tape

                {

                        ucEP_OUT &= 0xF8;

                        ucEP_OUT |= 0x06;

                }

                else if( bit_is_set(ucErrorCode, EC_NAT) )                // Not at temperature

                {

                        ucEP_OUT &= 0xF8;

                        ucEP_OUT |= 0x04;

                }

                else

                {

                        ucEP_OUT &= 0xF8;

                }



                for(ucIndex=0; ucIndex<7; ucIndex++)

                {

                        if( bit_is_set(ucErrorCode, ucIndex) )

                        {

                                ShowError(ucIndex);

                                break;

                        }

                }



                for(++ucIndex; ucIndex<7; ucIndex++)

                {

                        cbi(ucErrorFlag, ucIndex);

                }



                eoi(ucEP_OUT, OUT_SYSTEM_LED);

                delay_ms(250);



                cbi(ucSystemFlag, SF_BE_ERR);

        }

        else

        {

                sbi(ucEP_OUT, OUT_SYSTEM_LED);



                if( bit_is_clear(ucSystemFlag, SF_BE_ERR) && bit_is_clear(ucSystemFlag, SF_BE_SET) )

                {

                        PrimalScreen();

                        sbi(ucSystemFlag, SF_BE_ERR);

                }



                if( bit_is_clear(ucSystemFlag, SF_BE_SET) )

                {

                        if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) && bit_is_clear(ucSystemFlag, SF_BE_TAIL) ) ShowProdResidual();

                }

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_CamDisc(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        // Test code

        if( bit_is_set(ucEP_IN.ucBD, 7) )

        {

                uiProdResidual -= 3;



                if(uiProdResidual == 0) uiProdResidual = uiProdQty;

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_Miss_Extra(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        // Test code

        eoi(ucEP_OUT,0);

        delay_ms(100);



        OS_CallNext();



        goto TaskStart;

}





int main(void)

{

        LCD_Init();



        uiHeatDly = eeprom_read_word(0);

        uiLoadDly = eeprom_read_word(2);

        uiUnloadDly = eeprom_read_word(4);



        uiProdQty = uiProdResidual = eeprom_read_word(6);

        uiTailQty = uiTailResidual = eeprom_read_word(8);

        uiLeadQty = uiLeadResidual = eeprom_read_word(10);



        ucPWD = eeprom_read_byte(12);

        ucPWD = eeprom_read_byte(13);

        ucPWD = eeprom_read_byte(14);

        ucPWD = eeprom_read_byte(15);



        if(ucPWD == 0xFF) ucPWD = '1';

        if(ucPWD == 0xFF) ucPWD = '2';

        if(ucPWD == 0xFF) ucPWD = '3';

        if(ucPWD == 0xFF) ucPWD = '4';



        uTotalTaskNum = 0;

        uCurrentTaskID = 0;       

        OS_Timer0Init();

       

        OS_CreateTask(Task_ScanExPort, &uTaskStack);



        OS_CreateTask(Task_Keyboard, &uTaskStack);



        OS_CreateTask(Task_System, &uTaskStack);



        OS_CreateTask(Task_Load, &uTaskStack);



        OS_CreateTask(Task_Unload, &uTaskStack);



        OS_CreateTask(Task_SystemStatus, &uTaskStack);



        OS_CreateTask(Task_CamDisc, &uTaskStack);



        OS_CreateTask(Task_Miss_Extra, &uTaskStack);



        OS_Start();



        return(0);

}







// Head.h

#ifndef _HEAD_H

#define _HEAD_H





#define DDR_CS                DDRA

#define PORT_CS                PORTA

#define PIN_CS                PINA



#define DDR_EP                DDRB

#define PORT_EP                PORTB

#define PIN_EP                PINB



#define CS_OE                3

#define EP_LE                4       



//        PORTA

//        6,7:        NC

//        5:                A/B

//        4:                OUT_E

//        3:                OE1 138

//        A2-A0        addr



volatile struct PORT_EX_I

{

        unsigned char ucPV;

        unsigned char ucBA;                // Ascend

        unsigned char ucBD;                // Descend

}

ucEP_IN;



volatile unsigned char ucEP_OUT;



const unsigned char ucSetFlag PROGMEM = "";

const unsigned char ucErrFlag PROGMEM = "";

const unsigned char ucSucFlag PROGMEM = "";



const unsigned char ucMasterInfo0 PROGMEM = "Rising Sun";

const unsigned char ucMasterInfo1 PROGMEM = "Automation";



const unsigned char ucMachineInfo0 PROGMEM = "TAPE REEL";

const unsigned char ucMachineInfo1 PROGMEM = "V1.1";



const unsigned char ucProdMenu PROGMEM = "Product QTY:";

const unsigned char ucTailMenu PROGMEM = "Tail QTY:";

const unsigned char ucLeadMenu PROGMEM = "Lead QTY:";



const unsigned char ucPWS PROGMEM = "____";

const unsigned char ucPassword PROGMEM = "PASSWORD:";

const unsigned char ucHeat PROGMEM = "HEATER DELAY:";

const unsigned char ucLoad PROGMEM = "LOADER DELAY:";

const unsigned char ucUnload PROGMEM = "UNLOADER DELAY:";

const unsigned char ucNewPWD PROGMEM = "NEW PASSWORD:";



const unsigned char ucErr PROGMEM = "ERROR:";

const unsigned char ucErr_Code[] PROGMEM = {"SERVO OFF","HOST IS NOT READY","NOT AT TEMPERATURE","LOW COVER TAPE","PART UP IN TAPE","EXTRA PART","MISSING PART"};

const unsigned char ucErr_Leng = {9,17,18,14,15,10,12};



const unsigned char ucSpace PROGMEM = "                  ";



unsigned char ucStrTemp;



volatile unsigned char ucPWD;



volatile unsigned int uiHeatDly;

volatile unsigned int uiLoadDly;

volatile unsigned int uiUnloadDly;



volatile unsigned int uiProdQty;

volatile unsigned int uiProdResidual;

volatile unsigned int uiProdTemp;



volatile unsigned int uiTailQty;

volatile unsigned int uiTailResidual;



volatile unsigned int uiLeadQty;

volatile unsigned int uiLeadResidual;



volatile unsigned char ucKeyPulse;

volatile unsigned char ucKeyCode;

volatile unsigned char ucKeyFlag;

volatile unsigned char ucKeyTemp;





volatile unsigned char ucErrorFlag;

#define EF_BE_SVO        0

#define EF_BE_HRD        1

#define EF_BE_NAT        2

#define EF_BE_LCT        3

#define EF_BE_PIT        4

#define EF_BE_EXT        5

#define EF_BE_MIS        6

// 0: is svo on ?

// 1: is host ready ?

// 2: is not at temperatue ?

// 3: is low cover tape ?

// 4: is part up in tape ?

// 5: is extra part in tape ?

// 6: is missing part in tape



volatile unsigned char ucErrorCode;

#define EC_SVO        0

#define EC_HRD        1

#define EC_NAT        2

#define EC_LCT        3

#define EC_PIT        4

#define EC_EXT        5

#define EC_MIS        6

// 0: is servo on ?

// 1: is host ready ?

// 2: is not at temperature ?

// 3: is low cover tape ?

// 4: is part up in tape ?

// 5: is extra part in tape ?

// 6: is missing part in tape



volatile unsigned char ucSystemFlag;

#define SF_BE_LOG        0

#define SF_BE_SET        1

#define SF_BE_ERR        2

#define SF_BE_PROD        3

#define SF_BE_TAIL        4

#define SF_BE_LEAD        5

// 0: is finished to login ?

// 1: is in setting ?

// 2: is an error in system ?

// 3: is run porduct ?

// 4: is run tail ?

// 5: is run lead ?



volatile unsigned char ucCurrentMenu;

#define MENU_PROD        0

#define MENU_TAIL        1

#define MENU_LEAD        2

#define MENU_USET        0xFF



#define MENU_PW                0

#define MENU_HD                1

#define MENU_LD                2

#define MENU_UD                3

#define MENU_NP                4





#define true        1

#define false        0



#define KB_CLK        2

#define KB_DAT        3



#define F1                0xF1        //0x05

#define F2                0x06

#define F3                0x04

#define F4                0x0C

#define F5                0x03

#define F6                0x0B

#define N0                0x30        //0x70

#define N1                0x31        //0x69

#define N2                0x32        //0x72

#define N3                0x33        //0x7A

#define N4                0x34        //0x6B

#define N5                0x35        //0x73

#define N6                0x36        //0x74

#define N7                0x37        //0x6C

#define N8                0x38        //0x75

#define N9                0x39        //0x7D

#define ESC                0x76

#define ENTER        0x5A

#define POINT        0x71

#define CLEAR        0x66





//        Input Channel 0



#define        IN_LOAD                                                        0                // 上料传感器 OMRON EE-SX670A

#define IN_UNLOAD                                                1                // 下料传感器 OMRON EE-SX670A

#define IN_CAM_HIGH                                                2                // 凸轮高位          OMRON EE-SX670A

#define IN_CAM_LOW                                                3                // 凸轮低位          OMRON EE-SX670A



#define IN_NOT_AT_T_ALARM                                4                // 稳控器报警 OMRON E5GN

#define IN_LOW_COVER_TAPE_ALARM                        5                // 光纤传感器 KEYENCE FS-V12

#define IN_MISS_EXTRA_PART_ALARM                6                // 光纤传感器 KEYENCE FS-V12

#define IN_PART_UP_IN_TAPE_ALARM                7                // 光纤传感器 KEYENCE FS-V12



// Input Channel 1



#define IN_HOST_READY                                        0                // 主机就绪

#define IN_HOST_NEXT_STEP                                1                // 主机通知步进一步

#define IN_HOST_RESET_SIGNAL                        2                // 主机复位信号



#define IN_SVO_IS_READY                                        3                // SVO 就绪

#define IN_SVO_IS_ON                                        4                // SVO ON

#define IN_SVO_IS_TPOS                                        5                // SVO 目标位置到达

#define IN_SVO_IS_ALARM                                        6                // SVO 报警







// Output Channel 3



#define OUT_ENABLE_LOAD_MOTOR                        7                // 上料电机使能

#define OUT_ENABLE_UNLOAD_MOTOR                        6                // 下料电机使能

#define OUT_ENABLE_CAM_MOTOR                        5                // 凸轮电机使能

#define OUT_SYSTEM_LED                                        4                // 系统状态指示灯

#define OUT_ELEC_VALVE_PUSH                                3                // 汽缸电磁阀下推

#define OUT_ELEC_VALVE_PULL                                2                // 汽缸电磁阀上拉

#define OUT_SVO_CTRG                                        1                // SVO 步进触发

#define OUT_SVO_RESET                                        0                // SVO 错误复位

                                       

// Output Channel 2

#define OUT_HOST_WAIT_FOR_TAIL                        5                // HOST 701

#define OUT_HOST_WAIT_FOR_NEXT_PART                4                // HOST 702

#define OUT_HOST_WAIT_FOR_NEXT_LOT                3                // HOST 703

#define OUT_HOST_ALARM_BIT6                                2                // HOST 704

#define OUT_HOST_ALARM_BIT5                                1                // HOST 705

#define OUT_HOST_ALARM_BIT4                                0                // HOST 706



//                                                4        5        6

//                                1                0        0        1        : Missing part in Tape

//                                2                0        1        0        : Extra part in tape               

//                                3                0        1        1        : Part up in tape

//                                4                1        0        0        : Not at temperature       

//                                5                1        0        1        : Tape Index Failure                       

//                                6                1        1        0        : Low cover tape               





void DisplayString(unsigned char X, unsigned char Y, unsigned char ucLen, const prog_uchar* ucString)

{

        unsigned char n;

        for(n=0;n<20;n++) ucStrTemp = 0;



        memcpy_P(ucStrTemp, ucString, ucLen);

        LCD_DisplayString(X,Y, ucStrTemp);

}





void ShowProd(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,12, ucProdMenu);

        LCD_DisplayNum(0,1, uiProdQty);

        LCD_DisplayNum(16,1, uiProdResidual);       

}



void ShowTail(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,9, ucTailMenu);

        LCD_DisplayNum(0,1, uiTailQty);

        LCD_DisplayNum(16,1, uiTailResidual);       

}



void ShowLead(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,9, ucLeadMenu);

        LCD_DisplayNum(0,1, uiLeadQty);

        LCD_DisplayNum(16,1, uiLeadResidual);       

}



void ShowProdResidual(void)

{

        if(uiProdTemp != uiProdResidual)

        {

                DisplayString(16,1,4, ucSpace);

                LCD_DisplayNum(16,1, uiProdResidual);

                uiProdTemp = uiProdResidual;

        }

}



void PrimalScreen(void)

{

        if(ucErrorCode)

        {

                ucErrorFlag = 0;        // reset error flag that show error

        }

        else

        {

                if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) && bit_is_clear(ucSystemFlag, SF_BE_TAIL) ) ShowProd();

        }

}



void EscMenu(void)

{

        ucCurrentMenu = 0;

       

        PrimalScreen();



        cbi(ucSystemFlag, SF_BE_SET);

}



void SetERR(void)

{

        DisplayString(0,1,5, ucErrFlag);

        delay_ms(500);

        DisplayString(0,1,5, ucSetFlag);

}



void SetSUC(void)

{

        DisplayString(0,1,5, ucSucFlag);

        delay_ms(500);       

}



void SetParameters(unsigned char ucParaIndex)

{

        unsigned char ucPos = 0;

        unsigned int ucTemp = 0;       

        unsigned char ucIndex = 0;

        unsigned char ucInput;       



        while(true)

        {

                ucKeyCode = 0;       

                while(!ucKeyCode);                                // wait_until_key_is_pressed               



                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                {

                        if(ucParaIndex == MENU_PW || ucParaIndex == MENU_NP)

                        {

                                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                                {

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command('*', 1);                                       

                                        ucInput = ucKeyCode;

                                }

                        }

                        else

                        {                       

                                if(ucPos)

                                {

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command(ucKeyCode, 1);                                       

                                        ucInput = ucKeyCode-0x30;

                                }

                                else if(!ucPos && ucKeyCode != N0)

                                {

                                        DisplayString(16,1,4, ucSpace);

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command(ucKeyCode, 1);

                                        ucInput = ucKeyCode-0x30;

                                }

                        }

                }

                else if(ucKeyCode == ENTER)

                {

                        if(ucParaIndex == MENU_PW)

                        {

                                for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                                {

                                        if(ucPWD != ucInput)

                                        {

                                                SetERR();



                                                DisplayString(16,1,4, ucPWS);                                               

                                                break;

                                        }



                                        ucInput = 0;

                                }



                                ucPos = 0;



                                if(ucIndex == 4)

                                {

                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }                               

                        }

                        else if(ucParaIndex == MENU_NP)

                        {

                                if(ucPos < 4)

                                {

                                        SetERR();



                                        DisplayString(16,1,4, ucPWS);                                       

                                        ucPos = 0;                                                                                                       

                                }

                                else

                                {

                                        eeprom_write_byte(12, ucInput);

                                        eeprom_write_byte(13, ucInput);

                                        eeprom_write_byte(14, ucInput);

                                        eeprom_write_byte(15, ucInput);



                                        ucPWD = ucInput;

                                        ucPWD = ucInput;

                                        ucPWD = ucInput;

                                        ucPWD = ucInput;

                                       

                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }



                                for(ucIndex = 0; ucIndex < 4; ucIndex++) ucInput = 0;                               

                        }

                        else

                        {

                                ucTemp = 0;

                                for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                                {

                                        ucTemp = ucTemp*10 + ucInput;

                                        ucInput = 0;

                                }

                                       

                                if( ucTemp < 50)

                                {

                                        SetERR();

                       

                                        if(ucParaIndex == MENU_HD)                         LCD_DisplayNum(16,1, uiHeatDly);

                                        else if(ucParaIndex == MENU_LD)         LCD_DisplayNum(16,1, uiLoadDly);

                                        else if(ucParaIndex == MENU_UD)         LCD_DisplayNum(16,1, uiUnloadDly);

                                               

                                        ucPos = 0;

                                        ucTemp = 0;

                                }

                                else

                                {

                                        if(ucParaIndex == MENU_HD)

                                        {

                                                uiHeatDly = ucTemp;

                                                eeprom_write_word(0, ucTemp);

                                        }

                                        else if(ucParaIndex == MENU_LD)

                                        {

                                                uiLoadDly = ucTemp;

                                                eeprom_write_word(2, ucTemp);

                                        }

                                        else if(ucParaIndex == MENU_UD)

                                        {

                                                uiUnloadDly = ucTemp;

                                                eeprom_write_word(4, ucTemp);

                                        }



                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }

                        }                                       

                }

                else if(ucKeyCode == ESC)

                {

                        delay_ms(10);

                        EscMenu();

                        break;

                }

                else if(ucKeyCode == CLEAR)

                {

                        if(ucParaIndex == MENU_PW || ucParaIndex == MENU_NP)

                        {       

                                if(ucPos)

                                {

                                        --ucPos;



                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command('_', 1);

                                        ucInput = 0;

                                }

                        }

                        else

                        {

                                DisplayString(16,1,4, ucSpace);



                                ucTemp = 0;

                                for(ucIndex = 0; ucIndex < ucPos-1; ucIndex++)

                                {

                                        ucTemp = ucTemp*10 + ucInput;

                                }



                                if(ucPos)        ucPos--;

                                ucInput = 0;



                                LCD_DisplayNum(16,1, ucTemp);

                        }

                }

                else if(ucKeyCode == F1 && ucPos == 0 && ucParaIndex != MENU_PW)

                {

                        ucKeyCode = F1;

                        break;

                }

        }               

}



void MenuUpdate(unsigned char ucMenuIndex)

{

        unsigned char ucPos = 0;

        unsigned int ucTemp = 0;       

        unsigned char ucIndex = 0;

        unsigned char ucInput;       



        while(true)

        {

                ucKeyCode = 0;       

                while(!ucKeyCode);                                // wait_until_key_is_pressed               



                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                {

                        if(ucPos)

                        {

                                LCD_Set_XY(16+ucPos, 1);

                                LCD_Send_Command(ucKeyCode, 1);

                                ucInput = ucKeyCode-0x30;

                        }



                        else

                                               

                        if(!ucPos && ucKeyCode != N0)

                        {

                                DisplayString(16,1,4, ucSpace);

                                LCD_Set_XY(16+ucPos, 1);

                                LCD_Send_Command(ucKeyCode, 1);

                                ucInput = ucKeyCode-0x30;

                        }

                }

                else if(ucKeyCode == ENTER)

                {

                        ucTemp = 0;

                        for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                        {

                                ucTemp = ucTemp*10 + ucInput;

                                ucInput = 0;

                        }

                                       

                        if( ucTemp%3 || ucTemp==0)

                        {

                                SetERR();

                       

                                if(ucMenuIndex == MENU_PROD)                 LCD_DisplayNum(16,1, uiProdQty);

                                else if(ucMenuIndex == MENU_TAIL)         LCD_DisplayNum(16,1, uiTailQty);

                                else if(ucMenuIndex == MENU_LEAD)         LCD_DisplayNum(16,1, uiLeadQty);

                                               

                                ucPos = 0;

                                ucTemp = 0;

                        }

                        else

                        {

                                if(ucMenuIndex == MENU_PROD)

                                {

                                        uiProdQty = uiProdResidual = ucTemp;

                                        eeprom_write_word(6, ucTemp);

                                }

                                else if(ucMenuIndex == MENU_TAIL)

                                {

                                        uiTailQty = uiTailResidual = ucTemp;

                                        eeprom_write_word(8, ucTemp);

                                }

                                else if(ucMenuIndex == MENU_LEAD)

                                {

                                        uiLeadQty = uiLeadResidual = ucTemp;

                                        eeprom_write_word(10, ucTemp);

                                }



                                SetSUC();



                                ucKeyCode = F2;



                                break;

                        }                                       

                }

                else if(ucKeyCode == ESC)

                {

                        delay_ms(10);

                        EscMenu();                               

                        break;

                }

                else if(ucKeyCode == CLEAR)

                {

                        DisplayString(16,1,4, ucSpace);



                        ucTemp = 0;

                        for(ucIndex = 0; ucIndex < ucPos-1; ucIndex++)

                        {

                                ucTemp = ucTemp*10 + ucInput;

                        }



                        if(ucPos)        ucPos--;

                        ucInput = 0;



                        LCD_DisplayNum(16,1, ucTemp);



                }

                else if(ucKeyCode == F2 && ucPos == 0)

                {

                        ucKeyCode = F2;

                        break;

                }

        }       

}



void ShowError(unsigned char ucCode)

{

        if( bit_is_clear(ucErrorFlag, ucCode) && bit_is_clear(ucSystemFlag, SF_BE_SET) )

        {

                LCD_Clean_Screen();

                DisplayString(0,0,6, ucErr);

                DisplayString(20-ucErr_Leng,1,ucErr_Leng, ucErr_Code);



                sbi(ucErrorFlag, ucCode);

        }

}



SIGNAL(SIG_INTERRUPT0)

{

        if( ucKeyPulse < 8 )                        // Data

        {

                if( bit_is_set(PIND, KB_DAT) ) sbi(ucKeyTemp, ucKeyPulse);

                else cbi(ucKeyTemp, ucKeyPulse);



                ++ucKeyPulse;

        }

        else



        if( ucKeyPulse == 8)                        // Parity

        {

                ++ucKeyPulse;

        }



        else



        if( ucKeyPulse == 9)                        // Stopbit

        {

                if( bit_is_set(PIND, KB_DAT) )

                {

                        if( ucKeyTemp == 0xE0 )

                        {

                                ucKeyFlag = 1;

                        }

                        else if( ucKeyTemp == 0xF0 )

                        {

                                ucKeyFlag = 2;

                        }

                        else

                        {

                                if(ucKeyFlag)

                                {

                                        if(ucKeyFlag == 2)

                                        {

                                                if(ucKeyTemp == ENTER) ucKeyCode = ENTER;

                                        }

                                       

                                        ucKeyFlag = 0;

                                }

                                else

                                {

                                        if(ucKeyTemp == 0x70)                 ucKeyCode = N0;

                                        else if(ucKeyTemp == 0x69)         ucKeyCode = N1;

                                        else if(ucKeyTemp == 0x72)         ucKeyCode = N2;

                                        else if(ucKeyTemp == 0x7A)         ucKeyCode = N3;

                                        else if(ucKeyTemp == 0x6B)         ucKeyCode = N4;

                                        else if(ucKeyTemp == 0x73)         ucKeyCode = N5;

                                        else if(ucKeyTemp == 0x74)         ucKeyCode = N6;

                                        else if(ucKeyTemp == 0x6C)         ucKeyCode = N7;

                                        else if(ucKeyTemp == 0x75)         ucKeyCode = N8;

                                        else if(ucKeyTemp == 0x7D)         ucKeyCode = N9;

                                        else if(ucKeyTemp == 0x05)        ucKeyCode = F1;

                                        else                                                ucKeyCode = ucKeyTemp;

                                }

                        }



                }



                ++ucKeyPulse;

        }



        else



        if( ucKeyPulse == 10)                        // Startbit

        {

                if( bit_is_clear(PIND, KB_DAT) )ucKeyPulse = 0;

        }

}





#endif



// 1602LCD_H





#ifndef _1602LCD_H

#define _1602LCD_H



//                PORTD

//                 1:        E                        read(1->0); write(1);

//

//                0:        RS                        0:        read( p->address counter )

//                                                write( p->command register)

//                                        1:        p->data register

//                4-7: DATA



#define LCD_PORT        PORTD

#define LCD_DDR                DDRD



#define LCD_E        1

#define LCD_RS        0



#define NumL        4

#define LCD_DELAY_TIME        2



extern void LCD_Init();

extern void LCD_DisplayString(unsigned char X, unsigned char Y, unsigned char* uString);

extern void LCD_DisplayNum(unsigned char X, unsigned char Y, unsigned int ulNum);



void LCD_Clean_Screen();

void LCD_Set_XY(unsigned char X, unsigned char Y);

void LCD_Send_Command(unsigned char udata, unsigned char uCode);



#define sbi(Port, Bit)        (Port |= (1<<Bit))       

#define cbi(Port, Bit)        (Port &= ~(1<<Bit))       

#define eoi(Port, Bit)        (Port ^= (1<<Bit))

#define IsTrue(Pin, Bit)        (Pin & (1<<Bit) )



#endif





// 1602LCD.c

//        ************************************        1602 LCD Drive        ************************************



#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include "1602LCD.h"

#include "RTOS_T0.h"



//        uCode = 0:        Send Command

//        uCode = 1:        Send Data



void LCD_Send_Command(unsigned char udata, unsigned char uCode)

{

        if(uCode)        sbi(LCD_PORT, LCD_RS);

        else                cbi(LCD_PORT, LCD_RS);



        LCD_PORT &= 0x0F;                                                // HIGH

        LCD_PORT |= (udata & 0xF0);       

        sbi(LCD_PORT, LCD_E);

        cbi(LCD_PORT, LCD_E);

       

        LCD_PORT &= 0x0F;                                                // LOW

        LCD_PORT |= (udata << 4);       

        sbi(LCD_PORT, LCD_E);

        cbi(LCD_PORT, LCD_E);



        cbi(LCD_PORT, LCD_RS);



        delay_ms(LCD_DELAY_TIME);       

}



void LCD_Clean_Screen()

{

        LCD_Send_Command(0x01, 0);       

}



void LCD_Set_XY(unsigned char X, unsigned char Y)

{

        if( Y )        X = 0xc0 + X;

        else         X = 0x80 + X;



        LCD_Send_Command(X, 0);

}



void LCD_DisplayString(unsigned char X, unsigned char Y, unsigned char* uString)

{

        LCD_Set_XY(X, Y);

       

        while( *uString )

        {

                LCD_Send_Command(*uString, 1);

                *uString++;

        }

}



void LCD_DisplayNum(unsigned char X, unsigned char Y, unsigned int ulNum)

{

        LCD_Set_XY(X, Y);



        unsigned char i;

        unsigned char charNum;



        for(i=0; i < NumL; i++)

        {

                charNum = 0x30 + ulNum%10;

                ulNum = ulNum/10;

        }



        for(i = 0; i < NumL-1; i++)

        {

                if(charNum != 0x30)        break;                               

        }       



        for(; i < NumL; i++)

        {

                LCD_Send_Command(charNum, 1);

        }

}



void LCD_Init()

{

        LCD_DDR = 0b11110011;



        delay_ms(500);

               

        LCD_Send_Command(0x33, 0);

        LCD_Send_Command(0x32, 0);

        LCD_Send_Command(0x28, 0);

        LCD_Send_Command(0x0C, 0);



        LCD_Clean_Screen();

}



//        ************************************        LCD Drive End        ************************************



RTOS部分就是前面提到的那些了,仅参考

badboy7903 发表于 2006-12-7 11:24:57

register unsigned char ---tempR16--- asm("r16");

register unsigned char ---tempR16--- asm("r17");

正确吗?

zhudlmax 发表于 2006-12-7 11:31:36

不正确,前面说过了,应该是:

register unsigned char ---tempR16--- asm("r16");   

register unsigned char ---tempR17--- asm("r17");

avr-qq 发表于 2006-12-8 14:44:03

3Q

jackiezeng 发表于 2006-12-8 21:22:29

TOzhudlmax



好人 啊 ,这个 例子 好 ,DOWN下 来 好好 研究 ~!



另外 , 我也 有个 设备是 用 PC 键盘 控制 的 ,PS2 键盘做好 了 , 但是 现在 要兼容 AT,XT , VT 键盘 ,你有没有 XT, VT键盘的 资料 或者 是 键盘实体 呢 ?

yjbin 发表于 2006-12-8 22:59:01

楼主啊,谢谢啊!能不能提供打包下载啊?不好意思了!

archeng504 发表于 2006-12-8 23:41:42

高手!!作个 标记,有空来看看!!

zhudlmax 发表于 2006-12-9 02:33:58

TO:jackiezeng,键盘协议见附件



TO:yjbin,所以代码以在上列出,你可以复制过去的



因现在工作比较忙,相机也被朋友借走了,等几天,上传点实际的东东给大伙瞧瞧,在此谢谢大家的支持





点击此处打开armok01137597.pdf

shusheng 发表于 2006-12-9 11:11:58

有几个问题请楼主指点一下



#define Task_Stack_Size   50      为什么要定义为50呢?这个数是怎么样计算得到的?



// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间

register unsigned char tempR4asm("r4");

register unsigned char tempR5asm("r5");

register unsigned char tempR6asm("r6");

register unsigned char tempR7asm("r7");

register unsigned char tempR8asm("r8");

register unsigned char tempR9asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");



为什么要禁用这些寄存器呢,而不是其他?

zhb2000 发表于 2006-12-9 12:38:20

我以前也写过类似的贴子,为什么就没被站长评为"酷"呢? 



OS学习初探 --- 时间片轮转调度 (GCC)

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=663028&bbs_page_no=1&bbs_id=1000



呵呵,开个玩笑. :)



前段我也在研究这个,现在好久没搞了.希望楼主继续下去.

zhudlmax 发表于 2006-12-9 19:13:55

我参考的是:《建立一个属于自己的AVR的RTOS》



点击此处下载armok01137640.htm



TO:shusheng 书生



#define Task_Stack_Size   50



每个任务中因OS_ScheduleTask()会占用固定数量的RAM,再加上每个任务自己独立需要占有的RAM,其实具体到底占有多少我没研究过,但假如Task_Stack_Size设置过低,系统程序就无法运行,按照我上面公布的程序,给每个任务分配了相同的RAM,因任务占有的RAM不一定一样,所以对RAM资源的利用有一定的浪费,不过假如系统RAM资源很丰富,也没必要去斤斤计较,OS_ScheduleTask更安全的代码可以写成如下方式:



void OS_ScheduleTask(void)

{

        asm("PUSH        R2               
\t");

        asm("PUSH        R3               
\t");

        asm("PUSH        R4               
\t");

        asm("PUSH        R5               
\t");

        asm("PUSH        R6               
\t");

        asm("PUSH        R7               
\t");

        asm("PUSH        R8               
\t");

        asm("PUSH        R9               
\t");

        asm("PUSH        R10               
\t");

        asm("PUSH        R11               
\t");

        asm("PUSH        R12               
\t");

        asm("PUSH        R13               
\t");

        asm("PUSH        R14               
\t");

        asm("PUSH        R15               
\t");

        asm("PUSH        R16               
\t");

        asm("PUSH        R17               
\t");

        asm("PUSH        R18               
\t");

        asm("PUSH        R19               
\t");

        asm("PUSH        R20               
\t");

        asm("PUSH        R21               
\t");

        asm("PUSH        R22               
\t");

        asm("PUSH        R23               
\t");

        asm("PUSH        R24               
\t");

        asm("PUSH        R25               
\t");

        asm("PUSH        R26               
\t");

        asm("PUSH        R27               
\t");

        asm("PUSH        R28               
\t");

        asm("PUSH        R29               
\t");

        asm("PUSH        R30               
\t");

        asm("PUSH        R31               
\t");





        TaskCtrlBlock.uTaskStackEntry = SP+33;



        if(uCurrentTask >= uValidTaskIndex-1) uCurrentTask=0;

        else        uCurrentTask++;



        SP = TaskCtrlBlock.uTaskStackEntry;



        SP -= 33;





        asm("POP        R31               
\t");

        asm("POP        R30               
\t");

        asm("POP        R29               
\t");

        asm("POP        R28               
\t");

        asm("POP        R27               
\t");

        asm("POP        R26               
\t");

        asm("POP        R25               
\t");

        asm("POP        R24               
\t");

        asm("POP        R23               
\t");

        asm("POP        R22               
\t");

        asm("POP        R21               
\t");

        asm("POP        R20               
\t");

        asm("POP        R19               
\t");

        asm("POP        R18               
\t");

        asm("POP        R17               
\t");

        asm("POP        R16               
\t");

        asm("POP        R15               
\t");

        asm("POP        R14               
\t");

        asm("POP        R13               
\t");

        asm("POP        R12               
\t");

        asm("POP        R11               
\t");

        asm("POP        R10               
\t");

        asm("POP        R9               
\t");

        asm("POP        R8               
\t");

        asm("POP        R7               
\t");

        asm("POP        R6               
\t");

        asm("POP        R5               
\t");

        asm("POP        R4               
\t");

        asm("POP        R3               
\t");

        asm("POP        R2               
\t");



        asm("POP        R0               
\t");               

        asm("OUT        0x3F,R0       
\t");               

        asm("POP        R0               
\t");

        asm("POP        R1               
\t");



        TCNT0 = 0;

        asm("reti       
\t");

}



在此希望大家多多参与,优化、强大此系统,在应用中,一个好的稳定简洁的系统对于开发来说更为重要,想得更远,某天,MS倒闭...,呵呵~~~~也不是不可能啊,不过那得靠团队精神,好象对于中国人,很现实的说法是:一个中国人是条龙,一群中国人是一堆虫,扯远了,无意冒犯,别扔鸡蛋...呵呵

zhudlmax 发表于 2006-12-9 19:17:46

To: zhb2000



OS思路跟您的一模一样,我参考的是《建立一个属于自己的AVR的RTOS》作者是不是armok啊?

shusheng 发表于 2006-12-10 13:11:54

谢谢先

还有个问题 "每个任务自己独立需要占有的RAM" 是不是指在那个任务里面定义的局部变量?还是指其他变量?

jackiezeng 发表于 2006-12-11 13:59:38

楼主大哥,

       您能不能打个包, 传上来呢 ?我编译出现很多的警告, 我的水平低啊 ~!



还有就是你上传的那个是 PS/2 的资料, 你有没有 XT , VT 键盘的资料呢?

my_avr 发表于 2006-12-11 15:21:08

楼主指导一下:

uTaskEntry = SP+19;

后面的系数19是怎么算出来的,我弄了半天都没弄明白。谢谢!

zhudlmax 发表于 2006-12-11 20:20:37

看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:



.....



register unsigned char tempR2asm("r2");

register unsigned char tempR3asm("r3");

register unsigned char tempR4asm("r4");

register unsigned char tempR5asm("r5");

register unsigned char tempR6asm("r6");

register unsigned char tempR7asm("r7");

register unsigned char tempR8asm("r8");

register unsigned char tempR9asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR17 asm("r17");

register unsigned int tempRY   asm("r28");





#define PUSH_ALL()                                        \

asm volatile(                                                \

"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        R30"        "
\t"                                \

"PUSH        R31"        "
\t"                                \

)                                                                        \



#define        POP_ALL()                                        \

asm volatile(                                                \

"POP        R31"                "
\t"                        \

"POP        R30"                "
\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        R0"                        "
\t"                        \

"OUT        0x3F,R0"        "
\t"                        \

"POP        R0"                        "
\t"                        \

"POP        R1"                        "
\t"                        \

)



.......





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =uTaskEntry-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



.....



在AVR GCC中对寄存器的描述是这样的:



r0      可用做暂时寄存器。如果用户汇编代码使用了r0,且要调用C代码,则在调用之前必须保存r0。C中断例程会自动保存和恢复r0。



r1      C编译器假定此寄存器内容为“0”。如果用户使用了此寄存器,则在汇编代码返回之前须将其清零。C中断例程会自动保存和恢复r1。



r2-r17,r28,r29          C编译器使用这些寄存器。如果用户汇编代码需要使用这些寄存器,则必须保存并恢复这些寄存器。



R18-r27,r30,r31 如果用户汇编代码不调用C代码则无需保存和恢复这些寄存器。如果用户要调用C代码,则在调用之前须保存。





uTaskEntry = SP+15;



加减15的原因:先看GCC编译的汇编



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



@000002B0: __vector_19

22:       {

+000002B0:   921F      PUSH    R1               Push register on stack

+000002B1:   920F      PUSH    R0               Push register on stack

+000002B2:   B60F      IN      R0,0x3F          In from I/O location

+000002B3:   920F      PUSH    R0               Push register on stack

+000002B4:   2411      CLR   R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000002B5:   940C02E6    JMP   0x000002E6       Jump

+000002B7:   900F      POP   R0               Pop register from stack

+000002B8:   BE0F      OUT   0x3F,R0          Out to I/O location

+000002B9:   900F      POP   R0               Pop register from stack

+000002BA:   901F      POP   R1               Pop register from stack

+000002BB:   9518      RETI                     Interrupt return



....





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =uTaskEntry-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



@0000030D: OS_ScheduleTask

57:       {

+0000030D:   932F      PUSH    R18            Push register on stack

+0000030E:   933F      PUSH    R19            Push register on stack

+0000030F:   934F      PUSH    R20            Push register on stack

+00000310:   935F      PUSH    R21            Push register on stack

+00000311:   936F      PUSH    R22            Push register on stack

+00000312:   937F      PUSH    R23            Push register on stack

+00000313:   938F      PUSH    R24            Push register on stack

+00000314:   939F      PUSH    R25            Push register on stack

+00000315:   93AF      PUSH    R26            Push register on stack

+00000316:   93BF      PUSH    R27            Push register on stack

+00000317:   93EF      PUSH    R30            Push register on stack

+00000318:   93FF      PUSH    R31            Push register on stack

60:               uTaskEntry = SP+15;

+00000319:   912002F1    LDS   R18,0x02F1       Load direct from data space

+0000031B:   2FE2      MOV   R30,R18          Copy register

+0000031C:   27FF      CLR   R31            Clear Register

+0000031D:   0FEE      LSL   R30            Logical Shift Left

+0000031E:   1FFF      ROL   R31            Rotate Left Through Carry

+0000031F:   51EF      SUBI    R30,0x1F         Subtract immediate

+00000320:   4FFD      SBCI    R31,0xFD         Subtract immediate with carry

+00000321:   B78D      IN      R24,0x3D         In from I/O location

+00000322:   B79E      IN      R25,0x3E         In from I/O location

+00000323:   960F      ADIW    R24,0x0F         Add immediate to word

+00000324:   8391      STD   Z+1,R25          Store indirect with displacement

+00000325:   8380      STD   Z+0,R24          Store indirect with displacement

+00000326:   5F2F      SUBI    R18,0xFF         Subtract immediate

+00000327:   932002F1    STS   0x02F1,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000329:   918002F3    LDS   R24,0x02F3       Load direct from data space

+0000032B:   1728      CP      R18,R24          Compare

+0000032C:   F010      BRCS    PC+0x03          Branch if carry set

+0000032D:   921002F1    STS   0x02F1,R1      Store direct to data space

62:               SP =uTaskEntry-15;

+0000032F:   918002F1    LDS   R24,0x02F1       Load direct from data space

+00000331:   2FE8      MOV   R30,R24          Copy register

+00000332:   27FF      CLR   R31            Clear Register

+00000333:   0FEE      LSL   R30            Logical Shift Left

+00000334:   1FFF      ROL   R31            Rotate Left Through Carry

+00000335:   51EF      SUBI    R30,0x1F         Subtract immediate

+00000336:   4FFD      SBCI    R31,0xFD         Subtract immediate with carry

+00000337:   8180      LDD   R24,Z+0          Load indirect with displacement

+00000338:   8191      LDD   R25,Z+1          Load indirect with displacement

+00000339:   970F      SBIW    R24,0x0F         Subtract immediate from word

+0000033A:   BF9E      OUT   0x3E,R25         Out to I/O location

+0000033B:   BF8D      OUT   0x3D,R24         Out to I/O location

64:               POP_ALL();

+0000033C:   91FF      POP   R31            Pop register from stack

+0000033D:   91EF      POP   R30            Pop register from stack

+0000033E:   91BF      POP   R27            Pop register from stack

+0000033F:   91AF      POP   R26            Pop register from stack

+00000340:   919F      POP   R25            Pop register from stack

+00000341:   918F      POP   R24            Pop register from stack

+00000342:   917F      POP   R23            Pop register from stack

+00000343:   916F      POP   R22            Pop register from stack

+00000344:   915F      POP   R21            Pop register from stack

+00000345:   914F      POP   R20            Pop register from stack

+00000346:   913F      POP   R19            Pop register from stack

+00000347:   912F      POP   R18            Pop register from stack

+00000348:   900F      POP   R0               Pop register from stack

+00000349:   BE0F      OUT   0x3F,R0          Out to I/O location

+0000034A:   900F      POP   R0               Pop register from stack

+0000034B:   901F      POP   R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000034C:   BE12      OUT   0x32,R1          Out to I/O location

67:               asm("reti");

+0000034D:   9518      RETI                     Interrupt return

+0000034E:   9508      RET                      Subroutine return



....



执行PUSH后 SP+1,执行POP后 SP-1, 中断处理中最明显的特征就是保存与恢复现场环境。

zhudlmax 发表于 2006-12-11 20:41:35

看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:



.....



register unsigned char tempR2asm("r2");

register unsigned char tempR3asm("r3");

register unsigned char tempR4asm("r4");

register unsigned char tempR5asm("r5");

register unsigned char tempR6asm("r6");

register unsigned char tempR7asm("r7");

register unsigned char tempR8asm("r8");

register unsigned char tempR9asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR17 asm("r17");

register unsigned int tempRY   asm("r28");





#define PUSH_ALL()                                        \

asm volatile(                                                \

"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        R30"        "
\t"                                \

"PUSH        R31"        "
\t"                                \

)                                                                        \



#define        POP_ALL()                                        \

asm volatile(                                                \

"POP        R31"                "
\t"                        \

"POP        R30"                "
\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        R0"                        "
\t"                        \

"OUT        0x3F,R0"        "
\t"                        \

"POP        R0"                        "
\t"                        \

"POP        R1"                        "
\t"                        \

)



.......





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =uTaskEntry-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



.....



在AVR GCC中对寄存器的描述是这样的:



r0      可用做暂时寄存器。如果用户汇编代码使用了r0,且要调用C代码,则在调用之前必须保存r0。C中断例程会自动保存和恢复r0。



r1      C编译器假定此寄存器内容为“0”。如果用户使用了此寄存器,则在汇编代码返回之前须将其清零。C中断例程会自动保存和恢复r1。



r2-r17,r28,r29          C编译器使用这些寄存器。如果用户汇编代码需要使用这些寄存器,则必须保存并恢复这些寄存器。



R18-r27,r30,r31 如果用户汇编代码不调用C代码则无需保存和恢复这些寄存器。如果用户要调用C代码,则在调用之前须保存。





uTaskEntry = SP+15;



加减15的原因:先看GCC编译的汇编



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



@000002B0: __vector_19

22:       {

+000002B0:   921F      PUSH    R1               Push register on stack

+000002B1:   920F      PUSH    R0               Push register on stack

+000002B2:   B60F      IN      R0,0x3F          In from I/O location

+000002B3:   920F      PUSH    R0               Push register on stack

+000002B4:   2411      CLR   R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000002B5:   940C02E6    JMP   0x000002E6       Jump

+000002B7:   900F      POP   R0               Pop register from stack

+000002B8:   BE0F      OUT   0x3F,R0          Out to I/O location

+000002B9:   900F      POP   R0               Pop register from stack

+000002BA:   901F      POP   R1               Pop register from stack

+000002BB:   9518      RETI                     Interrupt return



....





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =uTaskEntry-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



@0000030D: OS_ScheduleTask

57:       {

+0000030D:   932F      PUSH    R18            Push register on stack

+0000030E:   933F      PUSH    R19            Push register on stack

+0000030F:   934F      PUSH    R20            Push register on stack

+00000310:   935F      PUSH    R21            Push register on stack

+00000311:   936F      PUSH    R22            Push register on stack

+00000312:   937F      PUSH    R23            Push register on stack

+00000313:   938F      PUSH    R24            Push register on stack

+00000314:   939F      PUSH    R25            Push register on stack

+00000315:   93AF      PUSH    R26            Push register on stack

+00000316:   93BF      PUSH    R27            Push register on stack

+00000317:   93EF      PUSH    R30            Push register on stack

+00000318:   93FF      PUSH    R31            Push register on stack

60:               uTaskEntry = SP+15;

+00000319:   912002F1    LDS   R18,0x02F1       Load direct from data space

+0000031B:   2FE2      MOV   R30,R18          Copy register

+0000031C:   27FF      CLR   R31            Clear Register

+0000031D:   0FEE      LSL   R30            Logical Shift Left

+0000031E:   1FFF      ROL   R31            Rotate Left Through Carry

+0000031F:   51EF      SUBI    R30,0x1F         Subtract immediate

+00000320:   4FFD      SBCI    R31,0xFD         Subtract immediate with carry

+00000321:   B78D      IN      R24,0x3D         In from I/O location

+00000322:   B79E      IN      R25,0x3E         In from I/O location

+00000323:   960F      ADIW    R24,0x0F         Add immediate to word

+00000324:   8391      STD   Z+1,R25          Store indirect with displacement

+00000325:   8380      STD   Z+0,R24          Store indirect with displacement

+00000326:   5F2F      SUBI    R18,0xFF         Subtract immediate

+00000327:   932002F1    STS   0x02F1,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000329:   918002F3    LDS   R24,0x02F3       Load direct from data space

+0000032B:   1728      CP      R18,R24          Compare

+0000032C:   F010      BRCS    PC+0x03          Branch if carry set

+0000032D:   921002F1    STS   0x02F1,R1      Store direct to data space

62:               SP =uTaskEntry-15;

+0000032F:   918002F1    LDS   R24,0x02F1       Load direct from data space

+00000331:   2FE8      MOV   R30,R24          Copy register

+00000332:   27FF      CLR   R31            Clear Register

+00000333:   0FEE      LSL   R30            Logical Shift Left

+00000334:   1FFF      ROL   R31            Rotate Left Through Carry

+00000335:   51EF      SUBI    R30,0x1F         Subtract immediate

+00000336:   4FFD      SBCI    R31,0xFD         Subtract immediate with carry

+00000337:   8180      LDD   R24,Z+0          Load indirect with displacement

+00000338:   8191      LDD   R25,Z+1          Load indirect with displacement

+00000339:   970F      SBIW    R24,0x0F         Subtract immediate from word

+0000033A:   BF9E      OUT   0x3E,R25         Out to I/O location

+0000033B:   BF8D      OUT   0x3D,R24         Out to I/O location

64:               POP_ALL();

+0000033C:   91FF      POP   R31            Pop register from stack

+0000033D:   91EF      POP   R30            Pop register from stack

+0000033E:   91BF      POP   R27            Pop register from stack

+0000033F:   91AF      POP   R26            Pop register from stack

+00000340:   919F      POP   R25            Pop register from stack

+00000341:   918F      POP   R24            Pop register from stack

+00000342:   917F      POP   R23            Pop register from stack

+00000343:   916F      POP   R22            Pop register from stack

+00000344:   915F      POP   R21            Pop register from stack

+00000345:   914F      POP   R20            Pop register from stack

+00000346:   913F      POP   R19            Pop register from stack

+00000347:   912F      POP   R18            Pop register from stack

+00000348:   900F      POP   R0               Pop register from stack

+00000349:   BE0F      OUT   0x3F,R0          Out to I/O location

+0000034A:   900F      POP   R0               Pop register from stack

+0000034B:   901F      POP   R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000034C:   BE12      OUT   0x32,R1          Out to I/O location

67:               asm("reti");

+0000034D:   9518      RETI                     Interrupt return

+0000034E:   9508      RET                      Subroutine return



....



PUSH以上的寄存器是保存刚释放CPU控制权的任务的环境,而执行PSUH后SP逐加1,在恢复下一个任务的环境时开始执行POP,POP语句SP逐减1。



TASK -> JMP(OR RJMP) -> PUSH [ SP-2-N_push] -> POP -> RET(OR RETI)



PUSH 与 POP 是相反过程,JMP、RJMP、RET、RETI是与SP专门打交道的指令,加减多少是根据你编译后实际的汇编代码确定的

zhudlmax 发表于 2006-12-11 20:50:25

【35楼】的本想放弃的,“提交”误点,赶忙取消,我以为OK,没想到我这网速这么快,呵呵,阿莫,帮我删掉吧,谢谢先



TO jackiezeng:XT,VT键盘资料我没有,你上网搜索就是了,网络是个好东东,可以很好利用的,按你的要求,先打包上传

点击此处下载armok01137758.rar

air23feng 发表于 2006-12-11 20:51:36

楼主厉害,佩服啊~

my_avr 发表于 2006-12-11 22:32:33

多谢楼主!

jackiezeng 发表于 2006-12-11 22:41:10

楼主大哥,



   

    我在网络上找了很久 , 只有一点点协议,协议比 PS/2 的 更简单 , VT , XT 键盘 都是 单向通信的, 只有 键盘发送信息给PC 。



但是我找不到东西来测试 , 不知道自己的程序 能不能 工作 啊 ,





    谢谢您 打包 的资料 ,我请教 个 问题 ,.elf是 什么 文件 ?

为什么一定要打开它 才能 编译呢 ?



    我不会用GCC , 我的理解 是只要 有 .c 和 .h文件 ,和 makefale文件 就可以 编译了,对么 ?

    但是为什么要.elf 呢 ?

zhudlmax 发表于 2006-12-11 23:17:20

叫兄弟就成,大哥不敢当,呵呵



makefile 我用AVR STUDIO内带的,只改了频率、优化两项,我用的是MEGA16,程序编译通过,是我正在进行中的一个项目,只刚刚写了一点点,给一家实验室控制水流用的,本周四得交货,现在急啊,我也不太清楚ELF,你再看看开发环境与我的有何不同?

jackiezeng 发表于 2006-12-12 00:22:45

zhudlmax 兄 :



   我现在大概弄明白 这个 WINAVR 了 , 现在晚了, 明天找个 板子也学着写两个任务来 运行 一 下~!



   THANK YOU

my_avr 发表于 2006-12-19 11:28:53

楼主支招啊,我的系统怎么不能调度?仿真的时候是能正常调度的,下载到单片机里就只运行一圈之后就不知道跑那里去了,不调度任务了,

zhudlmax 发表于 2006-12-19 11:59:04

上传你的代码看看,一般是由于分配的RAM过小造成的,将Task_Stack_Size改大点看看



#define Total_Task_Num   8

#define Task_Stack_Size   50

#define Total_Stack_Size   Total_Task_Num * Task_Stack_Size

my_avr 发表于 2006-12-19 12:04:49

好的,我试试看把Task_Stack_Size改大一点,不过问一下zhudlmax大侠:Task_Stack_Size与Task里的什么东西有关,也就是说任务里的变量还是其他什么东西需要用到Task_Stack?

my_avr 发表于 2006-12-19 12:28:14

现在我的程序在没有开始任务调度之前的系统初始化中,一旦调用子程序就会提示在调用的地方堆栈溢出

my_avr 发表于 2006-12-19 12:35:09

仿真进入了任务调度之后就不出现堆栈溢出的问题了

guantingwei 发表于 2006-12-19 12:54:41

全局变量存取冲突的控制呢?

my_avr 发表于 2006-12-20 10:07:55

代码已经贴出,麻烦楼主大哥帮我看一下.程序是四个单刀双掷开关控制四个电机的上升和下降,驱动电机继电器的是芯片是2803.PB口驱动电机,PC口为按键口,芯片为M16

点击此处下载armok01138397.rar

my_avr 发表于 2006-12-20 21:34:58

打错了,是四个双刀双掷按键控制四个电机

my_avr 发表于 2006-12-26 10:36:50

问题解决了,谢谢楼主大哥!

lionliu 发表于 2008-6-4 10:04:09

cool

glbest 发表于 2008-6-4 15:01:36

学习学习~~

ztxfhl 发表于 2008-6-4 16:02:15

楼主厉害

haerbintcl 发表于 2008-6-4 17:49:57

很强大

sunbody1986 发表于 2008-6-4 19:25:35

谢谢共享!

lxx_sea_sky 发表于 2008-6-28 11:35:10

标记,谢谢楼主!

cyq001 发表于 2008-6-28 12:21:11

zhudlmax和my_avr 大哥能不能帮小弟看一下程序,怎么不行,我程序中最简单的就创建了两个任务,POTRB和PORTC两个口取反一下,程序执行结果是 两个任务都只执行一次,就一直进入SIGNAL(SIG_OUTPUT_COMPARE0)中断程序了,一直在重复的执行,搞了两天,郁闷了两天点击此处下载 ourdev_329742.rar(文件大小:44K) (原文件名:AVR时间片法调度.rar)

lin28 发表于 2008-7-4 08:51:29

记号

taishandadi 发表于 2008-7-4 20:15:25

mark。

eaglelpx 发表于 2008-8-8 12:15:30

能看懂以后在看

coole 发表于 2008-10-6 22:54:50

楼主厉害,跟着学习!

liang503 发表于 2008-10-9 17:12:35

楼主写得非常详细,谢谢分享

kelvin9926 发表于 2008-10-21 14:03:46

不错,写得非常详细,,有机会自己也用一用.太感谢了!

mfkqqw 发表于 2008-10-24 12:48:37

记下

Totry 发表于 2008-10-24 14:01:45

mark!

shanlei300 发表于 2008-10-24 14:40:06

mark!&nbsp;

caixiong 发表于 2008-10-24 14:50:01

学习

huike_h 发表于 2008-10-30 16:37:40

ucOS好像没有此功能...不过仍然不失为一个优秀的嵌入式操作系统

letyoufly 发表于 2008-12-28 17:42:06

mark

thriller 发表于 2008-12-28 18:32:45

强帖留名

zcllom 发表于 2008-12-28 18:51:53

嘿,这里的宝藏真多啊,继续呆几天,挖完收工歇息。

Junker 发表于 2008-12-29 16:58:17

up

ybs777 发表于 2009-3-1 01:09:03

收藏,学习。

shushikuan 发表于 2009-5-12 05:10:20

顶一下!

lionliu 发表于 2009-5-12 15:35:24

m

mxh0506 发表于 2009-5-14 23:37:41

不错,这个坛子里讨论问题的气氛比较好

evilangell 发表于 2009-5-18 08:02:50

// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("r9");
register unsigned char tempR10 asm("r10");
register unsigned char tempR11 asm("r11");
register unsigned char tempR12 asm("r12");
register unsigned char tempR13 asm("r13");
register unsigned char tempR14 asm("r14");
register unsigned char tempR15 asm("r15");
register unsigned char tempR16 asm("r16");
register unsigned char tempR16 asm("r17");


这个怎么移植到ICC编译器上?

touch_mcu 发表于 2009-7-12 20:49:45

很有价值的贴呀

sange 发表于 2009-7-16 17:10:39

强贴留名

mengyubianyuan 发表于 2009-8-29 14:51:50

牛啊啊就是都不会啊

anxiangbo 发表于 2009-8-29 15:21:18

强贴留名

w860316 发表于 2009-9-12 15:55:40

mark

hxjsini 发表于 2009-9-12 23:53:45

强帖记下。

farmer 发表于 2009-9-28 09:15:38

mark

czxf 发表于 2009-9-28 10:09:23

good

zzwuyu 发表于 2009-9-28 10:48:23

mark

ch2003_23 发表于 2009-9-29 10:41:54

mark

cana11225 发表于 2009-11-12 09:59:39

good!

songzi2018 发表于 2009-11-17 16:55:40

gdmfq 发表于 2009-12-9 16:48:24

astudent 发表于 2009-12-9 17:49:37

好贴,要顶。

silvanesw 发表于 2009-12-9 17:51:01

打标。

mountaintop 发表于 2009-12-9 18:10:27

不错,比较简洁也很实用。

taishandadi 发表于 2009-12-9 22:37:05

好用。谢谢lz

yunhuisong 发表于 2009-12-16 19:37:40

mark

ddcour 发表于 2009-12-25 22:02:40

好!谢谢!

astudent 发表于 2009-12-30 19:57:49

mark

Adrian 发表于 2009-12-30 23:09:40

cool..
页: [1] 2 3
查看完整版本: 简洁实用的时间片调度法操作系统,献给大家