版本 95ed18770bf9ab813b24ff92abbdb67c81dac9c6
Changes from 95ed18770bf9ab813b24ff92abbdb67c81dac9c6 to 54a00ec73d84a652da7fdc3a0d4df30d0f72929d
---
title: Xenomai
categories: embedded, arm, raspberrypi
...
Building an RPi Xenomai Kernel
==============================
* Install Cross complier
.. code-block:: c
cd <working dir>
wget https://github.com/raspberrypi/tools/archive/master.tar.gz
tar xzf master.tar.gz
* Download source files and patches
- Download kernel
.. code-block:: c
git clone -b rpi-3.8.y --depth 1 git://github.com/raspberrypi/linux.git linux-rpi-3.8.y
- Download Xenomai
.. code-block:: c
git clone git://git.xenomai.org/xenomai-head.git xenomai-head
- Download minimal config
.. code-block:: c
wget https://www.dropbox.com/s/dcju74md5sz45at/rpi_xenomai_config
* Apply patches
- Apply ipipe core pre-patch
.. code-block:: c
cd linux-rpi-3.8.y
patch -Np1 < ../xenomai-head/ksrc/arch/arm/patches/raspberry/ipipe-core-3.8.13-raspberry-pre-2.patch
- Apply Xenomai ipipe core patch
.. code-block:: c
xenomai-head/scripts/prepare-kernel.sh --arch=arm --linux=linux-rpi-3.8.y --adeos=xenomai-head/ksrc/arch/arm/patches/ipipe-core-3.8.13-arm-3.patch
- Apply ipipe core post-patch
.. code-block:: c
cd linux-rpi-3.8.y
patch -Np1 < ../xenomai-head/ksrc/arch/arm/patches/raspberry/ipipe-core-3.8.13-raspberry-post-2.patch
* Compile kernel
- Create build directory
.. code-block:: c
mkdir linux-rpi-3.8.y/build
- Configure kernel
.. code-block:: c
cp rpi_xenomai_config linux-rpi-3.8.y/build/.config
cd linux-rpi-3.8.y
make mrproper
make ARCH=arm O=build oldconfig
- Compile
.. code-block:: c
make ARCH=arm O=build CROSS_COMPILE=../../tools-master/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-
- Install modules
.. code-block:: c
make ARCH=arm O=build INSTALL_MOD_PATH=dist modules_install
- Install headers
.. code-block:: c
make ARCH=arm O=build INSTALL_HDR_PATH=dist headers_install
find build/dist/include \( -name .install -o -name ..install.cmd \) -delete
* 編譯好的kernelImage,移到SD卡的 ``/boot/`` 路徑下並更改名稱為kernel.img
* 將``linux-rpi-3.8.y/build/dist``中的Module,移到SD卡中的``/lib/modules``
* Cyclictest
- Linux
.. code-block:: c
- Xenomai
.. code-block:: c
cd xenomai-head
export PATH=<your path>/tools-master/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/:$PATH
./configure --host=arm-bcm2708hardfp-linux-gnueabi
cd src
mkdir dist
make install DIST_DIR=dist
dist中會出現``usr/xenomai``
將這個資料夾移到sd卡中 ``/usr/``
在raspberry pi中
.. code-block:: c
export PATH=/usr/xenomai/bin:$PATH
export LD_LIBRARY_PATH=/usr/xenomai/lib
sudo modprobe xeno_posix
接著就能跑使用xenomai機制的cyclictest
- RT_preempt
作業系統架構
===========
.. image:: /xenoarch.jpg
Xenomai是一個linux kernel的patch
藉由在底層增加一個架構
負責硬體與接收interrupt 並將interrupt 傳給上層的OS(這邊稱為domain)
這個底層的架構是Adeos 是另一個open source的project
基本架構示意圖
http://dchabal.developpez.com/tutoriels/linux/xenomai/images/image04.png
在api呼叫上可以看到不同層級的抽象化
ipipe_XXX -> rthal_XXX -> xnXXX
上一層對下一層的操作方式基本上會固定 但下一層的實作一硬體或config有所差異
負責傳送interrupt的程式稱為ipipe
示意圖
http://www.xenomai.org/documentation/xenomai-2.6/html/pictures/life-with-adeos-img4.jpg
可以找到ipipe_raise_irq()將interrupt推到pipeline
在ipipe上每個domain都有自己的優先度
高優先度的domain會先接收到interrupt
高優先度的domain的thread 可以preempt 低優先度domain的thread
* 與 RT-PREEMPT 途徑的差異?
實作
==================
Context switch
.. code-block:: prettyprint
ksrc/arch/arm/switch.S
/*
/*
* Switch context routine.
*
* Registers according to the ARM procedure call standard:
* Reg Description
* r0-r3 argument/scratch registers
* r4-r9 variable register
* r10=sl stack limit/variable register
* r11=fp frame pointer/variable register
* r12=ip intra-procedure-call scratch register
* r13=sp stack pointer (auto preserved)
* r14=lr link register
* r15=pc program counter (auto preserved)
*
* Copied from __switch_to, arch/arm/kernel/entry-armv.S.
* Right now it is identical, but who knows what the
* future reserves us...
*
* XXX: All the following config options are NOT tested:
* CONFIG_IWMMXT
*
* Calling args:
* r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
*/
ENTRY(rthal_thread_switch)
add ip, r1, #TI_CPU_SAVE
ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
THUMB( str sp, [ip], #4 )
THUMB( str lr, [ip], #4 )
load_tls r2, r4, r5
#ifdef USE_DOMAINS
ldr r6, [r2, #TI_CPU_DOMAIN]
#endif
clear_exclusive_monitor
switch_tls r1, r4, r5, r3, r7
#ifdef USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif
fpu_switch r4
ARM( add r4, r2, #TI_CPU_SAVE )
ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
THUMB( add ip, r2, #TI_CPU_SAVE )
THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously
THUMB( ldr sp, [ip], #4 )
THUMB( ldr pc, [ip] )
ENDPROC(rthal_thread_switch)
Timer
+++++++++++
Scheduler
+++++++++++
依據預設 Xenomai 組態,nucleus 程式碼的兩個檔案未被編譯進去:
- sched-tp.c
- sched-sporadic.c
xnpod
+++++++++++
.. code-block:: prettyprint
struct xnpod {
xnflags_t status; /*!< Status bitmask. */
xnsched_t sched[XNARCH_NR_CPUS]; /*!< Per-cpu scheduler slots. */
xnqueue_t threadq; /*!< All existing threads. */
#ifdef CONFIG_XENO_OPT_VFILE
struct xnvfile_rev_tag threadlist_tag;
#endif
xnqueue_t tstartq, /*!< Thread start hook queue. */
tswitchq, /*!< Thread switch hook queue. */
tdeleteq; /*!< Thread delete hook queue. */
atomic_counter_t timerlck; /*!< Timer lock depth. */
xntimer_t tslicer; /*!< Time-slicing timer for aperiodic mode */
int tsliced; /*!< Number of threads using the slicer */
int refcnt; /*!< Reference count. */
#ifdef __XENO_SIM__
void (*schedhook) (xnthread_t *thread, xnflags_t mask); /*!< Internal scheduling hook. */
#endif /* __XENO_SIM__ */
};
硬體驅動原理
===========
* 硬體使用 Raspberry Pi
效能表現
=======
* `Cyclictest<https://rt.wiki.kernel.org/index.php/Cyclictest>`_
* Test case: POSIX interval timer, Interval 500 micro seconds,. 100000 loops, 100% load.
- Commandline: cyclictest -t1 -p 80 -i 500 -l 100000
* 使用 PREEMPT LINUX
.. code-block:: prettyprint
root@raspberrypi:/home/pi# sudo ./cyclictest -t1 -p 80 -i 500 -l 100000
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.00 0.01 0.05 1/61 2064
T: 0 ( 2063) P:80 I:500 C: 100000 Min: 27 Act: 49 Avg: 42 Max: 1060
* 使用 RT-PREEMPT
.. code-block:: prettyprint
Linux raspberrypi 3.6.11+ #474 PREEMPT Thu Jun 13 17:14:42 BST 2013 armv6l GNU/Linux
Min: 22 Act: 31 Avg: 32 Max: 169
* 使用 Xenomai
.. code-block:: prettyprint
Linux raspberrypi 3.8.13-core+ #1 Thu Feb 27 03:02:16 CST 2014 armv6l GNU/Linux
Min: 1 Act: 5 Avg: 6 Max: 41
.. code-block:: prettyprint
root@raspberrypi:/home/pi# /usr/xenomai/bin/cyclictest -t1 -p 80 -i 500 -l 10000
0.08 0.06 0.05 1/61 2060
T: 0 ( 2060) P:80 I: 500 C: 100000 Min: -4 Act: -2 Avg: 0 Max: 30
* cyclictest 做法
概念:
取得現在時間接著讓process睡一個間隔
等process醒來後再取一次時間
比對兩次取得的時間差與設定的間隔差距
pseudocode:
.. code-block:: prettyprint
clock_gettime((&now))
next = now + par->interval
while (!shutdown) {
clock_nanosleep((&next))
clock_gettime((&now))
diff = calcdiff(now, next)
# update stat-> min, max, total latency, cycles
# update the histogram data
next += interval
}
造成這時間差的可能原因:
timer精準度
interrupt latency
interrupt handler duration
scheduler latency
scheduler duration
context switch
討論用
======
https://embedded2014.hackpad.com/Xenomai-raspberry-note-XwJtuQn9nkD
組員
====
* 向澐
* 林家宏
* 呂科進
* 趙愷文
* 阮志偉
* 陳建霖
參考資料
=======
* https://code.google.com/p/picnc/wiki/RPiXenomaiKernel
* https://code.google.com/p/picnc/wiki/CreateRaspbianLinuxCNC
* http://www.camelsoftware.com/firetail/blog/raspberry-pi/real-time-operating-systems/
* `Quadruped Linux robot feels its way over obstacles<http://linuxgizmos.com/hyq-quadruped-robot-runs-real-time-linux/>`_
* ` Choosing between Xenomai and Linux for real-time applications<https://www.osadl.org/fileadmin/dam/rtlws/12/Brown.pdf>`_
* `Real Time Systems<http://www.slideshare.net/anil_pugalia/real-time-systems>`_
* `http://www.cs.ru.nl/lab/xenomai/exercises/`_