Chinaunix首页 | 论坛 | 博客
  • 博客访问: 805283
  • 博文数量: 106
  • 博客积分: 1250
  • 博客等级: 少尉
  • 技术积分: 1349
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-09 09:38
文章分类

全部博文(106)

文章存档

2014年(1)

2013年(13)

2012年(92)

分类:

2012-04-25 17:23:23

原文地址:μC/OS-II的学习 作者:fj1161

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向量;
  按照预先设计的寄存器值初始化堆栈结构;
  返回栈顶指针给调用该函数的函数;
}

点击(此处)折叠或打开

  1. OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
  2. {
  3.     INT16U *stk;
  4.     opt = opt;                         /* 'opt' is not used, prevent warning */
  5.     stk = (INT16U *)ptos;              /* Load stack pointer */
  6.     *stk-- = (INT16U)FP_SEG(pdata);    /* Simulate call to function with argument */
  7.     *stk-- = (INT16U)FP_OFF(pdata);
  8.     *stk-- = (INT16U)FP_SEG(task);
  9.     *stk-- = (INT16U)FP_OFF(task);
  10.     *stk-- = (INT16U)0x0202;           /* SW = Interrupts enabled */
  11.     *stk-- = (INT16U)FP_SEG(task);     /* Put pointer to task on top of stack */
  12.     *stk-- = (INT16U)FP_OFF(task);
  13.     *stk-- = (INT16U)0xAAAA;           /* AX = 0xAAAA */
  14.     *stk-- = (INT16U)0xCCCC;           /* CX = 0xCCCC */
  15.     *stk-- = (INT16U)0xDDDD;           /* DX = 0xDDDD */
  16.     *stk-- = (INT16U)0xBBBB;           /* BX = 0xBBBB */
  17.     *stk-- = (INT16U)0x0000;           /* SP = 0x0000 */
  18.     *stk-- = (INT16U)0x1111;           /* BP = 0x1111 */
  19.     *stk-- = (INT16U)0x2222;           /* SI = 0x2222 */
  20.     *stk-- = (INT16U)0x3333;           /* DI = 0x3333 */
  21.     *stk-- = (INT16U)0x4444;           /* ES = 0x4444 */
  22.     *stk = _DS;                        /* DS = Current value of DS */
  23.     return ((OS_STK *)stk);
  24. }
注:这是个初始化一个任务堆栈的函数."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);
阅读(1143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~