-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathcpu.c
More file actions
182 lines (152 loc) · 4.54 KB
/
cpu.c
File metadata and controls
182 lines (152 loc) · 4.54 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* SPDX-FileCopyrightText: 2013 Freie Universität Berlin (FUB)
* SPDX-License-Identifier: LGPL-2.1-only
*/
/**
* @ingroup cpu_lpc23xx
* @{
*/
#include <stdint.h>
#include "cpu.h"
#include "kernel_init.h"
#include "irq.h"
#include "VIC.h"
#include "stdio_base.h"
#include "periph/init.h"
void lpc23xx_pclk_scale(uint32_t source, uint32_t target, uint32_t *pclksel, uint32_t *prescale)
{
uint32_t pclkdiv;
*prescale = source / target;
if ((*prescale % 16) == 0) {
*pclksel = 3;
pclkdiv = 8;
}
else if ((*prescale % 8) == 0) {
*pclksel = 0;
pclkdiv = 4;
}
else if ((*prescale % 4) == 0) {
*pclksel = 2;
pclkdiv = 2;
}
else {
*pclksel = 1;
pclkdiv = 1;
}
*prescale /= pclkdiv;
if (*prescale % 2) {
(*prescale)++;
}
}
void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t *prescale)
{
uint32_t pclksel;
lpc23xx_pclk_scale(source, target, &pclksel, prescale);
PCLKSEL0 = (PCLKSEL0 & ~(BIT2 | BIT3)) | (pclksel << 2); /* timer 0 */
PCLKSEL0 = (PCLKSEL0 & ~(BIT4 | BIT5)) | (pclksel << 4); /* timer 1 */
PCLKSEL1 = (PCLKSEL1 & ~(BIT12 | BIT13)) | (pclksel << 12); /* timer 2 */
}
/******************************************************************************
** Function name: install_irq
**
** Descriptions: Install interrupt handler
** parameters: Interrupt number, interrupt handler address,
** interrupt priority
** Returned value: true or false, return false if IntNum is out of range
**
******************************************************************************/
#define VIC_BASE_ADDR 0xFFFFF000
bool install_irq(int IntNumber, void (*HandlerAddr)(void), int Priority)
{
VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */
if (IntNumber >= VIC_SIZE) {
return (false);
}
else {
/* find first un-assigned VIC address for the handler */
int *vect_addr = (int *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber * 4);
int *vect_cntl = (int *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber * 4);
*vect_addr = (int)HandlerAddr; /* set interrupt vector */
*vect_cntl = Priority;
VICIntEnable = 1 << IntNumber; /* Enable Interrupt */
return(true);
}
}
void arm_reset(void)
{
/*
* We abuse the watchdog timer for a reset.
*/
irq_disable();
/* Set the watchdog timeout constant to 0xFFFF */
WDTC = 0xFFFF;
/*
* Enable watchdog interrupt and enable reset on watchdog timeout.
* (The reset on watchdog timeout flag is ignored, if interrupt on watchdog
* timeout is not set. Thus, we set both. The reset takes precedence over
* the interrupt, anyway.)
*/
WDMOD = 0x03;
/*
* Feed the watchdog by writing 0xAA followed by 0x55:
* Reload the watchdog timer with the value in WDTC (0xFFFF)
*/
WDFEED = 0xAA;
WDFEED = 0x55;
/* Wait for the watchdog timer to expire, thus performing a reset */
while(1) {}
}
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
void cpu_init(void)
{
extern void board_init(void);
/* configure CPU clock */
cpu_init_clks();
/* set up GPIOs */
gpio_init_ports();
/* board specific setup of i/o pins */
board_init();
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
early_init();
/* trigger static peripheral initialization */
periph_init();
}
/* RSIR will only have POR bit set even when waking up from Deep Power Down
* Use signature in battery RAM to discriminate between Deep Power Down and POR
*/
bool cpu_backup_ram_is_initialized(void)
{
static char signature[] __attribute__((section(".backup.data"))) = {
'R', 'I', 'O', 'T'
};
/* Only in case when a reset occurs and the POR = 0, the BODR bit
* indicates if the V_DD (3V3) voltage was below 2.6 V or not.
*/
if ((RSIR & (RSIR_BODR | RSIR_POR)) == (RSIR_BODR | RSIR_POR)) {
RSIR |= RSIR_BODR;
}
/* external reset */
if (RSIR & RSIR_EXTR) {
return false;
}
if (signature[0] != 'R') {
return false;
}
if (signature[1] != 'I') {
return false;
}
if (signature[2] != 'O') {
return false;
}
if (signature[3] != 'T') {
return false;
}
/* When we wake from Deep Sleep only POR is set, just like in the real
* POR case. Clear the bit to create a new, distinct state.
*/
RSIR |= RSIR_POR;
return true;
}
/** @} */