移植UCOS到linux平台下倒是件费时的事情,本打算模拟一些API就行了,但google了一下,发现了这个移植版本。不错,省了偶不少力气。



address: http://www.it.fht-esslingen.de/~zimmerma/software/uCOS-II_LINUX.htm

Linux Port internals and Limitations

  • Task Scheduling

As LINUX does not allow application programs to bypass its own scheduler or provide
their own timers and interrupt handlers, uCOS-II scheduling and task managment functions
must be remapped to LINUX functions.

该移植版本并不是象for win32的移植版本那样有真实的时钟中断,而是将uCOS的调度及任务管理影射到linux本身的函数之上。可以看出来,该移植版本作了不少的内部手术。

The LINUX port is based on the WIN32 port of the same author, so in many points
a solution, which allowed to make the WIN32 and LINUX port match as closely as possible
instead of a more elegant LINUX solution was chosen. The WIN32 port uses WIN32 threads,
which are suspended and resumed via WIN32 API functions and scheduling is triggered by
WIN32 events. The LINUX port uses the same mechanisms with the system call clone() to
create threads and LINUX signals instead of WIN32 events.

LINUX 移植版本利用线程作为虚拟的进程,利用signal作为激活调度的出发事件。

uCOS-II tasks are mapped to LINUX threads. The mapping is done, when a task
is created in OSTaskCreateHook(). Additionally two special LINUX threads OSScheduleThread()
for thread scheduling handling and OSInterruptThread() for interrupt handling
are created in OSInitHookBegin(). The scheduling and the interrupt thread are created
with the a higher LINUX process priority. The threads associated with uCOS-II tasks
are created with a lower priority and set to suspended state (via signal SIGSTOP).

uCOS的任务被当作LINUX的线程,任务的调度则由OSScheduleThread函数负责,中断管理由OSInterruptThread管理。uCOS的任务在创建后,被作为最低优先级的挂起线程(SIGSTOP信号实现)

When the uCOS-II scheduler preempts a task and wants to switch context to a new uCOS-II task,
the uCOS-II context switch function OSCtxSw() or OSIntCtxSw() triggers the scheduler thread
via a signal hScheduleEvent (=SIGCONT). Because the scheduling thread OSScheduleThread() has
a higher LINUX priority than all the WIN32 threads associated with uCOS-II tasks, LINUX will
start the scheduling thread immediately. This thread will suspend the LINUX thread
associated with the preempted uCOS-II task and resume the LINUX thread
associated with the new uCOS-II task. Then the scheduler thread will wait for the next scheduler
event (via system call pause()). So always exactly one LINUX thread associated with a uCOS-II task will be ready to run,
all other uCOS-II task associated threads will be in LINUX suspended state. Thus this LINUX thread
will be invoked by the LINUX operating system’s internal
scheduler, once the OSScheduleThread() waits for the next scheduling event, and will remain running
until the uCOS-II scheduler is invoked the next time and retriggers the OSScheduleThread().

  • Time Tick Interrupts

To generate the uCOS-II time tick, a LINUX timer is used. Theoretically this timer
provides a 10ms resolution (LINUX internal time tick). Therefore
your application should set OS_TICKS_PER_SECOND to not more than 100 ticks per second (i.e.
to a tick period of 10ms min.). The timer will be started automatically via OSStartHighRdy()
and OSTimeTickInit(), once your application starts uCOS-II multitasking by calling OSStart().

关键的是时钟中断,也就是控制抢占内核行为的核心驱动,在该移植版本里利用LINUX的定时器实现。ticker为10ms。

LINUX periodically invokes a the signal handler OSTimeTickCallback() for the timer signal SIGALARM,
which triggers the signal hInterruptEvent. Due to this signal, LINUX immediately invokes
the interrupt thread OSInterruptThread(), because this thread has a higher process
priority than all uCOS-II task related threads. As expected by uCOS-II, the interrupt thread
calls OSTimeTick(), which may reschedule another uCOS-II task. Then the interrupt thread
waits for the next interrupt event.

uCOS-II’s critical sections normally disable interrupts. LINUX application programs, however,
cannot disable interrupts. This issue is resolved by LINUX suspending the interrupt thread
instead, once a uCOS-II critical section is entered by OS_ENTER_CRITICAL().

  • Limitations

uCOS-II provides several hook functions to allow applications to modify the uCOS internal
behaviour. Some of these hook functions are used to interact with the LINUX operating
system in the LINUX port. Thus the following hooks MUST NOT be used by your application:

	    OSInitHookBegin(), OSTaskCreateHook(), OSTaskIdleHook()

If your application must execute own code when uCOS-II calls these hooks, you should
add this code in file os_cpu_c.c. The appropriate points are marked in the code by

	    //ADD YOUR OWN HOOK CODE HERE IF NECESSARY

All other hook functions can be redefined by your application directly if you set OS_HOOKS_EN = 0,
as described in the uCOS-II documentation.

uCOS-II tasks are mapped to LINUX threads. These threads use their own LINUX stacks rather
than the ‘normal’ uCOS-II task stacks. Stack size
and stack management during context switches are automatically handled by LINUX. Nevertheless for
compatibility reasons, when a uCOS-II task is created, a uCOS-II stack must be provided. Only a few
bytes of this stack will be initialized, but this stack will not really be used by the running tasks.
If you plan to test your application under LINUX and then port it to an embedded system, you
***CANNOT*** use the LINUX simulation to find out the necessary stack size. Your uCOS-II LINUX application
should not rely on the uCOS-II stack checking and clearing functions and should not use
any stack related programming tricks.


每个任务的指定STACK,在移植版本中意义不大,因为每个任务都是一个线程,有自己的线程堆栈,并由LINUX控制。



2条评论

  1. 我嘗試用以上的方法把ucos-ii port到linux上,但是在example裡面make可以過,但執行./test後卻會一直出現killed,我不知道為什麼,我也嘗試過在別台機器跑,但結果還是一樣,不知有哪位高手有經驗,可以為我解答,謝謝!!

  2. 你说的问题,我碰到了,我家的是turbolinux10,移植没问题,但学校里的是mandrake10.1,直接被kill,

    后来发现是clone之前malloc失败,而且彻底失败,搞不清楚怎么回事

发表评论

评论也有版权!

click to change验证码