4

간단한 문자 드라이버를 작성하고 gpio 핀에 IRQ를 요청하고 이에 대한 처리기를 작성했습니다.장치 드라이버의 인터럽트 처리

err = request_irq (irq, irq_handler, IRQF_SHARED | IRQF_TRIGGER_RISING, INTERRUPT_DEVICE_NAME, raspi_gpio_devp);

정적 irqreturn_t irq_handler (int irq, void * arg);

지금부터 나는 이론을 알고 있습니다. 인터럽트가 발생하면 컨트롤러에 do_IRQ()를 호출하여 IDT를 확인하고이 줄에 대한 인터럽트 처리기를 호출합니다. 커널을 수행하는 방법을

또한 내가 인터럽트 핸들러는 모든 프로세스의 컨텍스트에서 실행되지 않는 것을 알고 인터럽트 핸들러가이 특정 장치 파일

에 대한 것을 알고있다. 그러나 처리기의 측면 범위 밖에서 선언 된 변수에 액세스한다고 가정 해 봅시다. 정적 전역 플래그 = 0, 처리기에서 인터럽트가 발생했음을 나타내는 flag = 1을 만듭니다. 해당 변수는 프로세스 컨텍스트에 있습니다. 그래서 어떤 핸들러 컨텍스트에서이 핸들러가 프로세스 컨텍스트의 변수를 수정하지 않는지 혼란 스럽습니다.

감사합니다.

답변

4

커널은이 특정 인터럽트가 특정 장치에 대한 것인지 알 수 없습니다.

매개 변수로 raspi_gpio_devp을 사용하여 irq_handler을 호출해야한다는 것만 알면됩니다. (예 : irq_handler(irq, raspi_gpio_devp)).

irq 라인이 공유되어있는 경우 장치에서 IRQ가 생성되었는지 확인해야합니다. 코드 :

int irq_handler(int irq, void* dev_id) { 
    struct raspi_gpio_dev *raspi_gpio_devp = (struct raspi_gpio_dev *) dev_id; 
    if (!my_gpio_irq_occured(raspi_gpio_devp)) 
     return IRQ_NONE; 
    /* do stuff here */ 
    return IRQ_HANDLED; 
} 

인터럽트 처리기는 인터럽트 컨텍스트에서 실행됩니다. 그러나 인터럽트 범위 외부에서 선언 된 정적 변수는에 액세스 할 수 있습니다.

일반적으로, 어떤 인터럽트 핸들러가하는 것은 :

  • 체크 인터럽트 상태
  • 하드웨어 정보를 검색하고 어딘가 (버퍼 예를 들어/FIFO)
  • wake_up() 커널 프로세스 대기를 보관 그 정보에 대해서

당신이 정말로 do에 확신을 갖고 인터럽트 처리를 원하지 않는다면, 읽을만한 가장 좋은 것은 무엇입니까? 프로세스는 커널을위한 것입니다.

이 다루는 훌륭한 책이 귀하의 질문에 응답하는 것입니다 Linux Kernel Developpement by Robert Love.

5

커널은 인터럽트와 관련된 장치를 알지 못합니다. 하나의 인터럽트가 여러 장치간에 공유 될 수 있습니다. 이전에는 이것이 아주 흔했습니다. 인터럽트 컨트롤러의 향상된 인터럽트 지원 및 메시지 신호 인터럽트의 도입으로 인해 점점 더 어려워지고 있습니다. 드라이버가 인터럽트가 장치에서 발생했는지 여부 (즉, 장치에 "서비스"가 필요한지 여부)를 결정해야합니다.

제공되는 "void * arg"를 통해 인터럽트 처리기에 컨텍스트를 제공 할 수 있습니다. 프로세스가 매달린 포인터를 남겨 두거나 (즉, 다른 목적을 위해 해방되거나 가능하면 재 할당 된 메모리를 참조하는) 프로세스가 종료 될 수 있으므로 프로세스 별 컨텍스트가 될 수 없습니다.

전역 변수는 "처리 중"이 아닙니다. 모든 컨텍스트에 있거나 원하는 경우 컨텍스트가 없습니다. "처리 과정에 있지 않다"는 말은 몇 가지 의미입니다 : (1) 당신은 어떤 프로세스를 잠들게 할 것이기 때문에 차단하거나 잠을 자지 못합니다. (2) 사용자 공간 가상 주소 (그 참조는 무엇을 가리 키니까?), (3) "현재 작업"에 대한 참조를 만들 수 없습니다 (하나 또는 그 주소가 알려지지 않았기 때문에).

일반적으로 드라이버 인터럽트 처리기는 드라이버의 프로세스 컨텍스트 끝에서 데이터를 전송할 수있는 "드라이버 전역"데이터 영역으로 데이터를 밀어 넣거나 끌어옵니다.

+0

방법 알려진 IRQ 값으로 IRQ 인수를 비교 ... 그 인터럽트가 내 장치입니다 결정하기 위해 나는 코드를합니까? 그래서 내가 말하고있는이 전역 변수는 예를 들어 : 인터럽트가 발생했음을 나타내는 int 플래그는 void * arg와 같이 핸들러에 전달되어야하는 장치 구조 당 측면에 있어야합니다. – Haswell

+1

일반적으로 장치에 문의하십시오. 장치가 인터럽트를 생성했는지 여부를 알 수없는 경우 인터럽트 회선이 공유되지 않는지 확인해야합니다 (IRQF_SHARED를 생략). –

+0

"void * arg"는 사용자가 원하는대로 사용할 수 있습니다. 일반적으로 장치 특정 데이터 구조를 가리 킵니다 (종종 하나 이상의 장치 인스턴스를 가질 수 있기 때문에). 전역 데이터를 전역/정적 변수에 보관할 수도 있습니다. –

0

입니다 : -

커널이 인터럽트 핸들러가이 특정> 장치 파일에 대한 것을 알고 않는 방법?

  1. 각각의 시스템 - 온 - 칩 문서는 서로 다른 인터럽트 라인에 연결된 다른 장치에 인터럽트 번호를 언급 할 것이다.

  2. 장치 드라이버의 인스턴스화를 위해 장치 트리 항목에서 동일한 인터럽트 번호를 언급해야합니다.

  3. 장치 드라이버의 일반적인 조사 기능은 장치 트리 데이터 구조를 구문 분석하고 IRQ 번호를 읽고 register_irq 함수를 사용하여 처리기를 등록합니다.

  4. 단일 IRQ 번호/라인에 여러 장치가있는 경우 IRQ 처리기 내에서 구분하기 위해 IRQ 상태 레지스터 (동일한 VM 공간에 매핑 된 경우 다른 장치 용)를 사용할 수 있습니다.

에서 자세한 내용을 읽어 보시기 바랍니다 내 blog