2
, 나는 무기한 다음과 같은 순서로 반복하고 싶습니다 : 시간 T에리눅스 커널 드라이버 : IRQ가 트리거 또는 리눅스 커널 드라이버에서 타임 아웃
- 을, 하드웨어 IRQ가 활성화되어 시간 T와 T 사이
- + "around 15ms, IRQ가 트리거되면 IRQ 콜백에 도달 할 수 있습니다. 나는 RT 커널을 사용하지 않기 때문에 주위를 말하고, 14 또는 16ms라면 괜찮습니다. IRQ 콜백에서 get cpu_clock (0)을 적어두고 wake_up_interruptible을 호출해야합니다. 타임 아웃을 삭제해야합니다. 전체 프로세스를 5ms 이내에 다시 시작해야합니다.
- T + "around"15ms로 IRQ가 트리거되지 않은 경우 다른 코드를 실행해야합니다. 그런 다음 IRQ를 비활성화해야합니다. 전체 프로세스를 5ms 이내에 다시 시작해야합니다.
따라서 T + "around"20ms로 최악의 경우 전체 프로세스를 다시 시작해야합니다.
IRQ가 18ms에서 물리적으로 트리거되는 경우 너무 나쁘다는 것을 유의하십시오. "나는 기차를 놓쳤습니다". 다음 순서에서 다른 하드웨어 트리거를 잡을 것입니다.
, 나는 다음과 같은 의사 코드 따라 뭔가하고 있던 테스트하는 동안 : 다음
INIT_DELAYED_WORK(&priv->work, driver_work);
INIT_DELAYED_WORK(&priv->timeout, driver_timeout);
request_irq(priv->irq, driver_interrupt, IRQF_TRIGGER_RISING, "my_irq", priv);
: 다음
queue_delayed_work(priv->workq, &priv->work, 0ms);
static void driver_work(struct work_struct *work) {
queue_delayed_work(priv->workq, &priv->timeout, 15ms);
priv->interruptCalled = 0;
enable_irq(priv->irq);
}
:
static irqreturn_t driver_interrupt(int irq, void *_priv) {
disable_irq_nosync(priv->irq);
priv->interruptCalled = 1;
cancel_delayed_work(&priv->timeout);
priv->stamp = cpu_clock(0);
wake_up_interruptible(&driver_wait);
queue_delayed_work(priv->workq, &priv->work, 5ms);
return IRQ_HANDLED;
}
과 :
static void driver_timeout(struct work_struct *work) {
if (priv->interruptCalled == 0) {
disable_irq_nosync(priv->irq);
//Do other small cleanup
queue_delayed_work(priv->workq, &priv->work, 5ms);
}
}
나는 강력하지만 간단한 드라이버를 작성하려고합니다. 적절한 구현입니까? 이 구현을 어떻게 향상시킬 수 있습니까?
cancel_delayed_work는 때때로 WARNING : at kernel/timer.c : 1061 del_timer_sync + 0x44/0x64()를 생성합니다. 어떻게 피할 수 있습니까? – gregoiregentil
이 경고는 WARN_ON (in_irq())에 해당합니다. 그것은 irq 컨텍스트에서 타이머를 삭제하는 것이 좋은 생각이 아닌 것 같습니다. – gregoiregentil
나는 "cancel_delayed_work (& priv-> timeout);"을 넣었습니다. "driver_work"의 첫 번째 행으로 더 이상 경고가 없으며, IRQ가 트리거 된 경우에도 시간 제한이 트리거되는 경우 priv-> interruptCalled가 '보호'하기 때문에 논리가 손상되지 않았다고 생각합니다. – gregoiregentil