星期四, 5月 29, 2014

AM335x efuse

efuse 是 TI 出廠寫入的,使用者只能讀取,不能更改。efuse 包括 Device ID、Version、唯一的 MAC Address 等。

參考來源:
  1. http://e2e.ti.com/support/arm/sitara_arm/f/791/t/209421.aspx

AM335x 建立開機 SD 卡及開發環境

TI SoC Sitara™ AM335x 的核心是 ARM Cortex™-A8 (ISA ARMv7),其 Starter Kit 型號是 TMDSSK3358,含有 256MB DDR3 SDRAM、4.3" 觸控螢幕、雙 GE、WL1271 Wi-Fi/Bluetooth 模組、XDS100 USB JTAG、,看上面的處理器晶片型號是 XAM3359ZCZ,跑 720 MHz。沒有內建 Flash,備有 SD Card 可以開機試用,使用外接 5V 電源透過 IC TPS65910 管理,需按 POWER 鍵才會開機。

依據 Sitara Linux SDK Getting Started Guide 在 Linux 電腦自製開機 SD Card 及開發環境。

安裝 SDK

首先要安裝 SDK,但在 Ubuntu 14.04 有些問題,要用文字模式安裝

chmod +x ti-sdk-am335x-evm-07.00.00.00-Linux-x86-Install.bin
./ti-sdk-am335x-evm-07.00.00.00-Linux-x86-Install.bin --mode text

預設產生目錄 ~/ti-sdk-am335x-evm-07.00.00.00,到此目錄下

建立開機 SD Card

bin/create-sdcard.sh 用來建立開機 SD Card,由於會解析 fdisk 指令的結果,漢文輸出會造成錯誤,需要將裡面的 fdisk 指令加上 LANG=C 成為
SIZE=`LANG=C fdisk -l $DRIVE | grep Disk | awk '{print $5}'`

再執行 create-sdcard.sh,就可以用 SDK 原本就有的影像檔建立開機 SD 卡。

建立 tftp + NFS 開發環境

setup.sh 可用來安裝 tftp、nfs、minicom,並且幫你設定好。setup.sh 會執行 bin 下的命令檔來完成建立,需要做一些修改:
  • bin/setup-host-check.sh 會檢查 Ubuntu 版本必須為 10.04 or 12.04,需加以修改。
  • bin/setup-package-install.sh 會安裝 uboot-mkimage,需改為 u-boot-tools。另外 tftpd可以改為 tftpd-hpa,但 tftpd-hpa 預設的檔案目錄是 /var/lib/tftpboot
  • bin/setup-uboot-env.sh 中 media 目錄再加上你的帳號名稱,這是 Ubuntu 14.04 的掛載方式
將 SD card 插到 AM335x 板子、接上網路、USB slave 接到電腦,AM335x 開機,然後在電腦執行 setup.sh 就會幫你設定好環境,並開 console。

參考來源

  1. http://e2e.ti.com/support/arm/sitara_arm/f/791/t/335816.aspx

星期二, 5月 27, 2014

device tree

Device Tree 是描述系統硬體的樹狀資料結構,讓作業系統知道有哪些週邊裝置。原始檔是 device tree source (*.dts),經過 device tree compiler (dtc) 編譯成二進位的 device tree blob (*.dtb),dtb 檔可由 bootloader 載入記憶體後,透過 ARM 處理器的 r2 暫存器傳給 kernel、或直接放到 kernel 的最後面 (使用 CONFIG_ARM_APPENDED_DTB)。

ARM 的 .dts 擋在 arch/arm/boot/dts,可以包含其它 .dtsi 檔後作 overlay (覆蓋)

Device Tree 由 node 組成,node 有名稱 (必要?作用?),可指定位址,可定一個 label 方便 reference。node 內容由 {} 包起來,裡面是其性質 (property)。每個性質是 name = value; 的格式,value 可以是 "字串",多個字串、<數字>、數字陣列、參考其它 node label 等。

透過性質 compatible 可以 binding 到特定 device driver,其它性質提供必要的驅動程式參數。所有 kernel 認得的 binding 說明都在 Documentation/devicetree/bindings/

root node (/) 通常包含有 cpus, memory 等。

參考來源:
  1. http://elinux.org/images/a/a3/Elce2013-petazzoni-devicetree-for-dummies.pdf
延伸閱讀

星期一, 5月 26, 2014

SD 腳位

CF (Compact Flash) 因 NOR Flash 而出現,MMC 因 NAND Flash 而出現,後來又發展成 SD (Secure Digital) 卡。

T-Flash → TransFlash → microSD

SD 有 SPI、1-bit、4-bit 三種模式,可用在 SD 記憶體或 SDIO (Secure Digital I/O)。

SD 共有 9 個接腳,斜角為接腳 9,再來為接腳 1 至 8。可以發現接腳 3 跟 4 較為突出,分別是 GND 跟 3V3。
pinSPI1-bit4-bit說明
1Card SelectNot UsedCard Detect/Data 3
2Data InputCommand
3Ground
42.7~3.6V
5Clock
6Ground
7Data OutputDataData 0
8(Interrupt)(Interrupt)Data 1 (Interrupt)SDIO 才有 Interrupt,SD Memory 沒有
9Not UsedRead WaitData 2 or Read Wait

SDIO 時,DATA1 可作為 IRQ, DATA2 可作為 Read Wait。microSD 卡只有 8 接腳,少一個 3V3 旁的 GND。MMC 比 SD 薄,可用在 SD 插槽,只有接腳 1 ~ 7,所以沒有 4-bit 模式。

另外在 SD 插槽還有 WP (Write Protection) 及 nCD 訊號。


SDSDHCSDXCSDUC
容量Min
>2 GB>32 GB>2 TB
Max2 GB32 GB2 TB128 TB
典型檔案系統FAT12/FAT16FAT32exFAT
速度25MB/s 以下可超過 25MB/s

速度

匯流排介面標誌匯流排速度說明
預設N/A12.5MB/s1.01
High Speed25MB/s
2.00
UHS-II50MB/s (SDR50) 100MHz 4-bit
104MB/s (SDR104)208MHz 4-bit
50MB/s (DDR50)50MHz 4-bit 升緣+降緣
N/ALexar 1066x series (160 MB/s)
Kingston Canvas Go Plus (170 MB/s)
MyMemory PRO (180 MB/s)
208MHz 4-bit 升緣+降緣
UHS-IIII156MB/s (FD156), 312MB/s (HD312)雙排接腳
UHS-IIIIII312MB/s (FD312), 624MB/s (FD624)
雙排接腳

寫入速度看 Speed Class

Minimum sequential writing speed
Speed Class錄影支援
Suggested max. bitrateClassUHS Video
2 MB/s15 Mbit/sC2N/AN/ASD
4 MB/s30 Mbit/sC4 HD / Full HD
6 MB/s45 Mbit/sC6V64K
10 MB/s75 Mbit/sC10U1V10
30 MB/s220 Mbit/sU3V308K
60 MB/s460 Mbit/sV60
90 MB/s700 Mbit/sV90

實作:
EE335_rev1.pdf《Interfacing SD Cards with Blackfin® Processors》(備份) 在 Blackfin 用 SPI, PPI, PPI + Timer + Tri-State buffers, Asynchronous Memory Interface + buffers 等方式實作 SD 介面,另外還有三種 Card Detection 方式。

參考

  1. http://en.wikipedia.org/wiki/Secure_Digital
  2. SD Card驅動程式開發2:SD 卡啟用 SPI 模式:SD 卡收到 CMD0 時,CS 為低電壓。在 CMD0 之前,要發送 >74 個CLK,其中 64 CLK 讓 SD 卡內部供電電壓上升,10 個 CLK 用於 SD 卡同步。SD 卡初始化時,CLK 不能超過 400KHz。
  3. http://ant.comm.ccu.edu.tw/course/93_Driver/9_Upload/presentation/presentation_694415016.ppt

Lubuntu 圖片列印

Lubuntu 預設的看圖程式是 GPicView,並沒有列印功能。用 Firefox 列印,又會多加了頁首及頁尾,即使設為空白,還是多預留了一些空間。最後我只好安裝 gThumb 解決。

安裝 gThumb 會額外安裝 bison flex gstreamer0.10-gnomevfs gthumb-data gvfs-bin libbison-dev libexiv2-12 libfl-dev libgnomevfs2-0 libgnomevfs2-common libgnomevfs2-extra libwebkit2gtk-3.0-25 m4

MBR

MBR (Master Boot Record, 主啟動記錄) 是放在硬碟 (或其它類似裝置) 啟動磁區的啟動程式和分割表 (partition table)。

硬碟由許多磁盤構成,包括
  • 磁頭 (Head):硬碟讀寫頭,磁頭數目表示總共有多少磁盤讀寫面。
  • 磁軌 (Track):每個磁盤有許多儲存資料的同心圓。
  • 磁柱 (Cylinder):同半徑的磁軌所組成的圓柱。
  • 磁區 (Sector):硬碟最小儲存單位,一般 512-byte。
硬碟的儲存量 = 磁柱 x 磁碩 x 磁區 x 512 bytes。

MBR 放第一個磁區 (編號 0),剩下的磁區最多可切出四個區塊,稱為分割區 (partition)。分割區分成主要分割 (Primary Partition) 跟擴充分割 (Extended Partition) 兩種。主要分割就是一個邏輯硬碟。擴充分割的架構就像一個實體硬碟,其第一個磁區放格式類似 MBR 的的 Extend Boot Record (EBR),但只能切出一個邏輯硬碟、以及一個擴充分割。邏輯硬碟以 DOS/Windows 觀點就是 C:、D:、E:... 這些硬碟機名稱。透過擴充分割再切出擴充分割,可分割出一系列邏輯硬碟。

MBR/EBR 內容
偏移byte 數內容說明
0 ~ 445446啟動資料與程式
446 ~ 50964分割表 可描述 4 個分割區,每個用 16 bytes。MBR 可用掉 1~ 4 個描述主要分割,如有剩下可描述 1 個擴充分割。EBR 第 1 個描述一個邏輯硬碟,第 2 個可描述內部的擴充分割,第 3、4 個不能使用。
510, 51120xAA55識別用

分割區描述

每個分割區描述用 16 bytes,如下:
偏移位址byte 數名稱說明
00H1啟動狀態80h 表示可啟動
00h 表示不可啟動
01H3起始磁頭、磁柱、及磁區位置為相對於 MBR。其中起始磁頭 8-bit、起始磁柱 10-bit、起始磁區 6-bit。
04H1檔案系統識別碼(partition types) 識別是擴充分割,還是主要分割所用的檔案系統
05H3結束磁頭、磁柱、及磁區格式同起始磁頭、磁柱、及磁區
08H4分割區相對位置相對於目前磁區的磁區數。
0CH4磁區數該分割磁區總數

磁柱、磁頭、及磁區合稱 CHS (cylinder, head and sector),可用作為磁區定址使用。另一種定址方式稱為 Logical Block Address (LBA),將一顆硬碟的磁區從 0 開始依序編碼。每個分割區需要從分割區描述知道其使用的磁區範圍:
定址方式CHSLBA
開始磁區起始 CHS分割區相對磁區數
結束磁區結束 CHS分割區相對磁區數 + 磁區數
最大容量8.4 GB = 210*28*(26-1)*512B2199 GB = 232*512B
BIOS 中斷INT 13hExtended INT 13h
(使用 64-bit LBA 定址,可支援達 9400000000 TB 的硬碟,實際上分割表只有 32-bit 的 LBA。)
因為 MBR 有最大容量 2.2 TB 的限制等問題,發展了 GPT

檔案系統識別碼
通常分割區會從下個磁軌開始,所以 MBR 跟分割區的起始間會有一些沒用的磁區,通常有 63 個磁區。

參考

  1. 小木偶的組合語言教學之Ch 32 硬碟 (1) 分割區
  2. http://www.48bitlba.com/
  3. http://ata-atapi.com/
  4. spfdisk
  5. Jamyy's《復原 Windows MBR 的各種方式

星期四, 5月 22, 2014

Asterisk Internal Database

Asterisk 內部使用的資料庫稱為 AstDB,在 reload 或 restart 時用來保留一些資料,或者使用者也可以用來儲存資料。在 dialplan 有提供 dialplan functions DB、DB_* 等及應用程式 DBdeltree。CLI 也有 database 指令查看。

AMI (內建) 有 DBGet、DBPut、DBDel、DBDelTree

AstDB 的資料以 family 為群組,在 family 中每筆資料 (value) 有唯一的 key。例如 SIP 註冊資訊的 family 是 SIP/Registry,key 為分機名稱,value 為 <addr>:<port>:<expire>:<username>:sip:<contact>:<port>。

一直到 Asterisk 1.8,Asterisk 內部資料庫都是使用 Berkeley DB。Asterisk 10 開始改用 SQLite3。Asterisk 原本就有模組使用 SQLite (SQLite 2) 來儲存 CDR,這裡提到 SQLite2 用字串儲存所有資料,而 SQLite3 用原生的格式儲存數字及 BLOBS,縮小檔案庫大小。

存取 AstDB 的 C 函數
ast_db_put(family, key, value)
ast_db_get(family, key, value, sizeof(value))
ast_db_del(family, key)

參考來源:
  1. https://wiki.asterisk.org/wiki/display/AST/Asterisk+Internal+Database
  2. Using the Asterisk Database (AstDB)
  3. http://www.voip-info.org/wiki/view/Asterisk+database 

星期日, 5月 11, 2014

sipp

sipp 是 SIP 效能測試工具程式

自己撥給自己測試

sipp -sn uas ;作為 UAS 接受來電
sipp 127..0.0.1 ;作為 UAC 撥號

測試 Asterisk

在 /etc/asterisk/extensions.conf 的 [public] 區塊新增 (假設 sip.conf 的 context= 是設成 public)
exten => service,1,Answer() ;sipp 預設撥給 service
exten => service,n,Wait(3600) ;等候 60 分鐘,測試時 sipp 會先掛電話
執行 sipp 測試
sipp <asterisk IP> -d 20000 ;
測試 OpenWrt 下的 Asterisk 11,大概每秒 8 通以上,就會有撥不通的情況

星期三, 5月 07, 2014

Asterisk 簡易設定

在 /etc/asterisk/sip.conf 最後面新增
[101]
type=peer
host=dynamic


在 /etc/asterisk/extensions.conf 的 [public] 區塊新增 (假設 sip.conf 的 context= 是設成 public)
exten => _1XX,1,Dial(SIP/${EXTEN})

如果需要很多帳號,sip.conf 可改成新增
[basic](!)
type=peer
host=dynamic

[101](basic)
[102](basic)

後記:SIP 也可以經由 SIP REGISTER 自動產生帳號,只需要 sip.conf 的 [general] 加設 autocreatepeer=yes。

星期四, 5月 01, 2014

byte order

在電腦,short (16-bit)、long (32-bit)、long long (64-bit) 分別需要 2、4、8 byte 的連續記憶體存放,這時候就有記憶體低位址放高位元組 (big endian),還是放低位元組 (little endian) 的問題,這就是位元組順序 (byte order)。big endian 跟 little endian 名稱由來是一個關於雞蛋哪頭先敲的故事

0x87654321 放記憶體的情形

big endian
little endian
資料0x870x650x430x21
0x210x430x650x87
位址0123
0123

x86 處理器就是典型使用 little endian 的處理器,而網路封包欄位通常是高位元組先送收,在記憶體會高位元組先放,所以是 big endian。如果資料的 endian 跟處理器不同,要運算時需要作 endian 轉換。

主機 (host,也就處理器架構) 的 byte order 跟不同 endian 的轉換函數:
  • uint16_t htobe16(uint16_t)
  • uint16_t htole16(uint16_t)
  • uint16_t be16toh(uint16_t)
  • uint16_t le16toh(uint16_t)
其中 h 代表 host byte order,16 亦可為 32 或 64

網路封包的欄位可以用上述 big endian 轉換的函數,但通常用 ntohs()、htons()、ntohl()、htonl() 函數。

問題:需要 preprocessor macro 嗎?有標準的 macro?

pthread

pthread、POSIX thread、執行緒。

程式 (program) 執行成為 process,一開始本身就是一個 thread,可建立其它 thread 在同一個虛擬記憶體下同時進行,共用 text、data 及 heap 區段,但有獨立的堆疊 (stack) 而有各自的函數呼叫及自動變數儲存。thread 之間的溝通可直接用放在 data 區段的全域變數,不需要使用負擔較重的 IPC。thread 的建立、結束、執行切換也比 process 快。

目前在 Linux 的主要實作是 Native POSIX Threads Library (NPTL),使用 cc -pthread 編譯。

屬性 (attributes) 有分是 process 層級和 thread 層級。process 層級屬性是 thread 共用:

  • process ID、parent process ID、PGID、SID、和控制終端機、user 和 group ID。
  • 開啟的 file descriptors、file mode creation mask (見 umask())
  • record locks (見 fcntl())
  • signal dispositions
  • current directory (見 chdir()) 及 root directory (見 chroot())
  • interval timers (見 setitimers()) 及 POSIX timers (見 timer_create())
  • nice 值:在 POSIX 是 per-process 設定,但目前 Linux/NPTL 實作是 per-thread 屬性。
  • resource limits (setrlimit())
  • 測量消耗的 CPU 時間 (times()) 及資源 (見 getrusage())

thread 層級是各自 thread 獨立:

  • thread ID:pthread_t,在 pthread_create() 時建立,在 process 內有唯一性。thread 結束後釋出可能再利用。thread_self() 可以取得自己的 thread ID。
    • Task ID:kernel 對 thread 另外編排的 ID,透過 gettid() 取得,也就是在 user space 工具程式 (例如 ps、top) 看到的 PID (Process ID)。
    • TGID (Thread Group ID):process 中第一個 thread 的 task ID,透過 getpid() 取得。
    • PPID:是親 process 的 task ID。
    • PGID、SID
  • signal mask (pthread_sigmask()):繼承
    • 繼承 mask (pthread_sigmask()),清空 pending (sigpending())
    • 不繼承 alternate signal stack (sigaltstack())
  • errno 變數 (不是全域變數,需 #include <errno.h> 使用)
  • 浮點計算環境 (fenv()):繼承
  • real-time scheduling policy and priority (sched_setscheduler() 及 sched_setparam())
  • capabilities
  • CPU affinity (sched_setaffinity):親和力,多處理器系統的個別處理器如何利用。
  • stack
  • CPU-time:pthread_getcpuclockid() 取得 thread 的 clock ID (process 固定為CLOCK_PROCESS_CPUTIME_ID,calling thread 用 CLOCK_THREAD_CPUTIME_ID。),在透過 clock_gettime() 取得時間

pthreads API 函數的回傳值:大部分成功時回傳 0、失敗時回傳錯誤碼,並不更動 errno。

thread 雖然比 process 效率好,但有些缺點:

  • thread-safe 函數多個 thread 同時呼叫可能造成錯誤。
  • thread 間共用虛擬記憶體,隔絕性較差,問題較容易互相干擾。
  • 每個 thread 佔用 process 部份虛擬記憶體,當 thread 很多的時候可能一個虛擬記憶體不夠用。
  • signal 處理
  • process 可以跑不同程式,而 thread 需要整合進來
  • 共用屬性視情況可能有好有壞

建立

#include <pthread.h>

int pthread_create(pthread_t *threadid, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);

使用 attr 的設定建立一個執行 start_routine(arg) 的新 thread,而且在 threadid 回傳 pthread_t。

attr 可設定 stack、guard、排程等,NULL 時則使用預設值。ulimit -s 可設預設 stack 大小。

guard 是 stack 之後額外的 page 空間 ,是不可存取的虛擬記憶體空間,讓 stack overflow 會有 SIGSEGV 的效果。在 NPTL 實作是算在 stack 一部分,但 POSIX.1 或廢棄的 LinuxThreads 實作則是外加。

問題:新 thread 何時開始執行?

結束

方式有:

  • start_routine() 用 return 結束,回傳值傳給 pthread_join()。
  • thread 自己呼叫 pthread_exit(void *retval),*retval 為傳給 pthread_join() 的結束值。*retval 應避免指到 thread 的堆疊。會進行 thread cleanup 動作。
  • 其它 thread 呼叫 pthread_cancel()。會進行 thread cleanup 動作。
  • 任一 thread 呼叫 exit()、或 process 的 main() 主程式結束,所有 thread 都會結束
thread 結束並不會釋出資源,除非設成 detached 或者其它 thread 用 pthread_join() 等候其結束。設成 detached 可執行 pthread_detach() 或建立 thread 時用 pthread_attr_setdetachstate() 設定屬性。等候結束除了 pthread_join() 外,還可以用 pthread_tryjoin_np() 跟 pthread_timedjoin_np()。

內部

  • thread 建立採用 Linux clone() 系統呼叫,相對於 process 建立使用 fork() 系統呼叫大概快十倍,不用複製 page tables、許多屬性共用、資料也不用 copy-on-write。
  • thread synchronization primitives (mutexes、thread joining 等等) 使用Linux futex() 系統呼叫實作。
  • 用了前兩個 real-time signals

參考

  1. man-page pthreads
  2. man pthread_create
  3. :《The Linux Programming Interface》chap. 29
  • pthread_yield():非標準,改用 POSIX sched_yield() 及 #include <sched.h>
  • 看 thread 狀態:ps -T [-p <pid>]、top -H [-p <pid>]、htop
  • concurrency and parallel
  • cond, sema
  • #include <syscall.h>
    int id = syscall(SYS_gettid);