早いもので、2016年から2017年に突入しようとしている
いろいろなことがあった。
まずは「Amis!」
これは、温湿度・デジタル入力変化をトリガーにメール通知(今はSlackに移行)するもの。
DD-Wrt化したBuffaloルーターに
・ARMクロスコンパイル環境の構築
・USB内臓PICの接続
・Node.jsを使ったメール通知
・iModelaにて基板切削
を行った。
次に「FON2405E拡張(シリアル通信)」
まだ実験段階だけど。
・下準備のためにラズベリー・パイのカーネルコンパイルやGPIO操作、ドライバ作成
・RalinkSDKを使用して上記を移植
・OpenWrtのtftpboot
を行った。
OpenWrtを入れるためにSPIFlashの載せ替えをするところで、年末を迎えてしまっていた。
その他
・Electronを使う機会もあり、簡易的なGUI環境を作れるようになった。
なんとなくJSを使う機会が増えたね。
・git(gogs)をいろいろ使い始めた
・親友が地元に戻り、実家を継いだ。 そして、結婚した。
・投資は目標クリア! 来年も頑張ろう
上半期は仕事が落ち着いていたので、安定的に時間をとれた気がする。
下半期は、忙しくて、なかなか時間が取れなかったかな。
でも、なんとか時間を確保して少しずつ前進できたと思う。
来年も引き続き家庭も仕事も充実するといいな。
ブログ的には
・目標探し
・楽しい教育
・投資を戦略的に行う
・「巨人の肩に乗る」
・「ググるよりもググられたい」
かな。
ちなみに年初の目標は
・Electon(NW.jsもか)を使った開発 → ×
・PICマイコンを使った開発をもっと行う → ○
・投資も頑張る → ◎
といった感じ。
2016年12月31日土曜日
2016年12月25日日曜日
ラズベリー・パイでSST26VF032の読み書き
11月の末頃にFONのフラッシュ容量拡張のために
SST26VF032Bを入手した。
microchipのオンラインストアから注文できるし、3日程度で到着した気がする。
しかし、そのまま交換してもフラッシュに書き込みができなかった。Orz
注意
SST26VF032はSPIモードでの書き込みに対応していないので、「B」有りが必要。
http://www.microchip.co.jp/support/faq_sst-fm.html
このあたりをあまり気にせずに購入していた。危なかった。。。
基礎知識
をあまり持っていなかったので、他の型番の日本語のデータシートなどを読んで雰囲気を学習
http://www.onsemi.jp/pub_link/Collateral/ENA2097JP-D.PDF
http://japan.xilinx.com/xcell/xl55/jp55xcell_13.pdf
そしてSST26VF032Bについて
・データシート
http://ww1.microchip.com/downloads/jp/DeviceDoc/jp566514.pdf
・サンプルプログラム
http://www.microchip.com/wwwproducts/jp/SST26VF032B
→末尾のソフトウェア
初期化
Quad I/Oとか特殊なものを使わないのであれば、初期化すべき項目は少ないと思う。
01H WRSRでIOCとWPENの設定くらい
JEDEC-IDを読んで対象のデバイスかどうかを確認しておく
読み込み方法
03H Readですんなりと読み出すことができる
書き込み方法
一番手こずった
PinのWriteProtectや06H WREN、そしてBlockProtectなんてものもあるOrz
最後のBlockProtectを失念していたために半月くらい悩んだ。
前述のサンプルプログラムを最初から見ておけばよかった。
こんな流れ
1.06H WREN WriteEnable
2.42H WBPR BlockProtection解除
3.02H PP PageProgram
4.05H RDSR BUSYチェック
こんな感じ。
SST26VF032Bを入手した。
microchipのオンラインストアから注文できるし、3日程度で到着した気がする。
しかし、そのまま交換してもフラッシュに書き込みができなかった。Orz
注意
SST26VF032はSPIモードでの書き込みに対応していないので、「B」有りが必要。
http://www.microchip.co.jp/support/faq_sst-fm.html
このあたりをあまり気にせずに購入していた。危なかった。。。
基礎知識
をあまり持っていなかったので、他の型番の日本語のデータシートなどを読んで雰囲気を学習
http://www.onsemi.jp/pub_link/Collateral/ENA2097JP-D.PDF
http://japan.xilinx.com/xcell/xl55/jp55xcell_13.pdf
そしてSST26VF032Bについて
・データシート
http://ww1.microchip.com/downloads/jp/DeviceDoc/jp566514.pdf
・サンプルプログラム
http://www.microchip.com/wwwproducts/jp/SST26VF032B
→末尾のソフトウェア
初期化
Quad I/Oとか特殊なものを使わないのであれば、初期化すべき項目は少ないと思う。
01H WRSRでIOCとWPENの設定くらい
JEDEC-IDを読んで対象のデバイスかどうかを確認しておく
読み込み方法
03H Readですんなりと読み出すことができる
書き込み方法
一番手こずった
PinのWriteProtectや06H WREN、そしてBlockProtectなんてものもあるOrz
最後のBlockProtectを失念していたために半月くらい悩んだ。
前述のサンプルプログラムを最初から見ておけばよかった。
こんな流れ
1.06H WREN WriteEnable
2.42H WBPR BlockProtection解除
3.02H PP PageProgram
4.05H RDSR BUSYチェック
こんな感じ。
2016年12月8日木曜日
FON2405E カスタムファーム用のドライバ開発
前回、準備としてなんちゃってドライバを作成して、insmodするところまでいけた。
次は自力シリアル通信ドライバを作成(ラズベリー・パイ用に作った奴の移植)をしてみる。
1.概要
ドライバ名はMy2nd(まだ名称が決まってないOrz)コードは末尾に記載。
Makefileは前回からドライバ名のみ変更した。
2.導入
nfsマウント
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
insmodしてみる
メッセージのメジャー番号が253 マイナー番号が0が重要で、コレがないと/dev/●●が作成できない。
カーネルのバージョンがアレなので、手動でスペシャルファイル?を作成する必要がある。
mknod /dev/My2nd0 c 253 0
とするとMy2nd0というデバイスファイルが作成できる。
3.テスト
作成したMy2nd0に対してechoで文字列を送ってみる。
echo -n HelloWorld!! > /dev/My2nd0
するとPIC側のコンソールに表示される。
やったーうまくいった!
4.コード
こんな感じ
次は自力シリアル通信ドライバを作成(ラズベリー・パイ用に作った奴の移植)をしてみる。
1.概要
ドライバ名はMy2nd(まだ名称が決まってないOrz)コードは末尾に記載。
Makefileは前回からドライバ名のみ変更した。
2.導入
nfsマウント
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
insmodしてみる
メッセージのメジャー番号が253 マイナー番号が0が重要で、コレがないと/dev/●●が作成できない。
カーネルのバージョンがアレなので、手動でスペシャルファイル?を作成する必要がある。
mknod /dev/My2nd0 c 253 0
とするとMy2nd0というデバイスファイルが作成できる。
3.テスト
作成したMy2nd0に対してechoで文字列を送ってみる。
echo -n HelloWorld!! > /dev/My2nd0
するとPIC側のコンソールに表示される。
やったーうまくいった!
4.コード
こんな感じ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __MY2ND_KM_H__ | |
#define __MY2ND_KM_H__ | |
#include <asm/rt2880/rt_mmap.h> | |
/* | |
* Address of RALINK_ Registers | |
*/ | |
#define RALINK_PRGIO_ADDR RALINK_PIO_BASE // Programmable I/O | |
#define RALINK_REG_PIODATA (RALINK_PRGIO_ADDR + 0x20) | |
#define RALINK_REG_PIODIR (RALINK_PRGIO_ADDR + 0x24) | |
#define RALINK_REG_PIOSET (RALINK_PRGIO_ADDR + 0x2C) | |
#define RALINK_REG_PIORESET (RALINK_PRGIO_ADDR + 0x30) | |
#define RALINK_GPIO(x) (1 << x) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/moduleparam.h> | |
#include <linux/kernel.h> | |
#include <linux/fs.h> | |
#include <linux/types.h> | |
#include <linux/kdev_t.h> | |
#include <linux/errno.h> | |
#include <linux/cdev.h> | |
#include <linux/sched.h> | |
#include <linux/stat.h> | |
#include <linux/io.h> | |
#include <linux/ioport.h> | |
#include <linux/init.h> | |
#include <linux/version.h> | |
#include <linux/device.h> | |
#include <linux/slab.h> | |
#include <linux/delay.h> | |
#include <asm/uaccess.h> | |
#include <linux/timer.h> | |
#include "my2nd.h" | |
MODULE_AUTHOR("Adeno"); | |
MODULE_LICENSE("Dual BSD/GPL"); | |
#define MYSFR9_VERSION "0.4" | |
#define MYSFR9_NUM_DEVS 1 /* このドライバが制御するデバイスの数 */ | |
#define MYSFR9_DEVNAME "My2nd" /* このデバイスドライバの名称 */ | |
#define MYSFR9_MAJOR 0 /* メジャー番号だが自動設定なので0 */ | |
#define MYSFR9_MINOR 0 /* マイナー番号のベース番号 */ | |
#define GPIONO_CLKOUT 11 //LAN-LED output | |
#define GPIONO_DATAOUT 12 //NET-LED output rev | |
#define GPIONO_DATAIN 14 //WPS-LED input | |
#define UDELAY 50 //us | |
#define CHARDELAY 592 //us | |
#define RCVPOLL 10000 //us | |
#define DEFAULT_RCV_QUEUE_SIZE 8 //SFR -> | |
#define DEFAULT_SND_QUEUE_SIZE 8 // -> SFR | |
static int _mysfr9_major = MYSFR9_MAJOR; | |
static int _mysfr9_minor = MYSFR9_MINOR; | |
static struct cdev *mysfr9_cdev_array = NULL; | |
static struct class *mysfr9_class = NULL; | |
static struct timer_list poll_timer; | |
//RCV関係 SFR -> | |
static int rcv_queue_size = DEFAULT_RCV_QUEUE_SIZE; | |
static unsigned char ircv,rcv; | |
static unsigned char *rcv_queue = NULL; | |
static int rq_head, rq_tail; | |
//SND関係 -> SFR | |
static int snd_queue_size = DEFAULT_SND_QUEUE_SIZE; | |
static unsigned char isnd,snd; | |
static unsigned char *snd_queue = NULL; | |
static int sq_head, sq_tail; | |
/*プロトタイプ宣言*/ | |
//GPIO関係 | |
static void mysfr9_gpio_setup(void); | |
static int mysfr9_gpio_getpin(int pin); | |
static void mysfr9_gpio_setpin(int pin,uint32_t val); | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv); | |
//カーネルへの登録関係 | |
static int mysfr9_register_dev(void); | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep); | |
static int mysfr9_release(struct inode *inode, struct file *filep); | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos); | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos); | |
//File Operations構造体 | |
struct file_operations mysfr9_fops = { | |
.open = mysfr9_open, | |
.release = mysfr9_release, | |
.write = mysfr9_write, | |
.read = mysfr9_read, | |
}; | |
//タイマー関係 | |
static void register_poll_timer(void); | |
static void poll_timer_handler(unsigned long data); | |
//QUEUE関係 | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n); | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n); | |
//Sleep | |
static DECLARE_WAIT_QUEUE_HEAD(wq); | |
static int wq_flg = 0; | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがロードされた時の処理 | |
static int mysfr9_init(void) | |
{ | |
int retval,i; | |
/* 開始のメッセージ */ | |
printk(KERN_INFO "%s Ver.%s loading...\n", MYSFR9_DEVNAME,MYSFR9_VERSION ); | |
/* queue */ | |
sq_head=0, sq_tail=0; | |
rq_head=0, rq_tail=0; | |
if(!(rcv_queue_size > 0 && rcv_queue_size < 65536)){ | |
rcv_queue_size = DEFAULT_RCV_QUEUE_SIZE; | |
} | |
rcv_queue = kmalloc(rcv_queue_size, GFP_KERNEL); | |
if (!rcv_queue) return -ENOMEM; | |
if(!(snd_queue_size > 0 && snd_queue_size < 65536)){ | |
snd_queue_size = DEFAULT_SND_QUEUE_SIZE; | |
} | |
snd_queue = kmalloc(rcv_queue_size, GFP_KERNEL); | |
if (!snd_queue) return -ENOMEM; | |
/* デバイスドライバをカーネルに登録 */ | |
retval = mysfr9_register_dev(); | |
if( retval != 0 ) { | |
printk( KERN_ALERT "[%s] driver register failed.\n",MYSFR9_DEVNAME); | |
return retval; | |
} | |
printk( KERN_INFO "[%s] driver register sccessed.\n",MYSFR9_DEVNAME); | |
/* GPIO初期化 */ | |
mysfr9_gpio_setup(); | |
//for(i=0;i<10;i++){ | |
isnd=1; snd='I'; | |
ircv=0; rcv=0; | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
//} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがアンロードされた時の処理 | |
static void mysfr9_exit(void) | |
{ | |
int i; | |
dev_t devno; | |
del_timer_sync(&poll_timer); | |
/* キャラクタデバイスの登録解除 */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
cdev_del(&(mysfr9_cdev_array[i])); | |
devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
device_destroy(mysfr9_class, devno); | |
} | |
/* メジャー番号/マイナー番号を取り除く */ | |
devno = MKDEV(_mysfr9_major,_mysfr9_minor); | |
unregister_chrdev_region(devno, MYSFR9_NUM_DEVS); | |
/* デバイスノードを取り除く */ | |
class_destroy(mysfr9_class); | |
kfree(mysfr9_cdev_array); | |
/* queue */ | |
kfree(rcv_queue); | |
kfree(snd_queue); | |
printk( KERN_INFO "[%s] driver unregister sccessed.\n",MYSFR9_DEVNAME); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep) | |
{ | |
printk(KERN_INFO "[%s] Device open sccessed.\n",MYSFR9_DEVNAME); | |
printk( KERN_INFO "[%s] FON HZ = %d\n",MYSFR9_DEVNAME,HZ); | |
register_poll_timer(); | |
return 0; | |
} | |
static int mysfr9_release(struct inode *inode, struct file *filep) | |
{ | |
//まだSFRに送信できていないないものがあるので、待ってみる | |
while ( sq_tail - sq_head ) { | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
del_timer_sync(&poll_timer); | |
printk(KERN_INFO "[%s] Device release sccessed.\n",MYSFR9_DEVNAME); | |
return 0; | |
} | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos) | |
{ | |
unsigned char c; | |
if(count > 0) { | |
if(copy_from_user( &c, buf, sizeof(char) )) { | |
return -EFAULT; | |
} | |
while(ArrayEnqueue(snd_queue, c, &sq_head, &sq_tail, snd_queue_size) == 0){ | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
return sizeof(char); | |
} | |
return 0; | |
} | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos){ | |
unsigned char c; | |
//printk( KERN_INFO "RCV READ cont=%d, RCVQ=%d\n",count,(rq_tail - rq_head)); | |
if(count > 0) { | |
if((rq_tail - rq_head) == 0){ | |
printk( KERN_INFO "[%s] <read> Process %i (%s) going to sleep.\n", | |
MYSFR9_DEVNAME,current->pid,current->comm); | |
wait_event_interruptible(wq,wq_flg != 0); | |
wq_flg = 0; | |
printk( KERN_INFO "[%s] <read> Awoken Process %i (%s).\n", | |
MYSFR9_DEVNAME,current->pid,current->comm); | |
} | |
c = ArrayDequeue(rcv_queue, &rq_head, &rq_tail, rcv_queue_size); | |
if(copy_to_user( buf,&c, sizeof(char) )) { | |
return -EFAULT; | |
} | |
return sizeof(char); | |
} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//カーネルへの登録 | |
static int mysfr9_register_dev(void) | |
{ | |
int retval; | |
dev_t dev; | |
size_t size; | |
int i; | |
/* 空いているメジャー番号を使ってメジャー& | |
マイナー番号をカーネルに登録する */ | |
retval = alloc_chrdev_region( | |
&dev, /* 結果を格納するdev_t構造体 */ | |
MYSFR9_MAJOR, /* ベースマイナー番号 */ | |
MYSFR9_NUM_DEVS, /* デバイスの数 */ | |
MYSFR9_DEVNAME /* デバイスドライバの名前 */ | |
); | |
if( retval < 0 ) { | |
printk(KERN_ERR "[%s] alloc_chrdev_region failed.\n",MYSFR9_DEVNAME); | |
return retval; | |
} | |
_mysfr9_major = MAJOR(dev); | |
//printk(KERN_INFO "[%s] alloc_chrdev_region sccessed.\n",MYSFR9_DEVNAME); | |
/* デバイスクラスを作成する */ | |
mysfr9_class = class_create(THIS_MODULE,MYSFR9_DEVNAME); | |
if(IS_ERR(mysfr9_class)) | |
return PTR_ERR(mysfr9_class); | |
/* cdev構造体の用意 */ | |
size = sizeof(struct cdev) * MYSFR9_NUM_DEVS; | |
mysfr9_cdev_array = (struct cdev*)kmalloc(size, GFP_KERNEL); | |
/* デバイスの数だけキャラクタデバイスを登録する */ | |
/* ただしデバイスは1個しかない */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
dev_t devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
/* キャラクタデバイスとしてこのモジュールをカーネルに登録する */ | |
cdev_init(&(mysfr9_cdev_array[i]), &mysfr9_fops); | |
mysfr9_cdev_array[i].owner = THIS_MODULE; | |
if( cdev_add( &(mysfr9_cdev_array[i]), devno, 1) < 0 ) { | |
/* 登録に失敗した */ | |
printk(KERN_ERR "[%s] cdev_add failed minor = %d\n",MYSFR9_DEVNAME, _mysfr9_minor+i ); | |
} | |
else { | |
printk(KERN_INFO "[%s] cdev_add major = %d minor = %d.\n",MYSFR9_DEVNAME,_mysfr9_major,_mysfr9_minor+i); | |
/* デバイスノードの作成 */ | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) | |
device_create( | |
mysfr9_class, | |
NULL, | |
devno, | |
NULL, | |
MYSFR9_DEVNAME"%u",_mysfr9_minor+i | |
); | |
#else | |
device_create( | |
mysfr9_class, | |
NULL, | |
devno, | |
MYSFR9_DEVNAME"%u",_mysfr9_minor+i | |
); | |
#endif | |
} | |
} | |
return 0; | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////////// | |
//GPIO関係 | |
static void mysfr9_gpio_setup(void) | |
{ | |
//入出力の設定 | |
//RALINK_GPIO_SET_DIR: Bit 1 means output | |
//GPIONO_CLKOUT | |
//GPIONO_DATAOUT | |
//GPIONO_DATAIN | |
unsigned long tmp; | |
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR)); | |
tmp |= cpu_to_le32(RALINK_GPIO(GPIONO_CLKOUT)); | |
tmp |= cpu_to_le32(RALINK_GPIO(GPIONO_DATAOUT)); | |
tmp &= ~cpu_to_le32(RALINK_GPIO(GPIONO_DATAIN)); | |
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp; | |
printk(KERN_INFO "[%s] Setup GPIO ...%ld\n", MYSFR9_DEVNAME,tmp); | |
//CLKとDATAOUT | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(1); //debug用 200ns程度しか無いから | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,0); | |
} | |
static int mysfr9_gpio_getpin(int pin){ | |
volatile unsigned long arg,tmp; | |
arg = RALINK_GPIO(pin); | |
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA)); | |
tmp &= RALINK_GPIO(pin); | |
return (tmp > 0 ? 1 : 0); | |
} | |
static void mysfr9_gpio_setpin(int pin,uint32_t val){ | |
unsigned long arg; | |
arg = RALINK_GPIO(pin); | |
if(val > 0) | |
*(volatile u32 *)(RALINK_REG_PIOSET) = cpu_to_le32(arg); | |
else | |
*(volatile u32 *)(RALINK_REG_PIORESET) = cpu_to_le32(arg); | |
} | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv) | |
{ | |
volatile int i=0; | |
volatile unsigned char _rcv = 0; | |
volatile unsigned char _send = send; | |
unsigned int _ircv = 0; | |
unsigned int rcvbit=0; | |
//D0 データ有無ビット | |
//--DATA | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,isend); | |
udelay(1); //debug用 200ns程度しか無いから | |
//--CLK=H | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,0); | |
udelay(UDELAY); | |
//--データ有無ビット入力 | |
_ircv = mysfr9_gpio_getpin((volatile u32)GPIONO_DATAIN); | |
//--CLK=L | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(UDELAY); | |
//printf("データ有無\t送信:%d(%c)\t受信:%d(%c)\n",isend,((isend>0) ? 'X':'-'),_ircv,((_ircv>0) ? 'X':'-')); | |
for(i=0;i<8;i++){ | |
//D1-9 データビット | |
//--データ出力 | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,((v & 0x80) == 0x80 ? 1 : 0)); | |
//printf("%d",((v & 0x80) == 0x80 ? 1 : 0)); | |
if((_send & 0x80) == 0x80){ | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,1); | |
}else{ | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,0); | |
} | |
udelay(1); //debug用 200ns程度しか無いから | |
//--CLK=H | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,0); | |
udelay(UDELAY); | |
//--データ入力 | |
_rcv = _rcv << 1 ; | |
rcvbit = mysfr9_gpio_getpin((volatile u32)GPIONO_DATAIN); | |
if(rcvbit > 0){ | |
_rcv = _rcv | 0x01; | |
} | |
_send=_send<<1; | |
//--CLK=L | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(UDELAY); | |
} | |
*ircv = _ircv; | |
*rcv = _rcv; | |
//printf("----------------------------------------------------------------------------------------------------\n"); | |
/*printk(KERN_INFO "### Send:%c = %c(%#x) Rcv:%c = %c(%#x) \n", | |
((isend>0) ? 'O':'X'),((isend>0) ? send:' '),((isend>0) ? send:0x00), | |
((_ircv>0) ? 'O':'X'),((_ircv>0) ? _rcv:' '),((_ircv>0) ? _rcv:0x00));*/ | |
udelay(CHARDELAY); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//タイマー処理関係 | |
static void register_poll_timer(void) | |
{ | |
init_timer(&poll_timer); | |
//poll_timer.expires = jiffies + HZ; | |
poll_timer.expires = jiffies + (HZ * RCVPOLL) / 1000000; | |
/* 最短のTickより短い場合は最短のTickに */ | |
if( poll_timer.expires == 0 ) poll_timer.expires = jiffies + 1; | |
poll_timer.data = jiffies; | |
poll_timer.function = poll_timer_handler; | |
add_timer(&poll_timer); | |
} | |
static void poll_timer_handler(unsigned long data) | |
{ | |
do{ | |
if(sq_tail - sq_head){ | |
isnd = 1; | |
snd = ArrayDequeue(snd_queue, &sq_head, &sq_tail, snd_queue_size); | |
}else{ | |
isnd = 0; | |
} | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
if(ircv > 0){ | |
//printk( KERN_INFO "RCV %c \n",rcv); | |
if(ArrayEnqueue(rcv_queue, rcv, &rq_head, &rq_tail, rcv_queue_size) > 0){ | |
wq_flg = 1; | |
wake_up_interruptible(&wq); | |
}else{ | |
printk( KERN_ALERT "[%s] RCV Buffer Full.\n",MYSFR9_DEVNAME); | |
} | |
} | |
}while ((sq_tail - sq_head) || (ircv > 0)); | |
register_poll_timer(); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//Queue | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n) { | |
if (*head % n != (*tail + 1) % n) { | |
queue[(*tail)++ % n] = data; | |
return *tail - *head; | |
} else { | |
return 0; | |
} | |
} | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n) { | |
if (*head != *tail) { | |
return queue[(*head)++ % n]; | |
} else { | |
return (unsigned char)0; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//initの登録 | |
module_init(mysfr9_init); | |
//exitの登録 | |
module_exit(mysfr9_exit); | |
登録:
投稿 (Atom)