콘텐츠로 바로가기

now0930 일지

이런저런 생각

  • 홈
  • 비공개
  • 강좌
  • 잔여 작업 조회
  • 위치

5장 인터럽트 실습2

msi가 xhci 드라이버를 잘못 만들었는지 인터럽트를 너무 많이 발생시킨다.

왼쪽부터 36: 인터럽트 번호, 40080: cpu0 발생 횟수, 0: cpu 1, 2, 3 발생횟수, mmc1, mmc0 인터럽트 이름 정도? 모든 인터럽트가 충분하게 많이 일어난다.

pi@raspberrypi:~ $ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 ...
 36:      40080          0          0          0     GICv2 158 Level     mmc1, mmc0
 37:      11075          0          0          0     GICv2 144 Level     vc4 firmware kms
...
 51:        707          0          0          0     GICv2  66 Level     VCHIQ doorbell
 52:          0          0          0          0     GICv2 175 Level     PCIe PME, aerdrv
 53:       2927          0          0          0  Brcm_MSI 524288 Edge      xhci_hcd

인터럽트 53이 524,288번 발생했다. 53번 인터럽트가 있을 때 printk로 메세지를 출력하려 했으나, 횟수가 많아서인지 부팅을 할 수 없다. 횟수가 적은 31번 인터럽트를 보기로 했고, sd카드 읽고 쓰는 이벤트로 짐작된다. dump_stack을 보면 __sdhci_add_host가 request_threaded_irq로 등록한다.

31번으로 바꾸면 잘 출력이 되는데, 아마 msi가 드라이버를 이상하게 만들어서 그런가 싶다. 인터럽트를 한번 등록하고 말아야 하는데, xhci_run으로 계속 등록하는 느낌이 든다.

[    0.824266] [+][irq_debug] irq_num: 36, func: request_threaded_irq, line: 1888, caller: __sdhci_add_host+0xcc/0x354
[    0.827401] CPU: 0 PID: 32 Comm: kworker/0:1 Not tainted 4.19.127-v7l+ #91
[    0.830475] Hardware name: BCM2835
[    0.833547] Workqueue: events deferred_probe_work_func
[    0.836652] [<c0212dd8>] (unwind_backtrace) from [<c020d3ec>] (show_stack+0x20/0x24)
[    0.839740] [<c020d3ec>] (show_stack) from [<c09c01dc>] (dump_stack+0xd8/0x11c)
[    0.842903] [<c09c01dc>] (dump_stack) from [<c0285ac8>] (request_threaded_irq+0x19c/0x1a0)
[    0.846078] [<c0285ac8>] (request_threaded_irq) from [<c0843ba0>] (__sdhci_add_host+0xcc/0x354)
[    0.849277] [<c0843ba0>] (__sdhci_add_host) from [<c0844a60>] (sdhci_add_host+0x34/0x48)
[    0.852508] [<c0844a60>] (sdhci_add_host) from [<c084e8e0>] (sdhci_iproc_probe+0x11c/0x150)
[    0.855711] [<c084e8e0>] (sdhci_iproc_probe) from [<c071ad64>] (platform_drv_probe+0x58/0xa8)
[    0.858963] [<c071ad64>] (platform_drv_probe) from [<c0718f24>] (really_probe+0x20c/0x2cc)
[    0.862234] [<c0718f24>] (really_probe) from [<c07191b8>] (driver_probe_device+0x70/0x188)
[    0.865503] [<c07191b8>] (driver_probe_device) from [<c071947c>] (__device_attach_driver+0xac/0xd0)
[    0.868788] [<c071947c>] (__device_attach_driver) from [<c0716f2c>] (bus_for_each_drv+0x90/0xd4)
[    0.872033] [<c0716f2c>] (bus_for_each_drv) from [<c0718c90>] (__device_attach+0xe0/0x148)
[    0.875327] [<c0718c90>] (__device_attach) from [<c07194fc>] (device_initial_probe+0x1c/0x20)
[    0.878644] [<c07194fc>] (device_initial_probe) from [<c0717f50>] (bus_probe_device+0x94/0x9c)
[    0.881988] [<c0717f50>] (bus_probe_device) from [<c07183e0>] (deferred_probe_work_func+0x70/0x9c)
[    0.885363] [<c07183e0>] (deferred_probe_work_func) from [<c023da28>] (process_one_work+0x23c/0x518)
[    0.888693] [<c023da28>] (process_one_work) from [<c023eb00>] (worker_thread+0x60/0x5b8)
[    0.892070] [<c023eb00>] (worker_thread) from [<c02445a4>] (kthread+0x16c/0x174)
[    0.895476] [<c02445a4>] (kthread) from [<c02010ac>] (ret_from_fork+0x14/0x28)
[    0.898876] Exception stack(0xef3e3fb0 to 0xef3e3ff8)

__sdhci_add_host 함수를 찾아 책 예제를 추가했다. linux/drivers/mmc/host/sdhci.c에 정의되어 있다. 함수를 추가하면, 에러난다. 어디에 정의되어 있는지 모르는 듯 하다.

/*210611, interrupt_debug_irq_desc 추가  */
static void interrupt_debug_irq_desc(int irq_num)
{
    struct irqaction *action;
    struct irq_desc *desc;

    desc = irq_to_desc(irq_num);

    if (!desc ) {
        pr_err("invalid desc at %s line: %d\n", __func__, __LINE__);
        return;
    }    

    action = desc->action;

    if (!action ) {
        pr_err("invalid action at %s line:%d \n", __func__, __LINE__);
        return;
    }    

    printk("[+] irq_desc debug start \n");

    printk("irq num: %d name: %8s \n", action->irq , action->name);
    printk("dev_id:0x%x \n", (unsigned int)action->dev_id);

    if (action->handler) {
        printk("interrupt handler: %pF \n", action->handler);
    }    

    printk("[-] irq_desc debug end \n");
}
int __sdhci_add_host(struct sdhci_host *host)
{
    struct mmc_host *mmc = host->mmc;
    int ret; 

    /*   
     * Init tasklets.
     */
    tasklet_init(&host->finish_tasklet,
        sdhci_tasklet_finish, (unsigned long)host);

    timer_setup(&host->timer, sdhci_timeout_timer, 0);
    timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0);

    init_waitqueue_head(&host->buf_ready_int);

    sdhci_init(host, 0);

    ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
                   IRQF_SHARED, mmc_hostname(mmc), host);
    if (ret) {
        pr_err("%s: Failed to request IRQ %d: %d\n",
               mmc_hostname(mmc), host->irq, ret);
        goto untasklet;
    }
    //210611 irq 실습
    interrupt_debug_irq_desc(host->irq);
...

usb 드라이버는 irq_to_desc를 잘 사용했는데, sdhci가 에러내는게 이상하다. 헤더에 extern으로 다른 파일에서 쓸 수 있도록 했음을 알았고, 앞쪽에 통쨰로 복사하여 붙였다.

/*
 *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
 *
 *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * Thanks to the following companies for their support:
 *
 *     - JMicron (hardware and technical support)
 */
...
//210618. irq_to_desc 실습
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/radix-tree.h>
#include <linux/bitmap.h>
#include <linux/irqdomain.h>
#include <linux/sysfs.h>
#include "../kernel/irq/internals.h"

부팅 메세지를 보면 정상적으로 출력된다.

[    0.912941] [+] irq_desc debug start 
[    0.918446] irq num: 36 name:     mmc1 
[    0.921869] dev_id:0xef827b40 
[    0.925260] interrupt handler: bcm2835_mmc_irq+0x0/0x6e8 
[    0.928658] [-] irq_desc debug end 

이 글 공유하기:

  • Tweet
발행일 2021-06-18글쓴이 이대원
카테고리 생활코딩 태그 linux, raspberry, request_irq, 임베디드 리눅스

댓글 남기기응답 취소

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.

글 내비게이션

이전 글

화면 보호기 동작 방지 with PowerShell

다음 글

전기차 사용자가 전해주는 전기차 이야기

2025 6월
일 월 화 수 목 금 토
1234567
891011121314
15161718192021
22232425262728
2930  
5월    

최신 글

  • 자기 회로 정리 2025-06-22
  • common mode, differential mode 2025-05-11
  • signal conditioner, 신호 처리기 2025-05-10
  • strain gage 2025-05-09
  • 칼만 필터 2025-05-01

카테고리

  • 산업계측제어기술사
  • 삶 자국
    • 책과 영화
    • 투자
  • 생활코딩
    • LEGO
    • ROS
    • tensorflow
  • 전기기사
  • 피아노 악보

메타

  • 로그인
  • 엔트리 피드
  • 댓글 피드
  • WordPress.org

페이지

  • 소개
  • 잔여 작업 조회
    • 작업 추가
    • 작업의 사진 조회
    • 작업 수정 페이지
  • 사진
    • GPS 입력된 사진
    • 사진 조회
  • 위치
    • 하기 휴가 방문지
    • 해외 출장

태그

android bash c docker driver FSM gps java kernel LEGO linux mysql network program opcua open62541 plc programmers python raspberry reinforcementLearning ros state space system program tensorflow transfer function 경제 미국 민수 삼국지 세계사 실기 에너지 역사 유전자 일본 임베디드 리눅스 전기기사 조선 중국 채윤 코딩 테스트 통계 한국사 한국어

팔로우하세요

  • Facebook
now0930 일지
WordPress로 제작.