Can EEPROM_Write() ever hang?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
HuEl_264296
Level 5
Level 5
First like given 25 sign-ins First solution authored

Looking into the generated code for the EEPROM component, I see this:

cystatus EEPROM_1_Write(const uint8 * rowData, uint8 rowNumber) 
{
    cystatus status;
    
    CySpcStart();

    if(rowNumber < (uint8) CY_EEPROM_NUMBER_ROWS)
    {
        /* See if we can get SPC. */
        if(CySpcLock() == CYRET_SUCCESS)
        {
            /* Plan for failure */
            status = CYRET_UNKNOWN;

            /* Command to load a row of data */
            if(CySpcLoadRow(CY_SPC_FIRST_EE_ARRAYID, rowData, CYDEV_EEPROM_ROW_SIZE) == CYRET_STARTED)
            {
                while(CY_SPC_BUSY)
                {
                    /* Wait until SPC becomes idle */
                }

In this code is a while() statement that relies on CY_SPC_BUSY becoming false in order for it to exit the loop.

Is there any way this code could get stuck here? Are there any circumstances (temperature, voltage fluctuations) under which CY_SPC_BUSY can stay true forever?

If EEPROM_UpdateTemperature() wasn't called recently, could this loop get stuck?

If I wanted to deliberately cause this loop to get stuck by messing with the external conditions of the chip, is there some way I could do it?

If I wanted to deliberately cause this loop to get stuck by incorrectly using the EEPROM component API, is there some way I could do it?

 

0 Likes
1 Solution
LeBa_1250741
Level 2
Level 2
5 sign-ins First solution authored 5 replies posted

It certainly hangs in the PSOC5A chips.

I've been trying to backport a design from PSOC5LP to PSOC5A. The first write to EEPROM would work, but subsequent writes would always hang and there is no 'state machine reset'  command for the EEPROM. I ended up having to emulate EEPROM in Flash and modify the linker to not overwrite.

View solution in original post

0 Likes
16 Replies
Aashita_R
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi @HuEl_264296 ,

So far as I have gone through PSoC 5LP architecture TRM, CY_SPC_BUSY will be set to 0 after the completion of EEPROM write. In case of an error while writing EEPROM, SPC will throw an error and exit the loop. Please provide me sometime to check the ways to keep CY_SPC_BUSY true always and I will provide an update as soon as possible.

Also for EEPROM_UpdateTemperature(), PSoC devices have an on-chip temperature sensor that is used to measure the internal die temperature. You must acquire the temperature at least once to use Flash and EEPROM write functions. If the application will be used in an environment where the die temperature changes 10 °C or more, the temperature should be refreshed to adjust the write times to the Flash for optimal performance. The die temperature is obtained by calling the CySetTemp() function. 

Best Regards,

Aashita

 

0 Likes

Hi Aashita,

Thanks for looking into this for me. We already do use the CySetTemp() function.

But what I'm really interested in is ways to make the firmware hang, even if this requires me to misuse it in some way.

I look forward to hearing back from you if you find any way that CY_SPC_BUSY can become stuck true.

Hugo

 

0 Likes

Hi @HuEl_264296 ,

As checked internally, I do not think so SPC can be kept busy always (at least not deliberately). Even if we keep calling write & read command, it is going to get free in between the calls. It is a HW controlled signal and whenever the command given to SPC is complete, SPC will become idle (that is how the HW is designed).

There may be cases where the write command itself gets hung in the SPC but I believe that should be rare or would not occur, given there are error handling mechanisms implemented in the SPC. So it either completes the command or returns an error and becomes idle.

Best Regards,

Aashita

0 Likes

@Aashita_R wrote:

There may be cases where the write command itself gets hung in the SPC but I believe that should be rare ...


But you think it might be possible? Can you explain more? Can this happen, and under what circumstances?

 

0 Likes

HuEl,

Because the CY_SPC_BUSY is connected to a HW state-machine, the only possible way to MAYBE get it into a 'hung' state is to provide out-of-spec voltage transients. (Usually under-transients)   The transients would have to be below operational voltage for a short enough time that the LVD or POR circuits would not detect and trigger a reset.

Again.  The  low-voltage transients is a MAYBE.   Proper IC design by Cypress would guard against condition.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi Len,

That's interesting.  There is a chance we're suffering from low voltage transients due to a manufacturing error. I think I might try injecting well timed voltage transients to see if I can cause the EEPROM state machine to get stuck.

Hugo

 

0 Likes

Hugo,

That's the theory.  The question is:  Did Cypress leave some use-case "holes" in the design of the EEPROM circuits?  I personally couldn't say that it exists.

Even if they did, that is one of the reasons for a good watchdog strategy.   Watchdog timeouts are designed for user design issues (most likely case) and the rare manufacturer design issues.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi Len,

Well, I'll see if I can find anything. The thing about the watchdog is that, even if it catches a hang, that's already too late. We really need to prevent the watchdog triggering at all.

I'd rather have the EEPROM write fail rather than have the motor control loop stop for a second while the system resets.

Hugo

 

 

0 Likes

Hugo,

I once worked on a project where I used a Watchdog and a "Watchdog predictor".

The Watchdog was the standard HW WDT set to 10ms.  I created a SW-only watchdog that 'predicted' that the WDT could trigger.  It used a HW timer and a ISR connected to the Terminal count.  The Terminal count period was set to 9ms.

During code operation, the WDT and WDT-predictor timers were reset at the same time.

The Watchdog predictor was intended to catch issues in questionable coding where something that was not predicted in the design that was not CPU-based.  The ISR would trigger at 9ms and log a WDT-predictor count.  This was particularly useful during the development cycle to catch coding issues or unanticipated functional operation.  The trap on the WDT-predictor ISR would allow for correction of issues found before product release.

Note:  This WDT-predictor technique was not guaranteed to work if the CPU had "gone-off-track".  However as long as the interrupts were not disabled, the WDT-predictor had the possibility to pre-catch a potential WDT event.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hugo,

Another solution to a potential "HW" hangup is never to use a blocking function for detecting completion status.

This is especially true if you have a time-critical, reliability-sensitive design.

For example in your EEPROM writing code, once you start a sector write operation, don't while(CY_SPC_BUSY).   Instead create a new function in a virtual task (vTask) (let's call it EEPROM_Write_Complete()) to check for EEPROM status done.  This vTask can be placed in the main() loop and checked every 1ms(?).

All other application operations can continue without the need of knowing whether the EEPROM write operation is complete.  In the EEPROM_Write_Complete() you can also place a timer on the expected completion count.  If it doesn't complete in a reasonable amount of time, you might have to schedule a HW reset when the system is not in a critical state.

In a previous project, I created multiple vTasks  that were run from main() as the vTask scheduler.   One the vTasks monitored potential stack overruns.  If a stack overrun occurred, just before the sleep phase I would reset the CPU.  This prevented that sleep phase but it ensured that the CPU stack state was 'fixed' for the next requested application cycle.  The CPU then almost immediately reentered the sleep phase after reset due to no requests to perform a function.   Since I waited until a sleep phase was to be entered, it provided a chance for the current requested function to be performed with a reasonable chance of completion.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Len,

Indeed, this is the dream. There are no while() loops in our code at all. But looking into the generated code for the EEPROM component, I see several:

HuEl_264296_0-1658841256406.png

... which is why I was asking about the possibility of CY_SPC_BUSY ever getting stuck true. I would prefer not to have to edit the components to remove this issue. But if I can glitch the chip to cause this error, then I might have to do that.

0 Likes

Hugo,

You are correct.  EEPROM_Write() is a blocking function.   EEPROM_WriteByte() is blocking also.

If you use EEPROM_StartWrite() and EEPROM_Query(), you can prevent the blocking functons.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi Len,

If we're talking about a hypothetical situation where CY_SPC_BUSY can get stuck true, then the following are potentially blocking functions:

  • EEPROM_WriteByte()
  • EEPROM_Write()
  • EEPROM_StartWrite()
  • EEPROM_ByteWritePos()

They all contain a while(CY_SPC_BUSY) statement.

Hugo

 

 

0 Likes

Hugh,

I've looked at the coding for the functions:

  • EEPROM_WriteByte()
  • EEPROM_Write()
  • EEPROM_StartWrite()
  • EEPROM_ByteWritePos()

EEPROM_StartWrite() is listed as a non-blocking function.   You are correct.  This function is actually a blocking(-ish) function.  All the functions mentioned first test for the EEPROM resource being idle.   This is a blocking operation.  They do with with a  while(CY_SPC_BUSY){}

Once the EEPROM device is no longer busy, it starts the EEPROM Write operation.

The functions:

  • EEPROM_WriteByte()
  • EEPROM_Write()
  • EEPROM_ByteWritePos()

then block using the same while(CY_SPC_BUSY){} block waiting for a EEPROM resource to complete with an idle status.

The EEPROM_StartWrite() could be considered a blocking function if the CY_SPC_BUSY ever got into a faulted state  as being forever busy.

In theory, for EEPROM_StartWrite() to be a non-blocking function you should perform the following sequence:

...
if(CY_SPC_BUSY != EEPROM_Query())
{
   ...
   EEPROM_StartWrite();
   ...
}
...
Len
"Engineering is an Art. The Art of Compromise."
0 Likes
LeBa_1250741
Level 2
Level 2
5 sign-ins First solution authored 5 replies posted

It certainly hangs in the PSOC5A chips.

I've been trying to backport a design from PSOC5LP to PSOC5A. The first write to EEPROM would work, but subsequent writes would always hang and there is no 'state machine reset'  command for the EEPROM. I ended up having to emulate EEPROM in Flash and modify the linker to not overwrite.

0 Likes

LeBa,

Good to know.  

It is my understanding that only the PSoC5LP family is supported by Infineon (and Cypress).   The PSoC5 and PSoC5A families were discontinued and not for new designs.   

It is my understanding that  PSoC5 and PSoC5A families had silicon issues that were successfully addressed in the PSoC5LP.   Most times when a family of devices is retired permanently it is because some of the silicon issues found may not have a workaround.

In your PSOC5A case with the EEPROM, it sounds like a silicon errata.

In the case of your PSoC5A, ask an Infineon rep if there is a recommended workaround.   It appears from your post that you found a (less than great) workaround with emulated EEPROM in FLASH.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes