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.

How to write to data flash in UCD3138A64?

Other Parts Discussed in Thread: UCD3138A64

Dear TI,

I need to store a byte in data flash. Since the byte can be modified on runtime the first step is erasing the data flash. As the manual says, it should be easy:

- write key to FLASHILOCK register,
- set page to be erased in DFLASHCTRL register,
- wait until BUSY flag in the same register deasserts.

I have also found this thread:
https://e2e.ti.com/support/power_management/digital_power/f/184/t/469002
about using the RONLY bit, and I've copied the line to remove the read-only protection.

However, this doesn't work for me.

I have written this code:

static void erase_dflash(void)
{
    const union DFLASHCTRL_REG dctrl = {.bit.PAGE_SEL = 0, .bit.PAGE_ERASE = 1};
    send_str("zz\n");
    while( DecRegs.DFLASHCTRL.bit.BUSY );
    send_str("uu\n");
    DecRegs.MFBALR2.all = 0x8820;
    send_str("vv\n");
    DecRegs.FLASHILOCK.all = DATA_FLASH_INTERLOCK_KEY;
    send_str("yy\n");
    DecRegs.DFLASHCTRL.all = dctrl.all;
    send_str("xx\n");
    while( DecRegs.DFLASHCTRL.bit.BUSY );
    send_str("ww\n");
}

'send_str' is a function which sends a string over UART and it's working fine.

After calling this function I can see "zz" and "uu" printed in the terminal, but nothing more, and without a reset the device cannot be accesed by the PMBUS probe (HPA172). So this looks like the device was hanging on the write to MFBALR2. I've tried to swap the order of writes to MFBALR2 and FLASHILOCK, with the same result.

Can you, please, help me with that? Is there something that the documentation doesn't mention? Maybe there is a working piece of code that I could use for that?

EDIT:

I have realized that there are ready "software interrupt" routines for this purpose, but these don't work for me either.

The code snippet is now:

send_str("\nnew addr\n");
erase_data_flash_segment(0);
send_str("\nerased\n");
write_data_flash_word(DFLASH_START_ADDRESS, dfs.addr);
send_str("\nall done\n");

dfs.addr is uint8_t.

I can see only "new addr" and "erased" displayed, the write operation causes a reset (I can find the device in ROM mode and make it run the program again). I did try to replace in the routine bitwise assignment to MFBALR2 with assignment to "all", as suggested in the post cited.

Best regards,
Adam

  • I suspect you need to wait for the data flash erase to complete.  Generally we just use the software interrupt to go to privileged mode so we can write to the flash control registers.   In your background program, you need to poll the busy bit in the dflasctrl register. 

  • Hello Ian,

    I do wait for the BUSY bit to deassert - that's the purpose of the last statement in "my code", and this is also present in the "software interrupt" routine (from training labs):

    while(DecRegs.DFLASHCTRL.bit.BUSY != 0)
    {
    ; //do nothing while it programs
    }

    The difference is that "my code" hangs before reaching this moment, at "DecRegs.MFBALR2.all = 0x8820;", while the erasing routine from "software interrupt" is able to end its operation and it is the writing routine that hangs.

    Do I need to set the privileged mode first? The documentation seems not to require this.

    Best regards,
    Adam
  • Yes, you do need to go to privileged mode before writing to the DEC registers.  That's why we call the software interrupt. 

    Sorry  I took so long to reply - I was off watching the eclipse in the cornfields of Nebraska - even where there was cell service, it was swamped.  And then it was cloudy. 

  • Hi Ian,

    thanks to your post about setting the RONLY bit I was able to guess how to correct the software interrupt routines (more precisely: "case statements" in the switch) and this now works fine. I don't remember exactly, but there was also something different in setting the higher byte of the word (for UCD3138A64). I basically ended up with copying the initial value from the register.

    However, it did not require calling the software interrupts to "set supervisor mode" - does the software interrupt function put the program in the privileged (or any special) mode in other way? This function is defined by a pragma as an interrupt, and is that it?

    BTW, have you ever encountered behaviour which looks like a high (10mV) offset of the error amplifier or EADC for small input voltages? We're having a problem (buck converter with current regulation) that when the reference of EADC is set to 0 the high-side PWM doesn't stop but remains with duty cycle for which the feedback voltage is ca. 10mV (ie. the input to the error amplifier is this value), and the error reported by the EADC is then equal to 0 (so the accumulated value of the integrator in the filter does not change and the PWM keeps on going). Is there a way to calibrate such offset somewhere in the digital part of the loop?

    Best regards,
    Adam