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