File size: 2,738 Bytes
829b19c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * HAL — Timer driver for OMAP3530 GP Timers
 */

#include "timer.h"

void timer_init(timer_dev_t *dev, uint32_t base, uint32_t clock_hz) {
    dev->base = (hw_reg32_t)base;
    dev->clock_hz = clock_hz;

    timer_stop(dev);

    /* Soft reset */
    reg_write32(dev->base + GPTIMER_TIOCP_CFG, 0x02);
    delay_cycles(50);
    while (!(reg_read32(dev->base + GPTIMER_TISTAT) & 0x01))
        ;

    /* Clear any pending IRQ */
    reg_write32(dev->base + GPTIMER_TISR, 0x07);

    /* No prescaler (1:1 from source clock) */
    reg_write32(dev->base + GPTIMER_TCLR, 0x00);

    /* Start from 0 */
    reg_write32(dev->base + GPTIMER_TCRR, 0x00000000);
    reg_write32(dev->base + GPTIMER_TLDR, 0x00000000);
}

void timer_start(timer_dev_t *dev) {
    reg_set32(dev->base + GPTIMER_TCLR, GPTIMER_TCLR_ST);
}

void timer_stop(timer_dev_t *dev) {
    reg_clr32(dev->base + GPTIMER_TCLR, GPTIMER_TCLR_ST);
}

void timer_set_period_ms(timer_dev_t *dev, uint32_t ms) {
    uint32_t ticks = (dev->clock_hz / 1000UL) * ms;
    reg32_t load = 0xFFFFFFFFUL - ticks + 1;
    reg_write32(dev->base + GPTIMER_TLDR, load);
    reg_write32(dev->base + GPTIMER_TCRR, load);
    /* Enable auto-reload */
    reg_set32(dev->base + GPTIMER_TCLR, GPTIMER_TCLR_AR);
}

void timer_set_period_us(timer_dev_t *dev, uint32_t us) {
    uint32_t ticks = (dev->clock_hz / 1000000UL) * us;
    reg32_t load = 0xFFFFFFFFUL - ticks + 1;
    reg_write32(dev->base + GPTIMER_TLDR, load);
    reg_write32(dev->base + GPTIMER_TCRR, load);
    reg_set32(dev->base + GPTIMER_TCLR, GPTIMER_TCLR_AR);
}

uint32_t timer_get_count(timer_dev_t *dev) {
    return reg_read32(dev->base + GPTIMER_TCRR);
}

void timer_reset(timer_dev_t *dev) {
    reg_write32(dev->base + GPTIMER_TCRR, 0x00000000);
    /* Trigger reload on next overflow */
    reg_write32(dev->base + GPTIMER_TTGR, 0x00);
}

int timer_expired(timer_dev_t *dev) {
    return (reg_read32(dev->base + GPTIMER_TISR) & 0x01) != 0;
}

void timer_clear_irq(timer_dev_t *dev) {
    reg_write32(dev->base + GPTIMER_TISR, 0x07);
}

void timer_enable_irq(timer_dev_t *dev) {
    reg_write32(dev->base + GPTIMER_TIER, 0x01);   /* Overflow IRQ */
    reg_write32(dev->base + GPTIMER_TWER, 0x01);   /* Wake-up on overflow */
}

void timer_delay_ms(timer_dev_t *dev, uint32_t ms) {
    timer_stop(dev);
    timer_set_period_ms(dev, ms);
    timer_clear_irq(dev);
    timer_start(dev);
    while (!timer_expired(dev))
        ;
    timer_stop(dev);
    timer_clear_irq(dev);
}

void timer_delay_us(timer_dev_t *dev, uint32_t us) {
    timer_stop(dev);
    timer_set_period_us(dev, us);
    timer_clear_irq(dev);
    timer_start(dev);
    while (!timer_expired(dev))
        ;
    timer_stop(dev);
    timer_clear_irq(dev);
}