
도와주세요!!
글 수 15,339
2002.08.24 12:12:29 (*.186.48.184)
8330
안녕하세요...
지노님이 답변을 잘 해주셔서 질문에 답이 되셨는지???
아울러 부가 설명을 드립니다..
#define GPIO_OUTPUT_MASK
이것은 GPIO 출력에 관련된 매크로를 정의 한 것입니다...
즉, GPIO 28개의 신호 중 8~15까지의 신호를 1로 세트한 것이지요...
xxxxxxxxxxxxxx00000000xxxxxxx
==> xxxxxxxxxxxxxx11111111xxxxxxx
: : 그리고... 세미나 시간에 보여줬던 test를 저도 해보기 위해서....보드 를 제작
: : 해서 시험을 해 봤는데....interrupt test를 해봤는데...좀 이상합니다.. 님
: : 의 소스대로 라면 어떤 결과가 나와야 옳은지요....
//***********************************************************
test.c
//***********************************************************
case '5':
printf( "
" );
printf( "# SW4를 눌러 주세요..
" );
pData.Cmd = 1;
pData.Data = 0xFF;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED ON
" );
pData.Cmd = 1;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED OFF
" );
pData.Cmd = 1;
pData.Data = 0xAA;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED ON
" );
pData.Cmd = 2;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
if( (pData.Data & MASK_GPIO_LED_1) != MASK_GPIO_LED_1 )
printf( "**** GPIO LED_1 [ ON ]..
" );
else
printf( "**** GPIO LED_1 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_2) != MASK_GPIO_LED_2 )
printf( "**** GPIO LED_2 [ ON ]..
" );
else
printf( "**** GPIO LED_2 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_3) != MASK_GPIO_LED_3 )
printf( "**** GPIO LED_3 [ ON ]..
" );
else
printf( "**** GPIO LED-3 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_4) != MASK_GPIO_LED_4 )
printf( "**** GPIO LED_4 [ ON ]..
" );
else
printf( "**** GPIO LED_4 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_5) != MASK_GPIO_LED_5 )
printf( "**** GPIO LED_5 [ ON ]..
" );
else
printf( "**** GPIO LED_5 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_6) != MASK_GPIO_LED_6 )
printf( "**** GPIO LED_6 [ ON ]..
" );
else
printf( "**** GPIO LED_6 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_7) != MASK_GPIO_LED_7 )
printf( "**** GPIO LED_7 [ ON ]..
" );
else
printf( "**** GPIO LED_7 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_8) != MASK_GPIO_LED_8 )
printf( "**** GPIO LED_8 [ ON ]..
" );
else
printf( "**** GPIO LED_8 [ OFF ]..
" );
printf( "
# TEST가 종료 되었습니다...
" );
GPIO_CommandList(); // 명령 목록을 보여준다.
break;
//***********************************************************
이 부분이 인터럽트 관련 TEST를 위한 소스입니다..
프로그램을 실행 시켜,
command? 에서 5번을 선택하시면,
처음으로
pData.Cmd = 1;
pData.Data = 0xFF;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 ON하게 됩니다..
두번째는
pData.Cmd = 1;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 OFF하게 됩니다..
세번째는
pData.Cmd = 1;
pData.Data = 0xAA;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 ON하게 됩니다..
네번째는
pData.Cmd = 2;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED의 상태를 읽어오게 됩니다..
그럼, 여기서 디바이스 드라이브인 gpio.c를 살펴 보겠습니다..
//***********************************************************
gpio.c
//***********************************************************
//-----------------------------------------------------------------------
-
// 설 명 : 모듈 생성
// 매 계 : 없음
// 반 환 : 없음
// 주 의 :
// 참 조 :
// include/asm/arch/irqs.h 에 GPIO핀 관련 정의가 있음..
//
// register_chrdev( 장치 메이저 번호,
// 장치 명,
// 장치 접근 함수 구조체 주소 );
//--------------------------------------------------------------------
int init_module( void )
{
// GPIO_IRQ_21 INTERRUPT
// 인터럽트 등록
if( !request_irq( IRQ_GPIO21, gpio_interrupt, SA_INTERRUPT, INT_NAME, NULL) )
{
#ifdef SA1100_IRQ_TO_GPIO
set_GPIO_IRQ_edge ( 1 << SA1100_IRQ_TO_GPIO(GPIO_IRQ_21), GPIO_RISING_EDGE );
#else
if ( 11 > GPIO_IRQ_21 )
set_GPIO_IRQ_edge ( 1 << GPIO_IRQ_21, GPIO_RISING_EDGE );
else
set_GPIO_IRQ_edge ( 1 << GPIO_11_27_IRQ(IRQ_GPIO21), GPIO_RISING_EDGE );
#endif
enable_irq (IRQ_GPIO21); // 인터럽트의 허용
//***********************************************************
<======
insmod 하여 디바이스 적재시 인터럽트를 등록합니다.
//---------------------------------------------------------------------
// 설 명 : ioctl interrupt Test
// 매 계 : 없음
// 반 환 : 없음
// 주 의 :
//---------------------------------------------------------------------
int gpio_int_test ( GPIO_CmdData *pData )
{
GPIO_CmdData *pGPIOData;
// 프로세서를 잠 재운다...
interruptible_sleep_on(&gpio_wait);
if( (pGPIOData = kmalloc(sizeof(GPIO_CmdData), GFP_KERNEL)) == NULL)
return -ENOMEM;
copy_from_user( pGPIOData, pData, sizeof(GPIO_CmdData) );
switch(pGPIOData->Cmd)
{
case 1:
gpio_outb( pGPIOData->Data );
break;
case 2:
pGPIOData->Cmd = 0;
// 스위치 입력값을 읽어 온다...
pGPIOData->Data = ( unsigned long )gpio_inc();
copy_to_user( pData, pGPIOData, sizeof(GPIO_CmdData) );
break;
}
kfree(pGPIOData);
return 0;
}
//***********************************************************
<======
프로세스를 잠재웁니다.. 인터럽트가 발생하여 깨우기 전까지 잠들어 있습니다.,,
//-----------------------------------------------------------------------
// 설명 : GPIO_IRQ_21에 대한 인터럽트를 처리한다.
// 매계 : 없음
// 반환 : 정상이면 0을 반환한다.
// 주의 : 없음
//-----------------------------------------------------------------------
void gpio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
save_flags_cli(flags);
cli(); // clear interrupt flag(인터럽트 플래그를 제거함)
// 잠들어 있던 프로세스들을 깨운다.
wake_up_interruptible (&gpio_wait);
restore_flags(flags);
}
//***********************************************************
<======
SW4를 눌러 인터럽트가 발생하면, 프로세스가 깨어나고,
위의 gpio_int_test()함수의 잠든 프로세스를 깨워 interruptible_sleep_on(&gpio_wait);
다음 문장을 수행하게 됩니다.
****
인터럽트가 재대로 동작하는가를 알기 위해서는 다음을 수행 하시면 됩니다..
1. # insmod gpio.o <<=== 모듈 적재
2. # ./test & <<=== test 프로그램 백 그라운드로 실행
3. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 0 SW_INT
47: 121 cs89x0
Err: 0
<<=== 여기서 보시면, SW_INT의 인터럽트가 생성되고, 한번도 인터럽트가
발생하지 않았습니다.
4. SW4 스위치를 한번 누른다.
5. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 1 SW_INT
47: 121 cs89x0
Err: 0
6. SW4 스위치를 한번 누른다.
7. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 2 SW_INT
47: 121 cs89x0
Err: 0
<<=== 여기서 보시면, SW_INT의 인터럽트가 생성되고, 스위치를 눌렀어 인터럽트를
확인하면 인터럽트의 숫자가 증가 하는것을 볼 수 있습니다.
물론 스위치의 체터링문제로 여러번 인터럽트가 발생할 수도 있음...
어째든..SW4를 눌렀을때 이 부분의 숫자가 증가 하여야 합니다..
만일, 42: x SW_INT라는 것이 존재하지 않으면, 인터럽트 등록이 재대로 되지
않은 것입니다...
그럼 좋은 하루 되세요...
지노 wrote..
: |는 OR 연산자 이구요.
: 는 여러줄에 써도 한줄처럼 인식하게 하는거예요.
:
: 인터럽트란 말은 버튼이 눌렸을 경우에 인터럽트 루틴 irq등록하는데서 인 터 럽트 핸들러를 써주 는데 그부분이 수행되는곳일텐데.
:
: 그함수부분에서 원하시는 작업을 하시면 됩니다.
:
: 그럼 허접답변입니다. ^^;
:
: 야옹이 wrote..
: :
: : gpio를 이용한 간단한 프로그램을 만들기위해서...지금 지난번 세미나 때 장형
: : 기님이 사용했던 프로그램을 소스를 분석하고 있는중입니다......
: : 근데 궁금한게 있어서...
: : gpio.h에서 보면.
: : #define GPIO_OUTPUT_MASK ( MASK_GPIO_LED_1
: :
: : | MASK_GPIO_LED_2
: :
: : | MASK_GPIO_LED_3
: :
: : | MASK_GPIO_LED_4
: :
: : | MASK_GPIO_LED_5
: :
: : | MASK_GPIO_LED_6
: :
: : | MASK_GPIO_LED_7
: :
: : | MASK_GPIO_LED_8 )
: : 있는데요....GPIO_OUTPUT_MASK 를 정의한 것인줄은 알겠는데.... 어떻 게 의미
: : 를 파악해야 할 지 모르겠습니다...."|" 와 기호의 의미를 모르겠습니 다..
: : 그리고... 세미나 시간에 보여줬던 test를 저도 해보기 위해서....보드 를 제작
: : 해서 시험을 해 봤는데....interrupt test를 해봤는데...좀 이상합니다.. 님
: : 의 소스대로 라면 어떤 결과가 나와야 옳은지요....
: :
: : 바쁘신데 노력해 주셔서 무지 감사하고요..성의있는 답변 부탁드립니
다.....
지노님이 답변을 잘 해주셔서 질문에 답이 되셨는지???
아울러 부가 설명을 드립니다..
#define GPIO_OUTPUT_MASK
이것은 GPIO 출력에 관련된 매크로를 정의 한 것입니다...
즉, GPIO 28개의 신호 중 8~15까지의 신호를 1로 세트한 것이지요...
xxxxxxxxxxxxxx00000000xxxxxxx
==> xxxxxxxxxxxxxx11111111xxxxxxx
: : 그리고... 세미나 시간에 보여줬던 test를 저도 해보기 위해서....보드 를 제작
: : 해서 시험을 해 봤는데....interrupt test를 해봤는데...좀 이상합니다.. 님
: : 의 소스대로 라면 어떤 결과가 나와야 옳은지요....
//***********************************************************
test.c
//***********************************************************
case '5':
printf( "
" );
printf( "# SW4를 눌러 주세요..
" );
pData.Cmd = 1;
pData.Data = 0xFF;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED ON
" );
pData.Cmd = 1;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED OFF
" );
pData.Cmd = 1;
pData.Data = 0xAA;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
printf( "**** LED ON
" );
pData.Cmd = 2;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
if( (pData.Data & MASK_GPIO_LED_1) != MASK_GPIO_LED_1 )
printf( "**** GPIO LED_1 [ ON ]..
" );
else
printf( "**** GPIO LED_1 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_2) != MASK_GPIO_LED_2 )
printf( "**** GPIO LED_2 [ ON ]..
" );
else
printf( "**** GPIO LED_2 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_3) != MASK_GPIO_LED_3 )
printf( "**** GPIO LED_3 [ ON ]..
" );
else
printf( "**** GPIO LED-3 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_4) != MASK_GPIO_LED_4 )
printf( "**** GPIO LED_4 [ ON ]..
" );
else
printf( "**** GPIO LED_4 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_5) != MASK_GPIO_LED_5 )
printf( "**** GPIO LED_5 [ ON ]..
" );
else
printf( "**** GPIO LED_5 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_6) != MASK_GPIO_LED_6 )
printf( "**** GPIO LED_6 [ ON ]..
" );
else
printf( "**** GPIO LED_6 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_7) != MASK_GPIO_LED_7 )
printf( "**** GPIO LED_7 [ ON ]..
" );
else
printf( "**** GPIO LED_7 [ OFF ]..
" );
if( (pData.Data & MASK_GPIO_LED_8) != MASK_GPIO_LED_8 )
printf( "**** GPIO LED_8 [ ON ]..
" );
else
printf( "**** GPIO LED_8 [ OFF ]..
" );
printf( "
# TEST가 종료 되었습니다...
" );
GPIO_CommandList(); // 명령 목록을 보여준다.
break;
//***********************************************************
이 부분이 인터럽트 관련 TEST를 위한 소스입니다..
프로그램을 실행 시켜,
command? 에서 5번을 선택하시면,
처음으로
pData.Cmd = 1;
pData.Data = 0xFF;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 ON하게 됩니다..
두번째는
pData.Cmd = 1;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 OFF하게 됩니다..
세번째는
pData.Cmd = 1;
pData.Data = 0xAA;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED를 ON하게 됩니다..
네번째는
pData.Cmd = 2;
pData.Data = 0x00;
ioctl( dev, IOCTL_GPIO_INT_TEST, &pData );
이 ioctl함수를 호출하게 되고, 이 함수는 프로세스를 잠들게 합니다..
이것을 SW4번을 한번 누르면 인터럽트를 발생시켜, 프로세스를 깨우고,
LED의 상태를 읽어오게 됩니다..
그럼, 여기서 디바이스 드라이브인 gpio.c를 살펴 보겠습니다..
//***********************************************************
gpio.c
//***********************************************************
//-----------------------------------------------------------------------
-
// 설 명 : 모듈 생성
// 매 계 : 없음
// 반 환 : 없음
// 주 의 :
// 참 조 :
// include/asm/arch/irqs.h 에 GPIO핀 관련 정의가 있음..
//
// register_chrdev( 장치 메이저 번호,
// 장치 명,
// 장치 접근 함수 구조체 주소 );
//--------------------------------------------------------------------
int init_module( void )
{
// GPIO_IRQ_21 INTERRUPT
// 인터럽트 등록
if( !request_irq( IRQ_GPIO21, gpio_interrupt, SA_INTERRUPT, INT_NAME, NULL) )
{
#ifdef SA1100_IRQ_TO_GPIO
set_GPIO_IRQ_edge ( 1 << SA1100_IRQ_TO_GPIO(GPIO_IRQ_21), GPIO_RISING_EDGE );
#else
if ( 11 > GPIO_IRQ_21 )
set_GPIO_IRQ_edge ( 1 << GPIO_IRQ_21, GPIO_RISING_EDGE );
else
set_GPIO_IRQ_edge ( 1 << GPIO_11_27_IRQ(IRQ_GPIO21), GPIO_RISING_EDGE );
#endif
enable_irq (IRQ_GPIO21); // 인터럽트의 허용
//***********************************************************
<======
insmod 하여 디바이스 적재시 인터럽트를 등록합니다.
//---------------------------------------------------------------------
// 설 명 : ioctl interrupt Test
// 매 계 : 없음
// 반 환 : 없음
// 주 의 :
//---------------------------------------------------------------------
int gpio_int_test ( GPIO_CmdData *pData )
{
GPIO_CmdData *pGPIOData;
// 프로세서를 잠 재운다...
interruptible_sleep_on(&gpio_wait);
if( (pGPIOData = kmalloc(sizeof(GPIO_CmdData), GFP_KERNEL)) == NULL)
return -ENOMEM;
copy_from_user( pGPIOData, pData, sizeof(GPIO_CmdData) );
switch(pGPIOData->Cmd)
{
case 1:
gpio_outb( pGPIOData->Data );
break;
case 2:
pGPIOData->Cmd = 0;
// 스위치 입력값을 읽어 온다...
pGPIOData->Data = ( unsigned long )gpio_inc();
copy_to_user( pData, pGPIOData, sizeof(GPIO_CmdData) );
break;
}
kfree(pGPIOData);
return 0;
}
//***********************************************************
<======
프로세스를 잠재웁니다.. 인터럽트가 발생하여 깨우기 전까지 잠들어 있습니다.,,
//-----------------------------------------------------------------------
// 설명 : GPIO_IRQ_21에 대한 인터럽트를 처리한다.
// 매계 : 없음
// 반환 : 정상이면 0을 반환한다.
// 주의 : 없음
//-----------------------------------------------------------------------
void gpio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
save_flags_cli(flags);
cli(); // clear interrupt flag(인터럽트 플래그를 제거함)
// 잠들어 있던 프로세스들을 깨운다.
wake_up_interruptible (&gpio_wait);
restore_flags(flags);
}
//***********************************************************
<======
SW4를 눌러 인터럽트가 발생하면, 프로세스가 깨어나고,
위의 gpio_int_test()함수의 잠든 프로세스를 깨워 interruptible_sleep_on(&gpio_wait);
다음 문장을 수행하게 됩니다.
****
인터럽트가 재대로 동작하는가를 알기 위해서는 다음을 수행 하시면 됩니다..
1. # insmod gpio.o <<=== 모듈 적재
2. # ./test & <<=== test 프로그램 백 그라운드로 실행
3. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 0 SW_INT
47: 121 cs89x0
Err: 0
<<=== 여기서 보시면, SW_INT의 인터럽트가 생성되고, 한번도 인터럽트가
발생하지 않았습니다.
4. SW4 스위치를 한번 누른다.
5. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 1 SW_INT
47: 121 cs89x0
Err: 0
6. SW4 스위치를 한번 누른다.
7. # cat /proc/interuppt
11: 121 GPIO 11-27
17: 498 serial_sa1100
26: 5303 timer
42: 2 SW_INT
47: 121 cs89x0
Err: 0
<<=== 여기서 보시면, SW_INT의 인터럽트가 생성되고, 스위치를 눌렀어 인터럽트를
확인하면 인터럽트의 숫자가 증가 하는것을 볼 수 있습니다.
물론 스위치의 체터링문제로 여러번 인터럽트가 발생할 수도 있음...
어째든..SW4를 눌렀을때 이 부분의 숫자가 증가 하여야 합니다..
만일, 42: x SW_INT라는 것이 존재하지 않으면, 인터럽트 등록이 재대로 되지
않은 것입니다...
그럼 좋은 하루 되세요...
지노 wrote..
: |는 OR 연산자 이구요.
: 는 여러줄에 써도 한줄처럼 인식하게 하는거예요.
:
: 인터럽트란 말은 버튼이 눌렸을 경우에 인터럽트 루틴 irq등록하는데서 인 터 럽트 핸들러를 써주 는데 그부분이 수행되는곳일텐데.
:
: 그함수부분에서 원하시는 작업을 하시면 됩니다.
:
: 그럼 허접답변입니다. ^^;
:
: 야옹이 wrote..
: :
: : gpio를 이용한 간단한 프로그램을 만들기위해서...지금 지난번 세미나 때 장형
: : 기님이 사용했던 프로그램을 소스를 분석하고 있는중입니다......
: : 근데 궁금한게 있어서...
: : gpio.h에서 보면.
: : #define GPIO_OUTPUT_MASK ( MASK_GPIO_LED_1
: :
: : | MASK_GPIO_LED_2
: :
: : | MASK_GPIO_LED_3
: :
: : | MASK_GPIO_LED_4
: :
: : | MASK_GPIO_LED_5
: :
: : | MASK_GPIO_LED_6
: :
: : | MASK_GPIO_LED_7
: :
: : | MASK_GPIO_LED_8 )
: : 있는데요....GPIO_OUTPUT_MASK 를 정의한 것인줄은 알겠는데.... 어떻 게 의미
: : 를 파악해야 할 지 모르겠습니다...."|" 와 기호의 의미를 모르겠습니 다..
: : 그리고... 세미나 시간에 보여줬던 test를 저도 해보기 위해서....보드 를 제작
: : 해서 시험을 해 봤는데....interrupt test를 해봤는데...좀 이상합니다.. 님
: : 의 소스대로 라면 어떤 결과가 나와야 옳은지요....
: :
: : 바쁘신데 노력해 주셔서 무지 감사하고요..성의있는 답변 부탁드립니
다.....