본문 바로가기
Linux BSP

[Device Driver] 어플리케이션 없이 insmod만으로 동작하는 모듈 프로그램으로 커널 타이머 GPIO제어

by TYB 2024. 2. 26.
반응형

이전 글에서 코드를 향상시켜봅니다.

 

[Device Driver] 어플리케이션 없이 insmod만으로 동작하는 모듈 프로그램으로 커널 타이머 인터럽트

어플리케이션 없이 insmod만으로 동작하는 모듈 프로그램으로 커널 타이머 인터럽트 구현 /dev에 등록하는 과정이 없는거임. timerVal를 ubuntu@ubuntu8:~/pi_bsp/drivers/p335_kerneltimer$ vi kerneltimer.c #include #incl

program-developers-story.tistory.com


ledVal의 값에 따라 led 제어하는 코드 짜봅시다잉

ubuntu@ubuntu8:~/pi_bsp/drivers/p335_kerneltimer_led$ cat Makefile
MOD := kerneltimer_ledkey
obj-m := $(MOD).o

CROSS = ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
#KDIR := /lib/modules/$(shell uname -r)/build
KDIR := /home/ubuntu/pi_bsp/kernel/linux
PWD := $(shell pwd)

default:
        $(MAKE) -C $(KDIR) M=$(PWD) modules $(CROSS)
        cp $(MOD).ko /srv/nfs
clean:
        rm -rf *.ko
        rm -rf *.mod.*
        rm -rf .*.cmd
        rm -rf *.o
        rm -rf modules.order
        rm -rf Module.symvers
        rm -rf $(MOD).mod
        rm -rf .tmp_versions

ubuntu@ubuntu8:~/pi_bsp/drivers/p335_kerneltimer_led$ cat kerneltimer_ledkey.c

 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/moduleparam.h>

#define DEBUG 1

#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
#define GPIOKEYCNT 8
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 timerVal = 100;
module_param(timerVal,int ,0);
static int ledVal =0;
module_param(ledVal,int,0);
struct timer_list timerLed;

void kerneltimer_func(struct timer_list *t);
void kerneltimer_registertimer(unsigned long timeover)
{
        timer_setup(&timerLed, kerneltimer_func,0);//timer 생성
        timerLed.expires = get_jiffies_64() + timeover;//timer 작동 시간 설정
        //get_jiffies_64는 1초에 100씩 늘어남. timeover는 10ms *100 =1sec
        add_timer(&timerLed);
}
void kerneltimer_func(struct timer_list *t)
{
#if DEBUG
        printk("ledVal : %#04x\n",(unsigned int)(ledVal));
#endif
        ledVal = ~ledVal & 0xff;
        gpioLedSet(ledVal);
        mod_timer(t,get_jiffies_64() + timerVal);
}
int kerneltimer_init(void)
{
#if DEBUG
        printk("timerVal : %d, sec : %d \n",timerVal,timerVal/HZ);//HZ는 0.01임. timerVal*100인거임.
#endif
        int ret;
    ret=gpioLedInit();
        if(ret < 0)
                return ret;
        kerneltimer_registertimer(timerVal);
        return 0;
}
void kerneltimer_exit(void)
{
    gpioLedFree();
        if(timer_pending(&timerLed))//만약 타이머가 등록되어있다면
                del_timer(&timerLed);//타이머 제거
}

module_init(kerneltimer_init);
module_exit(kerneltimer_exit);
MODULE_AUTHOR("AIOT WCM");
MODULE_DESCRIPTION("led key test module");
MODULE_LICENSE("Dual BSD/GPL");

 

 

여기까지가 led 제어

pi@pi08:/mnt/ubuntu_nfs $ sudo rmmod kerneltimer

pi@pi08:/mnt/ubuntu_nfs $ sudo insmod kerneltimer_ledkey.ko timerVal=10 ledVal=0x55

 

led는 이렇게 깜빡이구여~

 

커널메시지는 아래와 같이 출력됩니다.


그 다음에는 버튼 제어 들어갑니다.

 

 

반응형