S3C2410平台UCOS移植笔记.docx

上传人:b****8 文档编号:30057752 上传时间:2023-08-04 格式:DOCX 页数:8 大小:17.99KB
下载 相关 举报
S3C2410平台UCOS移植笔记.docx_第1页
第1页 / 共8页
S3C2410平台UCOS移植笔记.docx_第2页
第2页 / 共8页
S3C2410平台UCOS移植笔记.docx_第3页
第3页 / 共8页
S3C2410平台UCOS移植笔记.docx_第4页
第4页 / 共8页
S3C2410平台UCOS移植笔记.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

S3C2410平台UCOS移植笔记.docx

《S3C2410平台UCOS移植笔记.docx》由会员分享,可在线阅读,更多相关《S3C2410平台UCOS移植笔记.docx(8页珍藏版)》请在冰豆网上搜索。

S3C2410平台UCOS移植笔记.docx

S3C2410平台UCOS移植笔记

S3C2410之UCOS移植笔记

2011-10-0120:

10

μC/OS-II大部分代码是用移植性很高的ANSIC语言编写的,只包含一小部分汇编语言代码,因此可以很方便地将它移植到各种不同构架的微处理器上。

移植μC/OS-II,所用处理器和该处理器所用的C语言编译器必须满足以下条件:

1.处理器的C编译器能产生可重入代码;

2.处理器支持中断,并且能产生定时中断;

3.用C语言就可以开/关中断;

4.处理器能支持一定数量的数据存储硬件堆栈;

5.处理器有将堆栈指针以及其他CPU寄存器的内容读出、并存储到堆栈或内存中去的指令。

首先,由于处理器字长不同为了方便,我们通常要修改下字长定义,s3c2410是32位处理器所以定义如下:

     #defineU32unsignedint

#defineU16unsignedshort

#defineS32int

#defineS16shortint

#defineU8unsignedchar

#defineS8signedchar

 

下面我对以上的移植要求一次进行移植分析:

    1.修改ucos源代码中OS_CPU.S中的代码如下,主要是用开关中断实现代码的可重入要求:

 

EXPORTOSCPUSaveSR

OSCPUSaveSR

       mrsr0,CPSR       

       orrr1,r0,#NOINT  ;屏蔽irq,fiq

       msrCPSR_c,r1

       movpc,lr        ;跳回

 

       EXPORTOSCPURestoreSR

OSCPURestoreSR

       msrCPSR_c,r0

       movpc,lr

 

    2.  s2c2410支持中断,选择一个定时器作为时钟滴答,来对任务做时间片的调度,有关s3c2410的中断介绍可以参考我得另一片文章。

    产生中断后,代码自动跳转到0x0的中断向量表,然后在从中断向量表中跳到下面的程序,进行中断号的分析,然后利用ucos的中断任务切换到中断服务子程序中。

UCOS_IRQHandler

       stmfdsp!

{r0-r3,r12,lr};保存现场

       blOSIntEnter         ;跳到下面程序,实际上是中断嵌套

       blC_IRQHandler      ;计算出中断号

       blOSIntExit         ;中断减1,切换最高优先级任务

       ldrr0,=OSIntCtxSwFlag;判断是否需要中断切换

       ldrr1,[r0]

       cmpr1,#1

       beq_IntCtxSw        ;调用中断任务切换函数,后面分析

       ldmfdsp!

{r0-r3,r12,lr};恢复现场

       subspc,lr,#4

voidOSIntEnter(void)

{

   if(OSRunning==OS_TRUE){

       if(OSIntNesting<255u){

           OSIntNesting++;                     /*中断记数+1                       */

       }

   }

}

voidOSIntExit(void)

{

#ifOS_CRITICAL_METHOD==3                              

   OS_CPU_SRcpu_sr=0;

#endif

 

   if(OSRunning==OS_TRUE){

       OS_ENTER_CRITICAL();

       if(OSIntNesting>0){                           有中断,中断数-1

           OSIntNesting--;

       }

       if(OSIntNesting==0){                         如果没有中断的话

           if(OSLockNesting==0){                     

               OS_SchedNew();                       

               if(OSPrioHighRdy!

=OSPrioCur){         

                   OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];

#ifOS_TASK_PROFILE_EN>0

                   OSTCBHighRdy->OSTCBCtxSwCtr++;        

#endif

                   OSCtxSwCtr++;                     将最高优先级的任务调入

                   OSIntCtxSw();                         

               }

           }

       }

       OS_EXIT_CRITICAL();

   }

}

 

voidC_IRQHandler(void)

{

       U32wTemp;

       wTemp=rINTOFFSET<<2;          根据中断偏移量判断是什么中断

       ((void(*)(void))(*((U32*)(aISR_EINT0+wTemp))))();关键!

跳到相应中断服务程序

}

 

 

      其中的UCOS_IRQHandler就是实现中断跳转的关键代码,C语言中将irq中断函数的入口

都指向它实现中断跳转到C中对应的服务函数,代码如下:

pISR_IRQ=(U32)UCOS_IRQHandler;中断入口挂接

     然后初始化一个定时器作为时钟滴答,一般选择100ms左右,产生一次中断溢出,进行

一次任务调度。

 

3.有关堆栈的设置。

因为ucos进行任务切换时,就是相当于模拟的做中断操作。

所以在切换任务之前必须先保存任务的现场:

包括R0~R12,sp,lr,pc,cprs,sprs。

然后用sp从旧的任务堆栈指向新的任务的堆栈。

(这个堆栈在任务创建的时候已经分配好了)。

   在初始化任务堆栈之前,首先要设置两个参数,在CONFIG文件中:

大小端编译模式,堆栈得生长方向。

代码如下:

#defineOS_STK_GROWTH1;堆栈向上生长

然后在任务创建时的堆栈初始化函数,在OS_CPU_C.c文件中:

OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)

{

   OS_STK*stk;

   opt   =opt;                          /*'opt'isnotused,preventwarning                     */

   stk   =ptos;                         /*Loadstackpointer                                     */

   *(stk)=(OS_STK)task;                 /*EntryPoint                                            */

   *(--stk)=(INT32U)0;                  /*lr                                                     */

   *(--stk)=(INT32U)0;                  /*r12                                                    */

   *(--stk)=(INT32U)0;                  /*r11                                                    */

   *(--stk)=(INT32U)0;                  /*r10                                                    */

   *(--stk)=(INT32U)0;                  /*r9                                                     */

   *(--stk)=(INT32U)0;                  /*r8                                                     */

   *(--stk)=(INT32U)0;                  /*r7                                                     */

   *(--stk)=(INT32U)0;                  /*r6                                                     */

   *(--stk)=(INT32U)0;                  /*r5                                                     */

   *(--stk)=(INT32U)0;                  /*r4                                                     */

   *(--stk)=(INT32U)0;                  /*r3                                                     */

   *(--stk)=(INT32U)0;                  /*r2                                                     */

   *(--stk)=(INT32U)0;                  /*r1                                                     */

   *(--stk)=(INT32U)pdata;              /*r0:

argument                                          */

   *(--stk)=(INT32U)(SVCMODE|0x0);      /*PSR                                                    */

   *(--stk)=(INT32U)(SVCMODE|0x0);      /*SPSR                                                   */

       return(stk);

}

4.有关任务调度方面的移植:

   首先就是当运行OSSTART()后,系统要进入优先级最高的任务中,即第一个任务,这短代码的移植如下:

   OSStartHighRdy

       blOSTaskSwHook            ;

       ldrr4,=OSRunning          ;运行多任务

       movr5,#1

       strbr5,[r4]

       ldrr4,=OSTCBHighRdy       ;得到最高优先级任务的TCB地址

       ldrr4,[r4]                ;得到其堆栈地址

       ldrsp,[r4]                ;切换到新任务的堆栈

       ldmfdsp!

{r4}             ;把新任务堆栈的内容环境载进当片CPU

       msrSPSR_cxsf,r4

       ldmfdsp!

{r4}             ;popnewtask'spsr

       msrCPSR_cxsf,r4

       ldmfdsp!

{r0-r12,lr,pc}   ;popnewtask'sr0-r12,lr&pc

    其次时对任务调度函数的移植,主要是在时间片到时,读取就绪表中优先级最高的任务,并切换到该任务的环境中:

OSCtxSw

       ;保存要被切换出去的任务环境

       stmfdsp!

{lr}             ;pushpc(lrshouldbepushedinplaceofPC)

       stmfdsp!

{r0-r12,lr}      ;pushlr®isterfile

       mrsr4,cpsr

       stmfdsp!

{r4}             ;pushcurrentpsr

       mrsr4,spsr

       stmfdsp!

{r4}             ;pushcurrentspsr

       ;把就绪表中优先级最高的任务载入到当前任务指针指向

      ;OSPrioCur=OSPrioHighRdy

       ldrr4,=OSPrioCur

       ldrr5,=OSPrioHighRdy

       ldrbr6,[r5]

       strbr6,[r4]

      

       ;得到当前任务的TCB地址

       ;GetcurrenttaskTCBaddress

       ldrr4,=OSTCBCur

       ldrr5,[r4]

       strsp,[r5]                ;storespinpreemptedtasks'sTCB

       blOSTaskSwHook            ;callTaskSwitchHook

       ;得到最高优先级任务的地址,并把堆栈指针指向它的堆栈地址

       ;GethighestprioritytaskTCBaddress

       ldrr6,=OSTCBHighRdy

       ldrr6,[r6]

       ldrsp,[r6]                ;getnewtask'sstackpointer

       ;调出新任务的环境实现切换

       ;OSTCBCur=OSTCBHighRdy

       strr6,[r4]                ;setnewcurrenttaskTCBaddress

       ldmfdsp!

{r4}             ;popnewtask'sspsr

       msrSPSR_cxsf,r4

       ldmfdsp!

{r4}             ;popnewtask'spsr

       msrCPSR_cxsf,r4

       ldmfdsp!

{r0-r12,lr,pc}   ;popnewtask'sr0-r12,lr&pc

      最后是中断级的任务切换,这种情况发生在,在中断服务程序中报告了一个或多个事件的发生,而这些事件的发生使一些更高优先级的任务进入就绪状态。

因此在中断退出时不应该返回到被中断的任务,而应该返回到就绪态中优先级最高的任务。

函数OSIntCtxSw()的主要功能是完成中断级的任务切换。

与任务级的任务切换不同的时,在进入中断后,所有寄存器的值都被入栈了。

因此在进入任务级切换时寄存器的入栈操作应该再有。

另外,在中断服务程序中调用了函数OSIntExit()和OSIntCtxSw(),因此应该调整当前任务的堆栈指针,让任务下次再被执行时返回中断服务程序而不是返回函数OSIntExit()和OSIntCtxSw()。

剩下的任务就是进行任务切换了,这些代码同函数OSCtxSw()的大部分代码都相同。

   _IntCtxSw

       

       ;对堆栈指针的调整

       movr1,#0

       strr1,[r0]

       ldmfdsp!

{r0-r3,r12,lr}

       stmfdsp!

{r0-r3}

       movr1,sp

       addsp,sp,#16

       subr2,lr,#4

       mrsr3,spsr

       orrr0,r3,#NOINT

       msrspsr_c,r0

       ldrr0,=.+8

       movspc,r0

        ;以下代码和正常的任务切换过程完全一样

       stmfdsp!

{r2}             ;pusholdtask'spc

       stmfdsp!

{r4-r12,lr}      ;pusholdtask'slr,r12-r4

       movr4,r1                  ;Specialoptimisedcodebelow

       movr5,r3

       ldmfdr4!

{r0-r3}

       stmfdsp!

{r0-r3}          ;pusholdtask'sr3-r0

       stmfdsp!

{r5}             ;pusholdtask'spsr

       mrsr4,spsr

       stmfdsp!

{r4}             ;pusholdtask'sspsr

       

       ;OSPrioCur=OSPrioHighRdy

       ldrr4,=OSPrioCur

       ldrr5,=OSPrioHighRdy

       ldrbr5,[r5]

       strbr5,[r4]

       

       ;GetcurrenttaskTCBaddress

       ldrr4,=OSTCBCur

       ldrr5,[r4]

       strsp,[r5]                ;storespinpreemptedtasks'sTCB

       blOSTaskSwHook            ;callTaskSwitchHook

       ;GethighestprioritytaskTCBaddress

       ldrr6,=OSTCBHighRdy

       ldrr6,[r6]

       ldrsp,[r6]                ;getnewtask'sstackpointer

       ;OSTCBCur=OSTCBHighRdy

       strr6,[r4]                ;setnewcurrenttaskTCBaddress

       ldmfdsp!

{r4}             ;popnewtask'sspsr

       msrSPSR_cxsf,r4

       ldmfdsp!

{r4}             ;popnewtask'spsr

       msrCPSR_cxsf,r4

       ldmfdsp!

{r0-r12,lr,pc}   ;popnewtask'sr0-r12,lr&pc

         这样我们就可以实现ucos在s3c2410的移植了。

注意如果要是在ram中仿真时,必须把中断向量表预先烧录到0x0处才能正常实现中断的跳转。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 公务员考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1