Chinaunix首页 | 论坛 | 博客
  • 博客访问: 707878
  • 博文数量: 255
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 2811
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-09 13:29
个人简介

IT业行者,行者无疆

文章分类

全部博文(255)

文章存档

2011年(121)

2010年(134)

我的朋友

分类: 嵌入式

2010-09-27 09:24:12

ARM在UC/OS II的移植日记(连载3)

(2010-04-02 21:06:55)
标签:

杂谈

from:

http://fangheng1005.blog.163.com/

 

好长时间没有上博客写东东了,发现自己变懒了,唉,安逸的生活就是会使人变得懒散,忘记自己的方向啊,希望自己能够掌握好时间,发掘自己,努力提高自己,好吧,来今天的工作吧。

OS_CPU_C.C文件

这个文件主要是设计针对移植过程的任务堆栈结构,任务的堆栈结构对于整个系统的移植是至关重要的,应该设计一个高效的堆栈结构,综合ARM的结构,设计如下的堆栈结构。

---->>>>>任务的其他数据

---->>>>>PC值

---->>>>>LR值

---->>>>>R12

---->>>>>R11

---->>>>>R10

---->>>>>R9

---->>>>>R8

---->>>>>R7

---->>>>>R6

---->>>>>R5

---->>>>>R4

---->>>>>R3

---->>>>>R2

---->>>>>R1

---->>>>>R0       用于传递任务创建时的数据传递

---->>>>>SPSR  任务创建时是允许 IRQ, FIQ 中断的,这个值在任务切换时装载在CPSR中

---->>>>>OsEnterSum      这个就是ZLG的人定义的关中断计数器,每个任务是相互独立的,即任务1的开关中断次数不会影响其他任务的开关中断次数,为了防止任务间开关中断动作的不一致,造成误开关中断。

好的,来看zlg的代码吧,你会发现很简单,只要你按照你设计的堆栈来编写函数就可以了。

        OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;

这个是定义一个指向堆栈结构宽度的指针

    opt    = opt;                          
stk    = ptos;                         

                                           
*stk = (OS_STK) task;                  
*--stk = (OS_STK) task;                

    *--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = 0;                            
*--stk = (unsigned int) pdata;         
*--stk = (USER_USING_MODE|0x00);    
*--stk = 0;                            

    return (stk);
}

 

简单吧,这个很容易看的,再看不懂就自己翻开邵译的书吧,那里讲的很清楚,注意设计堆栈结构的时候,ARM支持向上或向下的堆栈结构,但是很可以,ADS只支持向下的堆栈结构,所以你必须使用这种大的堆栈结构方向,其他的你看自己的方便和习惯设计堆栈吧。

 

 

本来邵译的书说了,这个文件必须定义OS_STK *OSTaskStkInit ()函数,嘿嘿,不过具体的情况我们还得再这个文件定义其他的函数,往下看吧,这是邵译书上没有的哦,仔细看啦。

 

        void SWI_Exception(int SWI_Num, int *Regs)

这个函数是软件中断的函数,就是调用软件中断函数时会进入软件中断异常地址,然后跳转到SoftwareInterrupt函数,这个函数是在 OS_CPU_A.S文件中定义的,自己找找,而为什么会跳转到SoftwareInterrupt函数,那是因为在启动文件中startup.s中定义了软件中断的入口地址,可以知道SoftwareInterrupt函数进行了一些堆栈的保护后如果条件符合会跳转到SWI_Exception函数。 OSIntCtxSw和__OSStartHighRdy函数也是通过软件中断方式实现的,但是没有在SWI_Exception中实现,所以大家才会看到在SoftwareInterrupt函数中有两个判断,看是否是这两个函数的中断,至于为什么要这么做我也不清楚,但是肯定的是这两个函数在 SWI_Exception中也是能实现的。
{
OS_TCB   *ptcb;      

switch(SWI_Num)
{
//case 0x00:        
//    break;
//case 0x01:        
//    break;
case 0x02:          
__asm

内嵌汇编,ADS支持这种功能的。
            {
MRS     R0, SPSR    读出SPSR的值,这个值在中断返回的时候会复制回CPSR中
ORR     R0, R0, #NoInt
MSR     SPSR_c, R0        SPSR的值已经关中断了
}
OsEnterSum++;
break;
case 0x03:            
if (--OsEnterSum == 0)
{
__asm
{
MRS     R0, SPSR
BIC     R0, R0, #NoInt              参照上面的解释
                    MSR     SPSR_c, R0
}
}
break;

以下的函数不是很常用的,我也没有仔细搞清楚,可参照汇编指令来解释
#if OS_SELF_EN > 0
case 0x40:








Regs[0] =  _OSFunctionAddr[Regs[0]];
break;
case 0x41:








Regs[0] =  _UsrFunctionAddr[Regs[0]];
break;
case 0x42:                     
OSIntNesting++;
break;
case 0x43:                     
if (OSTCBHighRdy == OSTCBCur)
{
Regs[0] = 0;
}
else
{
Regs[0] = 1;
}
break;
#endif
case 0x80:                     
__asm
{
MRS     R0, SPSR
BIC     R0, R0, #0x1f
ORR     R0, R0, #SYS32Mode   
MSR     SPSR_c, R0
}
break;
case 0x81:                     
__asm
{
MRS     R0, SPSR
BIC     R0, R0, #0x1f
ORR     R0, R0, #USR32Mode   
MSR     SPSR_c, R0
}
break;
case 0x82:                     
if (Regs[0] <= OS_LOWEST_PRIO)
{
ptcb = OSTCBPrioTbl[Regs[0]];
if (ptcb != NULL)
{
ptcb -> OSTCBStkPtr[1] &= ~(1 << 5);
}
}
break;
case 0x83:                     
if (Regs[0] <= OS_LOWEST_PRIO)
{
ptcb = OSTCBPrioTbl[Regs[0]];
if (ptcb != NULL)
{
ptcb -> OSTCBStkPtr[1] |= (1 << 5);
}
}
break;
default:
break;
}
}

 

 

 

 

好了,看个简单的函数,呵呵

        void OSStartHighRdy(void)
{
_OSStartHighRdy();
}

够简单吧,_OSStartHighRdy()是一个软件中断函数,即调用_OSStartHighRdy()函数时就会进入软件中断,这个函数的功能是多任务初始化的时候启动优先级最高的任务,以后就不会再调用这个函数了,具体内容是通过汇编实现的。

 

 

后面定义了许多的钩子函数,嘿嘿,个人觉得应该是接口函数才对,这些函数是为了你增加一些函数的功能而预留的,可以使用,也可以不使用,但是一定要定义。

#if OS_VERSION > 203
void OSInitHookBegin (void)
{
}
#endif

 

 

#if OS_VERSION > 203
void OSInitHookEnd (void)
{
}
#endif

 

 

void OSTaskCreateHook (OS_TCB *ptcb)
{
ptcb = ptcb;                      
}

 

void OSTaskDelHook (OS_TCB *ptcb)
{
ptcb = ptcb;                      
}

 

void OSTaskSwHook (void)
{
}

 

void OSTaskStatHook (void)
{
}

 

#if OS_VERSION > 203
void OSTCBInitHook (OS_TCB *ptcb)
{
ptcb = ptcb;                                          
}
#endif

 

void OSTimeTickHook (void)
{
}

 

#if OS_VERSION >= 251
void OSTaskIdleHook (void)
{
}
#endif

 

这个文件就这些内容了,今天很晚了,就写到这吧,改天继续。

(待续连载4)
阅读(806) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~