本文来自s3c2440手册第10章,PWM Timer.
有5个16位定时器,Timer 0,1,2,3有PWM输出功能。Timer 4是内部定时器,没有输出引脚。Timer 0有一个dead-zone generator。
Timer 0,1共享一个8位预分频器,Timer 2,3,4共享另一个预分频器。每个定时器有自己的clock divider,产生5种不同的divided signals (1/2, 1/4, 1/8, 1/16, and TCLK)。每个定时器的timer block接收它自己的来自clock divider时钟信号。clock divider接收预分频器的信号。预分频器分频PCLK,预分频器可编程,通过TCFG0和TCFG1。
定时器计数缓存寄存器(TCNTBn)有一个初始化值,定时器开始时加载到down-counter。定时器比较缓存寄存器(TCMPBn)有一个初始值,加载到compare register。
每个定时器有自己的16位down counter,由定时器时钟驱动,当down counter减为0时,产生定时器中断,同时TCNBn自动装载进down counter,开始下一次定时。然而,如果定时器停止,例如在定时器运行过程中清除TCONn的对应位,TCNTBn不会装载进counter。
TCMPBn用来实现PWM。定时器控制逻辑改变输出电平,当down-counter的值等于compare register时。
prescaler & divider
二级分频,1级为8为预分频(1-256),二级为4位divider,1/2, 1/4, 1/8, 1/16 4种。
Auto reload & double buffering
外部寄存器TCNTBn和内部寄存器TCNTn,修改TCNTB不会改变TCNT,TCNT可设置为在达到0时自动加载。
Timer Initialization using manual update bit and inverter bit
步骤如下:
1 设置TCNTBn和TCMPBn的初始值。
2 设置manual update bit, 推荐设置inverter on/off 位。
3 设置start bit开始定时器,然后清除manual update bit
Ouput level control
TOUTn可以翻转,通过inverter on/off bit in TCON。
Dead zone generator
这是功率设备的特殊要求,配置成死区输出时,TOUT1脚输出nTOUT0_DZ。
DMA request mode
用来产生DMA请求,DMA模式的定时器不再产生定时器中断。
Timer configuration register 0 (TCFG0)
定时器输入时钟频率 = PCLK / (1 + prescalar value) / (divider value}
{prescalar value} = 0-255
{divider value} = 2, 4, 8, 16
| Register | Address | R/W | Desc | Reset value | 
| TCFG0 | 0x51000000 | R/W | Configures the two 8-bit prescalers | 0x0 | 
[31:24] 保留
[23:16] Dead zone length,8位,决定死亡区长度,1个单位是Timer 0的定时长度。
[15:8] prescaler 1
[7:0] prescaler 0
Timer configuration register 1 (TCFG1)
| Register | Address | R/W | Desc | Reset value | 
| TCFG1 | 0x51000004 | R/W | 5-MUX & DMA mode selection register | 0x0 | 
[31:24] reserved
[23:20] Select DMA request channel
            0000 = No DMA, 0001 = Timer 0, 0010 = Timer 1, 0010 = Timer2
            0100 = Timer 3, 0101 = Timer 4, 0110 = Reserved.
[19:16] MUX 4
            select MUX Input for PWM Timer4
            0000 = 1/2 0001 = 1/4 0010 = 1/8 0011 = 1/16 01xx = External TCLK1
[15:12] MUX 3
[11:8] MUX 2
[7:4] MUX 1
[3:0] MUX 0
Timer control register (TCON)
| Register | Address | R/W | Desc | Reset value | 
| TCON | 0x51000008 | R/W | Timer Control register | 0x0 | 
[22] Timer 4 auto reload on/off
0 = one-shot 1 = interval mode (auto reload)
[21] Timer 4 manual update, (需要再下一次写时清除)
        0 = No operation 1 = Update TCNTB4
[20] Determine start/stop for Timer 4
        0 = stop 1 = start for timer 4
[19] Timer 3 auto reload on/off
0 = one-shot 1 = interval mode (auto reload)
[18] Timer 3 output inverter on/off
        0 = off, 1 = on
[17] Timer 3 manual update
[16] Timer 3 start / top
[15:12] Timer2
[11:8] Timer 1
[7:5] reserved
[4] dead zone enable
[3:0] Timer 0
TCNTBn/TCMPBn/TCNTOn (n:0-3)
| Register | Address | R/W | Desc | Reset value | 
| TCNTB0 | 0x5100000C | R/W | Timer 0 count buffer register | 0x0 | 
| TCMPB0 | 0x51000010 | R/W | Timer 0 compare buffer register1 | 0 | 
| TCNTO0 | 0x51000014 | R | Timer 0 count observation register | 0 | 
其它几个定时器的依次编号。地址连续。均为16位寄存器。
TCNTB4/TCNTO4
4没有PWN输出引脚,也即不需要PWN,因此没有TCMPB寄存器。开始地址接上面最后一个地址。
| Register | Address | R/W | Desc | Reset value | 
| TCNTB4 | 0x5100003C | R/W | Timer 0 count buffer register | 0x0 | 
| TCNTO4 | 0x51000040 | R | Timer 0 count observation register | 0 | 
均为16位寄存器。
使用Timer 4来产生中断,在中断中实现跑马的效果。
首先,取消Timer 4的中断屏蔽:
1 2 3 4  | void init_interrupt_controller(){   intcont->INTMSK = ~ ((1<<14));    // timer 4 id: 14} | 
初始化Timer 4的参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37  | struct S3C2440_PWM_TIMER{    uint32_t TCFG0;    uint32_t TCFG1;    uint32_t TCON;    struct    {        uint32_t TCNTBn;        uint32_t TCMPBn;        uint32_t TCNTOn;    } TIMER0_3[4];    struct    {        uint32_t TCNTB4;        uint32_t TCNTO4;    } TIMER4;};volatile struct S3C2440_PWM_TIMER * timer =     (volatile struct S3C2440_PWM_TIMER *)0x51000000;void pwm_timer_init(){#define HZ 10    timer->TCFG0 = 255 << 8;      // Prescaler 1 [15:8]     timer->TCFG1 = 0x3<<16;  // MUX 4 [19: 16] 0011 = 1/16    timer->TIMER4.TCNTB4 = 67000000 / 255/ 16 / HZ;}void pwm_timer_start(){    // first set manual update and auto reload bit     timer->TCON = (1 << 22) | (1 << 21);     // now start timer and clear manual update bit    timer->TCON = (1 << 22) | (1 << 20);} | 
整个初始化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19  | void init(){    disable_watchdog();         clk_init();    init_gpio();    init_interrupt_controller();    pwm_timer_init();    asm volatile (        "msr cpsr_c, #0xd2\n\t"     // enter IRQ mode        "ldr sp, =3072\n\t"         // set IRQ mode stack        "msr cpsr_c, #0x53");       // re-enter svc mode and enable IRQ and FIQ    pwm_timer_start();} | 
中断处理函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | int led = 4;void irq_handler(){    unsigned long off = intcont->INTOFFSET;    GPFDAT = ~(1 << led);    led ++;    if (led >= 7)        led = 4;    if (off == 5) {            EINTPND = 1 << 11;        }    intcont->SRCPND = 1 << off;    intcont->INTPND = 1 << off;} |