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.

cc430f5137 flash operation

Other Parts Discussed in Thread: CC430F5137

Hi All,

I got some interesting behavior for the cc430f5137 flash operation here. I have a program runs in 0x8000~0x9FFF. Tried to write a test function to start segment of 0xA000 (0xA000~0xA1ff). 

It works fine if the code for erase and write of the segment directly run from flash. But it fails to write the flash segment 0xA000~0xA1ff (it is still all 0xffff after the function calls).

But from the cc430 family guide, it should be only possible to erase and write the flash via RAM for segment operation. While what happened here i got a totally reverse behavior. 

The code:

typedef void (*VFPTR)(void);

static uint16_t ramFunc[128];

#define RUN_FROM_RAM 1

void demo()
{
  printf("test function\n");

}

void test()
{

uint16_t *code = (uint16_t*)0xA000;
uint16_t i;
uint16_t *demo_code = (uint16_t*)(uint16_t)demo;
__disable_interrupt();
WDTCTL = WDTPW | WDTHOLD;
FCTL1 = FWKEY + ERASE; //segment erase
FCTL3 = FWKEY;
while(FCTL3 & BUSY);
*code = 0;
FCTL1 = FWKEY + WRT;
for(i = 0;i < 0x200;i++)
{
while(FCTL3 & BUSY);
*code++ = *demo_code++;
}

FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;

P2OUT |= BIT3; //led on
((void (*)(void))0xA000)();
while(1);
}

void run_from_ram(VFPTR func, uint16_t *ramAddr, uint16_t len)
{
VFPTR f = (VFPTR)(uint16_t)ramAddr;
uint16_t *code = (uint16_t *)(uint16_t)func;
uint16_t i = 0;
for(i = 0; i < len; i++)
{
ramAddr[i] = code[i];
}

(*f)();
}

int main(int argc, char **argv)
{
cpu_init();

P2SEL &= ~BIT3;
P2DIR |= BIT3;
P2OUT &= ~BIT3; //led off

#if RUN_FROM_RAM

run_from_ram(test, ramFunc, sizeof(ramFunc));

#else

test();

#endif

return 0;
}

Is there any suggestion or explanation on this?

thanks,

  • Kyle Zhang said:
    But from the cc430 family guide, it should be only possible to erase and write the flash via RAM for segment operation.

    Not for 'segment operation'. Only for block write operation.

    If the flash controller is busy writing to flash, it cannot provide data from flash, even if it is requested from an area that isn't currently written to. So if the erase/write code runs from flash, the CPU is stopped while the flash is written to.
    For a single erase or write operation, this is no problem. (however,Interrupts must be disabled, as the vector table can't be read too)
    In block write mode, the flash is busy until the CPU ends block write mode. Which it can't if it is stopped because it can't read its next instruction.

    So block write mode can only be executed from ram, where the CPU doesn't need to read its code form blocked flash. However, block write mode is much faster, as the controller does not need to switch the programming voltage on and off for every single write.
    (in case of erase, there's also the block erase mode, which allows the CPU to access other flash blocks while one block Is being erased. Don't confuse this.)

  • Thanks for the reply.

    I know how it works, but the problem is if I run the erase and write function from RAM then nothing happened (still all 0xffff) even in the single operation mode.  Is there anything wrong with the code listed below?

    void test()
    {

    uint16_t *code = (uint16_t*)0xA000;
    uint16_t i;
    __disable_interrupt();
    WDTCTL = WDTPW | WDTHOLD;
    FCTL1 = FWKEY + ERASE; //segment erase
    FCTL3 = FWKEY;
    while(FCTL3 & BUSY);
    *code = 0;
    FCTL1 = FWKEY + WRT;
    for(i = 0;i < 0x200;i++)
    {
    while(FCTL3 & BUSY);
    *code++ = 0x1234;
    }

    FCTL1 = FWKEY;
    FCTL3 = FWKEY + LOCK;

    P2OUT |= BIT3; //led on
    //((void (*)(void))0xA000)();
    while(1);
    }

    void run_from_ram(VFPTR func, uint16_t *ramAddr, uint16_t len)
    {
    VFPTR f = (VFPTR)(uint16_t)ramAddr;
    uint16_t *code = (uint16_t *)(uint16_t)func;
    uint16_t i = 0;
    for(i = 0; i < len; i++)
    {
    ramAddr[i] = code[i];
    }

  • Kyle Zhang said:
    I know how it works, but the problem is if I run the erase and write function from RAM then nothing happened (still all 0xffff) even in the single operation mode.  Is there anything wrong with the code listed below?

    The run_from_ram function just copies from a function in flash to RAM an executes it. Not sure that the code which is copied from flash to RAM will correctly operate in that condition.

    With the TI MSP430 compiler and CCS the documented approach is you have to modify the linker command file to tell the linker the function will have a load address in flash and a run address is RAM.

  • I use gcc to compile the code. And the copy and execute function are verified if the test function change the status of the led, printf. All run as expected. I think the copy and run function is not the problem.

    Thanks,

  • Hi All,

    I found the problem, it should check the WAIT bit of the FCTL3 but not BUSY bit during writing.

    void test()
    {

    uint16_t *code = (uint16_t*)0xA000;
    uint16_t i;
    uint16_t *demo_code = (uint16_t*)(uint16_t)demo;
    __disable_interrupt();
    WDTCTL = WDTPW | WDTHOLD;
    FCTL1 = FWKEY + ERASE; //segment erase
    FCTL3 = FWKEY;
    while(!(FCTL3 & WAIT));
    *code = 0;
    FCTL1 = FWKEY + WRT;
    for(i = 0;i < 0x200;i++)
    {
    while(!(FCTL3 & WAIT));
    *code++ = *demo_code++;
    }

    FCTL1 = FWKEY;
    FCTL3 = FWKEY + LOCK;

    P2OUT |= BIT3; //led on
    ((void (*)(void))0xA000)();
    while(1);
    }

  • Hello,

    I am a newbie to CC430f5137, I purchased MSP430-ccrf boards from Olimex to do some simple communication or relay switching. The code on Olimex website was for IAR and couldn't use it for CCS so I tried uploading FIFO examples from here: http://www.ti.com/lit/zip/slac525 to test run and  Toggle the LED's. The code gets uploaded to the boards without any issue but when i press button on the board there is no response of the toggle on the other boards.

    I am using ez430 that comes with Chronos to program using Spy-by-wire.

    Any help on his would be appreciated. :)

    -Nish

  • If you want an answer to your question, you should start a new thread with a topic that matches your problem.
    This thread is about self-programming parts of flash form the running application and has nothing to do with your problem. So nobody who could possibly answer your question will read it at all.
    Also, problems with Olimex boards are not really the scope of the TI support forum, even though you might have luck and find someone here who might help you,

    Well, it could simply be that the examples (which are TI examples and therefore not designed for an Olimex baord) do not match the board hardware (LEDs and/or buttons on different pins etc.)

**Attention** This is a public forum