2012年10月18日木曜日

関数の入口出口で関数を呼ぶには

gcc でコンパイルする場合、関数の入口と出口で別の関数を呼ぶことができる。
まず、コンパイル時に -finstrument-functions を付けて、コンパイルしておく。
すると、各関数の入口と出口で

void __cyg_profile_func_enter(void* func_addr, void* call_site);
void __cyg_profile_func_exit(void* func_addr, void* call_site);
が呼ばれるので、これらの関数を共有ライブラリとして用意しておいて使う。

2012年10月17日水曜日

あるカーネルモジュールで定義したグローバル変数を別のモジュールから参照する

あるカーネルモジュールで定義したグローバル変数を別のモジュールから参照する。

まず、最初のカーネルモジュール A で外部に見せたい変数を EXPORT_SYMBOL() で囲む。
次に、別のカーネルモジュール B で、その変数を参照するわけだが、これで通常のコンパイルをすると、その変数は undefined だと言われる。

これを解決するためには、カーネルモジュール B をコンパイルする際に、
make -C ... M=... KBUILD_EXTRA_SYMBOLS=<path>/Module.symvers modules
のように、KBUILD_EXTRA_SYMBOLS にモジュール A の Modules.symvers のパスを指定するとうまくいく。

2012年9月23日日曜日

syslogd

syslog は UNIX domain socket を利用しているので、カーネルのコンフィギュレーションで UNIX domain socket をサポートさせるようにしないと利用できない。

buildroot で生成したクロスコンパイル環境のパス

buildroot で生成したクロスコンパイル環境は、./output/host/usr/bin/ 以下にある。

2012年9月13日木曜日

一般ユーザーの sudo パスワードなし実行

一般ユーザー(user1 というユーザー名だとする)の sudo パスワードなし実行を設定する。
Ubuntu12.04 では、visudo して下記の一行を追記すれば良い。
%user1 ALL=NOPASSWD: ALL

isc-dhcpd-server

ubuntu 12.04 で isc-dhcpd-server を apt-get install し、service isc-dhcpd-server start で起動しようとしたが、うまく動かない。dhcpd -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcpd/dhcpd.conf で起動したらうまくいった。
dhcpd.conf の設定は、下記を dhcpd.conf の末尾に追加した。

subnet 192.168.10.0 netmask 255.255.255.0 {
  range 192.168.10.10 192.168.10.30;
  option domain-name-servers 192.168.10.1;
  option domain-name "hoge.piyo";
  option routers 192.168.10.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.10.255;
}

2012年9月9日日曜日

Ubuntu 12.04 で WLI-UC-GNM2

http://somememos.blogspot.jp/2012/06/usblan-wli-uc-gnm2linux.html にある通り、rt2800usb.c を修正したモジュールを利用することにより、Ubuntu 12.04 から WLI-UC-GNM2 を使用することができた。

2012年8月25日土曜日

rint がない

buildroot で wpa_supplicant をコンパイルしたら、rint という関数がないと言われた。
uclibc の libm に入っているのだが、明示的に指定しないと見えないらしい。
wpa_supplicant の Makefile のライブラリ指定のところに -lm を付けたら通った。

具体的には、output/build/wpa_supplicant-0.7.3/src/drivers/drivers.mak
の、nl80211 の DRV_LIBS に -lm を追加。

2012年8月19日日曜日

TLMu で ARM Linux

■ TLMu で ARM Linux
http://www.hdlab.co.jp/web/a050consulting/b009armcpumodel/ から環境をダウンロードして動かしてみた。

環境は、Ubuntu 12.04
- systemc-2.2.0.tgz
- TLM-2.0.1.tgz
- scml-2.1.1-pv-20111213.tgz
を利用し、tlmu_arm_example/INSTALL に従ってインストールを行う。

ただし、途中 g++ のコンパイルで mutable のエラーに何度かあうので -fpermissive を付けた。

tlmu.20120529/Makefile.target で、--whole-archive オプションがあるとエラーになるので外した。

tlmu_arm_example で、LIBS に pthread を追加。また、ライブラリの順序を変えないとコンパイルが通らなかった。また、hdlab_lib/ip/versatile_vic.c cpp で、uint32_t が未定義だと言われたので、typedef unsigned int uint32_t; を追加。


無事コンパイルが通り、./run.x を実行すると xterm が立ち上がり linux が起動できた。

追記1:buildroot により作成されるルートファイルシステムには、/lib 以下が空になっているので、共有ライブラリを参照しているプログラムは動かない(busybox 以外のプログラムは基本的に動かない)。buildroot/output/toolchain/uClibc-<version>/lib/*.so* を /lib にコピーする必要がある。

追記2:起動した Linux でファイルを作成しても、Linux を起動し直すと作成したファイルは消えてしまっている。シミュレーション開始時に ramdisk.img をメモリ上に読み込んでいるが、シミュレーションした結果をもとの ramdisk.img に書き戻していないためである。

2012年8月16日木曜日

TLMu

QEMU で TLM が使えるという TLMu を Ubuntu 12.04 にインストールした。

http://edgarigl.github.com/tlmu/ 参照。


■systemc-2.3.0 をインストール。
% mkdir objdir
% cd objdir
% ../configure --prefix=<install_dir> (なんか prefix の扱いにバグがあるような気が…)
% make
% make install
% make check
※コンパイル時に -fPIC を付けないと make が通らなかった。



■tlmu 取得
% git clone git://github.com/edgarigl/tlmu.git (tlmu というディレクトリができる)

■tlmu ビルド
% mkdir build-tlmu
% cd build-tlmu
% ../tlmu/configure --extra-cflags=-fPIC
% make && make tlmu
% make install-tlmu DESTDIR=/tmp/my-tlmu/
※zlib1g-dev, libglib2.0-dev をインストールしておく必要があった

■tlmu インストールチェック(c_example)
% cd ../tlmu/tests/tlmu
% ln -sf /tmp/my-tlmu/* ./
% make c_example
% LD_LIBRARY_PATH=./lib ./c_example

■tlmu インストールチェック(sc_example)
% cd sc_example
% emacs Makefile
 (SYSTEMC, TLM2 を systemc-2.3.0 をインストールしたディレクトリに変更)
% make sc_example
% cd ..
% LD_LIBRARY_PATH=./lib:<libsystemc のパス> ./sc_example/sc_example

■arm バイナリのコンパイル
AMR926 なので、-march=armv5te を付けてコンパイルする必要あり。






2012年8月14日火曜日

Adaptive Performance Compensation with In-Situ. Timing Error Prediction for Subthreshold Circuits

・worst case を想定した設計では、消費電力が大きくなりすぎる⇒ばらつき量に応じた制御が必要。
・ばらつきの見積もり方法として、critical path replica, razor, canary FF などがある。critical path replica は、sub threshold 回路では、within die ばらつきが大きすぎて効果的ではない。また、razor はタイミング違反を発見して再実行する思想なので、シンプルなプロセッサは再実行には向かない。なので、canary FF が良い。
・in situ とは、本来の場所にてという意味。

JP 2011-199486

2 つのチャネルでそれぞれ、AP, STA として通信している無線 LAN システムにおいて、バッテリ残量が閾値以下に低下したら、1 つのチャネルで AP, STA として通信させるようにチャネルを移動することで、消費電力を削減する特許。

JP 2005-57633

・送信データレートを決定する際に、相手から受信したフレームのサブキャリア毎の振幅の変動値を見て、レートを決定する特許。
・各サブキャリアについて、I^2+Q^2 を計算し、全サブキャリアの平均と分散を計算。分散が大きければ、フェージングの影響が大きいチャネルと判断し、低レートで送信する。

特開2003-110575

送信キューを複数設け、レートが高いフレームをレートが低いフレームより優先度を上げて送信することで、レートが低い STA 間の通信に引っ張られてスループットが落ちることがないようにする特許。

AN OVERVIEW OF TECHNIQUES FOR REDUCING PEAK. TO AVERAGE POWER RATIO AND ITS SELECTION. CRITERIA FOR ORTHOGONAL FREQUENCY DIVISION. MULTIPLEXING RADIO SYSTEMS

AN OVERVIEW OF TECHNIQUES FOR REDUCING PEAK. TO AVERAGE POWER RATIO AND ITS SELECTION. CRITERIA FOR ORTHOGONAL FREQUENCY DIVISION. MULTIPLEXING RADIO SYSTEMS

PAPR 低減技術の紹介論文です。

■ block coding techniques
符号化の段階で、PAPR が高くなるようなパターンが出ないような符号化を行う。サブキャリア数がいくつになっても、またどんなマッピング方法でも PAPR が下がらないように符号を選ぶので、短い符号以外は現実的ではない。

■ sub block coding techniques
符号化率 3/4 の組織符号で、最後のビットが odd parity check にすると、PAPR が低いという性質がある?
"OFDM peak power reduction by sub-block-coding and its extended versions" 参照。

■ selected mapping
同じ内容をマッピングする方法をいくつか用意しておき、その中で最も PAPR が低いものを選択する。
side information として、どのマッピング方法を選択したかを別途送信する必要がある。
"Reducing the peak-to-average power ratio of multicarrier modulation by selective mapping"

■ Interleaving
複数のインタリーブを実行してみて、一番 PAPR が低いものを選択する。
インタリーブを最後まで実行する前に判断することもできる。

■ PTS (partial transmit sequence)
サブキャリアマッピングの後で、いくつかのサブキャリアを回転させる。
どのくらい回転させたかを受信側が知る必要がある。

■ Hadmard transform
入力列をアダマール変換すると、PAPR が 2dB 低減するらしい。

■ dummy sequence insertion
不明
"Dummy Sequence Insertion (DSI) for PAPR Reduction in the OFDM Communication System"

■ tone reservation
いくつかのサブキャリアを PAPR 低減のために利用する。(データ送受信のために使用しない)

■ active constellation
コンスタレーションの点を外側にずらして、PAPR を下げる。demap 時の境界から離れる方向に constellation を
広げるので、BER はよくなるが、送信電力が増加してしまうので、送信電力一定とすると、BER は劣化する。

■ クリッピング
振幅をクリッピングする。BER は劣化する。


A sub-pW timer using gate leakage for ul- tra low-power sub-Hz monitoring systems.

sub-pW timer using gate leakage for ul- tra low-power sub-Hz monitoring systems.

・ゲートリークを利用したタイマ。
・ゲートリークを電流源として使用し、キャパシタの電荷を徐々に放出していく。電圧が一定以下になることをコンパレータで検出するとタイムアウト。
・ゲートリークは、サブスレッショルドリークに比べて温度依存性が低い。バイオメディカル用途で、数十度の温度変動を仮定すれば十分実用的。Process ばらつきは事前に補正する。

0.5-V Input Digital Low-Dropout Regulator (LDO) with 98.7%. Current Efficiency in 65 nm CMOS

0.5-V Input Digital Low-Dropout Regulator (LDO) with 98.7%. Current Efficiency in 65 nm CMOS

・conventional LDO は、(出力電圧と参照電圧を比較する)オペアンプと(オペアンプの出力に接続され、出力電圧を制御する) 1 つの Power Transistor から成るが、0.5V 電源ではオペアンプは動作しないし、Power Transistor のゲート制御もできない。
⇒0.5V でもデジタル回路を動作させることはできるので、デジタル的に LDO を構成する。
・オペアンプはコンパレータ、Power Transistor は低電圧で動作する Transistor(=switch) array に置き換えて、0.5V 動作。


ビット線充放電電力を 53%削減する動画像処理応用 2-port SRAM

ビット線充放電電力を 53%削減する動画像処理応用 2-port SRAM。藤原 英弘ら。

2-port SRAM はトランジスタの構成により、"0" を読み出すときに電力を消費し、"1" を読み出す時に電力を消費しない。

なので、複数のデータビットを 1 ワードとし、ワード内に"0" が多ければビットを反転し、"1" が多いときはそのまま書き込む。反転したかどうかをもう一ビット使って覚えておくという構成にすることで消費電力を低減できる。

また、動画像応用では、隣接データの同じビット位置のビット(特に上位ビット)は相関が大きいという性質を使い、同じビット位置の隣接データを集めてきて 1 ワードとすることで、ランダムデータより消費電力を削減できる。

2012年3月18日日曜日

KNOPPIX のカスタマイズ

使用しないであろうパッケージの削除

aptitude purge <package_name>

# purge と remove の違いは、設定ファイルも削除するかしないか


私が使用しないであろうパッケージ

・python
・xpdf
・linux-sound-base
・libreoffice-common
・anthy-common
・cups
・bluez
・java-common
・imagemagick
・ghostscript
・dvd+rw-tools
・mp3

2012年3月10日土曜日

verilog auto

組み合わせ回路
always @(/*AS*/) begin


入出力


module(/*AUTOARG*/) begin



submodule instancename(/*AUTOINST*/)

M-x verilog-auto C-c C-z

2012年3月7日水曜日

キャラクタデバイスのデバイスドライバ例

#include <linux/fs.h>    // file_operations, inode
#include <asm/uaccess.h> // copy_to_user
#include <linux/module.h>
#include <linux/kernel.h>


static int devmajor = 77;
static char devname[] = "logdev";
static char devbuf[] = "this is my message.\n";

static int
logdev_read(struct file *filp, char *buf, size_t count, loff_t *pos)
{
  int copy_len = sizeof(devbuf);

  copy_to_user(buf, devbuf, copy_len);

  return copy_len;
}


static struct file_operations logdev_fops = {
  .read = logdev_read,
};


int
init_module(void)
{
  register_chrdev(devmajor, devname, &logdev_fops);
  printk(KERN_INFO "logdev init\n");

  return 0;
}

void
cleanup_module(void)
{
  unregister_chrdev(devmajor, devname);
  printk(KERN_INFO "logdev clean\n");
}

MODULE_DESCRIPTION( "sample char device driver" );



$ ls -l /dev/logdev
crw-r--r-- 1 root root 77, 0  /dev/logdev

2012年3月4日日曜日

Linux で WPS を使う方法2


STA が Registrar、AP が Enrollee の場合、

■ AP 側 (hostapd)
# cat hostapd.conf
wpa=2
wpa_passphrase=xxxxxxxx
wps_state=1 (not configured)
eap_server=1

# hostapd_cli wps_ap_pin random
35344414 (PIN の生成)
# hostapd_cli wps_ap_pin get
35344414 (同じ PIN が得られる)


■ STA 側
wpa_supplicant 起動後
# wpa_cli wps_reg xx:xx:xx:xx:xx:xx 35344414 new_ssid WPA2PSK CCMP new_passphrase
ただし、xx:xx:xx:xx:xx:xx は AP の MAC アドレス
35344414 は STA Registrar の PIN を入力する。
これで、AP が新しい設定(new_ssid, new_passphrase) で再起動される。

うまくいけば、hostapd.conf は新しい設定に書き換えられている。
# cat hostapd.conf
wps_state=2
ssid=new_ssid
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
wpa_passphrase=new_passphrase
auth_algs=1

2012年3月1日木曜日

Linux で WPA/WPA2 を使う方法

[AP]
# ./hostapd /etc/hostapd/hostapd.conf

ただし、hostapd.conf には、下記を記載。
wpa = 1(WPA) or 2(WPA2) or 3(WPA/WPA2 mixed)
wpa_passphrase = my_passphrase

[STA]
# wpa_passphrase my_ssid my_passphrase
# wpa_supplicant -i wlan1 /etc/wpa_supplicant/wpa_supplicant.conf
(これで、iw connect を実行しなくても自動的に接続される)

WLAN 接続メモ

[AP]
# ./hostapd hostapd.conf

[STA]
# iw -i wlan1 scan
# iw -i wlan1 connect my_ssid
# iw -i wlan1 disconnect

[capture(1024Byte までダンプする)]
# tcpdump -i hwsim0 -w dump.pcap -s 1024

2012年2月25日土曜日

Linux で WPS を使う方法

STA(wext/nl80211) が Enrollee、AP(nl80211) が Registrar の場合、

■ STA 側
# cat wpa_supplicant.conf

ctrl_interface=/var/run/wpa_supplicant
update_config=1

wpa_supplicant 起動後
# wpa_cli wps_pbc (PBC の場合)
# wpa_cli wps_pin any 12345678 (PIN の場合)

■ AP 側 (hostapd)
# cat hostapd.conf
wpa=2
wpa_passphrase=xxxxxxxx
wps_state=2 (configured)
eap_server=1

hostapd 起動後
# hostapd_cli wps_pbc (PBC の場合)
# hostapd_cli wps_pin any 12345678 (PIN の場合)

WPS の実行と、configure 後の WPA2 による再接続は続けて行われる。
また、WPS 実行後、wpa_supplicant.conf が更新される。
(update_config=1 を書かなければ更新されない。)

# cat wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
update_config=1

network={
        ssid="myssid"
        psk="xxxxxxxx"  # PSK ではなく、パスフレーズが書かれている
        proto=RSN
        key_mgmt=WPA-PSK
        pairwise=CCMP
        auth_alg=OPEN
}


2012年2月23日木曜日

カーネルモジュールのデバッグ

カーネルモジュールのデバッグ方法として、
printk + dmesg があるが、多くの文字列を出力するには適さない。

一つの方法として、proc ファイルシステムを使う方法がある。

■使い方
cat /proc/myprocentry
とすると、情報が読み出せる。

■ハンドラの登録
  struct proc_dir_entry *dirp;
  dirp = (struct proc_dir_entry *) create_proc_entry("/proc/myprocentry", 0444, (struct proc_dir_entry *) 0);
  dirp->read_proc = myproc_read;

これで、/proc/myprocentry に読み出しを行った際に、myproc_read が呼び出されるようになる。

wireless extensions

iwconfig などのコマンドは、内部で wireless extensions のインタフェースを使っている。
その先で、さらに呼ばれるのが、wireless_handlers である。

■wireless_handlers の登録
  mynet_dev = alloc_netdev(PRIV_SIZE, MYDEV_NAME, ether_setup);
  mynet_dev->netdev_ops = &mynet_dev_ops;
  mynet_dev->wireless_handlers = &mynet_wext_handlers;
  register_netdev(mynet_dev);

net_device の wireless_handlers に適切な関数を登録しておけば、
iwconfig から(ioctl 経由で)呼ばれる。

登録の仕方は、
static const iw_handler cfg80211_handlers[] = {
        [IW_IOCTL_IDX(SIOCGIWNAME)]     = (iw_handler) cfg80211_wext_giwname,
        [IW_IOCTL_IDX(SIOCSIWFREQ)]     = (iw_handler) cfg80211_wext_siwfreq,
        [IW_IOCTL_IDX(SIOCGIWFREQ)]     = (iw_handler) cfg80211_wext_giwfreq,
        [IW_IOCTL_IDX(SIOCSIWMODE)]     = (iw_handler) cfg80211_wext_siwmode,
        [IW_IOCTL_IDX(SIOCGIWMODE)]     = (iw_handler) cfg80211_wext_giwmode,
        [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,
        [IW_IOCTL_IDX(SIOCSIWAP)]       = (iw_handler) cfg80211_wext_siwap,
        [IW_IOCTL_IDX(SIOCGIWAP)]       = (iw_handler) cfg80211_wext_giwap,
        [IW_IOCTL_IDX(SIOCSIWMLME)]     = (iw_handler) cfg80211_wext_siwmlme,
        [IW_IOCTL_IDX(SIOCSIWSCAN)]     = (iw_handler) cfg80211_wext_siwscan,
        [IW_IOCTL_IDX(SIOCGIWSCAN)]     = (iw_handler) cfg80211_wext_giwscan,
}
const struct iw_handler_def cfg80211_wext_handler = {
        .num_standard           = ARRAY_SIZE(cfg80211_handlers),
        .standard               = cfg80211_handlers,
};
など。詳しくは、/usr/src/linux/net/wireless/wext-compat.c を参照。

iwconfig を引数なしで実行するためには、少なくとも SIOCGIWNAME に対するハンドラの登録が必要。それ以外の iwconfig のコマンドを実行するためには、他の SIOC*IW ハンドラを実装する必要あり。

ifconfig

ネットワークインタフェースを追加し、ifconfig できるところまで行います。

■ネットワークインタフェースの確保
  struct net_device *mynet_dev;
  mynet_dev = alloc_netdev(PRIV_SIZE, NDEV_NAME, ether_setup);
  // PRIV_SIZE にプライベートデータを保存する領域のサイズ(int。特になければ 0)
  // NDEV_NAME にネットワークインタフェースの名前 (char *)

■ネットワークインタフェースの登録
  mynet_dev->netdev_ops = &mynet_dev_ops;
  register_netdev(mynet_dev);

これで、カーネルにネットワークインタフェースの登録が完了する。
ただし、最低限、下記の netdev_ops を定義しておかなければならない。

static struct net_device_ops mynet_dev_ops = {
  .ndo_init = mynet_init,
  .ndo_open = mynet_open,
  .ndo_start_xmit = mynet_xmit,
};

.ndo_open が ifconfig を実行したとき呼ばれる関数である。
また、.ndo_init は reigster_netdev() 実行時に呼ばれる関数、
ndo_start_xmit は、パケット送信時に呼ばれる関数である。

カーネルモジュールの書き方

モジュール名 moduletest のモジュールを作ります。



■使い方
(モジュールの読み込み)
# insmod moduletest.ko
(モジュールの取り外し)
# rmmod moduletest


■C コード
#include <linux/module.h>
#include <linux/kernel.h> // for printk
#include <linux/sched.h>  // for jiffies

// insmod 時に呼ばれる
int init_module()
{
  printk("module being installed at %lu\n", jiffies);
  return 0; // 0 以外の値を返すと、insmod は成功しない
}

// rmmod 時に呼ばれる
void cleanup_module()
{
  printk("module being removed at %lu\n", jiffies);
}

■Makefile
KERNEL_SRCDIR = /usr/src/linux
BUILD_DIR = $(shell pwd)

TARGET = moduletest

obj-m := $(TARGET).o

all:
        make -C $(KERNEL_SRCDIR) M=$(BUILD_DIR) modules

■注1
カーネルのシンボルを使うので、カーネルのヘッダファイルが必要。
apt-get install linux-headers などを行う。

■注2
init_module, cleanup_module という名前を変えるためには、
module_init, module_exit などのマクロを使う。


static int __init modtest_module_init( void )
{
  printk( KERN_INFO "modtest is loaded\n" );
  return 0;
}


static void __exit modtest_module_exit( void )
{
  printk( KERN_INFO "modtest is removed\n" );
}

module_init( modtest_module_init );
module_exit( modtest_module_exit );

■注3
デバッグ出力したいときは、printk を使う。出力は dmesg で確認する。

■注4
モジュールが insmod できたかどうかは lsmod で確認する。