[Armadillo:07919] Re: Armadillo-210で繰り返しのGPIO割り込み

Toru Ito email@hidden
2012年 2月 29日 (水) 14:45:11 JST


伊藤と申します。

ソースを見てみましたが、特に問題となるような箇所は見当たりませんでした。
gpioの設定も問題なくできているように思います。

プログラムの結果とcat /proc/interruptsの結果で割り込み回数が
一致しているので、特にプログラムの処理で問題ということもなさそうです。

ですので、実際にgpioの設定が正しく行われているかを
確認してみるとよいかと思います。

gpioの設定が正しく行われているかを確認するには、
Atmark Distに含まれる、gpioctrlを使うと簡単です。

gpioctrlで、以下のようにコマンドを入力すると現在のgpioの設定が
表示されます。

- gpioctrl 実行例
[armadillo ~]# gpioctrl --get=gpio0
GPIO No.   : 1 (GPIO0)
MODE       : 1 (MODE_INPUT)
VALUE      : 1 (HIGH)
INTERRUPT  : 1 (ENABLE)
INT-TYPE   : 3 (TYPE_RISING_EDGE)

他には、ファンクションジェネレータ以外の機器につないで、
動作を確認してみてもよいかもしれません。

(2012年02月24日 22:57), 埼広 村上 wrote:
> お世話になります。村上と申します。
> Armadillo-210で繰り返しのGPIO割り込みが思うように動作しません。
> 
> <やりたいこと>
> GPIO0にパルス信号を入力し、パルス数をカウントしたい。
> (C言語でプログラミングして実現したい)
> 
> <実現方法>
> 1.ioctl()関数を使用し、GPIO0を立ち上がりエッジで割り込みがかかるように設定。
> 2.ioctl()関数でINTRRUPT_WAITで割り込みを待ち、割り込みが発生する毎にカウンタをカウントアップ
> 3、カウンタに変化があれば、カンタ値を標準出力へ表示
> 
> <実行結果>
> ・実際のパルス数の倍近くをカウントする(100パルスに対し、192カウントなど)
> ・実際のパルスとの誤差が毎回一致しない
> ・1パルスに対し、1回割り込みがかかる時と2回割り込みがかかるときがある
> ・以下のコマンドでカーネル側の割込み回数を確認すると、プログラムの結果と一致する
> 
> [email@hidden (ttyAM1) ~]# cat /proc/interrupts
> CPU0
> 4: 332258 timer tick
> 19: 2 ethphyint
> 39: 3799 ep93xxethernet
> 52: 14 ttyAM0
> 54: 5320 ttyAM1
> 59: 1490 gpio
> Err: 0
> 
> 
> 入力するパルスはファンクションジェネレータで出力し、カウンタとオシロスコープで確認しました。
> 入力されるパルスはHiレベルが10msec以上、Lowレベル10msec以上と短いですが、
> パルス幅を伸ばしても現象は変わりませんでした。
> 立ち上がり、立ち下りエッジの波形もきれい(チャタリングなし)で50μsec以下です。
> 
> 明らかに1パルス(立ち上がりエッジは1回)しか出てないのに2回割り込みが発生します。
> 
> 何が悪いのか判らない状態で困っています。
> ソースを送りますのでご教授願います。
> 
> なお、割り込み発生後、GPIOの入力状態を監視し、状態変化後ioctl()関数で
> INTRRUPT_WAITで割り込みを待つと正しくカウントされましたが、
> このような強引な方法はとりたくありません。
> 
> 以下、ソースです。
> (#define PLS_GOOD 0→1に変更すると上記で書いた正しくカウントされる状態になります )
> 
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include <sys/types.h>
> #include <sys/ioctl.h>
> #include <signal.h>
> #include <pthread.h>
> #include <error.h>
> 
> #include <asm/arch/armadillo210_led.h>
> #include <asm/arch/armadillo210_gpio.h>
> 
> #define DEVICE_LED "/dev/led"
> #define DEVICE_GPIO "/dev/gpio"
> 
> #define PLS_GOOD 0
> 
> extern int errno;
> 
> 
> int myglobal;
> struct wait_param wait_param;
> static int exit_flg = 0;
> static unsigned long pls_cnt = 0;
> static int fd_gpio0;
> struct gpio_param gpio0;
> 
> //----------------------------------------------------------------------------------
> // LED制御関数
> //----------------------------------------------------------------------------------
> static int led_action( int id )
> {
> int fd;
> int ret;
> char buf[16];
> 
> fd = open(DEVICE_LED,O_RDWR);
> if(fd == -1){
> perror("ledctrl: " DEVICE_LED " open");
> return -1;
> }
> 
> if( id == (LED_RED_STATUS | LED_GREEN_STATUS) ){
> ret = ioctl(fd, id, buf);
> }else{
> ret = ioctl(fd, id);
> }
> if(ret == -1){
> perror("ledctrl: ioctl");
> close(fd);
> return -1;
> }
> 
> /*
> printf("RED(%s),GREEN(%s)\n",
> buf[0] & LED_RED ? "on":"off",
> buf[0] & LED_GREEN ? "on":"off"
> );
> */
> close(fd);
> return 0;
> }
> 
> //----------------------------------------------------------------------------------
> // 割り込み関数 Ctl+Cキー入力割り込み
> //----------------------------------------------------------------------------------
> static void int_ctl_c( int int_no )
> {
> exit_flg = 1;
> }
> 
> 
> //----------------------------------------------------------------------------------
> // スレッド関数 GPIO0割り込み入力
> //----------------------------------------------------------------------------------
> void *thread_gpio0( void *arg )
> {
> int ret;
> 
> while( exit_flg==0 ){
> wait_param.list = GPIO0;
> wait_param.timeout = 0;
> 
> ret = ioctl( fd_gpio0, INTERRUPT_WAIT, &wait_param );
> if( ret ){
> printf( "err!\r\n" );
> exit_flg = 1;
> break;
> }
> if( wait_param.list & GPIO0 ){
> pls_cnt++;
> }
> 
> #if PLS_GOOD //ここから
> do{
> ioctl( fd_gpio0, PARAM_GET, &gpio0 );
> }while( exit_flg == 0 && gpio0.data.i.value == 1 );
> //ここまでを外すと正しくカウントされない
> #endif
> }
> return NULL;
> }
> 
> 
> //----------------------------------------------------------------------------------
> // main関数
> //----------------------------------------------------------------------------------
> int main( int argc, char *argv[] )
> {
> pthread_t mythread; //スレッド用
> int retcode;
> unsigned long old_pcnt = 0;
> 
> //initialize
> memset( &gpio0, 0, sizeof(struct gpio_param) );
> memset( &wait_param, 0, sizeof(struct wait_param) );
> 
> //GPIO設定
> gpio0.no = GPIO0; //GPIO0
> gpio0.mode = MODE_INPUT; //入力
> gpio0.data.i.int_enable = 1; //割り込み有効
> gpio0.data.i.int_type = TYPE_RISING_EDGE; //立上りエッジで割り込み
> 
> fd_gpio0 = open( DEVICE_GPIO, O_RDWR );
> if( fd_gpio0 < 0 ){
> perror( "open error" );
> return -1;
> }
> ioctl( fd_gpio0, PARAM_SET, &gpio0 );
> 
> //signal()関数によるキー入力(Ctl+C)割り込みセット
> if( signal( SIGINT, int_ctl_c ) == SIG_ERR ){
> printf( "failed to set signal handler\n" );
> exit(1);
> }
> 
> //スレッド生成
> retcode = pthread_create (&mythread, NULL, thread_gpio0, (void *) "thread gpio0");
> if ( retcode != 0 ) printf( "create a failed %d\n", retcode );
> 
> //パルスカウント表示
> while( exit_flg == 0 ){
> if( old_pcnt != pls_cnt ){
> old_pcnt = pls_cnt;
> if( pls_cnt%2 ) led_action(LED_RED_ON);
> else led_action(LED_RED_OFF);
> printf( "PLS:%10lu\r\n", pls_cnt );
> }
> };
> 
> //スレッド開放
> if ( pthread_join ( mythread, NULL ) ) {
> printf("error joining thread.");
> abort();
> }
> 
> close( fd_gpio0 );
> printf( "\r\n" );
> 
> return 0;
> }
> 
> 
> 
> 
> 
> 
> _______________________________________________
> armadillo mailing list
> email@hidden
> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo
> 
> 


-- 
______________________________________

株式会社アットマークテクノ
開発部
伊藤 透(いとう とおる)

TEL: 011-207-6550 FAX: 011-207-6570
URL: http://www.atmark-techno.com/
E-mail: email@hidden
______________________________________




armadillo メーリングリストの案内