当前位置:首页 > 嵌入式 > 嵌入式软件
[导读] 本章描述如何从μC/OS 升级到 μC/OS-II。如果已经将μC/OS移植到了某类微处理器上,移植μC/OS-II所要做的工作应当非常有限。在多数情况下,用户能够在1个小时之

 本章描述如何从μC/OS 升级到 μC/OS-II。如果已经将μC/OS移植到了某类微处理器上,移植μC/OS-II所要做的工作应当非常有限。在多数情况下,用户能够在1个小时之内完成这项工作。

如果用户熟悉μC/OS的移植,可隔过本章前一部分直接参阅10.05节。

10.0目录和文件

用户首先会注意到的是目录的结构,主目录不再叫 SOFTWAREuCOS。而是叫SOFTWAREuCOS-II。 所有的μC/OS-II文件都应放在用户硬盘的SOFTWAREuCOS-II 目录下。面向不同的微处理器或微处理器的源代码一定是在以下两个或三个文件中: OS_CPU.H,OS_CPU_C.C,或许还有OS_CPU_A.ASM.。汇编语言文件是可有可无的,因为有些C编译程序允许使用在线汇编代码,用户可以将这些汇编代码直接写在 OS_CPU_C.C.中。

与微处理器有关的特殊代码,即与移植有关的代码,在 μC/OS 中是放在用微处理器名字命名的文件中的,例如,Intel80x86的实模式(RealMode),在大模式下编译(LargeModle)时,文件名为Ix86L.H, Ix86L_C.C,和Ix86L_A.ASM.。

表L10.1在μC/OS-II中重新命名的文件.

升级可以从这里开始:首先将μC/OS目录下的旧文件复制到μC/OS-II 的相应目录下,并改用新的文件名,这比重新建立一些新文件要容易许多。表10.2给出来几个与移植有关的新旧文件名命名法的例子。

表 L10.2对不同微处理器从μC/OS到μC/OS-II,要重新命名的文件.

10.1 INCLUDES.H

用户应用程序中的INCLUDES.H 文件要修改。以80x86 实模式,在大模式下编译为例,用户要做如下修改:

? 变目录名 μC/OS 为 μC/OS-II

? 变文件名 IX86L.H 为 OS_CPU.H

? 变文件名UCOS.H 为 uCOS_II.H

新旧文件如程序清单 L10.1和 L10.2所示

10.2 OS_CPU.H

OS_CPU.H 文件中有与微处理器类型及相应硬件有关的常数定义、宏定义和类型定义。

10.2.1 与编译有关的数据类型s

为了实现 μC/OS-II, 用户应定义6个新的数据类型: INT8U、 INT8S、 INT16U、 NT16S、INT32U、和INT32S。这些数据类型有分别表示有符号和无符号8位、16位、32位整数。在μC/OS中相应的数据类型分别定义为:UBYTE、BYTE、UWORD、WORD、ULONG和LONG。用户所要做的仅仅是复制μC/OS中数类型并修改原来的UBYTE为INT8U,将BYTE为INT8S,将UWORD修改为INT16U等等,如程序清单 L10.3所示。

程序清单 L10.1μC/OS 中的 INCLUDES.H.

/*

***************************************************************

*INCLUDES.H

***************************************************************

*/

#include

#include

#include

#include

#include

#include

#include"SOFTWAREUCOSIX86LIX86L.H"

#include"OS_CFG.H"

#include"SOFTWAREUCOSSOURCEUCOS.H"

程序清单 L10.2μ$04** 中的 INCLUDES.H.

/*

***************************************************************

*INCLUDES.H

***************************************************************

*/

#include

#include

#include

#include

#include

#include

#include"SOFTWAREuCOS-IIIX86LOS_CPU.H"

#include"OS_CFG.H"

#include"SOFTWAREuCOS-IISOURCEuCOS_II.H"

程序清单 L10.3μC/OS到μC/OS-II 数据类型的修改.

/*uC/OSdatatypes:*/

typedefunsignedcharUBYTE;/*Unsigned8bitquanTIty*/

typedefsignedcharBYTE;/*Signed8bitquantity*/

typedefunsignedintUWORD;/*Unsigned16bitquantity*/

typedefsignedintWORD;/*Signed16bitquantity*/

typedefunsignedlongULONG;/*Unsigned32bitquantity*/

typedefsignedlongLONG;/*Signed32bitquantity*/

/*uC/OS-IIdatatypes*/

typedefunsignedcharINT8U;/*Unsigned8bitquantity*/

typedefsignedcharINT8S;/*Signed8bitquantity*/

typedefunsignedintINT16U;/*Unsigned16bitquantity*/

typedefsignedintINT16S;/*Signed16bitquantity*/

typedefunsignedlongINT32U;/*Unsigned32bitquantity*/

typedefsignedlongINT32S;/*Signed32bitquantity*/

在μC/OS中, 任务栈定义为类型OS_STK_TYPE, 而在μC/OS-II中任务栈要定义类型OS_STK.,为了免于修改所有应用程序的文件, 可以在OS_CPU.H中建立两个数据类型, 以Intel80x86 为例,如程序清单 L10.4所示。

程序清单 L10.4μC/OS 和 μC/OS-II任务栈的数据类型

#defineOS_STK_TYPEUWORD/* 在 uC/OS 中 */

#defineOS_STKINT16U/* 在 uC/OS-II 中 */

10.2.2OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()

μC/OS-II和μC/OS一样,分别定义两个宏来开中断和关中断:OS_ENTER_CRITICAL()和

OS_EXIT_CRITICAL()。在μC/OS向μC/OS-II升级的时候,用户不必动这两个宏。.

10.2.3OS_STK_GROWTH

大多数微处理器和微处理器的栈都是由存储器高地址向低地址操作的,然而有些微处理器的工

作方式正好相反。μC/OS-II设计成通过定义一个常数OS_STK_GROWTH来处理不同微处理器栈操作的取向:[!--empirenews.page--]

对栈操作由低地址向高地址增长,设OS_STK_GROWTH 为 0

对栈操作由高地址向低地址递减,设OS_STK_GROWTH 为 1

有些新的常数定义(#define constants )在μC/OS中是没有的,故要加到OS_CPU.H中去。

10.2.4OS_TASK_SW()

OS_TASK_SW()是一个宏,从μC/OS升级到μC/OS-II时,这个宏不需要改动。当μC/OS-II从低优先级的任务向高优先级的任务切换时要用到这个宏,OS_TASK_SW()的调用总是出现在任务级代码中。

10.2.5OS_FAR

因为Intel80x86的结构特点, 在μC/OS中使用过OS_FAR 。 这个定义语句 (#define ) 在μC/OS-II中去掉了,因为这条定义使移植变得不方便。结果是对于Intel80x86,如果用户定义在大模式下编译时,所有存储器属性都将为远程(FAR).

在μC/OS-II中,任务返回值类型定义如程序清单L10.5所示。用户可以重新编辑所有OS_FAR的文件,或者在μC/OS-II中将OS_FAR定义为空,去掉OS_FAR,以实现向μC/OS-II的升级。

程序清单 L10.5 在 μC/OS 中任务函数的定义

voidOS_FARtask(void*pdata)

{

pdata=pdata;

while(1){

.

.

}

}

10.3 OS_CPU_A.ASM

移植μC/OS 和μC/OS-II 需要用户用汇编语言写4个相当简单的函数。

OSSTartHighRdy()

OSCtxSw()

OSIntCtxSw()

OSTickISR()

10.3.1OSStartHighRdy()

在μC/OS-II中,OSStartHighRdy()要调用OSSTaskSwHook()。OSTaskSwHook()这个函数在μC/OS中没有。用户将最高优先级任务的栈指针装入CPU之前要先调用OSTaskSwHook()。

还有, OSStartHighRdy要在调用OSTaskSwHook()之后立即将OSRunning设为1。程序清单L10.6 给出OSStartHighRdy()的示意代码。.μC/OS只有其中最后三步。

程序清单 L10.6 OSStartHighRdy()的示意代码

OSStartHighRdy:

CallOSTaskSwHook(); 调用OSTaskSwHook();

SetOSRunningto1; 置 OSRunning 为

1;

LoadtheprocessorstackpointerwithOSTCBHighRdy->OSTCBStkPtr;

将 OSTCBHighRdy->OSTCBStkPtr 装入处理器的栈指

针;

POPalltheprocessorregistersfromthestack; 从栈中弹出所有寄存器的值;

ExecuteaReturnfromInterruptinstruction; 执行中断返回指令;

10.3.2OSCtxSw()

在μC/OS-II中,任务切换要增作两件事,首先,将当前任务栈指针保存到当前任务控制块TCB后要立即调用OSTaskSwHook()。其次,在装载新任务的栈指针之前必须将OSPrioCur设为OSPrioHighRdy 。OSCtxSw()的示意代码如程序清单L10.7所示。μC/OS-II加上了步骤L10.7(1)和(2)。

程序清单 L10.7 OSCtxSw()的示意代码

OSCtxSw:

PUSHprocessorregistersontothecurrenttask’sstack;

所有处理器寄存器的值推入当前任务栈;

SavethestackpointeratOSTCBCur->OSTCBStkPtr;

CallOSTaskSwHook();1)

OSTCBCur=OSTCBHighRdy;

OSPrioCur=OSPrioHighRdy;(2)

LoadtheprocessorstackpointerwithOSTCBHighRdy->OSTCBStkPtr;

将 OSTCBHighRdy->OSTCBStkPtr 装入处理器的栈指

针;

POPalltheprocessorregistersfromthestack; 从栈中弹出所有寄存器的值;

ExecuteaReturnfromInterruptinstruction;

10.3.3OSIntCtxSw()

如同上述函数一样,在μC/OS-II.中,OSCtxSw()也增加了两件事。首先,将当前任务的栈指针保存到当前任务的控制块TCB后要立即调用OSTaskSwHook()。其次,在装载新任务的栈指针之前必须将OSPrioCur 设为OSPrioHighRdy。程序清单L10.8给出OSIntCtxSw()的示意代码。μC/OS-II.中增加了L10.8(1)和(2)。

程序清单L10.8OSIntCtxSw()的示意代码

OSIntCtxSw():

AdjustthestackpointertoremovecalltoOSIntExit(),localsin

OSIntExit()

andthecalltoOSIntCtxSw();

调整由于调用上述子程序引起的栈指针值的变化;

SavethestackpointeratOSTCBCur->OSTCBStkPtr;

保存栈指针到OSTCBCur->OSTCBStkPtr;

CallOSTaskSwHook(); 调用OSTaskSwHook();(1)

OSTCBCur=OSTCBHighRdy;

OSPrioCur=OSPrioHighRdy;(2)

LoadtheprocessorstackpointerwithOSTCBHighRdy->OSTCBStkPtr;

将 OSTCBHighRdy->OSTCBStkPtr 装入处理器的栈指针;

POPalltheprocessorregistersfromthestack; 从栈中弹出所有寄存器的值;

ExecuteaReturnfromInterruptinstruction; 执行中断返回指令;

10.3.4OSTickISR()

在μC/OS-II和μC/OS 中,这个函数的代码是一样,无须改变。

10.4 OS_CPU_C.C

移植 μC/OS-II 需要用C语言写6个非常简单的函数:

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskStatHook()

OSTimeTickHook()

其中只有一个函数OSTaskStkInit()是必不可少的。其它5个只需定义,而不包括任何代码。

10.4.1OSTaskStkInit()

在μC/OS中,OSTaskCreate()被认为是与使用的微处理器类型有关的函数。实际上这个函数中只有一部分内容是依赖于微处理器类型的。在μC/OS-II中,与使用的微处理器类型有关的那一部分已经从函数OSTaskCreate() 中抽出来了,放在一个叫作OSTaskStkInit()的函数中。

OSTaskStkInit()只负责设定任务的栈,使之看起来好像中断刚刚发生过,所有的CPU寄存器都被推入堆栈。作为提供给用户的例子,程序清单L10.9给出Intel80x86实模式,在大模式下编译的 μC/OS的OSTaskCreate()函数的代码。程序清单L10.10是同类微微处理器的μC/OS-II的OSTaskStkInit()函数的代码。比较这两段代码,可以看出:从 [L10.9(1)]

OS_EXIT_CRIITICAL() 到 [L10.9(2)] 调用 OSTaskStkInit() 都抽出来并移到了[!--empirenews.page--]

OSTaskStkInit()中。

程序清单L10.9μC/OS 中的 OSTaskCreate()

UBYTEOSTaskCreate(void(*task)(void*pd),void*pdata,void*pstk,UBYTE

p)

{

UWORDOS_FAR*stk;

UBYTEerr;

OS_ENTER_CRITICAL();

if(OSTCBPrioTbl[p]==(OS_TCB*)0){

OSTCBPrioTbl[p]=(OS_TCB*)1;

OS_EXIT_CRITICAL();(1)

stk=(UWORDOS_FAR*)pstk;

*--stk=(UWORD)FP_OFF(pdata);

*--stk=(UWORD)FP_SEG(task);

*--stk=(UWORD)FP_OFF(task);

*--stk=(UWORD)0x0202;

*--stk=(UWORD)FP_SEG(task);

*--stk=(UWORD)FP_OFF(task);

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=(UWORD)0x0000;

*--stk=_DS;

err=OSTCBInit(p,(voidfar*)stk);(2)

if(err==OS_NO_ERR){

if(OSRunning){

OSSched();

}

}else{

OSTCBPrioTbl[p]=(OS_TCB*)0;

}

return(err);

}else{

OS_EXIT_CRITICAL();

return(OS_PRIO_EXIST);

}

}

程序清单 L10.10 μC/OS-II中的OSTaskStkInit()

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

INT16Uopt)

{

INT16U*stk;

opt=opt;

stk=(INT16U*)ptos;

*stk--=(INT16U)FP_SEG(pdata);

*stk--=(INT16U)FP_OFF(pdata);

*stk--=(INT16U)FP_SEG(task);

*stk--=(INT16U)FP_OFF(task);

*stk--=(INT16U)0x0202;

*stk--=(INT16U)FP_SEG(task);

*stk--=(INT16U)FP_OFF(task);

*stk--=(INT16U)0xAAAA;

*stk--=(INT16U)0xCCCC;

*stk--=(INT16U)0xDDDD;

*stk--=(INT16U)0xBBBB;

*stk--=(INT16U)0x0000;

*stk--=(INT16U)0x1111;

*stk--=(INT16U)0x2222;

*stk--=(INT16U)0x3333;

*stk--=(INT16U)0x4444;

*stk=_DS;

return((void*)stk);

}

10.4.2OSTaskCreateHook()

OSTaskCreateHook()在μC/OS中没有,如程序清单L10.11所示,在由.μC/OS 向μC/OS-II升级时,定义一个空函数就可以了。注意其中的赋值语句,如果不把Ptcb赋给Ptcb,有些编译器会产生一个警告错误,说定义的Ptcb变量没有用到。

程序清单10.11 μC/OS-II 中的OSTaskCreateHook()

#ifOS_CPU_HOOKS_EN

OSTaskCreateHook(OS_TCB*ptcb)

{

ptcb=ptcb;

}

#endif

OS_CFG.H

OS_CPU_HOOKS _EN设为1时,OSTaskCreateHook()的代码才会生成。这样做的好处是允许

用户移植时可在不同文件中定义钩子函数。

10.4.3OSTaskDelHook()

OSTaskDelHook() 这个函数在μC/OS中没有,如程序清单10.12所示,从μC/OS 到μC/OS-II,只要简单地定义一个空函数就可以了。注意,如果不用赋值语句将ptcb赋值为ptcb,有些编译程序可能会产生一些警告信息,指出定义的ptcb变量没有用到。

程序清单L10.12 μC/OS-II中的OSTaskDelHook().

#ifOS_CPU_HOOKS_EN

OSTaskDelHook(OS_TCB*ptcb)

{

ptcb=ptcb;

}

#endif

也还是要用条件编译管理指令来处理这个函数。只有把OS_CFG.H. 文件中的

OS_CPU_HOOKS_EN 设为1,OSTaskDelHook()的代码才能生成。这样做的好处是允许用户移植时在不同的文件中定义钩子函数。

10.4.4OSTaskSwHook()

OSTaskSwHook() 在μC/OS 中也不存在。从μC/OS向μC/OS-II升级时,只要简单地定义一个空

函数就可以了,如程序清单L10.13所示。

程序清单L10.13 μC/OS-II中的OSTaskSwHook()函数

#ifOS_CPU_HOOKS_EN

OSTaskSwHook(void)

{

}

#endif

也还是要用编译管理指令来处理这个函数。 只有把OS_CFG.H 文件中的OS_CPU_HOOKS_EN设为1,OSTaskSwHook() 的代码才能生成。.

10.4.5OSTaskStatHook()

OSTaskStatHook()在μC/OS中不存在,从μC/OS向μC/OS-II升级时,只要简单地定义一个空函数就可以了,如程序清单L10.14所示。

也还是要用编译管理指令来处理这个函数。 只有把OS_CFG.H 文件中的OS_CPU_HOOKS_EN设为1,OSTaskSwHook() 的代码才能生成。

程序清单L10.14 μC/OS-II中的OSTaskStatHook()函数

#ifOS_CPU_HOOKS_EN

OSTaskStatHook(void)

{

}

#endif

10.4.6OSTimeTickHook()

OSTimeTickHook()在μC/OS中不存在,从μC/OS向μC/OS-II升级时,只要简单地定义一个空函数就可以了,如程序清单L10.15所示。

也还是要用编译管理指令来处理这个函数。 只有把OS_CFG.H 文件中的OS_CPU_HOOKS_EN设为1,OSTimeTickHook()的代码才能生成。

.

程序清单L10.15 μC/OS-II中的OSTimeTickHook()

#ifOS_CPU_HOOKS_EN

OSTimeTickHook(void)

{

}

#endif

10.5总结

表T10.3总结了从μC/OS向μC/OS-II.升级需要改变得地方。其中processor_name.?是μC/OS中

移植范例程序的文件名。

表 T10.3 升级 μC/OS到 μC/OS-I要修改的地方

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

利用LogiCoA™微控制器,以更低功耗实现与全数字控制电源同等的功能

关键字: 微控制器 电源 CPU

2024年4月18日 – 提供超丰富半导体和电子元器件™的业界知名新品引入 (NPI) 代理商贸泽电子 (Mouser Electronics) 很荣幸地宣布与Edge Impulse建立新的全球合作关系。Edge Im...

关键字: 机器学习 MCU CPU

无论您是在研究如何使用 10GigE 还是寻求所需考虑事项的建议,本文均提供有实践,帮助确保单相机 10GigE 视觉系统设置顺利并拥有良好性能。 我们列出了主机系统配置、布线和相机设置的实践。

关键字: 视觉系统 CPU 存储器

Apr. 16, 2024 ---- NVIDIA新一代平台Blackwell,包含B系列GPU及整合NVIDIA自家Grace Arm CPU的GB200等。TrendForce集邦咨询指出,GB200的前一代为GH2...

关键字: CPU GPU

人工智能是集合众多方向的综合性学科,在诸多应用领域均取得了显著成果[1]。随着航空领域人工智能技术研究的不断深入,面向开放式机载智能交互场景,人工智能的应用可解决诸多问题。例如智能感知、辅助决策等,可利用人工智能算法对多...

关键字: 人工智能 PCIe CPU

CPU针脚弯了,用工具调正就不会有影响。开机自检也通过,CPU 再出问题就不是针脚引起的问题。针脚只要不断就没有问题,有的CPU出厂的时候针脚就有点弯,这并不是什么大问题,只要用镊子轻轻地弄直就可以了。

关键字: CPU 针脚 开机自检

瑞典乌普萨拉,2024年3月27日 – 全球领先的嵌入式系统开发软件解决方案供应商IAR自豪地宣布:公司备受全球数百万开发者青睐的开发环境再次升级,已率先支持瑞萨首款通用32位RISC-V MCU,该 MCU 搭载了瑞萨...

关键字: MCU RISC-V CPU

联发科与高通骁龙的对决可以说是一场性能与价值的较量,那么,你对两者的芯片有了解吗?在移动设备领域,芯片制造商的竞争愈发激烈。其中,来自台湾的联发科(MediaTek)与美国的高通(Qualcomm)无疑是该领域的两大巨头...

关键字: 联发科 高通骁龙 CPU 处理器

云和超大规模服务运营商正不断增大计算密度。随着 Microsoft Cobalt、阿里巴巴的倚天 710、AmpereOne等配置 128 核或以上的 CPU 设计进入市场,单个封装可实现的性能更强,且下一代的目标还将远...

关键字: CPU 处理器

Arm Neoverse 旨在为从云到边缘的全场景基础设施用例提供高性能和出色能效。针对需要更高性能的工作负载和用例,Arm 推出了 Neoverse V 系列。其中,Neoverse V2 核心已被行业先行者广泛部署于...

关键字: 云计算 人工智能 CPU
关闭
关闭