2440 2.4.20 커널에서 timer부분만 발췌했습니다.
밑의 time.h의 설명을 보시면 원하시는 부분의 공식이 나와있으니
참조하시기 바랍니다.
님이 원하시는 답이 나와있을듯 보여지네요.
참고로 리눅스커널에서는 10ms timer를 설정해서 씁니다.
Linux 2.4.20 for S3C2440
- include/asm/arch/pwm-timers.h
#ifndef _PWM_TIMERS_H
#define _PWM_TIMERS_H
#define DRIVER_VERSION "0.1"
#define PASSIVE 0
#define ACTIVE 1
#define ABSENT 2
#define OFF 0
#define ON 1
#define TIMER0 0
#define TIMER1 1
#define TIMER2 2
#define TIMER3 3
#define TIMER4 4
#define TIMER0_RES 10000 /* 1 usec */ // B'coz value_PCLK /= 100, so all RES too are scaled down by 100
#define TIMER1_RES 10000 /* 1 usec */
#define TIMER2_RES 1000 /* 10 usec */
#define TIMER3_RES 100 /* 100 usec */
#define TIMER4_RES 1 /* 10 msec */
#define PRESCALAR0 30 /* Timer 0 */
#define PRESCALAR1 30 /* Timer 1 */
#define PRESCALAR2 15 /* Timer 2 */
#define PRESCALAR3 15 /* Timer 3 */
#define PRESCALAR4 15 /* Timer 4 */
#define MUX0 0 /* Div0 = 2 */
#define MUX1 0 /* Div1 = 2 */
#define MUX2 0 /* Div2 = 2 */
#define MUX3 0 /* Div3 = 2 */
#define MUX4 0 /* Div4 = 2 */
#define DIV0 2
#define DIV1 2
#define DIV2 2
#define DIV3 2
#define DIV4 2
#define MAX_TCNTB_VAL 65535
#define TMR_0_ON (1<<0)
#define TMR_1_ON (1<<8)
#define TMR_2_ON (1<<12)
#define TMR_3_ON (1<<16)
#define TMR_4_ON (1<<20)
/*
TCNTBn = (PCLK / (PS+1) / DIVn / TIMERn_RES)*(no. of resolution units) For timer 2, 3 and 4
TCNTBn = (PCLK / (PS+1) / DIVn / TIMERn_RES)*(delay) For timer 0 and 1
*/
#define MAX_TIMER_REQUESTS 5 // Max no. of total reqs on _all_ the timers
typedef enum {
SET,
START,
STOP
}TIMER_OP;
typedef enum {
TIMER_0,
TIMER_1,
TIMER_2,
TIMER_3,
TIMER_4
}TIMER_NUM;
typedef struct{
TIMER_NUM timer;
TIMER_OP op;
}timer_cmd_t;
struct timer_request {
void *req_id; /* Unique request token */
int delay; /* No. of usecs to wait after the timeout of previous request */
unsigned long time_stamp;
void (*handler)(int, void *, struct pt_regs *); /* Callback */
struct timer_request *next;
};
int elfin_timer(timer_cmd_t, int , void (*handler)(int, void *, struct pt_regs *), void *);
#endif
/*
Preface :-
We have 5 PWM-Timers for S3C2440(A0,10 as well). These timers are utilized to provide
different kinds of services. Like the Timers 0 and 1 are for micro-sec(usec) delay requests.
Timer-2 is for delays of multiples of 10usecs (i.e, 10usec is the time unit for timer-2).
Likewise Timer-3 can be used for still higher delays (100usec time unit) .
Right now I have spared the Timer-4, as it is used by the kernel. But once this driver is
tested enough, it can easily be integrated in this driver, providing uniform acess to PWM-Timers.
Design :-
There are two types of requests that can be made to this driver ::
a). CallBack Req :- The 'delay' period and a handler is provided. After that particular
'delay' period, the handler will be called. The 'delay' is the number
of time units of the corrsp. timer.
b). Time Measure :- This is used to measure the time-interval between two specified points.
The returned value is the number of the time units lapsed between the SET
and STOP calls.
How to use :-
void handler(int i, void *vp, struct pt_regs *p)
{
......
}
void callback_test
{
.....
timer_cmd_t tmr;
tmr.timer = TIMER_0; //or whichever timer you want
tmr.op = SET;
elfin_timer(tmr, delay, handler, &token1);
......
// When you want the timer to start (SET starts only the TIME-MEASURE requests)
tmr.timer = TIMER_0;
tmr.op = START;
elfin_timer(tmr, 0, NULL, &token1); // only "tmr" and "token" is necessary
// after "delay+overhead" number of units, "handler" will be called.
}
void measure_test
{
unsigned int count;
.....
timer_cmd_t tmr;
tmr.timer = TIMER_0; //or whichever timer you want
tmr.op = SET;
elfin_timer(tmr, 0, handler, &token2); // delay MUST be 0 (handler may be null)
.....
// When you want the timer to STOP (Need not call START)
tmr.timer = TIMER_0;
tmr.op = STOP;
count = elfin_timer(tmr, 0, NULL, &token2); // only "tmr" and "token" is necessary
// "handler" is never called, even if it is Non-NULL.
}
FIXME :: callback request has an overhead of 20-30 usecs
FIXME :: time measure has an error of ~1-2 usecs
------------------------------
In CPU: 400Mhz(1 : 3: 6 ), S3C2440,
TIMER0,1 latency : 20 usec
TIMER2,3 latency : 30 usec
Measurement:
Tolerance : 2 usec
------------------------------
*/
- include/asm/arch/time.h
/*
* priod = (prescaler value + 1) * (divider value) * buffer count / PCLK = 10 ms
*
* e.g.; PCLK = 50 Mhz
* 10 ms = (15 + 1) * 2 * 15625 / (50000 * 1000)
* 15626 = 10 ms * (50000 * 1000) / 2 / (15 + 1)
*
*/
static inline void setup_timer(void)
{
/*auto calcurate tick count register set
struct timer_counts *timer_count = count_values; */
unsigned long pclk;
gettimeoffset = elfin_gettimeoffset;
set_rtc = elfin_set_rtc;
xtime.tv_sec = elfin_get_rtc_time();
TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(PRESCALAR4) | TCFG0_PRE0(0));
TCFG1 |= TCFG1_MUX4(DIV4);
pclk = elfin_get_bus_clk(GET_PCLK);
TCNTB4 = (unsigned int) (pclk / ((PRESCALAR4 + 1) * DIV4)) / HZ;
TCON = (TCON_4_AUTO | TCON_4_UPDATE | COUNT_4_OFF);
timer_irq.handler = elfin_timer_interrupt;
setup_arm_irq(IRQ_TIMER4, &timer_irq);
TCON = (TCON_4_AUTO | COUNT_4_ON);
}
>안녕하세요!
>
>timer에 대한 부분중에 질문입니다.
>
>timer의 input clock는
>
>PCLK/{prescaler value+1}/{divider value}로 정해진다고 알고 있습니다.
>
>만약 1초에 1000번 인터럽트가 발생되게 하려고 했을때 어떻게 위의 공식을 응용을 해야하나요.
>
>PCLK = FCLK(399650000)/8
>prescaler value = 0
>divider value = 4
>
>이 값을 위의 공식에 대입해서 나온결과에서
>1000을 나눈값이면 되는것인가요.
HZ는 일반적으로 100입니다.