当前位置:   article > 正文

关于uc/os-ii在c51上的移植总结_ucosii在51单片机的移植

ucosii在51单片机的移植

关于uc/os-ii在c51上的移植总结

难以避免会出现理解错误 欢迎指正。

现在我手上的参考书是很薄很薄的用x86作为实验的参考书,提供了不太完整的c51移植代码,移植主要需要修改的底层抽象层文件大致是一下四个:

  • OS_CPU_A.ASM(最重要的一个文件)
  • OS_CPU_C.H
  • OS_CPU_C.C
  • OS_CFG.H(该文件用于系统剪裁等)
uc/os-ii底层需要实现的大致接口如下:
OS_CPU_A.ASM
  • OSStartHighRdy()
  • OSCtxSw()
  • OSIntCtxSw()
  • OSTickISR()
OS_CPU_C.C
  • OSTaskStkInit()
  • OSTaskCreateHook()
  • OSTaskDelHook()
  • OSTaskSwHook()
  • OSTaskStatHook()
  • OSTimeTickHook()

这里的六个函数中也就只有OSTaskStkInit需要改写,另外的五个函数只要声明即可。

移植会遇到许多问题

将一个操作系统移植到不同的硬件环境中,需要修改操作系统硬件抽象层来适应不同的实际环境,这里不仅是与硬件相同,与编译器也息息相关。在不同的硬件环境以及不同的编译器面前可能都会采用不同的策略来实现或者提高效率。这里我用的是C51 STC89C51 以及Keil51编译器,而因为C51的片内内存非常少,所以对于函数而言默认是不可重入的,如果需要重入就需要添加关键字reentrant。

关于可重入函数以及堆栈(系统堆栈以及模拟堆栈)的关系

如果有两个函数void A(){ int a =0;[输出a]} void B(){int b=0;[输出b]}
默认这两个函数是不可重入的,那么他们的数据段中的临时变量将会定位在一个可以被覆盖的段中,此时如果发生中断,这个段可能被覆盖,如果A函数在执行到输出a的那个部分的代码段被中断转而运行B函数时,如果恰好a所在的存储位置被覆盖,在执行完B回去执行A的时候,A的结果就非常有可能出错。这是不希望出现的结果。那么就应该将函数声明为可重入的函数。
这个时候在KEIL里的STARTUP文件中声明的全局指针变量?C_XBP指向的便是模拟堆栈(这个堆栈存储在片外内存,以改善51单片机片内内存小的特点)的栈顶地址,也依赖这个编译器的特点来实现移植。

c51中的堆栈

系统堆栈与模拟堆栈。

  • 系统堆栈:在片内的data区。由sp指向栈顶,上电初始化为07H。在通用寄存器后一位开始。通过指令PUSH与POP进行操作。
  • 模拟堆栈:与名字相符就是模拟出来的堆栈,在响应中断的时候可以将内容保存下来,这样在操作的时候不会使函数返回继续运行的时候出错。存储在片外的xdata区,在STARTUP文件中声名了全局变量?C_XBP来指向这个区域。所以在进行任务切换的时候除了保存sp还要保存与恢复这个变量。这个变量就是对应每个变量的TCB结构体的堆栈栈顶指针变量。操作的方式是通过mov,movx等指令来进行片外与片内数据域的交换。

。。未完待续

移植过程中遇到的困难 主要是对汇编的不熟悉

于是在复习完51的汇编后,一切感觉都能迎刃而解。

Note:
临界段的本质作用:

  • 保护互斥变量
  • 实现 函数的可重入性:在临界段里的代码 不会被中断打断,就会使得这个函数可被重入。

· 普通任务与中断任务的不同:
中断任务会使用OSIntEnter()与 OSIntExit
而在OSIntExit中会使OSIntNesting-=1;然后检查OSIntNesting与OSLockNesting确定目前是否可以进行任务调度。也就是说中断任务本身会更快完成,因为OSIntNesting不为0的时候不会进行新的任务调度,肯定会先完成中断的任务。而OSTickISR函数会一直调用OSIntEnter与OSIntExit来调度最新的优先度最高的函数,当然 在符合以上条件时。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/654991
推荐阅读
相关标签
  

闽ICP备14008679号