This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TI App to program MSP430 via JTAG -> two questions

Other Parts Discussed in Thread: MSP430F1121A, MSP430F1132, MSP430F123, MSP430F1232, MSP430F149, MSP430F169, MSP430F1610, MSP430F2013, MSP430F2131, MSP430F2274, MSP430F2370, MSP430F249, MSP430F2619, MSP430F413, MSP430FW427, MSP430F437, MSP430FG439, MSP430F449, MSP430FG4619, MSP430F2618

I need to download application code from a 32bit IMX CPU to a MSP430 via the jtag interface.  The IMX CPU is running Linux and there are some I/O pins on the IMX that go directly to the jtag pins on the MSP430. This was done in the past with a different CPU and a different MSP430 and the old MSP430 was a MSP430F1619 CPU.  In the past, an application from TI was used to read a srec file the bit banging and the srec data to the MSP430 Flash as described on the TI Document “Programming a Flash Based MSP430 Using JTAG Interface” SLAA149.  The link below has the document and source code provided by TI.

 

http://www.ti.com/lit/an/slaa149h/slaa149h.pdf

 

I think the IMX is set up properly with the GPIO pins working correctly since I can control them high and low via the software running on the IMX that was ported from the old project.  Also, the port from the old system compiles and executes but I have yet to successfully using this software to update the current MSP430 we are using now.  The current CPU is a MSP430F2618TZQW.  The programming fails when the software does the eraseAllSections using the ERASE_MASS option.

Before the software does the erase operation, it gets the device ID from the CPU via the JTAG interface.  The new MSP430 is the MSP430F2618TZQW and it returns a device ID of 0xF23F.  This value (0xF23F) is then used to look up in the following table to get the CPU configuration details.  I looked and that ID is not in the table probably because the CPU is new and the software was done before the MSP430F2618TZQW was released.  I added a table entry for the device and took a shot at filling it in but it still fails at the erase operation.

 

My two questions are:

1)      Is the device ID of 0xF23F correct for a MSP430F2618TZQW?  This would indicate I am reading the part correctly via JTAG and things are working properly up to that point.

2)      I added an entry for my part (MSP430F2618TZQW) as the last entry in the table before the default entry at the end and want to verify I did this correctly.  The entry I made is bold and wasn't sure about some of the items in the table (testpin, CpuX, DataQuick etc)

Thanks,

Doug

 

static const struct tsDeviceFeatures sDeviceFeatures[] =

{

//                      TestPin      DataQuick      EnhVerify     SpyBiWire        RamEnd

//                Id       |    CpuX     |  FastFlash  |    JTAG     |    RamStart    |   MainStart

//                 |       |      |      |      |      |     |       |        |       |       |

/* F11x(1)(A)*/ { 0xF112, TRUE,  FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xF000 }, // MSP430F1121A

/* F11x2 */     { 0x1132, TRUE,  FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430F1132

/* F12x(A) */   { 0xF123, TRUE,  FALSE, FALSE, FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430F123

/* F12x2 */     { 0x1232, TRUE,  FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430F1232

/* F13x

   F14x  */     { 0xF149, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x09FF, 0x1100 }, // MSP430F149

/* F15x

   F16x  */     { 0xF169, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x09FF, 0x1100 }, // MSP430F169

/* F161x */     { 0xF16C, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x1100, 0x24FF, 0x8000 }, // MSP430F1610

/*
F20xx */     { 0xF201, TRUE,  FALSE, TRUE , TRUE,  FALSE, TRUE , TRUE  , 0x0200, 0x027F, 0xF800 }, // MSP430F2013

/* F21x1

   F21x2 */     { 0xF213, TRUE,  FALSE, TRUE , TRUE,  FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430F2131

/* F22x2

   F22x4 */     { 0xF227, TRUE,  FALSE, TRUE , TRUE,  TRUE,  TRUE , TRUE  , 0x0200, 0x05FF, 0x8000 }, // MSP430F2274

/* F23x0 */     { 0xF237, TRUE,  FALSE, TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x0200, 0x09FF, 0x8000 }, // MSP430F2370

/* F23x

   F24x

   F24x1

   F2410 */     { 0xF249, FALSE, FALSE, TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x0200, 0x09FF, 0x1100 }, // MSP430F249

/* F241x

   F261x */     { 0xF26F, FALSE, TRUE,  TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430F2619

/* F41x */      { 0xF413, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430F413

/* F42x(x) */   { 0xF427, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }, // MSP430FW427

/* F43x 80p */  { 0xF437, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x05FF, 0xA000 }, // MSP430F437

/* FG43x */     { 0xF439, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x09FF, 0x1100 }, // MSP430FG439

/* F44x

   F43x 100p */ { 0xF449, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x09FF, 0x1100 }, // MSP430F449

/* FG461x */    { 0xF46F, FALSE, TRUE,  TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430FG4619

 

/*430F2618TZ */ { 0xF23F, FALSE, FALSE,  TRUE , FALSE,  TRUE,  TRUE , FALSE , 0x1100, 0x30FF, 0x3100 }, // MSP430F2618TZQW

 

/* GENERIC */   { 0xFFFF, FALSE, FALSE, TRUE , FALSE, FALSE, TRUE , FALSE , 0x0200, 0x02FF, 0xE000 }

};

  • slaa149h.pdf has been superceeded by http://www.ti.com/lit/ug/slau320e/slau320e.pdf slau320e Table 1-14 JTAG Features Across Device Families contains the information you need for a MSP430F2618

  • Doug Baker said:
    /* F241x
       F261x */     { 0xF26F, FALSE, TRUE,  TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430F2619

    /*430F2618TZ */ { 0xF23F, FALSE, FALSE,  TRUE , FALSE,  TRUE,  TRUE , FALSE , 0x1100, 0x30FF, 0x3100 }, // MSP430F2618TZQW

    I'd expect the 2618 to have the very same features as the other devices 241x/261x device group. Especially the CPUX (as it has more than 64k addressing range).
    The differences in RamEnd and MainStart are negligible: it limits the ram available for operation to 4k but thsi is still way more than needed. And the lower main start, well, if the code to be written wants to be written to the valid range 0x03100 to 0x1FFFF, who cares if the table falsely tells that it could start at 0x2100?

    I really wonder why the device ID is different. BTW, the 'TZ' is referring to the package and not the functionality, so it is meaningless and the 2618 definitely belongs to the 261x group.
    (Different packages may have different pinout and maybe a smaller package does not support dedicated 4-wire JTAG on devices that also support SBW, but this doesn't apply to this chip.)

  • After looking at the documentation I agree that I expect to see my device report an ID of 0xF26F and not 0xF23F so I do not understand why I do not get the ID I expect to see.  After looking at the links provided above, I am now using the following table:

    /*430F2618TZ */ { 0xF23F, FALSE, TRUE,  TRUE,  TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430F2618TZQW

    I also found in SLAU2565 (feb 2009) page 98 the table entry you listed above:

    F261x */     { 0xF26F, FALSE, TRUE,  TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430F2619

    The memory map for my deviceMSP430F2618TZQW  see the following link on page 17/120

    http://www.ti.com/lit/ds/symlink/msp430f2618.pdf

    shows that the RAM is from 0x1100 to 0x30ff and the main start is 0x3100. 

     

    Do these differences indicate that the part I have is not rally the same as a  F261x and the part I have may be new and not in the tables yet? 

     

    I do not have experience programming via JTAG so I don't know if is something that would explain why I can't erase the flash using the JTAG utility of I should be looking at something else.

     

    The problem I see when I run the software to update the MSP430 via jtag is I get the following message when I attempt to flash the MSP430.

    Erasure of section[1] failed. addr = 0x3100 len = 3473

    The code the message above come from is below.

     Thanks for any and all help,

    Doug

     

     

    word

    eraseAllSections(void)

    {

    word addr;

              int i;

              word status = STATUS_OK;

              EraseFLASH(ERASE_MASS, 0x3300); 

               for ( i = 0; i < sections; i++ )

              {

                      addr = section_addresses[i];                  

                       if (EraseCheck( section_addresses[i], section_lengths[i] ) != STATUS_OK )

                       {

                                 printf("Erasure of section[%d] failed. addr = 0x%04hX len = %d\n",

                                                              i+1, addr, section_lengths[i]);

                                 return(STATUS_ERROR);

                       }

                       else

                       {

                                 printf("Erasure of section[%d] passed. addr = 0x%04hX len = %d\n",

                                                              i+1, addr, section_lengths[i]);

                       }

              }

             

              if (g_verbose)

                       printf("Erasure Verified\n");

              return status;

    }

     

    void EraseFLASH(word EraseMode, word EraseAddr)

    {

        //word StrobeAmount = 4820;       // default for Segment Erase

        word StrobeAmount = 4832;       // default for Segment Erase  450/451

        word i, loopcount = 1;          // erase cycle repeating for Mass Erase

        word FCTL3_val = 0xA500;        // ok for all devices; if Info-Seg. A on F2xxx should not be erased

    //  word FCTL3_val = 0xA540;        // only if Info-Seg. A on F2xxx should be erased

              char *ModeStr;

     

              switch(EraseMode){

                       case ERASE_MASS:

                                 ModeStr = "ERASE_MASS";

                                 break;

                       case ERASE_SGMT:

                                 ModeStr = "ERASE_SGMT";

                                 break;

                       case ERASE_MAIN:

                                 ModeStr = "ERASE_MAIN";

                                 break;

                       default: 

                                 ModeStr = "Uknown";

                                 break;

              }

     

              if (g_verbose)

                       printf("EraseFLASH mode = %s[0x%04hX], addr = 0x%04hX \n", ModeStr, EraseMode, EraseAddr );

     

        if ((EraseMode == ERASE_MASS) || (EraseMode == ERASE_MAIN))

        {

            if(DeviceHas_FastFlash())

            {

                StrobeAmount = 10600;        // Larger Flash memories require

                                 printf("EraseFLASH DeviceHas_FastFlash() is TRUE\n");

                                 loopcount = 200;

            }

            else

            {

                //StrobeAmount = 5300;        // Larger Flash memories require   (DRX1 used 5300)

                                 StrobeAmount = 53000;        // (cascade needs more)

                                                                     // Larger Flash memories require 

                                                                                                    // 'cuz my TCLK is 451 not 350+/-100

                loopcount = 19;             // additional cycles for erase. bumped up from 19

                                 printf("EraseFLASH ***NO*** DeviceHas_FastFlash() \n");

            }

        }

        HaltCPU();

     

        for (i = loopcount; i > 0; i--)

        {

            ClrTCLK();

            IR_Shift(IR_CNTRL_SIG_16BIT);

            DR_Shift16(0x2408);         // set RW to write

            IR_Shift(IR_ADDR_16BIT);

            DR_Shift16(0x0128);         // FCTL1 address

            IR_Shift(IR_DATA_TO_ADDR);

            DR_Shift16(EraseMode);      // Enable erase mode

            SetTCLK();

     

            ClrTCLK();

            IR_Shift(IR_ADDR_16BIT);

            DR_Shift16(0x012A);         // FCTL2 address

            IR_Shift(IR_DATA_TO_ADDR);

            DR_Shift16(0xA540);         // MCLK is source, DIV=1

            SetTCLK();

     

            ClrTCLK();

            IR_Shift(IR_ADDR_16BIT);

            DR_Shift16(0x012C);         // FCTL3 address

            IR_Shift(IR_DATA_TO_ADDR);

            DR_Shift16(FCTL3_val);      // Clear FCTL3; F2xxx: Unlock Info-Seg. A by toggling LOCKA-Bit if required,

            SetTCLK();

     

            ClrTCLK();

            IR_Shift(IR_ADDR_16BIT);

            DR_Shift16(EraseAddr);      // Set erase address

            IR_Shift(IR_DATA_TO_ADDR);

            DR_Shift16(0x55AA);         // Dummy write to start erase

            SetTCLK();

     

            ClrTCLK();

            IR_Shift(IR_CNTRL_SIG_16BIT);

            DR_Shift16(0x2409);         // Set RW to read

            TCLKstrobes(StrobeAmount);  // Provide TCLKs

            IR_Shift(IR_CNTRL_SIG_16BIT);

            DR_Shift16(0x2408);         // Set RW to write

            IR_Shift(IR_ADDR_16BIT);

            DR_Shift16(0x0128);         // FCTL1 address

            IR_Shift(IR_DATA_TO_ADDR);

            DR_Shift16(0xA500);         // Disable erase

            SetTCLK();

        }

        // set LOCK-Bits again

        ClrTCLK();

        IR_Shift(IR_ADDR_16BIT);

        DR_Shift16(0x012C);         // FCTL3 address

        IR_Shift(IR_DATA_TO_ADDR);

        DR_Shift16(FCTL3_val);      // Lock Inf-Seg. A by toggling LOCKA (F2xxx) and set LOCK again

        SetTCLK();

     

        ReleaseCPU();

    }

     

     

     

  • Doug Baker said:
    F261x */     { 0xF26F, FALSE, TRUE,  TRUE , TRUE,  TRUE,  TRUE , FALSE , 0x1100, 0x20FF, 0x2100 }, // MSP430F2619

    The memory map for my deviceMSP430F2618TZQW  see the following link on page 17/120
    http://www.ti.com/lit/ds/symlink/msp430f2618.pdf
    shows that the RAM is from 0x1100 to 0x30ff and the main start is 0x3100. 

    Do these differences indicate that the part I have is not rally the same as a  F261x and the part I have may be new and not in the tables yet?

    No. Indeed, the parts with 8k ram (not only the 2618) have other values as in the table. But this is unimportant. If the table reports 4k ram, then the JTAG will use only 4k ram isntead of 8, but this won't do any harm. And the fact that main flash starts later than described is also no problem, as no binary file for the 2618 will tell the JTAG to flash code before 0x3100 (which would of course be ram).
    The only situation where this could cause problems would be an erase check. Testing 0x2100 to 0x20FF for being erased by a flash mass erase will probably return an error (a mass erase won't erase the ram there).

    Doug Baker said:
    The problem I see when I run the software to update the MSP430 via jtag is I get the following message when I attempt to flash the MSP430.

    The message comes when function EraseCheck() doen't return STATUS_OK. Probably because not all bytes in this area are 0xff.

    Maybe your mass EraseFlash code isn't working. What value does ERASE_MASS have? IMHO, it should be 0xa506. For FCTL2, using MCLK/1 most likely is way too much. The clock must be in teh range of 250..500kHz (see datahsset for exact ranges) and MCLK is ~1MHz. So you're overclockign the flash controller, causing the erase to be incomplete.

    For your project, keep in mind that 5x devices have a different flash controller without FCTL2 register (internal clock generator).

  • I can confirm the Mass erase I am using is 0xA506 for FCTL1.

    For the FCTL2, I am using 0xA540 so it’s set to use MCLK and divide by 1. Isn't MCLK from the JTAG interface and thus the 350kHz +/- 100kHz for the erase operation? If that is wrong, then that would be the problem. I assume the clock from the JTAG bit TCLK is the clock used for the erase operation and I set it for ~ 410kHz normally so if interrupts occur in the CPU, the freq will drop some and still stay in spec of 250-450 kHz.

    I do not want to erase the info block A since I use the values there to set the clocks up.  For FCTL3, should I use 0xA540 so the LOCKA bit is set? I think using 0xA500 would allow the info block A to be erased. I also don't know if I do a mass erase and flash block A is locked, if I would get an error and thus not erase anything.

    Thanks,

    Doug

     

     

  • Doug Baker said:
    Isn't MCLK from the JTAG interface and thus the 350kHz +/- 100kHz for the erase operation? If that is wrong, then that would be the problem.

    I don't know, but if the CPU is stopped, MCLK is 0Hz, which would also not be sufficient.

    Doug Baker said:
    if interrupts occur in the CPU, the freq will drop some and still stay in spec of 250-450 kHz.

    If unmasked interrupts occur during a write/erase operation, this is a very bad thing, as the CPU would try to fetch the ISR address from unavailable flash (getting 0x3fff as result).

    Doug Baker said:
    I also don't know if I do a mass erase and flash block A is locked, if I would get an error and thus not erase anything.

    If you do a mass erase and block A is locked, block A is simply not erased. That's all. No error will be reported by the flash controller.

  • Jens-Michael Gross said:

    Isn't MCLK from the JTAG interface and thus the 350kHz +/- 100kHz for the erase operation? If that is wrong, then that would be the problem.

    I don't know, but if the CPU is stopped, MCLK is 0Hz, which would also not be sufficient.

    I'll check that.

    Doug Baker said:
    if interrupts occur in the CPU, the freq will drop some and still stay in spec of 250-450 kHz.

    If unmasked interrupts occur during a write/erase operation, this is a very bad thing, as the CPU would try to fetch the ISR address from unavailable flash (getting 0x3fff as result).

     

    The interupts I was talking about are on the CPU driving the jtag pins, not the MSP430.  The CPU that is downloading the app to the 430 generates the clock (TCLK). I verified the TCLK freq with a scope and it looked good but did have some jitter.  When the 430 is being downloaded, the CPU (430) should not be running. 

    Doug Baker said:
    I also don't know if I do a mass erase and flash block A is locked, if I would get an error and thus not erase anything.

    If you do a mass erase and block A is locked, block A is simply not erased. That's all. No error will be reported by the flash controller.

    Thanks, that's good to know.

    Doug

    [/quote]

  • According to the documenatationSLAU320E page 6, the clocks I am  generating should be OK for the flash erase.  It states:

    "The TCLK signal is an input clock, which must be provided to teh target device from an external source.  This clock is used internally as teh target devices system clock, MCLK, to load the data into memory locations and the clock to the CPU.  There is no dedicated pin for TCLK; instead, the TDI pin is used as the TCLK input.  This occures whil the MSP430 TAP controller is in teh Run-Test Idle state".

    The documenatation for the flash erase onthe MSP430 states the Flash memory clock needs to run between 257 to 476 kHz and I have verified this cloc with a scope.

    I have looked at the flash memory with a probe and it does not look erased "FF" so I do not know why the CPU is not erasing the flash through JTAG.

    Doug

  • Doug Baker said:
    I do not know why the CPU is not erasing the flash through JTAG.

    I have no clue too. I know that the MSPGCC flashing tool injects small flashing code and the data into ram and executes the code. This is likely faster than a direct JTAG flash write.

  • I did try a few more things but with no success. The CPU the code was ported from is slower than the new CPU I am trying to get this working on so in the driver for the new CPU, I tried writing the TMS, TCK and TDI all 3X and even tried 6x to slow things down. This didn't fix it but I figured it was worth a shot just in case the new CPU was running too fast and driving the signals too fast.  Also, when I am writing the registers in the MSP430 flash controller, I did a write to a register 2 times and on the second write I can read the value that was put in the first time.  I print out the value it reads back on the second write to confirm when I write a register that I actually get the value in the register correctly.  Everything looks good but so far I have not been able to erase the flash memory.

    Any ideas?

    Doug

  • Doug Baker said:
    Any ideas?

    Sorry, no. I did write several flash write functions for 1x and 5x family and they worked fine. But I never tried direct JTAG access to the MSP, let alone writing flash.

    All I know is that msp430-jtag is injecting 'funclets' into MSP ram which are then executed and do the flash erase and flash write by CPU. Here, the JTAG never directly initiates a flash write/erase. It may be that this is for speed reasons only, or because the authors encountered similar problems you did.

**Attention** This is a public forum