linux에서 rtc를 이용하여 정확한 타이머를 실현

2363 단어
rtc는 linux 시스템의 시간 장치로 오픈을 할 수 있으며 ioctl을 통해 주파수를 설정한 다음에 순환read 조작을 할 수 있다. 매번read의 소모 시간은 (1/주파수 단위: 초)이다.
선상 부호
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/rtc.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#define FREQ 2048
#define USEC_PER_SECOND 1000000
typedef int MILLSEC;

int g_fd = 0;
 
int calc_cnt(MILLSEC millseconds )
{
    return (int)(millseconds * 1000.0 / USEC_PER_SECOND * FREQ + 0.5); //add 0.5 to meet precision in common
}

void rtc_open()
{
	g_fd = open ("/dev/rtc", O_RDONLY);
	if(g_fd < 0)
	{   
		perror("open");
		exit(errno);
	}
	printf("opened.
"); } void set_freq() { /*Set the freq*/ if(ioctl(g_fd, RTC_IRQP_SET, FREQ ) < 0) { perror("ioctl(RTC_IRQP_SET)"); close(g_fd); exit(errno); } /* Enable periodic interrupts */ if(ioctl(g_fd, RTC_PIE_ON, 0) < 0) { perror("ioctl(RTC_PIE_ON)"); close(g_fd); exit(errno); } } void rtc_task() { printf("start counting...
"); struct timeval tvs,tve; unsigned long i = 0; unsigned long data = 0; while(true) { int time_to_wait; printf("please input time to wait in millsecond, -1 to break
"); scanf("%d",&time_to_wait); if(time_to_wait < 0) break; //calc how many times to loop int cnt = calc_cnt(time_to_wait); gettimeofday( &tvs , 0 ); for(i = 0; i < cnt; i++) { if(read(g_fd, &data, sizeof(unsigned long)) < 0) { perror("read"); ioctl(g_fd, RTC_PIE_OFF, 0); close(g_fd); exit(errno); } } gettimeofday(&tve,0); printf("[%ld]timer usec
" , (tve.tv_sec - tvs.tv_sec) * 1000000LL + (tve.tv_usec-tvs.tv_usec)); } /* Disable periodic interrupts */ ioctl(g_fd, RTC_PIE_OFF, 0); close(g_fd); } int main(int argc, char* argv[]) { rtc_open(); set_freq(); rtc_task(); return 0; }

예에서 사용한 주파수는 2048이고 주파수의 사용 가능한 범위는 2~8192이다. 반드시 2의 n차원이어야 한다. 그렇지 않으면 실행할 때 오류가 발생한다. 주파수는 1초에 몇 번을 실행할 수 있는지를 나타낸다. 만약에 2048번이라면 한 번의 시간은 1.0/2048(초)이다. 이로써time to wait를 실행할 때 몇 번을 실행해야 하는지를 확정한다.

좋은 웹페이지 즐겨찾기