CVS: jtag/msp430 JTAGfunc.c,1.4,1.5 JTAGfunc.h,1.2,1.3 funclets.c,1.5,1.6

Chris Liechti <[email protected]>
Newsgroups gmane.comp.hardware.texas-instruments.msp430.gcc.cvs
Message-ID <[email protected]>
Update of /cvsroot/mspgcc/jtag/msp430
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32154/jtag/msp430

Modified Files:
	JTAGfunc.c JTAGfunc.h funclets.c 
Log Message:
- support for F2xx devices
- second executeCode implementation in funclets.c: one for F1xx/F4xx and one for F2xx
- code cleanups

Index: JTAGfunc.c
===================================================================
RCS file: /cvsroot/mspgcc/jtag/msp430/JTAGfunc.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -w -d -r1.4 -r1.5
--- JTAGfunc.c	9 Oct 2003 23:30:18 -0000	1.4
+++ JTAGfunc.c	21 Dec 2005 23:08:15 -0000	1.5
@@ -60,6 +60,10 @@
     HIL_TMS(1);
     HIL_DelayMSec(FUSECHECK_DELAY);
 #else
+    HIL_TDI(1);
+    HIL_TMS(1);
+    HIL_TCK(1);
+    // Perform fuse check
     HIL_TMS(0);
     HIL_TMS(1);
     HIL_TMS(0);
@@ -101,7 +105,7 @@
         return(STATUS_ERROR);
     }
     
-    return(STATUS_OK);
+    return STATUS_OK;
 }
 
 //----------------------------------------------------------------------------
@@ -119,14 +123,14 @@
     ResetTAP();                                         // Reset JTAG state machine, check fuse HW
    
     if (IsFuseBlown()) {                                // Stop here if fuse is already blown
-        return(STATUS_ERROR);
+        return STATUS_ERROR;
     }
 
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2401, F_WORD);                        // Set device into JTAG mode + read
     if (HIL_JTAG_IR(IR_CNTRL_SIG_CAPTURE) != JTAG_ID) {
         MSP430_Log(1, "JTAGfunc: JTAG ID wrong\n");     //DEBUG
-        return(STATUS_ERROR);
+        return STATUS_ERROR;
     }
     
     // Wait until CPU is synchronized, timeout after a limited # of attempts
@@ -141,21 +145,21 @@
             break;
         } else if (i == 1) {
             MSP430_Log(1, "JTAGfunc: Sync failed\n");   //DEBUG
-            return(STATUS_ERROR);                       // Timeout reached, return false
+            return STATUS_ERROR;                        // Timeout reached, return false
         } else {
             HIL_DelayMSec(1);
         }
     }
     if (ExecutePUC() != STATUS_OK) {                    // Perform PUC, Includes  
         MSP430_Log(1, "JTAGfunc: PUC failed\n");        //DEBUG
-        return(STATUS_ERROR);                           // target Watchdog disable.
+        return STATUS_ERROR;                            // target Watchdog disable.
     }
     if (syncCPU() != STATUS_OK) {                       // verify state
         MSP430_Log(1, "JTAGfunc: syncCPU failed\n");        //DEBUG
-        return(STATUS_ERROR);                           // target Watchdog disable.
+        return STATUS_ERROR;                            // target Watchdog disable.
     }
     
-    return(STATUS_OK);
+    return STATUS_OK;
 }
 
 //----------------------------------------------------------------------------
@@ -172,10 +176,10 @@
     for (i = 50; i > 0; i--) {
         HIL_TCLK(POS_EDGE);
         if ((HIL_JTAG_DR(0x0000, F_WORD) & 0x0080) == 0x0080) {
-            return(STATUS_OK);
+            return STATUS_OK;
         }
     }
-    return(STATUS_ERROR); 
+    return STATUS_ERROR; 
 }
 
 //----------------------------------------------------------------------------
@@ -190,13 +194,14 @@
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x3401, F_WORD);                // CPU has control of RW & BYTE.
     HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                    			// F2xxx
     HIL_JTAG_DR(MOV_IMM_PC, F_WORD);            // "mov #addr,PC" instruction
-    HIL_TCLK(NEG_EDGE);
+    HIL_TCLK(POS_EDGE);
     HIL_JTAG_DR(Addr, F_WORD);                  // Send addr value
-    HIL_TCLK(NEG_EDGE);
-    HIL_TCLK(NEG_EDGE);                         // Now the PC should be on Addr
+    HIL_TCLK(POS_EDGE);
+    HIL_TCLK(0);                    			// F2xxx
     HIL_JTAG_IR(IR_ADDR_CAPTURE);
-    if (Addr != HIL_JTAG_DR(0, 16)) return STATUS_ERROR;//ERROR: SetPC failed!
+    if (Addr != HIL_JTAG_DR(0, F_WORD)) return STATUS_ERROR;//ERROR: SetPC failed!
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2401, F_WORD);                // JTAG has control of RW & BYTE.
     return STATUS_OK;
@@ -219,11 +224,12 @@
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x3401, F_WORD);                // CPU has control of RW & BYTE.
     HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                    			// F2xxx
     HIL_JTAG_DR(MOV_IMM_RX | Regnum, F_WORD); // "mov #addr, Rx" instruction
-    HIL_TCLK(NEG_EDGE);                         // instr fetch
+    HIL_TCLK(POS_EDGE);
     HIL_JTAG_DR(Value, F_WORD);                 // Send addr value
-    HIL_TCLK(NEG_EDGE);                         // data fetch
-    HIL_TCLK(NEG_EDGE);                         // instr exec
+    HIL_TCLK(POS_EDGE);
+    HIL_TCLK(0);                                // instr exec
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2401, F_WORD);                // JTAG has control of RW & BYTE.
     return STATUS_OK;
@@ -246,12 +252,13 @@
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x3401, F_WORD);                // CPU has control of RW & BYTE.
     HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                    			// F2xxx
     HIL_JTAG_DR(MOV_RX_MEM | (Regnum << 8), F_WORD); //"mov Rx, &a"
-    HIL_TCLK(NEG_EDGE);                         // instr fetch
+    HIL_TCLK(POS_EDGE);                         // instr fetch
     HIL_JTAG_DR(SAVE_ADDRESS, F_WORD);          // Dummy addr value
-    HIL_TCLK(NEG_EDGE);                         // data fetch
-    HIL_TCLK(NEG_EDGE);                         // instr exec
-    HIL_TCLK(NEG_EDGE);                         // (writes need 2 clks)
+    HIL_TCLK(POS_EDGE);                         // data fetch
+    HIL_TCLK(POS_EDGE);                         // (writes need 2 clks)
+    HIL_TCLK(0);                                // instr exec
     HIL_JTAG_IR(IR_DATA_CAPTURE);
     *Value = HIL_JTAG_DR(0, F_WORD);            // Read databus which contains the regsiters value
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
@@ -265,7 +272,7 @@
 void HaltCPU(void) {
     SetInstrFetch();                            // Set CPU into instruction fetch mode
     
-    ClrTCLK();                                  //lch
+    HIL_TCLK(0);                                //lch
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2401, F_WORD);
     HIL_JTAG_IR(IR_DATA_16BIT);
@@ -273,18 +280,18 @@
     HIL_TCLK(NEG_EDGE);
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2409, F_WORD);                // Set JTAG_HALT bit
-    SetTCLK();
+    HIL_TCLK(1);
 }
 
 //----------------------------------------------------------------------------
 /* Function to release the target CPU from the controlled stop state
 */
 void ReleaseCPU(void) {
-    ClrTCLK();
+    HIL_TCLK(0);
     HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
     HIL_JTAG_DR(0x2401, F_WORD);                // Clear the HALT_JTAG bit
     HIL_JTAG_IR(IR_ADDR_CAPTURE);
-    SetTCLK();
+    HIL_TCLK(1);
 }
 
 //----------------------------------------------------------------------------
@@ -323,8 +330,10 @@
     HIL_JTAG_DR(0x2401, F_WORD);
     SetInstrFetch();
     HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                                // F2xx
     HIL_JTAG_DR(0x4030, F_WORD);
     HIL_TCLK(NEG_EDGE);
+    HIL_TCLK(1);                                // F2xx
     HIL_JTAG_DR(StartAddr-2, F_WORD);
     HIL_TCLK(NEG_EDGE);
     HIL_TCLK(NEG_EDGE);
@@ -534,6 +543,41 @@
     return 0;                                   // fuse is not blown
 }
 
+//~ //------------------------------------------------------------------------
+//~ /* This function blows the security fuse.
+   //~ Arguments: None
+   //~ Result:    word (STATUS_OK if burn was successful, STATUS_ERROR otherwise)
+//~ */
+//~ word BlowFuse(void)
+//~ {
+  //~ word mode = VPP_ON_TEST;   // Devices with TEST pin: VPP to TEST
+
+  //~ if ((DEVICE == 0xF149) || (DEVICE == 0xF449) ||    // w/o TEST pin are:
+      //~ (DEVICE == 0xF413) || (DEVICE == 0xF169))        // F149, F449, F413, F169
+  //~ { // Devices without TEST pin
+    //~ IR_Shift(IR_CNTRL_SIG_16BIT);// TDO becomes TDI functionality
+    //~ DR_Shift16(0x7201);
+    //~ TDOisInput();
+    //~ mode = VPP_ON_TDI;           // Enable VPP on TDI
+  //~ }
+
+  //~ IR_Shift(IR_PREPARE_BLOW);     // Initialize fuse blowing
+  //~ MsDelay(1);
+  //~ VPPon(mode);                   // Switch VPP onto selected pin
+  //~ MsDelay(5);
+  //~ IR_Shift(IR_EX_BLOW);          // Execute fuse blowing
+  //~ MsDelay(1);
+
+  //~ // Switch off power to target and wait
+  //~ ReleaseTarget();               // switch VPP and VCC target off
+  //~ MsDelay(200);
+
+  //~ // Check fuse: switch power on, simulate an initial JTAG entry
+  //~ InitTarget();                  // Supply and preset Target Board
+  //~ ResetTAP();                    // Check fuse HW, reset JTAG state machine
+
+  //~ return(IsFuseBlown());         // Return result of "is fuse blown?"
+//~ }
 
 /****************************************************************************/
 /*                         END OF SOURCE FILE                               */

Index: JTAGfunc.h
===================================================================
RCS file: /cvsroot/mspgcc/jtag/msp430/JTAGfunc.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -w -d -r1.2 -r1.3
--- JTAGfunc.h	8 Jan 2003 04:43:16 -0000	1.2
+++ JTAGfunc.h	21 Dec 2005 23:08:15 -0000	1.3
@@ -82,7 +82,7 @@
 #define F_WORD                  16
 #define V_RESET                 0xFFFE
 
-#define SLOWFUSECHECK_BUG
+//~ #define SLOWFUSECHECK_BUG
 #define FUSECHECK_DELAY     50
 #define DEFAULT_VCC         3000    // Default Vcc to 3V (3000mV).
 #define N_REGS              16
@@ -94,6 +94,8 @@
 #define MOV_RX_MEM                      0x4082  // MOV #<val>,PC
 #define SAVE_ADDRESS                    0x01fe  // Pointing to nowhere
 
+extern WORD DEVICE;        // Global target device ID (e.g. 0xF149); is set 
+
 /****************************************************************************/
 /* Function prototypes                                                      */
 /****************************************************************************/

Index: funclets.c
===================================================================
RCS file: /cvsroot/mspgcc/jtag/msp430/funclets.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -w -d -r1.5 -r1.6
--- funclets.c	26 Nov 2003 01:29:14 -0000	1.5
+++ funclets.c	21 Dec 2005 23:08:15 -0000	1.6
@@ -11,17 +11,18 @@
 #endif
 
 // ----------------------------------------------------------------------------
-/* msp430 code and buffer to write flash
-
-As it's not implemented to read the MSP430 registers, return values have to be
-passed in memory. Due to a JTAG bug in certain devices that can corrupt RAM, the
-return value is passed in CCR0.
-*/
 #include "progFlash.ci"         //include the flash program
 
-WORD ramsize = 256;             //TODO: get device memory size
+WORD ramsize = 256;             //device memory used for funclets (see alse MSP430_Configure)
 void (*flash_callback)(WORD, WORD) = NULL;
 
+/**
+ * msp430 code and buffer to write flash.
+ *
+ * As it's not implemented to read the MSP430 registers, return values have to be
+ * passed in memory. Due to a JTAG bug in certain devices that can corrupt RAM, the
+ * return value is passed in CCR0.
+ */
 STATUS_T programFlash(WORD address, const CHAR* buffer, WORD count) {
     STATUS_T res = STATUS_OK;
     WORD blocksize;
@@ -30,7 +31,7 @@
     WORD *code = malloc(ramsize);
     if (code == NULL)   return STATUS_ERROR;                            //Out of memory
         
-    MSP430_Log(2, "funclets: Flash write...\n");
+    MSP430_Log(2, "funclets: programFlash(0x%04x, ..., %d)\n", address, count);
     memcpy(code, funclet_progFlash, sizeof(funclet_progFlash));         //copy program to working buffer
     while (done < count) {                                              //download in blocks
         blocksize = min(count-done, ramsize-sizeof(funclet_progFlash)); //calculate blocksize
@@ -39,18 +40,18 @@
         code[3] = 0;//srinit;                                           //TODO: need arg for DCO+?
         code[4] = address;                                              //starting address in flash
         code[5] = blocksize/2;                                          //number of words to write
-        MSP430_Log(2, "funclets: Flash write at 0x%04x %d bytes\n", address, blocksize);
+        MSP430_Log(2, "funclets: programFlash: Flash write at 0x%04x %d bytes\n", address, blocksize);
         //download data and start flash programing funclet in RAM
         for (tries=3; tries; tries--) {
             res =  executeCode(code, (sizeof(funclet_progFlash) + blocksize)/sizeof(WORD), 1, 1);
             if (res != STATUS_OK) {
-                MSP430_Log(1, "funclets: Flash write retrying in block 0x%04x\n", address);
+                MSP430_Log(1, "funclets: programFlash: Flash write retrying in block 0x%04x\n", address);
                 GetDevice();
             }
         }
         if (res != STATUS_OK) break;
         if (ReadMem(F_WORD, CCR0_ADDR)) {                               //read CCR0, it's used as return value
-            MSP430_Log(1, "funclets: Flash write error in block 0x%04x\n", address);
+            MSP430_Log(1, "funclets: programFlash: Flash write error in block 0x%04x\n", address);
             res = STATUS_ERROR;
             break;
         }
@@ -62,23 +63,23 @@
         }
     }
     free(code);                                                         //clean up memory
-    MSP430_Log(2, "funclets: Flash write finished\n");
+    MSP430_Log(2, "funclets: programFlash: Flash write finished\n");
     return res;
 }
 
 // ----------------------------------------------------------------------------
-/* msp430 code to erase flash
-*/
 #include "eraseFlash.ci"                        //include the program to erase the flash
 
+/** msp430 code to erase flash */
 STATUS_T eraseFlash(WORD type, WORD address) {
     WORD fctl1;
+    MSP430_Log(2, "funclets: eraseFlash(%d, 0x%04x)\n", type, address);
     //select correct erase mode
     switch (type) {
         case ERASE_SEGMENT:     fctl1 = 0xA502; break;
         case ERASE_MAIN:        fctl1 = 0xA504; break;
         case ERASE_ALL:         fctl1 = 0xA506; break;
-        default: return (STATUS_ERROR);
+        default: return STATUS_ERROR;
     }
     //fill in arguments
     funclet_eraseFlash[3] = 0;//srinit;         //TODO: need arg for DCO+?
@@ -94,18 +95,19 @@
 //simpified some parts
 //questions to chris.
 
-/* Read Memory Address Bus.
-This function can be used at any time (when the JTAG is syncronized)
-I may however return bogus results while the CPU is running.
-Using it in a loop and multiple checks if it returns the same address
-is a probable mean to check if the CPU waits on a "jmp $" insn.
+/**
+ * Read Memory Address Bus.
+ * This function can be used at any time (when the JTAG is syncronized)
+ * I may however return bogus results while the CPU is running.
+ * Using it in a loop and multiple checks if it returns the same address
+ * is a probable mean to check if the CPU waits on a "jmp $" insn.
 */
 static WORD readMab(void) {
     HIL_JTAG_IR(IR_ADDR_CAPTURE);
-    return ((WORD) HIL_JTAG_DR(0, 16));
+    return (WORD)HIL_JTAG_DR(0, 16);
 }
 
-/*wait until CPU is on an instruction load boundary*/
+/** wait until CPU is on an instruction load boundary */
 STATUS_T syncCPU(void) {
     WORD cntrlSig;
     int i;
@@ -128,7 +130,7 @@
                 break;
             } else if (i == 1) {
                 MSP430_Log(5, "funclets: Sync failed\n"); //DEBUG
-                return(STATUS_ERROR);                   // Timeout reached, return false
+                return STATUS_ERROR;                    // Timeout reached, return false
             } else {
                 HIL_DelayMSec(1);
             }
@@ -153,8 +155,8 @@
     // at this time the device type can be unknown. Consequently, advance to an instruction load boundary
     // for all devices.
     if (SetInstrFetch() != STATUS_OK) {
-        MSP430_Log(1, "funclets: Not in Fetch\n"); //DEBUG
-        return (STATUS_ERROR); // Synchronization failed!
+        MSP430_Log(1, "funclets: Not in Fetch (1)\n"); //DEBUG
+        return STATUS_ERROR; // Synchronization failed!
     }
     
     // Execute a dummy instruction (MOV R3,R3) to work around a problem in the F12x that can sometimes cause
@@ -169,15 +171,15 @@
     // (As in internal check) Must exit on an instruction load boundary.
     HIL_JTAG_IR(IR_CNTRL_SIG_CAPTURE);
     if (!(HIL_JTAG_DR(0, F_WORD) & CNTRL_SIG_INSTRLOAD)) {
-        MSP430_Log(1, "funclets: Not in Fetch\n"); //DEBUG
-        return (STATUS_ERROR);
+        MSP430_Log(1, "funclets: Not in Fetch (2)\n"); //DEBUG
+        return STATUS_ERROR;
     } else {
-        return (STATUS_OK);
+        return STATUS_OK;
     }
 }
 
-// Set PC and avoid corrupting RAM while doing so. used in executeCode
-static STATUS_T setPCsave(WORD addr) {
+/** Set PC and avoid corrupting RAM while doing so. used in executeCode*/
+static STATUS_T setPCsafe(WORD addr) {
     HIL_JTAG_IR(IR_DATA_16BIT);
     HIL_JTAG_DR(MOV_IMM_PC, F_WORD);            // Force PC into non-RAM area.
     HIL_TCLK(NEG_EDGE);
@@ -191,30 +193,30 @@
     return (STATUS_OK);
 }
 
-/* This function downloads programs (funclets) into RAM, and starts their execution.
-F413P, F41xC, and F12x devices contain a silicon bug that can corrupt memory when
-the JTAG instruction register or the JTAG data register is accessed while TCLK is
-high. The following sequence of steps has been carefully crafted to work around
-this bug. The bug destroys the contents of a RAM under the following conditions:
-- The device is under JTAG control
-- MCLK/TCLK is high
-- MAB selects a RAM address
-- A JTAG instruction is shifted in or a JTAG data is shifted in
+/** This function downloads programs (funclets) into RAM, and starts their execution.
+ * F413P, F41xC, and F12x devices contain a silicon bug that can corrupt memory when
+ * the JTAG instruction register or the JTAG data register is accessed while TCLK is
+ * high. The following sequence of steps has been carefully crafted to work around
+ * this bug. The bug destroys the contents of a RAM under the following conditions:
+ * - The device is under JTAG control
+ * - MCLK/TCLK is high
+ * - MAB selects a RAM address
+ * - A JTAG instruction is shifted in or a JTAG data is shifted in
 */
-STATUS_T executeCode(const WORD* code, WORD sizeCode, BOOL verify, BOOL wait) {
+STATUS_T executeCodeSafe(const WORD* code, WORD sizeCode, BOOL verify, BOOL wait) {
     int i;
 
     if (sizeCode == 0) {
-        return (STATUS_OK);
+        return STATUS_OK;
     }
     if (code[0] & 1) {                          // Address must be even.
-        return (STATUS_ERROR);
+        return STATUS_ERROR;
     }
     if (SetInstrFetch() != STATUS_OK) {         //Must start on an instruction load boundary.
-        return (STATUS_ERROR);
+        return STATUS_ERROR;
     }
 
-    MSP430_Log(3, "funclets: download %d words...\n", sizeCode); //DEBUG
+    MSP430_Log(3, "funclets: executeCodeSafe: download %d words...\n", sizeCode); //DEBUG
     SetPC(code[0] - 2);
     HIL_JTAG_IR(IR_DATA_16BIT);
     HIL_JTAG_DR(JMP_$, F_WORD);                 // Load "jmp $" instruction for use while HALT'ed.
@@ -232,11 +234,10 @@
     
     if (verify) {       // Verify the memory contents (without corrupting it!)
         WORD *Read = (WORD *) malloc(sizeCode*sizeof(WORD));
-        MSP430_Log(5, "funclets: verify...\n"); //DEBUG
-        if (setPCsave(code[0] - 2) != STATUS_OK) {
+        MSP430_Log(5, "funclets: executeCodeSafe: verify...\n"); //DEBUG
+        if (setPCsafe(code[0] - 2) != STATUS_OK) {
             free(Read);                         // Free read buffer
-            MSP430_Log(1, "funclets: setPCsave failed\n"); //DEBUG
-            return (STATUS_ERROR);
+            return STATUS_ERROR;
         }
         HIL_JTAG_IR(IR_DATA_16BIT);
         HIL_JTAG_DR(JMP_$, F_WORD);             // Load "jmp $" instruction for use while HALT'ed.
@@ -255,21 +256,21 @@
         for (i = 0; i < sizeCode; i++) {        // Verify the memory contents.
             if (Read[i] != code[i]) {
                 free(Read);                     // Free read buffer
-                MSP430_Log(1, "funclets: vfy error (word %d)\n", i);   //DEBUG
-                return (STATUS_ERROR);
+                MSP430_Log(1, "funclets: executeCodeSafe: verify error (word %d)\n", i);   //DEBUG
+                return STATUS_ERROR;
             }
         }
-        MSP430_Log(5, "funclets: vfy ok\n");    //DEBUG
+        MSP430_Log(5, "funclets: executeCodeSafe: verify ok\n");    //DEBUG
         free(Read);                             // Free read buffer
     } // if (verify)
     
     //this block is needed if device has JTAG bug, but it shouldn't hurt anyway
-    MSP430_Log(5, "funclets: park PC...\n");    //DEBUG
-    if (setPCsave(ROM_ADDR) != STATUS_OK) {
-        return (STATUS_ERROR);
+    MSP430_Log(5, "funclets: executeCodeSafe: park PC...\n");    //DEBUG
+    if (setPCsafe(ROM_ADDR) != STATUS_OK) {
+        return STATUS_ERROR;
     }
     
-    MSP430_Log(5, "funclets: set active...\n"); //DEBUG
+    MSP430_Log(5, "funclets: executeCodeSafe: set active...\n"); //DEBUG
     HIL_JTAG_IR(IR_DATA_16BIT);
     HIL_JTAG_DR(0x4032, 16);                    // Clear the Status Register (no low power modes, diable irqs).
     HIL_TCLK(NEG_EDGE);
@@ -277,12 +278,12 @@
     HIL_TCLK(1);
     HIL_TCLK(POS_EDGE);
 
-    MSP430_Log(5, "funclets: set PC\n");        //DEBUG
-    if (setPCsave(code[1]) != STATUS_OK) {      // Load the Program Counter.
-        return (STATUS_ERROR);
+    MSP430_Log(5, "funclets: executeCodeSafe: set PC\n");        //DEBUG
+    if (setPCsafe(code[1]) != STATUS_OK) {      // Load the Program Counter.
+        return STATUS_ERROR;
     }
 
-    MSP430_Log(5, "funclets: run...\n");        //DEBUG
+    MSP430_Log(5, "funclets: executeCodeSafe: run...\n");        //DEBUG
     HIL_JTAG_IR(IR_CNTRL_SIG_RELEASE);          // Release the CPU (but retain JTAG control signals).
     HIL_TCLK(1);
 
@@ -293,27 +294,152 @@
             if ((readMab() == code[2]) && (readMab() == code[2]) && (readMab() == code[2])) {
                 // For F413P, F41xC, and F12x devices, the following step will likely corrupt RAM.
                 // However, we don't care about this as the RAM contents will be reloaded in necessary.
-                MSP430_Log(5, "funclets: wait OK\n"); //DEBUG
-                return (syncCPU());             // Resume control of the CPU. Read/Write will be set.
+                MSP430_Log(5, "funclets: executeCodeSafe: wait OK\n"); //DEBUG
+                return syncCPU();               // Resume control of the CPU. Read/Write will be set.
             }
         }
-        MSP430_Log(1, "funclets: wait failed\n"); //DEBUG
-        return (STATUS_ERROR);
+        MSP430_Log(1, "funclets: executeCodeSafe: wait failed\n"); //DEBUG
+        return STATUS_ERROR;
     }
-    MSP430_Log(3, "funclets: exec OK\n");       //DEBUG
-    return (STATUS_OK);
+    MSP430_Log(3, "funclets: executeCodeSafe: exec OK\n");       //DEBUG
+    return STATUS_OK;
 }
 
-//check if the cpu is executing code or if its halted
-//may have some uncertainity if it hits a loop repeatedly on the same instruction...
-int isHalted(void)
-{
+
+/**
+ * This function downloads programs (funclets) into RAM, and starts their execution.
+ * F2xx compatible, but not withthe workaround.
+ */
+STATUS_T executeCodeUnsafe(const WORD* code, WORD sizeCode, BOOL verify, BOOL wait) {
+    int i;
+
+    if (sizeCode == 0) {
+        return STATUS_OK;
+    }
+    if (code[0] & 1) {                          // Address must be even.
+        return STATUS_ERROR;
+    }
+    if (SetInstrFetch() != STATUS_OK) {         //Must start on an instruction load boundary.
+        return STATUS_ERROR;
+    }
+
+    MSP430_Log(3, "funclets: executeCode: download %d words...\n", sizeCode); //DEBUG
+    SetPC(code[0] - 2);
+    HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                                // F2xxx
+    HIL_JTAG_DR(JMP_$, F_WORD);                 // Load "jmp $" instruction for use while HALT'ed.
+    HIL_TCLK(POS_EDGE);
+
+    HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
+    HIL_JTAG_DR(0x2408, F_WORD);                // Set JTAG_HALT bit
+    HIL_JTAG_IR(IR_DATA_QUICK);
+    for (i = 0; i < sizeCode; i++) {
+        HIL_JTAG_DR(code[i], F_WORD);           // Write data to memory.
+        HIL_TCLK(POS_EDGE);
+    }
+    HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
+    HIL_JTAG_DR(0x2401, F_WORD);                // Clear the HALT_JTAG bit (Release CPU)
+    
+    if (verify) {       // Verify the memory contents (without corrupting it!)
+        WORD *Read = (WORD *) malloc(sizeCode*sizeof(WORD));
+        MSP430_Log(5, "funclets: executeCode: verify...\n"); //DEBUG
+        if (SetPC(code[0] - 2) != STATUS_OK) {
+            free(Read);                         // Free read buffer
+            return STATUS_ERROR;
+        }
+        HIL_JTAG_IR(IR_DATA_16BIT);
+        HIL_TCLK(1);                            // F2xxx
+        HIL_JTAG_DR(JMP_$, F_WORD);             // Load "jmp $" instruction for use while HALT'ed.
+        HIL_TCLK(POS_EDGE);
+
+        HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
+        HIL_JTAG_DR(0x2409, F_WORD);            // Set JTAG_HALT bit
+        HIL_JTAG_IR(IR_DATA_QUICK);
+        for (i = 0; i < sizeCode; i++) {
+            HIL_TCLK(NEG_EDGE);
+            Read[i] = HIL_JTAG_DR(0, F_WORD);   // Read data from memory.
+        }
+        HIL_TCLK(1);                            // F2xxx
+        HIL_JTAG_IR(IR_CNTRL_SIG_16BIT);
+        HIL_JTAG_DR(0x2401, F_WORD);            // Clear the HALT_JTAG bit (Release CPU)
+
+        for (i = 0; i < sizeCode; i++) {        // Verify the memory contents.
+            if (Read[i] != code[i]) {
+                free(Read);                     // Free read buffer
+                MSP430_Log(1, "funclets: executeCode: verify error (word %d)\n", i);   //DEBUG
+                return STATUS_ERROR;
+            }
+        }
+        MSP430_Log(5, "funclets: executeCode: verify ok\n");    //DEBUG
+        free(Read);                             // Free read buffer
+    } // if (verify)
+    
+    //this block is needed if device has JTAG bug, but it shouldn't hurt anyway
+    MSP430_Log(5, "funclets: executeCode: park PC...\n");    //DEBUG
+    if (SetPC(ROM_ADDR) != STATUS_OK) {
+        return STATUS_ERROR;
+    }
+    
+    MSP430_Log(5, "funclets: executeCode: set active...\n"); //DEBUG
+    HIL_JTAG_IR(IR_DATA_16BIT);
+    HIL_TCLK(1);                                // F2xxx
+    HIL_JTAG_DR(0x4032, 16);                    // Clear the Status Register (no low power modes, diable irqs).
+    HIL_TCLK(POS_EDGE);
+    HIL_JTAG_DR(0, 16);
+    HIL_TCLK(POS_EDGE);
+
+    MSP430_Log(5, "funclets: executeCode: set PC\n");        //DEBUG
+    if (SetPC(code[1]) != STATUS_OK) {      // Load the Program Counter.
+        return STATUS_ERROR;
+    }
+
+    MSP430_Log(5, "funclets: executeCode: run...\n");        //DEBUG
+    HIL_JTAG_IR(IR_CNTRL_SIG_RELEASE);          // Release the CPU (but retain JTAG control signals).
+    HIL_TCLK(1);
+
+    if (wait) {
+        // Limit the number of cycles for the code to execute.
+        for (i = 0; i < 20000; i++) {
+            // Poll the device until it is executing the final code instruction.
+            if ((readMab() == code[2]) && (readMab() == code[2]) && (readMab() == code[2])) {
+                // For F413P, F41xC, and F12x devices, the following step will likely corrupt RAM.
+                // However, we don't care about this as the RAM contents will be reloaded in necessary.
+                MSP430_Log(5, "funclets: executeCode: wait OK\n"); //DEBUG
+                return syncCPU();               // Resume control of the CPU. Read/Write will be set.
+            }
+        }
+        MSP430_Log(1, "funclets: executeCode: wait failed\n"); //DEBUG
+        return STATUS_ERROR;
+    }
+    MSP430_Log(3, "funclets: executeCode: OK\n"); //DEBUG
+    return STATUS_OK;
+}
+
+/** 
+ * We dont have the correct code for a execute code that works with F1xx series
+ * with the JTAg bug AND F2xx devices. Solution: choose one or the other
+ * executeCode implementation, depending on CPU type.
+ */
+STATUS_T executeCode(const WORD* code, WORD sizeCode, BOOL verify, BOOL wait) {
+    if ((DEVICE & 0xff00) == 0xf200) {           //is it a F2xx series device?
+        //yes F2xx use new variant
+        return executeCodeUnsafe(code, sizeCode, verify, wait);
+    } else {
+        //no F1xx or F4xx series, use old variant with support for bad JTAGs
+        return executeCodeSafe(code, sizeCode, verify, wait);
+    }
+}
+
+/**
+ * check if the cpu is executing code or if its halted
+ * may have some uncertainity if it hits a loop repeatedly on the same instruction...
+ */
+int isHalted(void) {
     int i;
     WORD reference = readMab();
     HIL_JTAG_IR(IR_CNTRL_SIG_RELEASE);          // Release the CPU (but retain JTAG control signals).
     HIL_TCLK(1);
-    for (i=0; i<10; i++)
-    {
+    for (i=0; i<10; i++) {
         HIL_DelayMSec(1); //make sure that the target has the chance to execute some code
         if (readMab() != reference) {
             return 0;



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.