콘텐츠로 바로가기

now0930 일지

이런저런 생각

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

linux driver, softIrq 실습

인터럽트 후반부를 처리하는 soft irq를 배웠다. 자 이제 사용해 보자. 불행히도 요즘은 일반화된 tasklet을 사용하고 low level인 soft irq를 사용하지 않는다고 한다. 그래도 아래 사이트에서 강제로?? 사용할 수 있는 방법을 찾았다. 실습하고 쓰지 말아야 한다. 드라이버를 로딩 후 언로딩하면 시스템이 죽어버린다.

https://embetronicx.com/tutorials/linux/device-drivers/softirq-in-linux-kernel/

요점은 kernel에서 export_symbol로 raise_softirq, open_softiq 등 3개 함수를 내보내 사용할 수 있게한다. interrrupt.h에 사용자 정의 softirq를 설정해야 한다. 기존 등록된 이벤를 사용하면 시스템이 죽는다.

https://stackoverflow.com/questions/39691131/undefined-functions-while-compiling-linux-kernel-module

튜토리얼이 시스템에 장치를 설치하여 인터럽트를 하는 방법으로 했다. 딱히 장치를 추가할 이유가 없는데 왜 했는지 모르겠으나, 아래 사이트에서 간략한 규칙을 찾았다.

https://temp123.tistory.com/16?category=877924

https://hyeyoo.com/85

인터럽트를 만들어야 확인할 수 있다. 리눅스가 제공하는 명령어로 gpio를 쉽게 컨트롤 할 수 있다. 당연하게도 출력으로 설정하고 값을 써야한다.

https://infoarts.tistory.com/21

돌고 돌아 장치를 추가하고, 인터럽트를 만들어 softirq를 실행했다. tutorial site에 잘 설명되어 있다. 나중에 디바이스 read, write를 인터럽트로 설정할 수도 있을 듯 하다.

i@raspberrypi:~/RaspberryDebug/my_driver $ cat Makefile
obj-m := my_driver.o
#obj-m := sample_driver.o
all:
	make -C /lib/modules/`uname -r`/build M=`pwd` modules
clean:
	rm *.o *.ko *.mod  *.mod.c *.mod.o
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>     //GPIO

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

#define GPIO_10_OUT (10)
unsigned int GPIO_irqNumber;

//softirq handler
static void pesudo_interrupt_softirq_handler(struct softirq_action *action)
{
	pr_info("pesudo interreupt occured\n");
}


static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
	/* Raise the softirq */
	raise_softirq(TEST_SOFT_IRQ);
	return IRQ_HANDLED;

}


//device driver \uc791\uc131 \ubd80\ubd84.
/*************\ub4dc\ub77c\uc774\ubc84 \ud568\uc218 ******************/
static int mydriver_open(struct inode *inode, struct file *file);
static int mydriver_release(struct inode *inode, struct file *file);
static ssize_t mydriver_read(struct file *flip,
		char *buf, size_t len, loff_t *off);
static ssize_t mydriver_write(struct file *flip,
		const char *buf, size_t len, loff_t *off);
/********************************************/


//file operation structure

static struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.read = mydriver_read,
	.write = mydriver_write,
	.open = mydriver_open,
	.release = mydriver_release,
};

static int mydriver_open(struct inode *inode, struct file *file)
{
	pr_info("Deviced file was opend.\n");
	return 0;

}

static int mydriver_release(struct inode *inode, struct file *file)
{
	return 0;
}


static int mydriver_read(struct file *flip,
		char *buf, size_t len, loff_t *off)
{

	return 0;
}

static int mydriver_write(struct file *flip,
		const char *buf, size_t len, loff_t *off)
{
	return 0;

}

dev_t dev = 0;
static struct cdev my_cdev;
static struct class *dev_class;

static int __init init_hw(void)
{
	//\ub514\ubc14\uc774\uc2a4 \ub4f1\ub85d
	if(( alloc_chrdev_region(&dev, 0, 1, "test_device") < 0))
	{
		pr_err("[!]character device was not allocated\n");
		goto r_unreg;

	}
	pr_info("[=]%d-%d, was allocated\n", MAJOR(dev), MINOR(dev));


	//\ucd08\uae30\ud654
	cdev_init(&my_cdev, &fops);
	pr_info("[=]driver was initialized\n");
	

	//\uc2dc\uc2a4\ud15c\uc5d0 \ucd94\uac00
	if((cdev_add(&my_cdev, dev, 1)) < 0)
	{
		pr_err("[!]cannot add device to kernel\n");
		goto r_del;

	}


	//class \ub9cc\ub4e6.
	if((dev_class=class_create(THIS_MODULE, "my_class")) == NULL)
	{
		pr_err("[!]cannot add class\n");
		goto r_class;
	}


	if((device_create(dev_class, NULL, dev, NULL, "my_device")) == NULL)
	{

		pr_err("[!]cannot create device\n");
		goto r_device;
	}
	
	//gpio 10\ubc88\uc744 \uc0ac\uc6a9.
	//export\ud558\uc5ec \uac04\ub2e8\ud788 \uc0ac\uc6a9.
	//\uc785\ub825\uc740 \uac12\uc744 \uc368 \ub123\uc744 \uc218 \uc5c6\uc74c. \ucd9c\ub825\uc73c\ub85c \uc124\uc815.
	GPIO_irqNumber = gpio_to_irq(GPIO_10_OUT);
	pr_info("[=]irq %d was assinged\n",GPIO_irqNumber);
	
	//interrupt \ub4f1\ub85d \ud544\uc694
	if (request_irq(GPIO_irqNumber,
				(void*)gpio_irq_handler,
				IRQF_TRIGGER_RISING,
				"my_device",
				NULL))
	{
		pr_err("[!]my_device: cannot register IRQ\n");
		goto r_gpio;
	}
	
	open_softirq(TEST_SOFT_IRQ, pesudo_interrupt_softirq_handler);
	pr_info("[=]module was installed\n");
	return 0;
r_gpio:
	gpio_free(GPIO_10_OUT);
r_device:
	device_destroy(dev_class,dev);

r_class:
	class_destroy(dev_class);
r_del:
	cdev_del(&my_cdev);
r_unreg:
	unregister_chrdev_region(dev,1);

return -1;
}

static void __exit exit_hw(void) {
	device_destroy(dev_class,dev);
	class_destroy(dev_class);
	cdev_del(&my_cdev);
	unregister_chrdev_region(dev,1);
	printk(KERN_INFO "module was removed\n");
}


module_init(init_hw);
module_exit(exit_hw);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eunseong Park (esp-ark.com)");
MODULE_DESCRIPTION("Hello, world!");
pi@raspberrypi:~/RaspberryDebug/my_driver $ echo "10" > /sys/class/gpio/export
pi@raspberrypi:~/RaspberryDebug/my_driver $ echo "out" > /sys/class/gpio/gpio10/direction 
pi@raspberrypi:~/RaspberryDebug/my_driver $ gpio read 10
1
pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
[  281.496011] my_driver: loading out-of-tree module taints kernel.
[  281.496218] my_driver: no symbol version for raise_softirq
[  281.496487] [=]236-0, was allocated
[  281.496492] [=]driver was initialized
[  281.496679] [=]irq 54 was assinged
[  281.496713] [=]module was installed
[  439.643072] pesudo interreupt occured
pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
[   21.513881] input: Keyboard K480 Consumer Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input5
[   21.514017] input: Keyboard K480 System Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input6
[   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
[  281.496011] my_driver: loading out-of-tree module taints kernel.
[  281.496218] my_driver: no symbol version for raise_softirq
[  281.496487] [=]236-0, was allocated
[  281.496492] [=]driver was initialized
[  281.496679] [=]irq 54 was assinged
[  281.496713] [=]module was installed
[  439.643072] pesudo interreupt occured
                    CPU0       CPU1       CPU2       CPU3       
          HI:          1          0          0          0
       TIMER:      18713      21705      20854      19911
      NET_TX:         95         49        315         19
      NET_RX:       1125        324       1051        398
       BLOCK:          0          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:      44263        453        587        288
       SCHED:      17064      20646      19843      18418
     HRTIMER:          0          0          0          0
         RCU:      19242      23191      20816      20212
      (null):          1          0          0          0
pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
[   21.514017] input: Keyboard K480 System Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input6
[   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
[  281.496011] my_driver: loading out-of-tree module taints kernel.
[  281.496218] my_driver: no symbol version for raise_softirq
[  281.496487] [=]236-0, was allocated
[  281.496492] [=]driver was initialized
[  281.496679] [=]irq 54 was assinged
[  281.496713] [=]module was installed
[  439.643072] pesudo interreupt occured
[  471.316929] pesudo interreupt occured
                    CPU0       CPU1       CPU2       CPU3       
          HI:          1          0          0          0
       TIMER:      18828      21849      21047      20104
      NET_TX:         95         49        321         19
      NET_RX:       1125        324       1063        398
       BLOCK:          0          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:      44459        453        609        288
       SCHED:      17173      20815      20069      18623
     HRTIMER:          0          0          0          0
         RCU:      19350      23343      20917      20386
      (null):          2          0          0          0
pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
[   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
[  281.496011] my_driver: loading out-of-tree module taints kernel.
[  281.496218] my_driver: no symbol version for raise_softirq
[  281.496487] [=]236-0, was allocated
[  281.496492] [=]driver was initialized
[  281.496679] [=]irq 54 was assinged
[  281.496713] [=]module was installed
[  439.643072] pesudo interreupt occured
[  471.316929] pesudo interreupt occured
[  477.954727] pesudo interreupt occured
                    CPU0       CPU1       CPU2       CPU3       
          HI:          1          0          0          0
       TIMER:      18963      22041      21297      20379
      NET_TX:         95         50        325         19
      NET_RX:       1128        326       1068        409
       BLOCK:          0          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:      44749        453        647        288
       SCHED:      17324      21034      20344      18910
     HRTIMER:          0          0          0          0
         RCU:      19496      23548      21158      20547
      (null):          3          0          0          0
pi@raspberrypi:/sys/class/gpio $ sudo rmmod my_driver 
pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
[  281.496011] my_driver: loading out-of-tree module taints kernel.
[  281.496218] my_driver: no symbol version for raise_softirq
[  281.496487] [=]236-0, was allocated
[  281.496492] [=]driver was initialized
[  281.496679] [=]irq 54 was assinged
[  281.496713] [=]module was installed
[  439.643072] pesudo interreupt occured
[  471.316929] pesudo interreupt occured
[  477.954727] pesudo interreupt occured
[  497.174610] module was removed
                    CPU0       CPU1       CPU2       CPU3       
          HI:          1          0          0          0
       TIMER:      19416      22394      21661      20809
      NET_TX:         95         50        335         19
      NET_RX:       1141        331       1087        409
       BLOCK:          0          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:      45416        479        678        288
       SCHED:      17800      21462      20753      19347
     HRTIMER:          0          0          0          0
         RCU:      19908      23925      21541      20832
      (null):          3          0          0          0
pi@raspberrypi:/sys/class/gpio $ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 17:          0          0          0          0     GICv2  29 Level     arch_timer
 18:      13237       9026       7126      13623     GICv2  30 Level     arch_timer
 23:        352          0          0          0     GICv2 114 Level     DMA IRQ
 31:       3111          0          0          0     GICv2  65 Level     fe00b880.mailbox
 34:       8655          0          0          0     GICv2 153 Level     uart-pl011
 35:          0          0          0          0     GICv2 169 Level     brcmstb_thermal
 36:      33671          0          0          0     GICv2 158 Level     mmc1, mmc0
 37:      17923          0          0          0     GICv2 144 Level     vc4 firmware kms
 38:          0          0          0          0     GICv2  48 Level     arm-pmu
 39:          0          0          0          0     GICv2  49 Level     arm-pmu
 40:          0          0          0          0     GICv2  50 Level     arm-pmu
 41:          0          0          0          0     GICv2  51 Level     arm-pmu
 42:       8559          0          0          0     GICv2 106 Level     v3d
 44:       1557          0          0          0     GICv2 189 Level     eth0
 45:         52          0          0          0     GICv2 190 Level     eth0
 51:        707          0          0          0     GICv2  66 Level     VCHIQ doorbell
 52:          0          0          0          0     GICv2 175 Level     PCIe PME, aerdrv
 53:       1053          0          0          0  Brcm_MSI 524288 Edge      xhci_hcd
 54:          2          0          0          0  pinctrl-bcm2835  10 Edge      my_device
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:      12130      21051      27290      15651  Rescheduling interrupts
IPI3:        785       1597       1554       1937  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:        793        414        433        246  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0

자 이제 커널을 다시 돌리고 tasklet으로 가자. 드라이버를 언로딩하고 cat /proc/interrupt를 하면 시스템이 어쩃든 죽는다. softirq 문제가 아니라, 인터럽트 핸들러를 해제하지 않아서 죽었다.

pi@raspberrypi:~/RaspberryDebug/my_driver $ diff my_driver.c my_driver.c.bak
164d163
< 	free_irq(GPIO_irqNumber, NULL);

이 글 공유하기:

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

댓글 남기기응답 취소

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

글 내비게이션

이전 글

항공기 구조설계 실무

다음 글

character device를 tasklet으로 테스트

2025 5월
일 월 화 수 목 금 토
 123
45678910
11121314151617
18192021222324
25262728293031
4월    

최신 글

  • common mode, differential mode 2025-05-11
  • signal conditioner, 신호 처리기 2025-05-10
  • strain gage 2025-05-09
  • 칼만 필터 2025-05-01
  • positioner(I/P) 2025-04-26

카테고리

  • 산업계측제어기술사
  • 삶 자국
    • 책과 영화
    • 투자
  • 생활코딩
    • 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로 제작.