分享到plurk 分享到twitter 分享到facebook

版本 0abb222cad9ab543928875181e33479efabbec00

Xenomai

組員

  • 向澐
  • 林家宏
  • 呂科進
  • 趙愷文
  • 阮志偉
  • 陳建霖

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=/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

作業系統架構

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 途徑的差異?

依據預設 Xenomai 組態,nucleus 程式碼的兩個檔案未被編譯進去: - sched-tp.c - sched-sporadic.c

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)

硬體驅動原理

  • 硬體使用 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/_