타이머 드라이버

EEEFFEE·2024년 1월 7일
0

임베디드 리눅스

목록 보기
7/14

24.01.07 최초 작성
24.01.09 예제 추가

1. jiffies 관련 API

1.1 커널 타이머


struct timer_list {
	struct hlist_node	entry;
    unsigned long 		expires;
    void				(*function)(struct timer_list *);
    u32					flags;
}

///
entry : 타이머 리스트
expires : jiffies 단위의 만료 시간
function : 핸들러 함수
flags : 플래그

1.2 커널 타이머 API


#include <linux/timer.h>

timer_setup(timer, callback, flags);	//timer_list 초기화

extern void add_timer_on(struct timer_list *timer, int cpu);
										//지정한 cpu에 타이머 가동
extern int del_timer(struct timer_list *timer);					
										//타이머 삭제
extern int mod_timer(struct timer_list *timer, unsinged long expires);				//타이머의 expire 설정
extern int mod_timer_pending(struct timer_list *timer, unsinged long expires);
										//타이머의 expire 추가
extern int timer_reduce(struct timer_list *timer, unsigned long expires);				
										//expire에 입력한 만큼 expire에 설정된 시간 차감

2. buildroot jiffies 설정

  • /buildroot.confing 파일의 CONFIG_HZ=(정수)로 원하는 값 설정

3. High resolution timer

  • 4ms마다 타이머 인터럽트가 발생하는 기존 리눅스 타이머를 보완하기 위해 탄생한 타이머

  • nanosleep, itimers, posix-timers는 설정에 따라 High resolution timer 활용


#include <linux/hrtimer>

4. delay

  • 짧은 지연의 경우 busy waiting으로 처리 (mdelay(), udelay(), ndelay())

  • 긴 지연은 schedule_timeout(), usleep_range(int, int), usleep()으로 처리

5. Real Time Clock

  • 전원이 인가되지 않은 경우에도 설정한 시간 유지 (외부 배터리로 동작)

  • /dev/rtc에서 관리하며 xtime이라는 변수에 값 저장

예제

timer

  • 드라이버 등록 시 일정시간 이후 jiffies값 출력
드라이버 등록드라이버 해제타이머 인터럽트 핸들러
k_module_init()k_module_exit()test_timer_callback()
  • k_module_init() : 타이머와 타이머 인터럽트 핸들러 등록하고 500ms 이후 작동하도록 설정

static int __init k_module_init(void)
{
	int retval;

	pr_info("k 커널 모듈 \n");

	timer_setup(&test_timer, test_timer_callback, 0);
	pr_info( "현재 jiffies 값: (%ld)\n", jiffies);

	retval = mod_timer(&test_timer, jiffies + msecs_to_jiffies(500));
	if (retval)
		pr_info("타이머 설정 에러\n");

	return 0;
}

  • test_timer_callback() : 현재 jiffies값 출력

static struct timer_list test_timer;

void test_timer_callback(struct timer_list *t)
{
	pr_info("callback 함수: jiffies 값: (%ld).\n", jiffies);
}

  • k_module_exit() : 실행되지 않은 타이머를 해제

static void __exit k_module_exit(void)
{
	int retval;

	retval = del_timer(&test_timer);
	if (retval)
		pr_info("타이머 제거 실패...\n");

	pr_info("바이!!n");
}

hrtimer

  • 드라이버 등록 후 일정 시간 이후 jiffies 출력
드라이버 등록드라이버 해제타이머 인터럽트 핸들러
k_module_init()k_module_exit()test_timer_callback()
  • k_module_init() : 타이머 동작 간격을 설정, 타이머를 지정한 옵션으로 초기화하고 타이머 시작

#define TIMEOUT_NSEC	1000000000L
#define TIMEOUT_SEC		4

static int __init k_module_init(void)
{
	ktime_t ktime;

	pr_info("k 커널 모듈 \n");

	ktime = ktime_set(TIMEOUT_SEC, TIMEOUT_NSEC);
	hrtimer_init(&k_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	k_hrtimer.function = &timer_callback;
	hrtimer_start(&k_hrtimer, ktime, HRTIMER_MODE_REL);

	return 0;
}

  • test_timer_callback() : jiffies값을 출력하고 타이머 작동 시간을 초기화, 타이머 다시 동작시킴

static struct hrtimer k_hrtimer;

enum hrtimer_restart timer_callback(struct hrtimer *timer)
{
	pr_info("callback 함수: jiffies 값: (%ld).\n", jiffies);
	hrtimer_forward_now(timer, ktime_set(TIMEOUT_SEC, TIMEOUT_NSEC));

	return HRTIMER_RESTART;
}

  • k_module_exit() : 지정한 타이머 종료

static void __exit k_module_exit(void)
{
	int retval;

	retval = hrtimer_cancel(&k_hrtimer);
	if (retval)
		pr_info("타이머 제거 \n");

	pr_info("바이!!n");
}

0개의 댓글

관련 채용 정보