기존 이솝 임베디드 포럼의 지식인 서비스가 게시판 형태로 변경되었습니다.

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을 나눈값이면 되는것인가요.

고현철

2006.06.23 08:11:26
*.232.213.232

여기서 쓰인 값 중

HZ는 일반적으로 100입니다.

서연석

2006.06.23 13:18:34
*.219.92.133

고현철님 감사합니다.
List of Articles
번호 제목 글쓴이 날짜sort 조회 수

사용자 로그인