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 ); }
浙公网安备 33010602011771号