T-SH7706LSRのCN2 3番ピンのハイ/ローを制御するデバイスドライバを作成
T-SH7706LSRのCN2の3番ピンのハイ/ローを制御するデバイスドライバを作成しました。
主に、前回の記事(id:cupnes:20121229:1356786112)で参考にした、
http://wave2.iobb.net/doc/summary/sh3wiki/wifky.cgi?p=LED%C0%A9%B8%E6%A5%C9%A5%E9%A5%A4%A5%D0%A4%CE%BA%EE%C0%AE
を元に作成しました。T-SH7706LSRにおいてCN2の3番ピンへつながっているポートD1を制御します。
ソースコード
必要なものは、以下の2つです。
- ptd1.c
- Makefile
「ptd1.c」
#include <linux/init.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/io.h> #include <linux/uaccess.h> #include <linux/fs.h> #include <linux/cdev.h> #define PTD1_MAJOR 242 #define PTD1_MINORS 1 #define PTD1_NAME "shminptd1" #define PDDR 0xA4000126 /* 8bit access */ #define PDCR 0xA4000106 /* 16bit access */ static struct cdev ptd1dev; static int ptd1_open(struct inode *inode, struct file *file) { return 0; } static int ptd1_release(struct inode *inode, struct file *file) { return 0; } static ssize_t ptd1_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { unsigned char ptd1data; get_user(ptd1data,buf); if(ptd1data=='0') __raw_writeb(__raw_readb(PDDR)&~0x02,PDDR); /* PD1DT=0 */ if(ptd1data=='1') __raw_writeb(__raw_readb(PDDR)|0x02,PDDR); /* PD1DT=1 */ (*offset)++; return 1; } struct file_operations ptd1_fops = { .owner = THIS_MODULE, .open = ptd1_open, .write = ptd1_write, .release = ptd1_release, }; static int __init ptd1_init(void) { dev_t dev = MKDEV(PTD1_MAJOR, 0); int ret; cdev_init(&ptd1dev, &ptd1_fops); ret = cdev_add(&ptd1dev, dev, PTD1_MINORS); if (ret){ printk(KERN_WARNING "shminptd1: device add faiptd1.\n"); goto err0; } __raw_writew((__raw_readw(PDCR)&~0x000C)|0x0004,PDCR); /* PD1 output */ return 0; err0: unregister_chrdev_region(dev, PTD1_MINORS); return ret; } static void __exit ptd1_exit(void) { dev_t dev = MKDEV(PTD1_MAJOR, 0); __raw_writeb(__raw_readb(PDDR)&~0x02,PDDR); /* PD1DT=0 */ cdev_del(&ptd1dev); unregister_chrdev_region(dev, PTD1_MINORS); } module_init(ptd1_init); module_exit(ptd1_exit); MODULE_LICENSE("GPL");
「Makefile」
KERNELDIR ?= ../linux-2.6.39.4 PWD := $(shell pwd) obj-m := ptd1.o all: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
コンパイル
これら2つのファイルを以下の様に配置します。「linux-2.6.39.4/」はカーネルのソースディレクトリです。
以下の様にコマンドを実行します。なお、ここでは上記した「linux-2.6.39.4」と「ptd1」の2つのディレクトリが「~/work/」にあるものとします。
$ cd ~/work/ptd1/
$ make ARCH=sh CROSS_COMPILE=sh3-linux-
何も問題が無ければ、
ptd1.ko
というファイルが生成されるはずです。
使用方法
生成した「ptd1.ko」をT-SH7706LSRで起動するLinuxのためのファイルシステムを作成したSDカードへコピーします。
MES(Micro Embeded System)
にある「SH3/Linux」の「メモリカードセットアップ」にある通りの作業が終了しているものとします。(SDカードの第2パーティションにファイルシステムがインストール済みであるとします。)
カーネルオブジェクトをターゲットへコピー
「/dev/sdb2」がSDカードの第2パーティションを指しているとすると、以下の様に作業してください。また、マウントポイント「/mnt/storage/」は例です、適宜作成、読み替えなど行ってください。
$ sudo mount /dev/sdb2 /mnt/storage $ sudo cp ~/work/ptd1/ptd1.ko /mnt/storage/root/ $ sudo umount /mnt/storage
デバイスドライバの使用
「ptd1.ko」のコピーが完了した後、SDカードを取り外し、再度T-SH7706LSRへ挿入して、ターゲットでLinuxを起動、ログインしてください。
以下の様にコマンドを実行すると、ポートD1の制御が出来ます。
# mknod /dev/shminptd1 c 242 0 # insmod ptd1.ko # echo 1 > /dev/shminptd1 # ポートD1をハイに設定 # echo 0 > /dev/shminptd1 # ポートD1をローに設定
備考
http://japan.renesas.com/products/mpumcu/superh/sh7700/sh7706/Documentation.jsp#type44Om44O844K244O844K644Oe44OL44Ol44Ki44OrOiDjg4!jg7zjg4njgqbjgqfjgqI=
ルネサスエレクトロニクス株式会社の公開している「SH7706」のハードウェアマニュアルによると、
「表24.2 DC特性」より
- 全出力端子の出力ハイレベル電圧(V_OH)
- min 2.4V (@V_CCQ=3.0V、I_OH=-200マイクロA)
- min 2.0V (@V_CCQ=3.0V、I_OH=-2mA)
- 全出力端子のローレベル電圧(V_OL)
- max 0.55V (@V_CCQ=3.6V、I_OL=1.6mA)
また、「表24.3 出力許容電流値」より
- 出力ローレベル許容電圧(1端子当たり)(I_OL)
- max 2.0mA
- 出力ハイレベル許容電圧(1端子当たり)(-I_OH)
- max 2.0mA
とあるので、順方向電圧2V程の赤色LEDで、300Ωの抵抗を使用しています。