본문 바로가기
Linux BSP

[RaspberryPi DeviceDriver] 디바이스 드라이버 매개변수 명령어로 입력 받는 함수 만들기

by TYB 2024. 2. 22.
반응형
 

[Linux DeviceDriver] 디바이스 드라이버 코드 수정해서 커널에 포함시키기

디바이스 드라이버에 대한 간단한 이론 지식은 아랫글의 중후반부에 있음 [Linux DeviceDriver] Yocto Project 설정 초기화 및 디바이스 파일 만들어보기 [Linux File System] Yocto Project 2 이전 글 먼저 진행해

program-developers-story.tistory.com

 

이전 글에서 사용한 p106_ledkey 폴더 복사해서 진행합니다.

 

 

ubuntu@ubuntu8:~/pi_bsp/drivers/p122_ledkey_modparam$ vi ledkey_modparam.c

 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>

#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
#define GPIOKEYCNT 8

static int onevalue = 1;
static char * twostring = NULL;

module_param(onevalue, int , 0);
module_param(twostring, charp, 0);

static int gpioLed[GPIOLEDCNT] = {6,7,8,9,10,11,12,13};
static int gpioKey[GPIOKEYCNT] = {16,17,18,19,20,21,22,23};

static int gpioLedInit(void);
static void gpioLedSet(long);
static void gpioLedFree(void);
static int gpioKeyInit(void);
static int gpioKeyGet(void);
static void gpioKeyFree(void);

static int gpioLedInit(void)
{
        int i;
        int ret=0;
        char gpioName[10];
        for(i=0;i<GPIOLEDCNT;i++)
        {
                sprintf(gpioName,"led%d",i);
                ret = gpio_request(gpioLed[i],gpioName);
                if(ret < 0) {
                        printk("Failed gpio_request() gpio%d error \n",i);
                        return ret;
                }

                ret = gpio_direction_output(gpioLed[i],OFF);
                if(ret < 0) {
                        printk("Failed gpio_direction_output() gpio%d error \n",i);
                        return ret;
                }
        }
        return ret;
}

static void gpioLedSet(long val)
{
        int i;
        for(i=0;i<GPIOLEDCNT;i++)
        {
                gpio_set_value(gpioLed[i],(val>>i) & 0x1);
        }
}
static void gpioLedFree(void)
{
        int i;
        for(i=0;i<GPIOLEDCNT;i++)
        {
                gpio_free(gpioLed[i]);
        }
}
static int gpioKeyInit(void)
{
        int i;
        int ret=0;
        char gpioName[10];
        for(i=0;i<GPIOKEYCNT;i++)
        {
                sprintf(gpioName,"key%d",gpioKey[i]);
                ret = gpio_request(gpioKey[i], gpioName);
                if(ret < 0) {
                        printk("Failed Request gpio%d error\n", 6);
                        return ret;
                }
        }
        for(i=0;i<GPIOKEYCNT;i++)
        {
                ret = gpio_direction_input(gpioKey[i]);
                if(ret < 0) {
                        printk("Failed direction_output gpio%d error\n", 6);
                return ret;
                }
        }
        return ret;
}
static int      gpioKeyGet(void)
{
        int i;
        int ret;
        int keyData=0;
        for(i=0;i<GPIOKEYCNT;i++)
        {
//              ret=gpio_get_value(gpioKey[i]) << i;
//              keyData |= ret;
                ret=gpio_get_value(gpioKey[i]);
                keyData = keyData | ( ret << i );
        }
        return keyData;
}
static void gpioKeyFree(void)
{
        int i;
        for(i=0;i<GPIOKEYCNT;i++)
        {
                gpio_free(gpioKey[i]);
        }
}

static int hello_init(void)
{
        int ret,i;
        int key_data;
        char ledStatus[16]="0:0:0:0:0:0:0:0";
        printk("Hello, world onevalue:%d, twostring:%s \n",onevalue, twostring);
    ret=gpioLedInit();
    if(ret < 0)
       return ret;

        gpioLedSet(onevalue);

    ret=gpioKeyInit();
    if(ret < 0)
                return ret;

        key_data = gpioKeyGet();
        if(key_data)
        {
                gpioLedSet(key_data);
                printk("0:1:2:3:4:5:6:7\n");
                for(i=0;i<8;i++)
                {
                        if((key_data >> i) & 0x01)
                                ledStatus[i*2] = 'O';
                        else
                                ledStatus[i*2] = 'X';
                }
                printk("%s\n\n",ledStatus);
        }
        return 0;
}
static void hello_exit(void)
{
        printk("Goodbye, world \n");
        gpioLedSet(0x00);
//      printk("led all off \n");
    gpioLedFree();
    gpioKeyFree();
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("KCCI-AIOT");
MODULE_DESCRIPTION("led key test module");
MODULE_LICENSE("Dual BSD/GPL");

make하고

 

 

 


pi@pi08:/mnt/ubuntu_nfs $ sudo insmod ledkey_modparam.ko onevalue=0xff twostring =\"hi hello\"

 

아무것도 매개변수를 주지않고 insmod를 하면 0x01이 출력될거임. 

dmesg를 쳐보면 onevalue에 1이 default로 들어가기 때문

[15960.486236] onevalue:1 twostring: (null)

pi@pi08:/mnt/ubuntu_nfs $ sudo insmod ledkey_modparam.ko

 

버튼을 누른채 insmod를 하면 해당되는 led만 켜지고 dmesg에 버튼이 눌렸다고 출력된다.

pi@pi08:/mnt/ubuntu_nfs $ sudo insmod ledkey_modparam.ko


 

pi@pi08:/mnt/ubuntu_nfs $ sudo insmod ledkey_modparam.ko onevalue=0xff

이라믄 다 켜짐.

 


pi@pi08:/mnt/ubuntu_nfs $ sudo insmod ledkey_modparam.ko onevalue=0xff twostring=\"hi hello\"

이라믄 일단 led 다 켜지고

그냥 "hi hello"만 하면 hi에서 짤려서 출력됨.

hi hello를 그대로 넣기 위해 \" \"를 써서 문자열로 인식하지말라고 저장해준다.

 

 


여기서 끝내면 아쉬우니까 디버깅 메시지 띄울 때 규칙을 알아보자

120     printk(KERN_DEBUG "Hello, world onevalue:%d, twostring:%s \n",onevalue, twostring);

코드 수정하고 make한 후 

 

pi에서 insmod 한 후 dmesg 출력해보면 커널 메시지 시간 앞에 디버깅 메시지가 나온다. 의미는 위의 표를 보고 해석하면 되겠다.

<7> [17922.957866] Hello, world onevalue:1, twostring:(null)

 

 

 

 

반응형