-
Notifications
You must be signed in to change notification settings - Fork 2
/
m68hc705c8s_dumper.ino
232 lines (173 loc) · 4.99 KB
/
m68hc705c8s_dumper.ino
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// M68HC705C8S dumper
// CPU reset
#define P_CPURESET 10
// CPLD SPI bus
#define P_SPI_DATA 13
#define P_SPI_CLOCK 12
#define P_SPI_NRESET 11
#define P_CPURESET 10
// Serial I/O port linked to CPU
#define S_CPU Serial1
// set to 1 for power glitching, 0 for clock glitching
#define POWER_GLITCH 1
void sendGlitchConfig(uint8_t clockCount, uint8_t glitchStart, uint8_t glitchStop)
{
uint16_t shiftval;
shiftval = (glitchStart & 0x0F) | ((glitchStop & 0x0F) << 4) | ((clockCount & 0x7F) << 8) | (POWER_GLITCH ? 0 : 0x8000);
digitalWrite(P_SPI_NRESET, LOW);
digitalWrite(P_SPI_NRESET, HIGH);
for (uint8_t i=0; i<16; i++) {
digitalWrite(P_SPI_DATA, shiftval & 0x8000 ? HIGH : LOW);
digitalWrite(P_SPI_CLOCK, HIGH);
digitalWrite(P_SPI_CLOCK, LOW);
shiftval <<= 1;
}
}
void setup() {
// set up console serial
Serial.begin(115200);
Serial.println(F("Booting..."));
// hold CPU in reset
digitalWrite(P_CPURESET, LOW);
pinMode(P_CPURESET, OUTPUT);
// set up SPI pins
digitalWrite(P_SPI_NRESET, LOW);
digitalWrite(P_SPI_CLOCK, LOW);
digitalWrite(P_SPI_DATA, LOW);
pinMode(P_SPI_NRESET, OUTPUT);
pinMode(P_SPI_CLOCK, OUTPUT);
pinMode(P_SPI_DATA, OUTPUT);
// set up CPU serial
S_CPU.begin(4800);
Serial.println(F("Ready..."));
}
/////
// Glitch search parameters
// Number of clock phases (depends on the clock divide ratio)
#define NPHASES 16
// Maximum glitch position
#define POSMAX 30
// Minimum glitch position
#define POSMIN 20
// Minimum glitch width
#define WIDMIN 0
// Maximum glitch width
#define WIDMAX 15
void loop() {
// glitch is 32 clocks, we've found it
// findGlitch();
for (uint8_t glitchPos = POSMAX; glitchPos > POSMIN; glitchPos--) {
for (uint8_t glitchPhase = 0; glitchPhase < NPHASES; glitchPhase++) {
for (uint8_t glitchWidth = WIDMIN; glitchWidth < (WIDMAX-glitchPhase); glitchWidth++) {
// hold chip in reset
digitalWrite(P_CPURESET, LOW);
// clear the serial buffer
while (S_CPU.available() > 0) {
S_CPU.read();
}
Serial.print(F("Glitch: clks="));
Serial.print(glitchPos);
Serial.print(F(" phase="));
Serial.print(glitchPhase);
Serial.print(F(" width="));
Serial.print(glitchWidth);
Serial.println();
// load glitch configuration
sendGlitchConfig(glitchPos, glitchPhase, glitchPhase+glitchWidth);
// CPU internal reset delay. Min 8192 cycles (we use 15,000 for safety) of the 2MHz CPU clock
delay(100);
// release chip from reset
digitalWrite(P_CPURESET, HIGH);
// 1 byte at 4800bd = 2ms, this is 20 bytes
// the Arduino buffers a max of 64 bytes
delay(40);
if (S_CPU.available() > 3) {
uint8_t n = 0;
Serial.println(F("--> DATA RECEIVED"));
while (true) {
while (S_CPU.available() == 0);
uint8_t databyte = S_CPU.read();
Serial.print(databyte, HEX);
Serial.print(F(" "));
if (++n == 32) {
Serial.println();
n = 0;
}
}
}
//delay(200);
}
}
}
}
///////
// Next is the code to try and find the glitch offset using the CLKO pin
#if 0
// CPU reset
#define P_CPURESET 2
// CPU clock and fast write macro -- connect to CLK1
// this is PE5 / OC3C
#define P_CPUCLK 3
#define W_CPUCLK_slow(v) digitalWrite(P_CPUCLK, v); /* if(v) { PORTE |= 0x20; } else { PORTE &= 0x20; } */
#define W_CPUCLK(v) if(v) { PORTE |= _BV(PE5); } else { PORTE &= _BV(PE5); }
// CPU clock feedback -- connect to CLK2
#define P_CPUCLKFB 4
// Serial I/O port linked to CPU
#define S_CPU Serial1
// nop macro
#define NOP __asm__ __volatile__ ("nop\n\t")
void setup() {
// set up console serial
Serial.begin(115200);
Serial.println(F("Booting..."));
// hold CPU in reset
digitalWrite(P_CPURESET, LOW);
pinMode(P_CPURESET, OUTPUT);
// clock low
digitalWrite(P_CPUCLK, LOW);
pinMode(P_CPUCLK, OUTPUT);
// set clock feedback as an input
pinMode(P_CPUCLKFB, INPUT);
// set up CPU serial
S_CPU.begin(4800);
Serial.println(F("Ready..."));
}
void findGlitch() {
// *******
// * Find glitch time
// *
// reset cpu
digitalWrite(P_CPURESET, LOW);
for (word i=0; i<9000; i++) { // Oscillator startup delay -- 4096 internal processor cycles per datasheet section 3.1.1 = 8128 external clocks
W_CPUCLK_slow(1);
W_CPUCLK_slow(0);
}
digitalWrite(P_CPURESET, HIGH);
// clock
for (word i=0; i<60000; i++) {
// one clock
W_CPUCLK_slow(0);
W_CPUCLK_slow(1);
// settling delay
//NOP;
// Per MC68HC05C8/D Rev 1 page 2-2 fig 2-1b, the oscillator is a NAND gate with inputs /STOP and OSC1.
// That means that when the oscillator stops, OSC2 (feedback) will go high and stay there.
// We've set CPUCLK=1 so we should get CPUCLK=0 out.
if (digitalRead(P_CPUCLKFB)) {
Serial.print(F("Extclk stopped after "));
Serial.print(i+1);
Serial.println(F(" clocks."));
return;
}
}
Serial.println(F("No glitch found"));
}
void loop() {
// glitch is 32 clocks, we've found it
// findGlitch();
digitalWrite(P_CPURESET, HIGH);
digitalWrite(P_CPURESET, LOW);
digitalWrite(P_CPURESET, LOW);
delay(2000);
}
#endif