从零开始学习UCOSII操作系统13--系统移植理论篇

1、什么是系统移植?

(1)UCOSII移植到不同的处理器上,所谓的移植就是将一个实时的内核能在其他的微处理器或者微控制器上运行。

为了方便移植,UCOSII的大部分的代码都是C语言写的,因为不同机器的汇编代码是不一样的。这是由于UCOSII在设计的时候已经充分考虑到了可移植性这一点。

但是仍然有一部分的代码是需要用C语言和汇编语言写一些与处理器有关的代码。

(2)要使用UCOSII正常的运行,处理器必须满足以下的条件
2.1、处理器的C编译器能产生可重入型的代码

原因:如果不行的话,那么就不能在任务之间随意的切换,因为当你切换到别的任务的时候,该任务在这个函数的数据就会被破坏。

2.2、处理器支持中断,并能产生定时中断

2.3、用C语言就可以开关中断

原因:连中断都没有的话,是不可能进行任务切换的。

2.4、处理器能够支持一定数量的数据存储硬件堆栈,也就是栈

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

原因:因为我们在任务切换的时候,需要将当前的CPU指针保存到刚刚执行的任务当中。然后切换到优先级更高的任务当中。

2、移植UCOSII实际上需要移植什么文件?

其实我们移植UCOSII额时候,大部分的代码是基于底层进行编写的,所以我们不需要进行移植。有一些是对这个UCOSII进行的配置的,所以我们不需要进行移植。

我们唯一需要关注的三个文件就是下面的三个文件。
OS_CPU.h
OS_CPU_A.ASM
OS_CPU_C.c

一般我们在开发的时候,我们会把所有的头文件定义在同一个头文件当中,因为这样我们只需要包含一个头文件就可以了,不会重复的包含多个头文件。

需要移植的几个文件:
INCLUDES.H
是一个主头文件,出现在每个.c 文件的第一行。

使得每个.c的文件中无需分别考虑它实际上需要哪些头文件,使用INCLUDE.H唯一的缺点就是,它可能包含一些与当前的编译的.c文件不相干的头文件。

OS_CPU.H
包含了用#define 语句定义的,与处理器相关的常数,宏以及类型。
OS_CPU.H的大体结构如程序清单所列。

这里面使用typedef用的比#define更加的好,因为#define仅仅相当于字符串的拷贝,但是typedef相当于命名了一个别名。

/*        数据类型       */typedef unsigned char BOOLEAN;typedef unsigned int OS_STK;   //堆栈入口的宽度为16位
typedef unsigned short OS_CPU_SR; //定义CPU状态寄存器的宽度为16位/*         与处理器有关的代码    */
#define OS_ENTER_CRITICAL()     //进入临界区的代码
#define OS_EXIT_CRITICAL()      //跳出临界区的代码#define OS_STK_GHOWTH   1  定义堆栈的方向:1=向下递减,0=向上递增#define OS_TASK_SW()  ??  //定义软件任务切换的函数。

最关键的移植文件:CPU的文件
移植文件3:OS_CPU_C.c
UCOSII的移植范例要求用户编写10个简单的C函数:

OSTaskStkInit();
OSTaskCreateHook();
OSTaskDelHook();
OSTaskSwHook();
OSTaskIdleHook();
OSTaskStatHook();
OSTimeTickHook();
OSInitHookBegin();
OSInitHookend();
OSTCBInitHook();

PS:唯一必要的函数是OSTaskStkinit();其余的9个函数必须声明,但是并不一定要包含任何代码,这些函数的原型放在本章的末尾。

(1)因此堆栈看起来就像中断刚发生的一样,所有的寄存器都保存在堆栈中,OSTaskStkInit()的示例性代码:

OS_STK * OSTaskStkInit(void (*task)(void * pd),void * pada,OS_STK  *ptos,INT16U  opt);
{pada = pada;模拟ISR向量;//按照预先设计的寄存器值初始化堆栈结构;//不断的在堆栈中相应的位置填入你要传递的参数//返回栈顶指针给调用该函数的函数//在这里假定堆栈是从上往下递减的,下面讨论同样适用于以相反方向从下到上递增的堆栈结构。
}

(2)OSTaskCreateHook():
每当添加任务的时候,OS_TCBInit()函数都会调用OSTaskCreateHook()函数,该函数允许扩展UCOSII的功能,当UCOSII设置完任务控制块OS_TCB初始化的绝大部分的工作后,但是在任务控制块被链接到相应的任务链中之前,以及在该任务就绪运行之前,UCOSII会调用OSTaskCreateHook(),该函数被调用的时候中断是打开的。

钩子函数就是为了检查相应的操作有没有成功的。

(3)OSTaskIdleHook()
很多微处理器都允许执行相应的指令,将CPU置于低功耗模式。而当接收到中断信号的时候,CPU就会退出低功耗模式,OSTaskIdle()函数可调用OSTaskIdleHook()函数,实现CPU的这种低功耗的模式:

PS:其实这里真的设计的非常的巧妙,因为你没有任何的任务进行调度的时候,应该是没有什么执行的,但是我们UCOSII系统,规定当没有任何的任务需要强占CPU的时候,我们应该让其进入低功耗的模式,真的设计的很好。

void OS_TaskIdle(void *pdata)
{pdata = pdata;for(;;){OS_ENTER_CRITICAL();OSIdleCtr++;OS_EXIT_CRITICAL();OSTaskIdleHook();}
}void OSTaskIdleHook(void)
{asm("STOP");//收到中断并完成中断服务。
}

OS_CPU_A.ASm
UCOSII的移植实例就是要求用户编写4个简单的汇编语言函数:
OSStartHighRdy(); //使得最高优先级的任务运行的函数
OSCtxSw(); //任务的切换的函数
OSIntCtxSw();
OSTickISR();

如果编译器支持插入行汇编代码就可以将所有的与处理器相关的代码放置到OS_CPU_C.c里面种,就不需要适用汇编文件了。

(1)OSStartHighRdy()

OSStart()函数调用OSStartHighRdy()来使得就绪太任务中最高优先级的任务开始运行,这个函数的示例性的代码

void OSStartHighRdy()
{调用用户定义的OSTaskSwHook();OSRunning = TRUE;//得到将要恢复运行的任务的堆栈指针。stack pointer = OSTcbHighRdy->OSTCBStkPtr;//从新的堆栈中恢复处理器的所有的寄存器,就是把刚刚切换的堆栈保存到别的地方当中//执行中断返回,然后跳转PC指针到别的地方中去。}

(2)OSCtxSw():

任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TPAP陷阱指令执行的。中断服务子程序,陷阱或者异常处理的向量的地址必须指向OSCtxSw();

void OSCtxSw()
{保存处理器寄存器;在当前的任务的任务控制块中保存当前任务的堆栈指针;OSTCBCur->OSTCBStkPtr = stack pointer;OSTaskSwHook();OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy;//得到将要重新开始运行的任务的堆栈指针:stack pointer = OSTCBHighRdy->OSTCBstkPtr;//从新的任务堆栈中恢复所有的寄存器的值;//执行中断返回的指令。
}

(3)OSTickISR()
UCOSII要求用户提供一个周期性的时钟源,来实现时间延迟和超时功能,时钟节拍应该每秒发生10或者100次每秒,为了完成任务,可以使用硬件定时器,也可以从交流电中获得50~60Hz的时钟频率。

必须在开启多任务后,即调用OSStart()后,启动时钟节拍中断,但是由于OSStart()函数不会返回。不能在还没有运行第一个任务的时候,启动时钟节拍中断。会导致程序跑飞。

在没有执行OSStart()之前不能打开时钟节拍中断。千万不能在这里开中断。

因为UCOSII此时仍然处于未知的状态,所以一旦跳入中断,就会跑飞。

定时器允许用户被挂起一定的时间:

void OSTickISR(void)
{//保存处理器的寄存器//调用OSIntEnter或者直接给OSIntNesting加1if(OSIntNesting ==1){OSTCBCur->OSTCBStkPtr = Stack Pointer;}//给产生中断的设备清中断//重新允许中断OSTimeTick();   //硬件的产生中断的原理OSIntExit();    //中断退出//恢复处理器寄存器//执行中断返回指令
}

OSIntCtxSw()

void OSintCtxSw(void)
{//调整堆栈指针OSintExit();OSINTCtxSw();
}

从零开始学习UCOSII操作系统13--系统移植理论篇相关推荐

  1. 从零开始学习UCOSII操作系统2--UCOSII的内核实现

    从零开始学习UCOSII操作系统2--UCOSII的内核实现 参考书籍:<嵌入式实时操作系统μCOS-II原理及应用>.<嵌入式实时操作系统uCOS-II 邵贝贝(第二版)> ...

  2. [从零开始学习FPGA编程-13]:快速入门篇 - 操作步骤3(功能仿真)-2-Mentor HDL仿真工具modelsim工具的简介、功能仿真的基本原理

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  3. STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植

    本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...

  4. STM32MP157 Linux系统移植开发篇17:Linux内核摄像头驱动移植

    本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...

  5. STM32MP157 Linux系统移植开发篇11:Linux HDMI驱动移植

    本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...

  6. STM32MP157 Linux系统移植开发篇4: BootLoader(Uboot)移植

    本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...

  7. 学习ARM架构,系统移植和驱动开发总结

    本次结束了对ARM架构,系统移植和驱动开发的学习,它们都是属于底层,难度想对都比较的难一点,但先学习arm架构之后去学习系统移植和驱动开发,会使自己对系统移植和驱动开发容易理解点. arm架构 arm ...

  8. 《STM32从零开始学习历程》——USART串口通讯实验篇1——中断接收与发送

    <STM32从零开始学习历程>@EnzoReventon USART串口通讯实验篇1--中断接收与发送 最近开始接触了STM32F4xx系列单片机,对于我这个从零开始学习的小白来说,可谓困 ...

  9. 《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验

    <STM32从零开始学习历程>@EnzoReventon USART串口通讯实验篇2--指令控制LED灯实验 本实验是在<USART串口通讯实验篇1--中断接收与发送>的基础上 ...

最新文章

  1. 世界五百强世硕科技工作经历——05
  2. Graph Search就是语义搜索
  3. 微服务实践分享(9)文档中心
  4. Linux进入单用户模式(passwd root修改密码)
  5. 微软将人工智能嵌入Windows 10更新
  6. Oracle入门(十四B)之PL/SQL异常处理
  7. Hbuilder如何创建并运行Vue项目
  8. php与web服务器关系
  9. Win7下PDF文件无法显示缩略图的解决方法
  10. 如何解决端口冲突的问题???
  11. PC端微信全面的多开方法详解
  12. 06、Flutter FFI 类
  13. React从零到一Demo演练(上)
  14. HRBU 2021年暑期训练阶段二Day3
  15. UEBA在信息安全领域的使用
  16. 虚拟机装vpn,主机通过虚拟机的vpn代理实现vpn共享
  17. 台式计算机硬盘的安装位置,台式主机扩大存储,7步教你完美安装机械硬盘
  18. 金堂县五月花计算机学院,成都五月花高级技工学校计算机专业引领未来
  19. WPS 配置MathType
  20. wpsppt加载项在哪里_《wps表格加载项在哪里》 WPS版的EXCEL中 加载宏和数据分析在哪?...

热门文章

  1. Auto.js脚本开发入门
  2. Android 网页无法访问
  3. 别再问我为什么你敲的代码很水了!
  4. 同一局域网下,一台电脑连接另一台电脑的虚拟机(从属机(window)连接主机(window)虚拟机(Linux)的连接流程)
  5. java 调用弗雷_JAVASE(九)面向对象特性之 : 继承性、方法重写、关键字super、
  6. 121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的
  7. Python netCDF4
  8. 前端获取微信头像 base64 数据的踩坑实践
  9. android studio中的apk位置
  10. 邮箱邀请涵wm05.html文件怎么阅读,群邮箱里发来的“邀请函”暗藏木马,千万别点后面的链接...