zhliao2

风雨兼程,一路向北-------fpga (Keep a quiet heart study)
setjmp() longjmp() setTaskJmp()

选自<<项目驱动-单片机应用设计基础>>

 

//空指针
/*
**空指针既不会指向任何对象或函数,也不是任何对象或函数的地址
**一般来说,未初始化的指针,实际上是非法的指针,不能使用,未初始
**化的指针完全有可能指向任何地方,从而导致程序无法判断它为非法
**指针

**注意了:空指针和未初始化的指针是完全不同的两个概念
*/

//定义了pucBuf为unsigned char 类型指针并初始化为空指针
data unsigned char *pucBuf = ( data void * )0; 



//setjmp()定义
extern unsigned char bp;  //编译器为简化重入操作而定义的变量

char setjmp ( jmp_buf jbBuf )    //jbBuf主要保存当前调用的上下文信息
{
    data unsigned char *pucBuf = ( data void * )0;  //指向上下文信息存储位置的指针

    pucBuf = ( data unsigned char * )jbBuf;  //将jbBuf数组的首地址赋给pucBuf

    *pucBuf ++ = bp;  //保存bp的当前值
    *pucBuf ++ = SP;  //保存SP的当前值
    *pucBuf ++ = *( ( data unsigned char * )SP );  //保存返回地址的高8位
    *pucBuf = *( ( data unsigned char * )( ( char )( SP - 1 ) ) );  //保存返回地址的低8位
}


//longjmp()定义
extern unsigned char bp;  //编译器为简化重入操作而定义的变量

char longjmp ( jmp_buf jbBuf )  //jbBuf主要保存当前调用的上下文信息
{
    unsigned char ucSpSave;  //保存堆栈指针的变量
    data unsigned char *pucBuf = ( data void * )0;  //指向上下文信息存储位置的指针

    pucBuf = ( data unsigned char * )jbBuf;  //将jbBuf数组的首地址赋给pucBuf

    bp = *pucBuf ++;  //恢复bp
    ucSpSave = *pucBuf ++;  //暂存SP堆栈指针的原始值
    *( ( data unsigned char * )( unSpSave ) ) = *pucBuf ++;  //恢复返回地址的高8位
    *( ( data unsigned char * )( ( char )( ucSpSave - 1 ) ) ) = *pucBuf;  //恢复返回地址低8位
}


//填充上下文信息( _setjmp.c )    
void setTaskJmp(
        void( *pfuncTask )( void ),   //指向任务函数的函数指针
        idata unsigned char *pucStk,  //指向任务堆栈栈顶的指针
        jmp_buf jbTaskContext          //用于存储任务的上下文信息
)                              
{
    idata unsigned char *pucBuf = ( data void * )0;  //指向上下文信息存储位置的指针

    pucBuf = ( data unsigned char * )jbTaskContext;  //指向jbTaskContext数组
    *pucBuf ++ = 0;
    *pucBuf ++ = ( unsigned char  )( pucStk + 2 );   //保存SP,堆栈空2字节用于保存返回地址,
                                                     //用来模拟setjmp()调用了( LCALL指令 )
                                                     //压栈返回地址的操作,因为longjmp()会修改
                                                     //这两个字节,所以不必真实的保存数据

    *pucBuf ++ = ( ( unsigned int )pfuncTask ) / 256;  //保存返回地址的高8位
    *pucBuf = ( ( unsigned int )pfuncTask ) % 256;     //保存返回地址的低8位
}

 

举例:

//任务切换模型
#include< 8051.h >
#include " .\lib\setjmp.h "

static idata unsigned char __GucTaskStks[2][32];  //分配堆栈

static unsigned char __GucTask0;  //任务0测试变量
static unsigned char __GucTask1;  //任务1测试变量

static jmp_buf __GjbTask0;  //任务0上下文
static jmp_buf __GjbTask1;  //任务1上下文

void task0( void )
{
    char cTmp1;

    while( 1 )
    {
        __GucTask0 ++;

        //任务切换
        cTmp1 = setjmp( __GjbTask0 );   //返回值为0,即cTemp1 = 0
        if( cTemp1 == 0 )   
        {
            longjmp( __GjbTask1 );  //执行任务1      如果执行了这条语句,则下一条语句是task1中的if( cTemp1 == 0 ) 
        }

        __GucTask0 ++;
    }
}

void task1( void )
{
    char cTmp1;

    while( 1 )
    {
        __GucTask1 ++;

        //任务切换
        cTmp1 = setjmp( __GjbTask1 );   //返回值为0,即cTemp1 = 0
        if( cTemp1 == 0 )   
        {
            longjmp( __GjbTask0 );  //执行任务1
        }

        __GucTask1 ++;
    }
}

void main( void )
{
    setTaskJmp( task0, __GucTaskStks[0], __GjbTask0 );
    setTaskJmp( task1, __GucTaskStks[1], __GjbTask1 );
    longjmp( __GjbTask0 );
}           

 

 

 

 

 

 

 

posted on 2012-08-09 13:02  zhliao  阅读(499)  评论(0)    收藏  举报