(7) Liux 의 타이머 구동 led 반 짝 임
51017 단어 링크 ux 구동
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 는 재 미 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
u - boot 2 단계 빗질 시작\ #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t * gd asm ("r8") 설명: register 를 통 해 레지스터 변 수 를 표시 하고, asm ("r8")...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.