1.void PC_DisClrCol(INT8U x,INT8U color)//清除屏幕的列
{
INT8U far *pscr;
INT8U i;
pscr = (INT8U far *)MK_FP(DISP_BASE,(INT16U)x*2); //#define DISP_BASE 0xB800
//Base segment of display (0xB800=VGA,0xB000=Mono)
for(i=0;i
{
*pscr++=''; //put '' character in video RAM
*pscr--=color; //put video attribute in video RAM
pscr=pscr+DISP_MAX_X*2; //position on next row
}
}
注:起初一直在想这里的"*2"是什么意思,但仔细看下面的for循环发现这里出现"*2"是因为video RAM中要存储两个东西,一个是字符,另一个是颜色,所以要花费两倍的存储空间.
函数名:MK_FP
函数原型:#define MK_FP(seg,ofs)((void _seg*)(seg) (void near*)(ofs))
函数位置: dos.h
函数说明: MK_FP()不是一个函数,只是一个宏。功能是做段基址加上偏移地址的运算,也就是取实际地址。
功 能: 设置一个远指针
用 法: void far *MK_FP(unsigned seg, unsigned off);
near指针和far指针
far指针和near指针是对应的,就是一般16位系统下程序的函数调用都在64k地址范围内,就是16位寻址就够了,但是当代码比较庞大时,16位就可能不够了.far就代表32位寻址,含有一个16位的基地址和16位的偏移地址,将基地址乘以16后再与偏移量相加,(所以实际上far指针是20位的长度)即可得到far指针的1M字节的偏移量。.一般不写默认就是near.
什么时候使用far指针?
当使用小代码或小数据存储模式时,不能编译一个有很多代码或者数据的程序.因为在64k的一个段中,不能放下所有的代码与数据.为了解决这个问题,需要指定以far函数或far指针来使用这部分的空间(64k以外的空间).许多库函数就是显示地指定为far函数的形式.far指针通常和farmalloc()这样的内存分配函数一起使用.
2.unsigned int *OSTaskStkInit(void (*task)(void *pd),void *pdata,unsigned int *ptos,INT16U opt)
{
模拟带参数(pdata)的函数调用;
模拟ISR向量;
按照预先设计的寄存器值初始化堆栈结构;
返回栈顶指针给调用该函数的函数;
}
- OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
- {
- INT16U *stk;
- opt = opt; /* 'opt' is not used, prevent warning */
- stk = (INT16U *)ptos; /* Load stack pointer */
- *stk-- = (INT16U)FP_SEG(pdata); /* Simulate call to function with argument */
- *stk-- = (INT16U)FP_OFF(pdata);
- *stk-- = (INT16U)FP_SEG(task);
- *stk-- = (INT16U)FP_OFF(task);
- *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */
- *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */
- *stk-- = (INT16U)FP_OFF(task);
- *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */
- *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */
- *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */
- *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */
- *stk-- = (INT16U)0x0000; /* SP = 0x0000 */
- *stk-- = (INT16U)0x1111; /* BP = 0x1111 */
- *stk-- = (INT16U)0x2222; /* SI = 0x2222 */
- *stk-- = (INT16U)0x3333; /* DI = 0x3333 */
- *stk-- = (INT16U)0x4444; /* ES = 0x4444 */
- *stk = _DS; /* DS = Current value of DS */
- return ((OS_STK *)stk);
- }
注:这是个初始化一个任务堆栈的函数."task"是一个指向任务代码的指针,"pdata"是当任务第一次执行时指向转到用户给任务提供的数据区的指针,"ptos"是一个指向栈顶的指针,"opt"是一种特殊的选项,可以用来改变
OSTaskStkInit()函数的操作.下面是uCOS_II.H文件中对TASK OPTIONS的定义:
#define OS_TASK_OPT_STK_CHK 0x0001 //Enable stack checking for the task
#define OS_TASK_OPT_STK_CLR 0x0002 //Clear the stack when the task is create
#define OS_TASK_OPT_SAVE_FP 0x0004 //save the contents of any floating-point
//regesiters
所以如果"opt"不想使用如上操作就把它定义为0,但是为了消除可能出现的警告就加上"opt = opt;"这句,防止出现警告.
设置状态字(SW)也是为了模拟中断发生后的堆栈结构.堆栈中的SW初始化为0x0202,这将使任务启动后允许中断发生;如果设置为0x0202,则任务启动后将禁止中断发生.但需要注意如果选择任务启动后允许中断发生,则所有的任务运行期间中断都允许;同样,如果选择任务启动后禁止中断,则所有的任务都禁止中断发生,而不能有所选择.
程序清单中的标记处使用_DS直接把DS寄存器拷贝到堆栈中.堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()或 OSTaskCreateExt()将指针保存在任务的OS_TCB中.
另外注意:OSStartHighRdy()将永远不返回到OSStart(),因为OSStartHighRdy()被OSStart()调用的函数返回地址以及相关的上下文环境都没有被保存.
函数名:
FP_SEG
功 能: 获取远地址段值
用 法: unsigned FP_SEG(void far *farptr);
函数名:
FP_OFF
功 能: 获取远地址偏移量
用 法: unsigned FP_OFF(void far *farptr);
阅读(3470) | 评论(2) | 转发(1) |