1 /**
2 * \ingroup MODULMACROS
3 *
4 * \file GetDcoFrequency.c
5 *
6 * \brief <FILEBRIEF>
7 *
8 */
9 /*
10 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
11 *
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #include "arch.h"
43 #include "edt.h"
44 #include "hal.h"
45 #include "hal_ref.h"
46 #include "stream.h"
47 #include "JTAG_defs.h"
48 #include "error_def.h"
49 #include "../include/hw_compiler_specific.h"
50
51 #define FlashUpperBoarder 2140000ul // 2,14 MHz
52 #define FlashLowerBoarder 1410000ul // 1,41 MHz
53
54 static unsigned short loopDco[] =
55 {
56 0x40b2, 0x5a80, 0x0120, 0xc232, 0xc0f2, 0x003f, 0x0057, 0xd0f2,
57 0x0007, 0x0057, 0x45c2, 0x0056, 0x46c2, 0x0057, 0x43c2, 0x0058,
58 0xea0a, 0xe909, 0x5319, 0x23fe, 0x531a, 0x23fc, 0x4303, 0x3fff
59 };
60 static const unsigned short sizeLoopDco = (unsigned short)(sizeof(loopDco)/sizeof(*loopDco));
61
62 static unsigned short loopFll[] =
63 {
64 0x40b2, 0x5a80, 0x0120, 0xc232, 0xd072, 0x0040, 0x4032, 0x0040,
65 0x40f2, 0x0080, 0x0052, 0x43c2, 0x0050, 0x45c2, 0x0051, 0xd0f2,
66 0x0080, 0x0053, 0xc0f2, 0x005f, 0x0054, 0xea0a, 0xe909, 0x5319,
67 0x23fe, 0x531a, 0x23fc, 0x4303, 0x3fff
68 };
69 static const unsigned short sizeLoopFll = (unsigned short)(sizeof(loopFll)/sizeof(*loopFll));
70
71 /*--------------------------------------------------------------------------------*/
72 #ifdef MSP430_UIF
73 static unsigned short Time = 0;
74
75 #pragma vector=TIMERA1_VECTOR
TIMER_A_ISR_(void)76 __interrupt void TIMER_A_ISR_(void)
77 {
78 Time++;
79 TACTL &= ~TAIFG;
80 }
81
StartTimer()82 static void StartTimer()
83 {
84 TACTL = 0; // STOP Timer
85 TACTL &= ~CCIFG; // Clear the interrupt flag
86 TACTL = TASSEL_2; // Timer is runnig at 1 Mhz
87 TACCR0 = 0x2E9; // Load CCR0 with delay... (1ms delay)
88 TAR = 0;
89 TACTL |= TACLR + MC_1 + TAIE; // Start Timer
90 }
91
StopTimer()92 static void StopTimer()
93 {
94 TACTL &= ~MC_1;
95 TACTL &= ~TAIE; // Start Timer
96 }
97 #endif
98
99 /*--------------------------------------------------------------------------------*/
100
101 #ifdef eZ_FET
StartTimer()102 static void StartTimer()
103 {
104 TB0CTL = 0; // STOP Timer
105 TB0CTL = ID__8 + TBSSEL__SMCLK; // Timer_B source:SMCLK ,SMCLK/0 = 25
106 TB0CCR0 = 0x9cf; // Load CCR0 with delay... (1ms delay)
107 TB0CCTL0 &= ~CCIFG; // Clear the interrupt flag
108 TB0CCTL0 |= CCIE ;
109 TB0CTL |= TBCLR + MC__UP;
110 }
111
StopTimer()112 static void StopTimer()
113 {
114 TB0CTL &= ~MC__UP;
115 TB0CTL = 0; // STOP Timer
116 // restore timer B0 1ms delay value
117 IHIL_InitDelayTimer();
118 }
119 #endif
120
121 /*--------------------------------------------------------------------------------*/
122
123 #ifdef MSP_FET
StartTimer()124 static void StartTimer()
125 {
126 TA2CTL = 0; // STOP Timer
127 TA2CTL = ID__8 + TASSEL__SMCLK; // Timer_A source:SMCLK ,SMCLK/0 = 25
128 TA2CCR0 = 0x7d8; // Load CCR0 with delay... (1ms delay)
129 TA2CCTL0 &= ~CCIFG; // Clear the interrupt flag
130 TA2CCTL0 |= CCIE ;
131 TA2CTL |= TACLR + MC__UP;
132 }
133
StopTimer()134 static void StopTimer()
135 {
136 TA2CTL &= ~MC__UP;
137 TA2CTL = 0; // STOP Timer
138 // restore timer A2 1ms delay value
139 IHIL_InitDelayTimer();
140 }
141 #endif
142
143
144 static unsigned long (*ReadCounterRegsFunc)() = 0;
145 static void (*WriteRegFunc)(int, unsigned long) = 0;
146 static void (*SetPCFunc)(unsigned long) = 0;
147 static void (*WriteRamFunc)(unsigned short, unsigned short*, unsigned short) = 0;
148 static void (*ReadRamFunc)(unsigned short, unsigned short*, unsigned short) = 0;
149 static HalFuncInOut SyncFunc = 0;
150
151
readFromRam(unsigned short address,unsigned short * buffer,unsigned short numWords)152 static void readFromRam(unsigned short address, unsigned short* buffer, unsigned short numWords)
153 {
154 while (numWords-- > 0)
155 {
156 *buffer = ReadMemWord(address);
157 address += 2;
158 ++buffer;
159 }
160 }
161
writeToRam(unsigned short address,unsigned short * data,unsigned short numWords)162 static void writeToRam(unsigned short address, unsigned short* data, unsigned short numWords)
163 {
164 while (numWords-- > 0)
165 {
166 WriteMemWord(address, *data);
167 address += 2;
168 ++data;
169 }
170 }
171
readFromRamX(unsigned short address,unsigned short * buffer,unsigned short numWords)172 static void readFromRamX(unsigned short address, unsigned short* buffer, unsigned short numWords)
173 {
174 while (numWords-- > 0)
175 {
176 *buffer = ReadMemWordX(address);
177 address += 2;
178 ++buffer;
179 }
180 }
181
writeToRamX(unsigned short address,unsigned short * data,unsigned short numWords)182 static void writeToRamX(unsigned short address, unsigned short* data, unsigned short numWords)
183 {
184 while (numWords-- > 0)
185 {
186 WriteMemWordX(address, *data);
187 address += 2;
188 ++data;
189 }
190 }
191
readCounterRegisters()192 static unsigned long readCounterRegisters()
193 {
194 unsigned short r9 = 0 , r10 = 0;
195 unsigned long counter = 0;
196
197 r9 = ReadCpuReg_uShort(9);
198 r10 = ReadCpuReg_uShort(10);
199 counter = r10;
200 return (counter << 16) | r9;
201 }
202
readCounterRegistersX()203 static unsigned long readCounterRegistersX()
204 {
205 unsigned long r9 = 0, r10 = 0;
206
207 r9 = ReadCpuRegX(9);
208 r10 = ReadCpuRegX(10);
209 return (r10 << 16) | r9;
210 }
211
writeRegister(int r,unsigned long value)212 static void writeRegister(int r, unsigned long value)
213 {
214 WriteCpuReg(r, value);
215 }
216
writeRegisterX(int r,unsigned long value)217 static void writeRegisterX(int r, unsigned long value)
218 {
219 WriteCpuRegX(r, value);
220 }
221
setPC(unsigned long address)222 static void setPC(unsigned long address)
223 {
224 SetPc(address);
225 }
226
setPCX(unsigned long address)227 static void setPCX(unsigned long address)
228 {
229 SetPcX(address);
230 }
231
setPCJtag(unsigned long address)232 static void setPCJtag(unsigned long address)
233 {
234 SetPcJtagBug(address);
235 IHIL_Tclk(1);
236 }
237
238
239
measureFrequency(unsigned short RamStart,unsigned short DCO,unsigned short BCS1)240 static unsigned long measureFrequency(unsigned short RamStart, unsigned short DCO, unsigned short BCS1)
241 {
242 unsigned long startTime;
243 unsigned long stopTime;
244 unsigned long elapseTime = 0;
245 unsigned long counter = 0;
246 unsigned long freq = 0;
247
248 #if defined(eZ_FET) || defined(MSP_FET)
249 unsigned short *TimerTick = 0;
250 #endif
251 WriteRegFunc(5, DCO);
252 WriteRegFunc(6, BCS1);
253
254 SetPCFunc(RamStart);
255 cntrl_sig_release();
256
257 #if defined(eZ_FET) || defined(MSP_FET)
258 STREAM_getSharedVariable(ID_SHARED_MEMORY_TYPE_TIMER_TICK, &TimerTick);
259 #endif
260
261 StartTimer(); // Time the delay (as we could be interrupted, etc.).
262
263 #if defined(eZ_FET) || defined(MSP_FET)
264 startTime = *(unsigned short*)TimerTick; // System timestamp (in milliseconds).
265 __delay_cycles(800000ul);
266 stopTime = *(unsigned short*)TimerTick;
267 #endif
268
269 #ifdef MSP430_UIF
270 startTime = Time; // System timestamp (in milliseconds).
271 __delay_cycles(240000ul); //~30ms
272 stopTime = Time;
273 #endif
274
275 StopTimer();
276 {
277 StreamSafe stream_tmp;
278 unsigned char DummyIn[8] = {0x20,0x01,0x80,0x5A,0,0,0,0}; // wdtAddr, wdtCtrl
279 STREAM_internal_stream(DummyIn, sizeof(DummyIn), 0, 0, &stream_tmp);
280 SyncFunc(MESSAGE_NEW_MSG | MESSAGE_LAST_MSG);
281 STREAM_external_stream(&stream_tmp);
282 }
283
284 elapseTime = startTime < stopTime ? stopTime - startTime : startTime - stopTime; // System time can wrap.
285
286 counter = ReadCounterRegsFunc();
287
288 // Calculate a device speed (cycles/second). Multiply counter value by 3 (3 clock cycles per loop),
289 // and add 31 cycles for funclet setup, then normalize to one second.
290 freq = ((counter * 3 + 31) * 1000) / elapseTime;
291
292 #if defined(eZ_FET) || defined(MSP_FET)
293 STREAM_deleteSharedVariable(ID_SHARED_MEMORY_TYPE_TIMER_TICK);
294 #endif
295 return freq;
296 }
297
298
299
findDcoSettings(unsigned short jtagBug)300 short findDcoSettings(unsigned short jtagBug)
301 {
302 unsigned short MAXRSEL = 0x7;
303 unsigned short DCO = 0x0;
304 unsigned short BCS1 = 0x6;
305 unsigned short BackupRam[30];
306 unsigned short RamStart = 0;
307 unsigned long DcoFreq = 0;
308
309 // get target RAM start
310 if(STREAM_get_word(&RamStart) < 0)
311 {
312 return(HALERR_EXECUTE_FUNCLET_NO_RAM_START);
313 }
314
315 if(STREAM_get_word(&MAXRSEL) < 0)
316 {
317 return(HALERR_EXECUTE_FUNCLET_NO_MAXRSEL);
318 }
319
320 if (MAXRSEL == 0xF)
321 {
322 BCS1 = 0x9;
323 }
324
325 SetPCFunc(ROM_ADDR); //Prevent Ram corruption on F123/F413
326
327 //----------------Backup original Ram content--------------
328 ReadRamFunc(RamStart, BackupRam, sizeLoopDco);
329
330 // ----------------Download DCO measure funclet------------
331 WriteRamFunc(RamStart, loopDco, sizeLoopDco);
332
333 // do measurement
334 int allowedSteps = 40;
335
336 do
337 {
338 DcoFreq = measureFrequency(RamStart, (DCO<<5), (0x80|BCS1));
339 //Ram content will probably be corrupted after each measurement on devices with jtag bug
340 //Reupload on every iteration
341 if (jtagBug)
342 {
343 WriteRamFunc(RamStart, loopDco, sizeLoopDco);
344 }
345
346 if (DcoFreq == 0)
347 {
348 return (-1);
349 }
350
351 if (DcoFreq > FlashUpperBoarder) // Check for upper limit - 10%.
352 {
353 if(DCO-- == 0)
354 {
355 DCO = 7;
356 if (BCS1-- == 0)
357 {
358 return (-1); // Couldn't get DCO working with correct frequency.
359 }
360 }
361 }
362 else if (DcoFreq < FlashLowerBoarder) // Check for lower limit + 10%.
363 {
364 if(++DCO > 7)
365 {
366 DCO = 0;
367 if (++BCS1 > MAXRSEL)
368 {
369 return (-1); // Couldn't get DCO working with correct frequency.
370 }
371 }
372 }
373 else
374 {
375 break;
376 }
377 }
378 while (--allowedSteps > 0);
379
380 // restore Ram content
381 WriteRamFunc(RamStart, BackupRam, sizeLoopDco);
382
383 if (allowedSteps <= 0)
384 {
385 return (-1); // Couldn't get DCO working with correct frequency.
386 }
387 // measurement end
388
389 // return measured values
390 STREAM_put_word( (DCO<<5) );
391 STREAM_put_word( (0x80|BCS1) );
392 STREAM_put_word( 0 );
393 return 0;
394 }
395
396
findFllSettings(unsigned short jtagBug)397 short findFllSettings(unsigned short jtagBug)
398 {
399 unsigned short first = 0, last = 27, mid, reload;
400 unsigned short BackupRam[30];
401 unsigned short RamStart = 0;
402 unsigned long DcoFreq = 0;
403
404 // get target RAM start
405 if(STREAM_get_word(&RamStart) < 0)
406 {
407 return(HALERR_EXECUTE_FUNCLET_NO_RAM_START);
408 }
409
410 SetPCFunc(ROM_ADDR); //Prevent Ram corruption on F123/F413
411
412 //----------------Backup original Ram content--------------
413 ReadRamFunc(RamStart, BackupRam, sizeLoopFll);
414
415 // ----------------Download FLL measure funclet------------
416 WriteRamFunc(RamStart, loopFll, sizeLoopFll);
417
418 // Binary search through the available frequencies selecting the highest frequency < (476KHz - 10%).
419 while (first + 1 < last)
420 {
421 mid = (last + first) / 2;
422 reload = 0;
423
424 // Select DCO range from 0.23MHz to 11.2MHz. Specify frequency via Ndco. Disable Modulation. Enable DCO+.
425 DcoFreq = measureFrequency(RamStart, (mid << 3), 0);
426
427 //Ram content will probably be corrupted after each measurement on devices with jtag bug
428 //Reupload on every iteration
429 if (jtagBug)
430 {
431 WriteRamFunc(RamStart, loopFll, sizeLoopFll);
432 }
433
434
435 if (DcoFreq == 0)
436 {
437 break;
438 }
439 else
440 {
441 if (DcoFreq > FlashUpperBoarder) // Max. Flash Controller frequency - 10%.
442 {
443 last = mid;
444 reload = 1;
445 }
446 else
447 {
448 first = mid;
449 }
450 }
451 }
452 if (reload)
453 {
454 DcoFreq = measureFrequency(RamStart, (first << 3), 0);
455 }
456
457 // restore Ram content
458 WriteRamFunc(RamStart, BackupRam, sizeLoopDco);
459
460 if (((DcoFreq < 257000 * 5) || (DcoFreq > 476000 * 5)))
461 {
462 return -1;
463 }
464 // measurement end
465
466 // return measured values
467 STREAM_put_word(0x00);
468 STREAM_put_word( (first << 3) );
469 STREAM_put_word(0x80);
470 STREAM_put_word(0x80);
471 STREAM_put_word(0);
472 return 0;
473 }
474
475
HAL_FUNCTION(_hal_GetDcoFrequency)476 HAL_FUNCTION(_hal_GetDcoFrequency)
477 {
478 ReadCounterRegsFunc = readCounterRegisters;
479 WriteRegFunc = writeRegister;
480 SetPCFunc = setPC;
481 WriteRamFunc = writeToRam;
482 ReadRamFunc = readFromRam;
483 SyncFunc = HAL_SyncJtag_Conditional_SaveContext;
484 return findDcoSettings(0);
485 }
486
HAL_FUNCTION(_hal_GetDcoFrequencyJtag)487 HAL_FUNCTION(_hal_GetDcoFrequencyJtag)
488 {
489 ReadCounterRegsFunc = readCounterRegisters;
490 WriteRegFunc = writeRegister;
491 SetPCFunc = setPCJtag;
492 WriteRamFunc = writeToRam;
493 ReadRamFunc = readFromRam;
494 SyncFunc = HAL_SyncJtag_Conditional_SaveContext;
495 return findDcoSettings(1);
496 }
497
HAL_FUNCTION(_hal_GetDcoFrequencyX)498 HAL_FUNCTION(_hal_GetDcoFrequencyX)
499 {
500 ReadCounterRegsFunc = readCounterRegistersX;
501 WriteRegFunc = writeRegisterX;
502 SetPCFunc = setPCX;
503 WriteRamFunc = writeToRamX;
504 ReadRamFunc = readFromRamX;
505 SyncFunc = HAL_SyncJtag_Conditional_SaveContextX;
506 return findDcoSettings(0);
507 }
508
HAL_FUNCTION(_hal_GetFllFrequency)509 HAL_FUNCTION(_hal_GetFllFrequency)
510 {
511 ReadCounterRegsFunc = readCounterRegisters;
512 WriteRegFunc = writeRegister;
513 SetPCFunc = setPC;
514 WriteRamFunc = writeToRam;
515 ReadRamFunc = readFromRam;
516 SyncFunc = HAL_SyncJtag_Conditional_SaveContext;
517 return findFllSettings(0);
518 }
519
HAL_FUNCTION(_hal_GetFllFrequencyJtag)520 HAL_FUNCTION(_hal_GetFllFrequencyJtag)
521 {
522 ReadCounterRegsFunc = readCounterRegisters;
523 WriteRegFunc = writeRegister;
524 SetPCFunc = setPCJtag;
525 WriteRamFunc = writeToRam;
526 ReadRamFunc = readFromRam;
527 SyncFunc = HAL_SyncJtag_Conditional_SaveContext;
528 return findFllSettings(1);
529 }
530
HAL_FUNCTION(_hal_GetFllFrequencyX)531 HAL_FUNCTION(_hal_GetFllFrequencyX)
532 {
533 ReadCounterRegsFunc = readCounterRegistersX;
534 WriteRegFunc = writeRegisterX;
535 SetPCFunc = setPCX;
536 WriteRamFunc = writeToRamX;
537 ReadRamFunc = readFromRamX;
538 SyncFunc = HAL_SyncJtag_Conditional_SaveContextX;
539 return findFllSettings(0);
540 }
541