(7) Liux 의 타이머 구동 led 반 짝 임

51017 단어 링크 ux 구동
1. Liux 의 타이머 구동 led 반 짝 임
1.1 내장 형 개발 판
임 베 디 드 개발 판 은 정시 원자 Liux 개발 판 을 사용한다.
1.2. Liux 의 timer
Liux 커 널 타 이 머 는 jiffies 박 자 를 바탕 으로 스케줄 링 을 수행 하 는 메커니즘 으로 '소프트 인 터 럽 트' 와 유사 하 며 한 번 실행 하면 로그아웃 된다.자원 의 접근 을 중단 하기 때문에 일부 방문 한 데이터 구조 에 대해 동시 방문 보 호 를 사용 하여 경쟁 조건 을 방지 해 야 합 니 다. 또한 그 는 비 프로 세 스 의 문맥 에 있 기 때문에 리 셋 함 수 는 휴면 과 스케줄 을 수행 할 수 없 음 을 주의해 야 합 니 다.
timer 정의 에 관 한 구조 체
struct timer_list {
	/*
	 * All fields that change during normal runtime grouped to the
	 * same cacheline
	 */
	struct list_head entry;
	unsigned long expires;
	struct tvec_base *base;

	void (*function)(unsigned long);
	unsigned long data;

	int slack;

#ifdef CONFIG_TIMER_STATS
	int start_pid;
	void *start_site;
	char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

그 중에서 우 리 는 두 개의 점 void (* function) (unsigned long) 에 관심 을 가진다.unsigned long data 와;이 두 개 는 첫 번 째 는 timer 의 반전 함수 이 고 두 번 째 는 반전 함수 의 전달 매개 변수 입 니 다.
1. timer 를 사용 하 는 절 차 는 timer 구조 체 를 정의 한 다음 init 를 추출 하 는 것 입 니 다.timer () 는 이 구조 체 를 초기 화한 다음 에 리 셋 함수 와 전 달 된 매개 변 수 를 대응 하 는 값 을 부여 합 니 다.2. 하지만 아직 timer 의 시작 이 시작 되 지 않 았 습 니 다. 함수 mod 를 찾 아야 합 니 다.timer (), timer 의 시작 을 진행 하 는 것 도 다른 함 수 를 통 해 timer 를 열 수 있 습 니 다.3 、 타 이 머 를 삭제 하려 면 deltimer_sync() 。
1.3. 구동 코드 의 작성
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define TIMER_NAME  "timer_led"
#define TIMER_CT    1

#define CLOSE_CMD   (_IO(0xEF,0x01))
#define OPEN_CMD    (_IO(0xEF,0x02))
#define SET_CMD     (_IO(0xEF,0x03))

struct timer_struct{
    spinlock_t	lock;
    int major;
    dev_t devid;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    struct timer_list timer;

    struct device_node *nd;
    int gpio_num;

    int time_period;
};

struct timer_struct timer_dev;


static int timer_open(struct inode *inode, struct file *file)
{

	file->private_data = &timer_dev;
    

    return 0;

}

static long timer_unlocked_ioctl(struct file *file, unsigned int cmd,unsigned long arg)
{
    struct timer_struct *dev = (struct timer_struct *)file->private_data;
    int time_period = 0;
    unsigned long flags;

    printk("input\r
"
); switch (cmd) { case CLOSE_CMD: del_timer_sync(&dev->timer); gpio_set_value(dev->gpio_num,1); break; case OPEN_CMD: spin_lock_irqsave(&dev->lock,flags); time_period = dev->time_period; mod_timer(&dev->timer,jiffies + msecs_to_jiffies(dev->time_period)); spin_unlock_irqrestore(&dev->lock,flags); break; case SET_CMD: spin_lock_irqsave(&dev->lock,flags); dev->time_period = arg; mod_timer(&dev->timer,jiffies + msecs_to_jiffies(dev->time_period)); spin_unlock_irqrestore(&dev->lock,flags); break; default: break; } return 0; } static const struct file_operations timer_fops = { .owner = THIS_MODULE, .open = timer_open, .unlocked_ioctl = timer_unlocked_ioctl, }; void timer_function(unsigned long arg) { struct timer_struct *dev = (struct timer_struct *)arg; static int status = 0; unsigned long flags; int time_period; status = !status; gpio_set_value(dev->gpio_num,status&0x01); spin_lock_irqsave(&dev->lock,flags); time_period = dev->time_period; mod_timer(&dev->timer,jiffies + msecs_to_jiffies(dev->time_period)); spin_unlock_irqrestore(&dev->lock,flags); } int led_init(void) { int ret; timer_dev.nd = of_find_node_by_path("/gpioled"); if(timer_dev.nd == NULL){ printk("not find node\r
"
); return -1; } printk("find node\r
"
); timer_dev.gpio_num = of_get_named_gpio(timer_dev.nd,"led-gpio",0); if(timer_dev.gpio_num < 0){ printk("no get gpio\r
"
); return -2; } printk("gpio num:%d\r
"
,timer_dev.gpio_num); ret = gpio_request(timer_dev.gpio_num,"led0"); if(ret < 0){ printk("led already use\r
"
); return -3; } ret = gpio_direction_output(timer_dev.gpio_num,1); if(ret < 0){ printk("gpio set err\r
"
); return -4; } return 0; } static int __init timer_init(void) { int ret = 0; timer_dev.major = 0; spin_lock_init(&timer_dev.lock); if(timer_dev.major){ timer_dev.devid = MKDEV(timer_dev.major,0); ret = register_chrdev_region(timer_dev.devid,TIMER_CT,TIMER_NAME); } else{ ret = alloc_chrdev_region(&timer_dev.devid,0,TIMER_CT,TIMER_NAME); timer_dev.major = MAJOR(timer_dev.devid); } if(ret < 0){ printk("chrdev err\r
"
); goto chrdev_err; } printk("major num:%d\r
"
,timer_dev.major); timer_dev.cdev.owner = THIS_MODULE; cdev_init(&timer_dev.cdev,&timer_fops); ret = cdev_add(&timer_dev.cdev,timer_dev.devid,TIMER_CT); if(ret < 0){ printk("cdev err\r
"
); goto cdev_err; } timer_dev.class = class_create(THIS_MODULE,TIMER_NAME); if(IS_ERR(timer_dev.class)){ printk("class err\r
"
); ret = PTR_ERR(timer_dev.class); goto class_err; } timer_dev.device = device_create(timer_dev.class,NULL,timer_dev.devid,NULL,TIMER_NAME); if(IS_ERR(timer_dev.device)){ printk("device err\r
"
); ret = PTR_ERR(timer_dev.device); goto device_err; } ret = led_init(); if(ret < 0){ printk("led err\r
"
); goto led_err; } timer_dev.time_period = 1000; init_timer(&timer_dev.timer); timer_dev.timer.function = timer_function; timer_dev.timer.data = (unsigned long)&timer_dev; // mod_timer(&timer_dev.timer, jiffies+ msecs_to_jiffies(timer_dev.time_period)); return 0; led_err: device_destroy(timer_dev.class,timer_dev.devid); device_err: class_destroy(timer_dev.class); class_err: cdev_del(&timer_dev.cdev); cdev_err: unregister_chrdev_region(timer_dev.devid,TIMER_CT); chrdev_err: return ret; } static void __exit timer_exit(void) { gpio_set_value(timer_dev.gpio_num,1); gpio_free(timer_dev.gpio_num); del_timer_sync(&timer_dev.timer); device_destroy(timer_dev.class,timer_dev.devid); class_destroy(timer_dev.class); cdev_del(&timer_dev.cdev); unregister_chrdev_region(timer_dev.devid,TIMER_CT); } module_init(timer_init); module_exit(timer_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("gale");

이번 에는 fops 구조 체 에 함수 unlocked 를 추가 하 였 습 니 다.ioctl, 구동 에 있어 서 이 함 수 는 주로 명령 을 실현 하 는 기능 입 니 다. 사실은 처음에 저 는 명령 이 있 으 면 write 로 실현 할 수 있 는데 왜 unlocked 가 나 타 났 는 지 모 르 겠 습 니 다.ioctl (사실은 ioctl 함수). 사실 write 로 실현 하면 안 되 는 것 도 아니 지만 어 지 러 운 느낌 을 줄 수 있 습 니 다. 구동 은 닫 기, 열기 등 조작 과 관련 될 수 있 기 때문에 전문 적 인 함수 로 처리 하면 명확 한 느낌 을 줄 수 있 습 니 다. 이것 은 개인 적 인 이해 일 뿐 구체 적 으로 이 블 로그 Liux 커 널 - ioctl 함수 에 대한 상세 한 설명 을 참고 할 수 있 습 니 다.
static const struct file_operations timer_fops = {
    .owner          = THIS_MODULE,
    .open           = timer_open,
    .unlocked_ioctl = timer_unlocked_ioctl,
};

병발 보호 에 사용 되 는 자전거 자물쇠 에 대해 자전거 자물쇠 의 사용 은 상대 적 으로 간단 하 다. 주로 이 부분 코드 의 집행 일치 성, 완전 성 을 확보 하기 위해 다른 어떠한 프로 세 스 도 동시에 접근 하지 않 는 다.
1.4 응용 프로그램
#include 
#include 
#include 
#include 
#include 
#include 
#include "stdlib.h"
#include 

#define CLOSE_CMD   (_IO(0xEF,0x01))
#define OPEN_CMD    (_IO(0xEF,0x02))
#define SET_CMD     (_IO(0xEF,0x03))


int main(int argc,char *argv[])
{
    int ret = 0;
    int cmd;
    int arg;
    int fd;
    char *filename;
    char writebuff[1];
    unsigned char str[100];

    if(argc != 2)
    {
        printf("Error usage!\r
"
); return -1; } filename = argv[1]; fd = open(filename, O_RDWR); if (fd < 0) { printf("Can't open file %s\r
"
, filename); return -1; } while(1){ printf("Input CMD:"); ret = scanf("%d",&cmd); printf("cmd:%d\r
"
,cmd); if(cmd == 1){ cmd = CLOSE_CMD; } else if(cmd == 2){ cmd = OPEN_CMD; } else if(cmd == 3){ cmd = SET_CMD; printf("Input arg:"); ret = scanf("%d",&arg); printf("arg:%d\r
"
,arg); } ioctl(fd,cmd,arg); } ret = close(fd); if(ret < 0){ printf("close file err:%s\r
"
,filename); } else{ } return 0; }

1.5、Makefile
정점 원자 가 제공 하 는 Makefile 을 사용 합 니 다.
KERNELDIR := /home/gale/linux/linux/nxp_alientek_linux

CURRENT_PATH := $(shell pwd)

obj-m := timer.o

build: kernel_modules

kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

개인 적 이해
timer 는 상대 적 으로 쉽게 이해 할 수 있 습 니 다. 게다가 이전에 구동 한 led 와 자전 자물쇠 도 있 습 니 다. 이 규칙 은 세 가지 지식 을 사 용 했 습 니 다. timer, 자전 자물쇠, led 는 재 미 있 습 니 다.

좋은 웹페이지 즐겨찾기