-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclock.hpp
More file actions
203 lines (193 loc) · 5.6 KB
/
clock.hpp
File metadata and controls
203 lines (193 loc) · 5.6 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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#ifndef XC32_CLOCK_INC
#define XC32_CLOCK_INC
#include <XC32_config.hpp>
#include <device_include.h>
//#define HMLIB_NOLIB
#ifndef XC32_DEBUGMODE
//# include <peripheral/timer.h>
#endif
#include<XCBase/type.hpp>
#include<XCBase/lock.hpp>
//******* 必ず必要な初期化関数 ******
//一番初めに必ずオシレータのクロック指定が必要
//クロック自体は、コンフィギュレーションビットで指定
//あくまでも、クロックを設定するのではなく、ただ関数にクロックを教えているだけであることに注意!!
namespace xc32{
using namespace xc;
namespace oscillator{
struct mutex{
private:
bool IsLock;
public:
mutex() :IsLock(false){}
public:
bool lock(){
if(is_lock())return false;
__asm("nop");
//lock code1 0xAA996655,lock code2 0x556699AA 以外の数字を入れることでロックする
SYSKEY = 0x00;
__asm("nop");
//lock code1 0xAA996655 を入れる
SYSKEY = 0xAA996655;
__asm("nop");
//lock code2 0x556699AAを入れる
SYSKEY = 0x556699AA;
__asm("nop");
//unlock
IsLock = true;
return false;
}
bool is_lock()const{ return IsLock; }
void unlock(){
if(!is_lock())return;
__asm("nop");
//lock code1 0xAA996655,lock code2 0x556699AA 以外の数字を入れることでロックする
SYSKEY = 0x00;
IsLock = false;
}
};//}Mutex;
extern mutex Mutex;
typedef xc::lock_guard<mutex> lock_guard;
typedef xc::unique_lock<mutex> unique_lock;
}
namespace clock_div {
#if defined(XC32_PIC32MX)
enum type {
div1=0,
div2=1,
div4=2,
div8=3
};
#elif defined(XC32_PIC32MZ)
enum type {
div1=0,
div2=1,
div4=3,
div8=7,
div16=15,
div32=31,
div64=63,
div128=127
};
#else
# error unknow device!
#endif
}
struct clock_block{
private:
static uint64 SystemClock;
static clock_div::type BusDiv;
public:
bool IsLock;
uint64 RequestSystemClock;
clock_div::type RequestBusDiv;
public:
clock_block()
: IsLock(false)
, RequestSystemClock(10000000) //1MHz
, RequestBusDiv(clock_div::div8){
}
public:
void config(uint64 Hz_, clock_div::type Div_ = clock_div::div8){
RequestSystemClock = Hz_;
RequestBusDiv = Div_;
}
bool lock(uint64 Hz_, clock_div::type Div_ = clock_div::div8){
config(Hz_, Div_);
return lock();
}
bool lock(){
if(is_lock())return false;
initialize(RequestSystemClock, RequestBusDiv);
IsLock = true;
return false;
}
bool is_lock()const{return IsLock;}
void unlock(){
IsLock = false;
}
public:
static void set_system_clock(uint64 Hz_) { SystemClock = Hz_; }
static uint64 get_system_clock() { return SystemClock; }
static void set_bus_div(clock_div::type Div_) {
//oscillatorへの書き込みmutexをロック
oscillator::lock_guard Lock(oscillator::Mutex);
#if defined(XC32_PIC32MX)
//本当はPBDIVRDYを待たなければいけないはずだが、ヘッダにレジスタ設定されていない・・・
//while(!OSCCONbits.PBDIVRDY);
OSCCONbits.PBDIV = static_cast<unsigned char>(Div_);
#elif defined(XC32_PIC32MZ)
//本当はPBDIVRDYを待たなければいけないはずだが、ヘッダにレジスタ設定されていない・・・
while(!PB1DIVbits.PBDIVRDY);
PB1DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB2DIVbits.PBDIVRDY);
PB2DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB3DIVbits.PBDIVRDY);
PB3DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB4DIVbits.PBDIVRDY);
PB4DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB5DIVbits.PBDIVRDY);
PB5DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB7DIVbits.PBDIVRDY);
PB7DIVbits.PBDIV = static_cast<unsigned char>(Div_);
while(!PB8DIVbits.PBDIVRDY);
PB8DIVbits.PBDIV = static_cast<unsigned char>(Div_);
#else
# error unknow device!
#endif
BusDiv = Div_;
}
static uint64 get_bus_clock() {
#if defined(XC32_PIC32MX)
return (SystemClock >> static_cast<unsigned int>(BusDiv));
#elif defined(XC32_PIC32MZ)
return (SystemClock / (static_cast<unsigned int>(BusDiv) + 1));
#endif
}
static void change_cpu_clock(clock_div::type Div_) {
//oscillatorへの書き込みmutexをロック
oscillator::lock_guard Lock(oscillator::Mutex);
#if defined(XC32_PIC32MX)
//本当はPBDIVRDYを待たなければいけないはずだが、ヘッダにレジスタ設定されていない・・・
//while(!OSCCONbits.PBDIVRDY);
OSCCONbits.PBDIV = static_cast<unsigned char>(Div_);
#elif defined(XC32_PIC32MZ)
//PBCLK7がCPUに対応する
while(!PB7DIVbits.PBDIVRDY);
PB7DIVbits.PBDIV = static_cast<unsigned char>(Div_);
#else
# error unknow device!
#endif
}
private:
static void initialize(uint64 Hz_, clock_div::type Div_ = clock_div::div8) {
set_system_clock(Hz_);
set_bus_div(Div_);
#if defined(XC32_PIC32MZ)
//oscillatorへの書き込みmutexをロック
oscillator::lock_guard Lock(oscillator::Mutex);
__asm("nop");
PB2DIVbits.ON = 1;
__asm("nop");
PB3DIVbits.ON = 1;
__asm("nop");
PB4DIVbits.ON = 1;
__asm("nop");
PB5DIVbits.ON = 1;
__asm("nop");
PB7DIVbits.ON = 1;
__asm("nop");
PB8DIVbits.ON = 1;
#endif
}
};
namespace clock{
inline void set_system_clock(uint64 Hz_) { clock_block::set_system_clock(Hz_); }
inline uint64 get_system_clock() { return clock_block::get_system_clock(); }
inline void set_bus_div(clock_div::type Div_) {clock_block::set_bus_div(Div_);}
inline uint64 get_bus_clock() { return clock_block::get_bus_clock(); }
inline void change_cpu_clock(clock_div::type Div_) {clock_block::change_cpu_clock(Div_);}
}
}
#
#endif