星期三, 8月 26, 2009

uImage

給 u-boot 用的開機映像檔
格式:image header + linux kernel + rootfs

header 有 64kB,包含 target architecture、作業系統、kernel size、entry points 等。


建立
  1. 編譯 kernel 產生 vmlinux,以及編譯與產生 root 檔案系統
  2. strip -g vmlinux
  3. rootfs.ext2:ext2 檔案系統的 root 檔案系統,包括 /dev 目錄
    genext2fs -m 0 -i 1024 -b $(SIZE_MB) -d $(the_root_dir) -D device_table.txt rootfs.ext2
  4. linux.ext2:kernel 附上 rootfs.ext2
    objcopy --add-section .romfs=rootfs.ext2 --adjust-section-vma .romfs=$(addr_of_bss_end) --no-adjust-warnings --set-section-flags .romfs=alloc,load,data vmlinux linux.ext2
  5. 轉換成 binary:
    objcopy -O binary -S linux.ext2 linux.bin
  6. 壓縮成 linux.bin.gz:
    gzip -f9 linux.bin
  7. 使用 mkimage 加入 image header 所需要的資訊
使用:
  1. uImage 如無法直接定址,需放到可直接定址的位置,如 SDRAM。
  2. 執行 u-boot 指令 bootm,會作下列動作
    1. 檢查 checksum
    2. 解壓縮到 Load Address,也就是 0x1000
    3. 複製 bootargs 到 scratchpad
    4. 最後從 Linux Kernel 的 Entry Point,也就是 0x1000 開始執行

參考:
  1. Bootable U-Boot Images (Blackfin Linux Docs)
  2. uClinux-dist Compiled Images (Blackfin Linux Docs)

星期五, 8月 14, 2009

top

top 讀取 proc/meminfo、proc/loadavg、proc/{pid}/stat 等檔案來顯示目前系統的執行狀態。

第 一行顯示記憶體使用狀態,是讀取 proc/meminfo 顯示下列數值: used (MemTotal - MemFree)、free (MemFree)、shrd (MemShared)、buff (Buffers), 及 cached (Cached)。

第二行顯示系統負載,是讀取 proc/loadavg 內容的前三個數值。

剩下部份顯示依資源使用多寡排行的 process 列表,主要資料是掃描每一個 proc/{pid}/stat 整理而來。

參考

星期四, 8月 13, 2009

quilt

Greg KH 的書「Linux Kernel in a Nutshell」(online) 特別推薦 Quilt 這個管理 patch 檔的工具,它會追蹤你在原本的原始碼所作的修改來方便更新 patch 檔,可以疊上更多 patch 檔,也可不採用等,讓維護 patch 檔變得容易。

使用 quilt 建立 patch 檔:
$ mkdir patches # patches 是放 patch 檔的目錄
$ quilt new patch1 # 建立一個新 patch,稱為 patch1
$ quilt add Makefile # 告知 quilt patch1 包含 Makefile 的更動
$ vi Makefile # 編輯 Makefile 並儲存
$ quilt refresh # 更動更新到 patch1
同理,可以在 patch1 外,再疊上其它 patch 檔。

$ quilt series -v # 列出目前所有使用的 patch 檔列表

如果有新版軟體釋出,先都不 patch,只 patch 釋出的更新,再嘗試全部 patch 回來:
$ quilt pop -a # 全部 patches 都不採用
$ patch -p1 < new_release.patch # 加入更新
$ quilt push
$ quilt push -f
$ vi ...
$ quilt refresh# 更新 patch 檔
$ quilt push # 更新 patch 檔

引進現成的 patch 檔:
$ quilt import the_exist_patch
例如舊的 patch 檔需更新
$ quilt import the_exist_patch
$ quilt refresh
就可以產生新的 patch

小整理:
  • new/delete:新增/移除 patch 檔
  • add/remove:新增/移除 檔案
  • push/pop

星期二, 8月 11, 2009

bfin Linux Reboot

版本:uClinux-dist-2007R1.1-RC3
指 令 reboot 透過 uClibc libcall reboot(),執行 syscall reboot(),完成 reboot 動作。其中進入 kernel space 執行 syscall 會執行 except 0 及 raise 15 產生兩次中斷,步驟如下:
  1. 指令 reboot @uClinux-dist/user/sysutils/reboot.c

    • 結束所有 processes

      kill(1, SIGTSTP);
      sync();
      signal(SIGTERM,SIG_IGN);
      setpgrp();
      kill(-1, SIGTERM);
      kill(-1, SIGHUP);
      sleep(1);
      kill(-1, SIGKILL);
      sync();
      sleep(1);
    • 呼叫 libcall reboot(0x1234567)
  2. libcall int reboot(int flag) @uClibc/libc/sysdeps/linux/common/reboot.c (uClibc 內建於 bfin-linux-uclibc- 系列編譯程式裡 (svn source svn://sources.blackfin.uclinux.org/toolchain/trunk))




    • 其實就是呼叫 _reboot((int) 0xfee1dead, 672274793, flag),並且由 _syscall3() 定義產生。
    • _syscall3() @uClibc/libc/sysdeps/linux/bfin/bits/syscalls.h : registers P0 = __NR_reboot、D0 = 0xfee1dead、D1 = 672274793、D2 = flag 後執行 excpt 0 (EVT3, EXCAUSE=0) 產生中斷,進入 kernel space。




      #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)  \
      type name(type1 arg1,type2 arg2,type3 arg3) {    \
      long __res;       \
      __asm__ __volatile__ (      \
      "excpt 0;\n\t"      \
      : "=q0" (__res)      \
      : "qA"   (__NR_##name),     \
      "q0"   ((long)(arg1)),    \
      "q1"   ((long)(arg2)),    \
      "q2"   ((long)(arg3))     \
      : "memory","CC");     \
      __syscall_return(type,__res);     \
      }
    • __NR_reboot @linux-2.6.x/include/asm-blackfin/unistd.h,也就是 syscall number:




      #define __NR_reboot   88
  3. interrupt vector EVT3


    • EVT3 由 int __init init_arch_irq() @linux-2.6.x/arch/blackfin/mach-common/ints-priority-sc.c 在 kernel 初始化時寫入 asmlinkage void trap(void)。
    • trap() @linux-2.6.x/arch/blackfin/mach-common/entry.S: 依據 EXCAUSE 查 extable[],跳到 extable[0] 是 ex_syscall(),所作的動作就是 raise 15 (EVT15)。過程中會用 exception statck 來備份並回復用到的 registes。
  4. interrupt vector EVT15

    • EVT15 由 init_arch_irq() @linux-2.6.x/arch/blackfin/mach-common/ints-priority-sc.c 在 kernel 初始化時寫入 asmlinkage void evt_system_call(void)。
    • evt_system_call() @ linux-2.6.x/arch/blackfin/mach-common/interrupt.S: 呼叫 system call handler system_call()。
    • system_call() @linux-2.6.x/arch/blackfin/mach-common/entry.S: 除了依照 syscall number 查 sys_call_table[] 來呼叫外,尚有許多細節,包括呼叫前及呼叫後。sys_call_table[88] 為 sys_reboot() 。
    • asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg) @ linux-2.6.x/kernel/sys.c: magic1 = 0xfeeldead 及 magic2 = 672274793 必須符合,cmd = 0x01234567 = LINUX_REBOOT_CMD_RESTART 會呼叫 kernel_restart(),內容包括呼叫 kernel_restart_prepare(NULL)、印出「Restarting system.」、以及呼叫 machine_restart(NULL)。
    • machine_restart() @linux-2.6.x/arch/blackfin/kernel/process.c: 執行 bfin_reset()。
    • bfin_reset() @linux-2.6.x/arch/blackfin/mach-bf533/head.S: 採用 Watchdog Timer Reset (參考 bfin Reset)。
__asm__: 參考 GCC Inline Assembly
asmlinkage: 在 linux-2.6.x/include/linux/linkage.h 定義,決定參數傳遞方式,bfin 採用 register 方式傳遞參數,另一種方式是用 statck 傳遞參數。

星期一, 8月 03, 2009

POTS DC signaling

利用話機的掛機時間長短來作信令傳輸給局端交換機:
  •  ≤ 100ms:Dial pulsing 用來表示撥號號碼
    • Pulse Per Second (PPS):10 PPS (相當於 100 ms) 或 20 PPS (相當於 50 ms)
    • Mark Duration:Pulse 的掛機 (on-hook) 時間,北美 60 on、40 off,歐洲 63 on、37 off。45 on 55 off。
    • Interdigit Pause Duration:暫停用來區隔數字,700ms?。
    • 撥號時間較長,1 要 0.8 sec、0 要 1.7 secs,現在大多改用較快的 DTMF
  • > 100ms, < 1sec:Hook Flash 暫切
    • 有來電 waiting 時,切換過去 (hold 原本的通話)
    • 轉接:hold 原本的通話,建立另一通電話,最後掛斷
    • 三方會議:hold 原本的通話,建立另一通電話,最後再暫切建立三方會議。
    • 代接
  • > 1 sec.:Hang up 掛斷