历史上的今天
返回首页

历史上的今天

今天是:2025年08月12日(星期二)

正在发生

2021年08月12日 | UCOS-II在MC9S12XS128上的移植

2021-08-12 来源:eefocus

操作系统是一种与硬件为基础的系统软件,硬件系统不一样,那在其上面运行的操作系统也会不一样。一般来说,操作系统是与芯片相关联的。要在某型号的芯片上运行操作系统,那得在操作系统内核的基础上编写一些与芯片相关的驱动程序,并对内核的配置文件做相应的改动,然后在编译器上编译,链接,然后下载到芯片上。这个过程就是所谓的操作系统的移植了。


UCOS-II是个开源的也就是原代码公开的内核,可以免费用于非商业的各种运用中。其原代码可以在http://micrium.com/page/products/rtos/os-ii上找到。上面有好多在某些芯片上移植成功的实例,如果芯片型号对应,则可以下载下来直接用。这样就可以省去好多移植的工作,而直接在上面编写用户任务就可以了。

 

UCOS-II的文件有:

一、与处理器无关的代码:

OS_CORE.C(与内核运作有关的文件)

OS_FLAG.C(事件标志组管理)

OS_MBOX.C(消息邮箱)

OS_MEM.C(内存管理)

OS_MUTEX.C(互斥型信号量)

OS_Q.C(消息列队)

OS_SEM.C(信号量)

OS_TASK.C(任务管理)

OS_TIME.C(时钟管理)

UCOS_II.C()

UCOS_II.H()


二、UCOS-II的配置文件(需要用户根据具体的运用来配置)

OS_CFG.H(配置使用哪些系统函数,按需裁剪操作系统)

INCLUDES.H(系统总头文件,把所有用的到头文件都加进来)


三、UCOS-II的移植文件(与处理器相对应的功能实现)

OS_CPU.H(定义数据类据、临界代码实现方法、堆栈方向、任务切换宏)

OS_CPU_C.C(与硬件相关的代码)

OS_CPU_A.S (若移植使用的C编译器允许在C代码中插入汇编语句,则汇编部分的代码可以放到OS_CPU_C.C中,此时0S_CPU_A.S就可以不要了)

 

要移植UCOS-II的芯片必须满足以下要求:

1、 处理器的C语言编译器能产生可重入型代码;

2、 处理器支持中断,并且能产生定时中断(通常为10~100Hz);

3、 用C语言就可以开或关中断;

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

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

 

下面结合UCOS-II在MC9S12XS128上的移植来讨论一下UCOS-II的移植方法及过程。

UCOS-II的移植分成几个步骤:

 

一、文件OS_CPU.H的编写,要求对处理器的内部结构有所了解:

#ifndef OS_CPU_H

#define OS_CPU_H

【定义数据类型。因为不同的编译器对数据的定义不尽相同,而UCOS-II系统中采用统一的数据类型名,以便于移植。故这里要把操作系统中的数据类型和所用的编译器的数据类型对应起来。】

typedef unsigned char  BOOLEAN; 【布尔变量类型】

typedef unsigned char  INT8U;     【无符号8位整数】

typedef signed   char INT8S;     【有符号8位整数】

typedef unsigned int   INT16U;     【无符号16位整数】

typedef signed   int  INT16S;     【有符号16位整数】

typedef unsigned long  INT32U;     【无符号32位整数】

typedef signed   long INT32S;     【有符号32位整数】

typedef float          FP32;      【单精度浮点数】

typedef double         FP64;     【双精度浮点数】

//

typedef unsigned char OS_STK;     【堆栈的数据类型,这由处理器决定,堆栈变量都由OS_STK定义】

typedef unsigned short OS_CPU_SR;    【CPU状态寄存器PSW的数据类型,因为在临界代码方法3中,会把PSW中的值存入到OS_CPU_SR定义的变量cpu_sr中】

【三个函数声明】       

void OSStartHighRdy(void);   

void OSIntCtxSw (void);

void OSCtxSw (void);


#define OS_CRITICAL_METHOD    3  【这里可以是1、2或者3,选择3表示用方法3进入临界代码区】

【这里定义临界代码方法3的具体程序实现,这跟处理器结构相关】

#if     OS_CRITICAL_METHOD == 3

#define OS_ENTER_CRITICAL()  (cpu_sr =OS_CPU_SR_Save())   

#define OS_EXIT_CRITICAL()  (OS_CPU_SR_Restore(cpu_sr))   

#endif

/

#define OS_TASK_SW()    _asm("swi")  【这里定义一个宏,是在UCOS-II做任务切换时必须用到的。在UCOS-II中,处于就绪态的任务的堆栈结构看起来就像刚发生过中断一样,所有的寄存器都保存大堆栈中。要运行就绪的任务时,系统要做的就是从任务堆栈中恢复处理器所有的寄存器,并执行中断返回指令。任务调度时,可以通过执行OS_TASK_SW()模仿中断的产生。绝大多数处理器会提供软中断或指令陷阱来完成这项功能。在XS128中就是通过软中断SWI来完成的。】

/

#define OS_STK_GROWTH    1     【用于根据处理器堆栈的方向来配置操作系统,当处理器的堆栈是从下(低地址)往上(高地址)递增时,OS_STK_GROWTH定为0;当处理器的堆栈是从上往下递减时,OS_STK_GROWTH定为1。】          

 

【声明两个与用方法3实现临界代码有关的函数】

#if     OS_CRITICAL_METHOD == 3

OS_CPU_SR OS_CPU_SR_Save(void);【返回PSW寄存器的值,保存在cpu_sr中,并关中断】                                                                

void   OS_CPU_SR_Restore(OS_CPU_SR  os_cpu_sr);  【把cpu_sr的值恢复到PSW寄存器中去】

#endif

 

#endif

 

二、文件OS_CPU_C.C的编写,要求对处理器的堆栈结构有所了解:

在这个文件中,得编写10个函数,分别是:

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskIdleHook()

OSTaskStatHook()

OSTimeTickHook()

OSInitHookBegin()

OSInitHookEnd()

OSTCBInitHook()

除了OSTaskStkInit()外,其他9个函数必须声明,但不一定要包含任何代码。

只有OS_CFG.H文件中的OS_CPU_HOOKS_EN置为1时,才会生成下面OS_XXXHook()的这些代码,这个由程序中的条件编译可以看出。这些函数相当于是用户对操作系统功能扩展的接口函数,它的设置是为了方便用户根据需要扩展UCOS-II的功能。这些函数在其相应的函数中初调用,来实现用户的扩展功能;如果不需要扩展功能,则只需声明一个空函数。强调一点是,不管是否需要扩展UCOS-II的功能,都必须得声明这些函数。

 

OS_CPU_C.C文件中的程序如下:

#include "includes.h"

 

【下面这个函数是堆栈初始化函数,需要在了解处理器堆栈结构的基础上编写。其中的参数分别表示:task是指向任务的函数指针,即任务的起始地址,其中pd为task指向的任务的参数;p_arg为任务开始执行时传递给任务的参数的指针;ptos为堆栈栈顶值,也就是传入堆栈的初始值; opt为OS_TCB的选择项,用于设定OSTaskCreateExt()的选项,指定是否允许堆栈检验,是否将堆栈清0,任务是否要进行浮点操作等,在OSTaskCreate()中没有opt参数,故当OSTaskCreate()调用OSTaskStkInit()时,将opt设置为0X0000。】

OS_STK *OSTaskStkInit (void (*task)(void*pd), void *p_arg, OS_STK *ptos, INT16U opt)

{

【因为要压入堆栈中的数据有十六位的,也有八位的,所以就定义了两个指针,一个十六位,一个八位。】

   INT16U *wstk;      

   INT8U  *bstk;      

opt     = opt;     【这条语句没有实际意义,因为这个参数没有用到,为了避免编译时发出警告,就令opt =opt,表示这个参数已经用过了,就不会有这个警告了。】                                      

wstk    = (INT16U *)ptos;   【载入堆栈的初始值】  

    *--wstk=  (INT16U)p_arg;   【任务中传递的参数】

    *--wstk=  (INT16U)(((INT32U)task) >>8);  【把任务的地址压入堆栈,相当于PC值入栈】

*--wstk =  (INT16U)(((INT32U)task) >> 8);  【????】 

 *--wstk =  (INT16U)0x2222;           【Y寄存器】 

*--wstk =  (INT16U)0x1111;           【X寄存器】

  *--wstk =  (INT16U)0xBBAA;          【D寄存器】 

*--wstk =  (INT16U)0x0080;           【CCR寄存器】

 bstk    = (INT8U *)wstk;    【十六位指针强制类型转化为八位后赋给八位指针bstk】 

*--bstk =*(INT8U *)0x10;      【GPAGE寄存器】

 *--bstk = *(INT8U*)0x17;      【EPAGE寄存器】  

*--bstk =*(INT8U *)0x16;      【RPAGE寄存器】

*--bstk =  (INT8U )task;     【任务的PPAGE寄存器值】

return ((OS_STK*)bstk);    【返回当前堆栈的值】

}

 

【OS_VERSION的值表示当前所用的UCOS-II的版本号,在文件UCOS_II.H中有定义。203表示的版本号是2.03;252表示的版本号是2.52 。这里用到条件编译,表示2.03以上的版本中才会用到OSInitHookBegin (void)和OSInitHookEnd (void)】

#if (OS_CPU_HOOKS_EN > 0) &&(OS_VERSION > 203)       

void OSInitHookBegin (void)

{

}

#endif

#if (OS_CPU_HOOKS_EN > 0) &&(OS_VERSION > 203)

void OSInitHookEnd (void)

{

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0)

void OSTaskCreateHook (OS_TCB *ptcb)

{

   (void)ptcb;

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0)

void OSTaskDelHook (OS_TCB *ptcb)

{

   (void)ptcb;

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0) &&(OS_VERSION >= 251)

void OSTaskIdleHook (void)

{

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0)

void OSTaskStatHook (void)

{

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0)

void OSTaskSwHook (void)

{

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0) &&(OS_VERSION > 203)

void OSTCBInitHook (OS_TCB *ptcb)

{

   (void)ptcb;

}

#endif

 

#if (OS_CPU_HOOKS_EN > 0)

void OSTimeTickHook (void)

{

}

#endif

 

三、编写OS_CPU_A.ASM文件(对于CW编译器,这部分代码可以放在OS_CPU_C.C文件中,以C语言插入汇编语言的方式出现)

在这部分中要编写的函数有:

1、 OSStartHighRdy()  【OSStart()函数调用OSStartHighRdy()来使就绪态任务中优先级最高的任务开始运行】

2、 OSCtxSw()   【任务级的任务切换,通过执行软中断指令来实现】

3、 OSIntCtxSw()   【中断级的任务切换】

4、 OSTickISR()   【时钟节拍中断服务函数】

 

四、产生时钟节拍中断

UCOS-II的运行要求处理器提供一个时钟中断节拍,用于任务的延时或挂起等功能,因此得编写代码产生时钟节拍中断。在XS128中可以利用实时中断模块RTI来实现时钟中断节拍功能。其实就两句:

RTICTL=0XCF;  【分频】

CRGINT|=0X80;  【开实时中断】

开实时中断的动作必须在UCOS-II初始化之后,多任务开始之前,所以这两句语句一般放在第一个建立的任务函数中。

最后要修改CW建立工程时自动生成的XXX.prm链连文件,把时钟节拍中断向量放到中断向量表中,即在XXX.prm文件后面添加语句VECTOR 7 OSTickISR。

 

到这里,移植工作就算是完毕了。在添加任务之前可以先编译一下,以及调试一下程序,排除在移植过程中产生的错误。

 

当然要运用这个操作系统的工作还没完成:

1、 把所有的头文件都包进系统总头文件INCLUDES.H中。

2、 根据实际运用需要在OS_CFG.C文件中配置及裁剪系统。

3、 编写main.c文件及任务函数。

 

UCOS-II在51单片机上的移植方面的信息可与杨屹先生沟通,其网址为www.armecos.com ,电子邮箱为asdjf@163.com。UCOS-II在ARM核上移植方面的信息可与周立功先生联系,其电子邮箱为zlg3@zlgmcu.com。 

 

参考文献

[1]嵌入式实时操作系统UC/OS-II(第二版)   [美] Jean J.Labrosse  著   邵贝贝等译  北京航空航天大学出版社

[2]嵌入式实时操作系统UC/OS-II原理及应用   任哲  编著   北京航空航天大学出版社

[3]单片机与嵌入式系统开发方法   薛涛 宫辉 龚光华 邵贝贝等编著    清华大学出版社

推荐阅读

史海拾趣

Hengstler GmbH公司的发展小趣事

Helium Systems Inc.公司发展的五个故事

故事一:从物联网初创到区块链转型

Helium Systems Inc.的故事始于2013年,由Napster的联合创始人Shawn Fanning和知名游戏设计师Amir Haleem等人共同创立。最初,公司名为Skynet Phase 1,灵感来源于《终结者》系列电影中的电脑系统,旨在为物联网(IoT)创建无线网络。然而,在经历了几年的产品开发和市场探索后,该项目并未取得显著成功。直到2017年,Helium团队意识到区块链技术的潜力,决定将项目转型为基于区块链的分布式无线网络项目,即后来的Helium Network。这一转型为Helium带来了全新的发展机遇。

故事二:Helium Network的迅速崛起

自2019年Helium Network正式启动以来,该项目迅速吸引了全球用户的关注。用户只需购买并部署Helium热点设备,即可为周围的物联网设备提供无线连接,并因此获得Helium的加密货币HNT作为奖励。这种创新的挖矿模式迅速吸引了大量用户参与,Helium网络在短时间内实现了全球范围内的快速扩张。到2021年,Helium网络已经覆盖了超过160个国家和地区,拥有数十万个热点,成为全球领先的分布式无线网络之一。

故事三:融资与合作伙伴的加入

Helium Systems Inc.在发展过程中获得了多轮融资支持,其中包括来自a16z和Tiger Global等知名投资机构的巨额投资。这些资金为Helium网络的进一步扩展和技术创新提供了有力保障。同时,Helium还积极寻求与全球范围内的合作伙伴建立战略合作关系,包括电信运营商、物联网设备制造商等。这些合作伙伴的加入不仅丰富了Helium网络的应用场景,还进一步提升了其市场影响力和竞争力。

故事四:技术挑战与解决方案

在Helium网络的发展过程中,团队也面临了诸多技术挑战。例如,如何确保网络的稳定性和安全性、如何优化热点设备的部署和性能等。针对这些问题,Helium团队不断进行技术创新和优化,推出了多项新技术和解决方案。例如,他们开发了独特的PoC(Proof of Coverage)共识机制,通过该机制可以确保热点设备在提供有效覆盖时才能获得奖励,从而有效防止了作弊行为的发生。此外,Helium还加强了与区块链安全公司的合作,共同提升网络的安全性。

故事五:公司更名与未来发展

为了更好地推动Helium网络的发展,Helium Systems Inc.在2022年宣布将公司更名为Nova Labs,并启用新的品牌形象。这一更名举措旨在进一步凸显Helium网络作为分布式无线网络联盟的地位和影响力。同时,Nova Labs还宣布完成了D轮融资,并计划将资金用于进一步扩展网络覆盖范围、提升技术性能和加强市场推广等方面。展望未来,Nova Labs将继续致力于推动Helium网络的发展和创新,为全球用户提供更加安全、高效、便捷的物联网连接服务。

Green Solution Technology Co Ltd公司的发展小趣事

对于听音耳机电路,网友可能的问题涉及多个方面,以下是一些常见问题及相应的回答:

一、技术性问题

  1. 耳机电路的工作原理是什么?
    • 回答:耳机电路主要通过音频信号放大器将音频设备(如手机、电脑等)输出的微弱电信号放大,然后驱动耳机的驱动单元(扬声器)产生声音。这个过程中,耳机电路还负责音频信号的传输和转换,确保音质清晰、音量适中。
  2. 为什么耳机电路会出现杂音或失真?
    • 回答:耳机电路出现杂音或失真的原因可能有很多,包括电路接触不良、线路老化、驱动单元故障、音频信号源问题等。此外,电磁干扰、设备不兼容等也可能导致音质问题。解决这类问题通常需要检查电路连接、更换损坏部件或调整设备设置。
  3. 如何判断耳机电路是否损坏?
    • 回答:判断耳机电路是否损坏可以通过以下方法:首先,检查耳机是否能正常发声,如果无声或声音异常,可能是电路问题;其次,使用万用表等工具检测电路中的电阻、电压等参数是否正常;最后,可以尝试将耳机连接到其他音频设备上进行测试,以排除设备问题。

二、维护与保养

  1. 如何保养耳机电路以延长使用寿命?
    • 回答:保养耳机电路的关键在于避免潮湿、防止碰撞和摔落,并定期清洁。使用时应注意避免拉扯耳机线,以免损坏内部电路。此外,在不使用耳机时,应将其存放在干燥、通风的地方,避免阳光直射和高温环境。定期使用软布轻轻擦拭耳机表面和插头,可以去除污垢和灰尘,保持电路清洁。
  2. 耳机电路进水了怎么办?
    • 回答:如果耳机电路进水,应立即停止使用并切断电源。然后,使用干燥的软布或纸巾轻轻擦拭耳机表面和插头上的水分。如果条件允许,可以将耳机放在通风良好的地方自然晾干,避免使用吹风机等热源直接吹干,以免损坏电路。如果进水情况严重或无法自行处理,建议送往专业维修中心进行检修。

三、升级与改造

  1. 如何升级耳机电路以提升音质?
    • 回答:升级耳机电路以提升音质需要一定的专业知识和技术。一般来说,可以通过更换更高品质的音频信号放大器、使用更优质的线路材料、优化电路设计等方式来实现。然而,这些操作可能比较复杂且存在风险,如果不熟悉相关技术,建议寻求专业人员的帮助。
  2. 是否可以自己动手改造耳机电路?
    • 回答:虽然理论上可以自己动手改造耳机电路,但这需要具备较高的电子技术和动手能力。如果操作不当,可能会导致电路损坏甚至耳机报废。因此,在没有足够经验和专业知识的情况下,不建议自己尝试改造耳机电路。

综上所述,针对听音耳机电路的问题,网友可能关心的方面包括技术性问题、维护与保养以及升级与改造等。在解决这些问题时,应根据具体情况采取相应的措施和方法。

Coiltronics公司的发展小趣事

随着全球化趋势的加强,Coiltronics公司开始将目光投向国际市场。公司制定了一系列国际化战略,包括在海外市场设立分支机构、与当地企业合作等。通过这些举措,Coiltronics成功将其技术和产品推向国际市场,进一步扩大了公司的业务范围。同时,国际化战略也带来了公司管理、文化等方面的变革,为公司的长远发展注入了新的活力。

Headland Technology Product Group公司的发展小趣事

在电子行业中,产品质量是企业生存和发展的基石。HBControls深知这一点,因此始终将品质管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产加工到成品检验,每一个环节都严格把关。此外,HBControls还定期对员工进行质量意识培训,确保每一位员工都能将品质理念融入到日常工作中。正是凭借卓越的产品质量和优质的服务,HBControls赢得了众多客户的信赖和好评。

Ericsson公司的发展小趣事

Ericsson公司在早期就非常注重市场拓展和全球布局。通过与各国电信运营商建立合作关系,Ericsson成功将其产品和服务推广到了全球各地。特别是在中国市场,Ericsson早在19世纪90年代就与中国签订了供货合同,成为中国通信网络建设的重要参与者。如今,Ericsson已经在中国扎根130余年,成为了唯一一家从1G到5G全程参与中国通信网络建设的企业。

智浦欣(Chipstar)公司的发展小趣事

为了进一步提升公司的技术实力和品牌影响力,智浦欣公司积极寻求与国际知名企业的合作机会。经过多次沟通和洽谈,公司成功与一家国际知名半导体企业达成了战略合作协议。双方将在技术研发、产品推广和市场开拓等方面展开深度合作。通过这一合作,智浦欣公司不仅获得了宝贵的技术支持和市场资源,还进一步提升了其品牌形象和市场份额。

问答坊 | AI 解惑

室内照明的个人愚见

replyreload += \',\' + 376426;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

哪位大虾有现代硬盘(大容量)接口编程的详细资料啊,小弟求教啊

小弟最近在研究Linux,看到这一部分的时候感觉很晕,希望高手赐教 如果有资料给小弟发一下,谢谢 chenhaiyang628@163.com…

查看全部问答>

JTAG仿真问题

仿真器正常,程序也正常,为什么在我的一块板子上下载不了程序呢?,不过以前是可以的 一下载的时候总是提示我说没有发现设备 我想问各位高手出现这种现象可能的原因 …

查看全部问答>

AVR ATmega16 驱动ULN2003无法同时吸合6个继电器

打算使用AVR ATmega16单片机控制ULN2003,驱动欧姆龙G6L-5V继电器。 遇到了继电器部分情况下响应不正确的问题。现象:控制单片机在PB口输出11111111(8个高电平)时,无法开启继电器,K1-K6均没有反应。但是当PB7-PB2有一个为低电平时,继电器响应 ...…

查看全部问答>

STLINK里的单片机用的是STM32101C8吗?

                                 今天找代理商要了一个STLINK,拆开看竟然STLINK里的单片机用的是STM32101C8,101系列不是没有USB接口吗。但是MINIUS ...…

查看全部问答>

怎么读取FAT16文件系统的FDT表

我的困惑是一次到底读多少,因为一个文件信息占32位,我想只读32位,然后查询file-name,再得到首簇号。 哪位大虾指点一下啊,谢谢 …

查看全部问答>

團購會是這個嗎?

這次團購會是這個嗎?  期待啊…

查看全部问答>

键盘按键时对P口赋值的影响。

接的是P0口,让P0=0xf0;假设按下的是s1,按下时p0=0x70:然后载对赋值P0=0x7f;键s1还按下着,赋值过后P0是不是=0x7e;键再松了p0还是=0x7e??是不是这样理解的?还一个问题赋初值p0=0xf0;按下s1再松开s1,p0=0x70还是p0=f0不变?…

查看全部问答>