-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathrpi.c
141 lines (116 loc) · 3.18 KB
/
rpi.c
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include "arm_exceptions.h"
#include "bcm283x.h"
#include "bcm283x_it.h"
#include "bcm283x_gpio.h"
#include "bcm283x_aux.h"
#include "bcm283x_mailbox.h"
#include "bcm283x_clockmgr.h"
#include "vc_property.h"
#include "rpi.h"
static uint32_t freq_cpu = 700000000;
static uint32_t freq_core = 250000000;
// System Timers
systimer_t *systimer = (systimer_t *) SYSTIMER;
volatile uint64_t systime(void) {
uint64_t t;
uint32_t chi;
uint32_t clo;
chi = systimer->CHI;
clo = systimer->CLO;
if (chi != systimer->CHI) {
chi = systimer->CHI;
clo = systimer->CLO;
}
t = chi;
t = t << 32;
t += clo;
return t;
}
volatile uint64_t elapsed_from(uint64_t t) {
uint64_t now;
uint32_t chi;
uint32_t clo;
now = systime();
if (now > t) {
return now - t;
} else {
return ULLONG_MAX - t + now;
}
chi = systimer->CHI;
clo = systimer->CLO;
if (chi != systimer->CHI) {
chi = systimer->CHI;
clo = systimer->CLO;
}
t = chi;
t = t << 32;
t += clo;
return t;
}
// IRQ handler
#define IRQ_SYSTIMERS (IRQ_SYSTIMER(0) | \
IRQ_SYSTIMER(1) | \
IRQ_SYSTIMER(2) | \
IRQ_SYSTIMER(3))
void __attribute__((interrupt("IRQ"))) irq_handler(void) {
if (IRQ_PEND1 & IRQ_SYSTIMERS) {
isr_irq_timer();
}
if (IRQ_PEND1 & IRQ_AUX) {
if (AUX_IRQ & AUX_FLAG_MU) {
isr_irq_mini_uart();
}
}
}
// Clock speed
uint32_t rpi_freq_core() {
return freq_core;
}
uint32_t rpi_freq_cpu() {
return freq_cpu;
}
// Initialize Raspberry Pi peripherals
#define MB_GET_CLK_RATE (0x00030002)
#define CLKID_ARM (3)
#define CLKID_CORE (4)
enum MB_BUFF { BUFSIZE=0, MB_REQ_RES, \
TAG0, VALBUFSIZE0, REQ_RES0, VALUE00, VALUE01,\
TAG1, VALBUFSIZE1, REQ_RES1, VALUE10, VALUE11,\
ENDTAG };
static void get_clock_value() {
__attribute__((aligned(16))) uint32_t clkinfo[ENDTAG + 1];
clkinfo[BUFSIZE] = 4 * (ENDTAG + 1);
clkinfo[MB_REQ_RES] = MB_PROP_REQUEST;
clkinfo[TAG0] = MB_GET_CLK_RATE;
clkinfo[VALBUFSIZE0] = 8;
clkinfo[REQ_RES0] = 0;
clkinfo[VALUE00] = CLKID_ARM;
clkinfo[VALUE01] = 0;
clkinfo[TAG1] = MB_GET_CLK_RATE;
clkinfo[VALBUFSIZE1] = 8;
clkinfo[REQ_RES1] = 0;
clkinfo[VALUE10] = CLKID_CORE;
clkinfo[VALUE11] = 0;
clkinfo[ENDTAG] = 0;
mailbox_write(MB_CH_PROP_ARM, (uint32_t) BUSADDR(clkinfo) >> 4);
mailbox_read(MB_CH_PROP_ARM);
if (clkinfo[MB_REQ_RES] == MB_PROP_SUCCESS) {
if (clkinfo[REQ_RES0] & MB_PROP_SUCCESS) {
freq_cpu = clkinfo[VALUE01];
}
if (clkinfo[REQ_RES1] & MB_PROP_SUCCESS) {
freq_core = clkinfo[VALUE11];
}
}
}
void rpi_init() {
// read values of freq_cpu, freq_core
get_clock_value();
// set PWM clock to 960KHz (19.2MHz / 20) as a default value
clockmgr_config_ctl((clockmgr_t *) CM_PWM, CM_CTL_MASH_1STG | CM_CTL_ENAB | CM_CTL_SRC_OSC);
clockmgr_config_div((clockmgr_t *) CM_PWM, 20, 0);
// any additional initialization
}