Hi,
I'm using HCS08 and Freescale Beekit and meet a problem when I try to use NvData and WatchDog at the same time.
The timeout period of watchdog is 2^18 cycles of BUSCLK (16MHz), which is about 16.4 ms. I think that is the longest timeout period I can set. I use a timer interrupt to kick dog periodically.
NvData provides an interface to save data into Flash memory safely. However, every time program runs at NvHalErasePage(), just after pfNvHalExecuteFlashCmd(), system is reset because of watchdog timeout.
I guess one explanation could be: NvHalErasePage function takes period longer than 16.4ms, so kick dog routing must be called during NvHalErasePage. But erase page halts Flash memory and stops kick dog routing executing. The watchdog resets system eventually.
I'm thinking there may be something I can do to figure it out. But I haven't tried yet. Is there any one has solution, suggestion, or same problem to share?
Thanks
已解决! 转到解答。
Thanks peg and mac.
My first try was to put feed dog interrupt routing into RAM, and expected the interrupt can still happen and feed the watchdog during Flash accessing. It didn't work because of the reason presented by peg. So I had to try another way.
The good thing is, I found the exactly place where access Flash routing is waiting. The following code is generated by freescale beekit, located in file NV_FlashHAL.c.
/***********************************************************/
static bool_t NvHalExecuteFlashCmd
(
uint8_t data, /* IN: Data to be written */
void *pDestination, /* IN: Address where data has to be written */
uint8_t flashCommand, /* IN: Flash command to be executed */
uint8_t loopIndex /* IN: Initial loop index. */
)
{
/* Wait for flash to be ready for a command. */
while ( !( FSTAT & FCCF ))
{/* Do nothing for a while. */}
/* Clear all errors. */
FSTAT = FPVIOL | FACCERR;
for (;/* Do it until a break point is reached. */; )
{
/* Write data to flash. This is required by the flash controller, even */
/* for commands that don't modify data. */
*( unsigned char * ) pDestination = data;
/* Load command register with flash command. */
FCMD = flashCommand;
/* Launch the command. */
FSTAT = FCBEF;
/* Get the next byte form the logical sector buffer. */
data = maNvSectorBuffer[ ++loopIndex ];
if ( loopIndex >= sizeof( maNvSectorBuffer ))
{
/* If we are done get out */
break;
}
/* Wait for the command buffer to clear. */
while ( !( FSTAT & FCBEF ))
{/* Do nothing for a while. */}
}/* for (;; ) */
/* Wait for the command to complete. */
while ( !( FSTAT & FCCF ))
{/* Do nothing for a while. */}
if ( FSTAT & ( FPVIOL | FACCERR ))
{
/* If somethig got wrong, the set and return error. */
return FALSE; /* An error bit is set. */
}
/* We are totally done return success. */
return TRUE;
}/* NvHalExecuteFlashCmd() */
/***********************************************************/
Notice there are three while loops with "/* Do nothing for a while. */" in them. As mac said, adding "SIMRS = 0x01;" to feed dog there will keep system alive. It solves the problem.
Again, thanks for all replies!
Charlie.
Sorry, I cannot really help you as I did not use the Beekit :smileysad:.
However I wanted to mention that feeding the watchdog from the timer interrupt defeats (part of) the purpose of the COP, the timer interrupt might still occur peridically when the application code is hung somewhere.
Daniel
Hi, Daniel.
Thanks for your reply! Your are right, feeding the watchdog from the timer interrupt is not a good way. I agreed. My purpose of using timer interrupt is to obtain a longer watchdog timeout period.
I increase a variable (let me call it, "cnt") each time I feed the watchdog. If "cnt" is larger than N, I will not feed the watchdog any more and let system reset. I assign "cnt" back to zero in my main program to keep system alive. If the default watchdog timeout period is about 16ms, I want to make it longer to N times 16ms by this way. Meanwhile, I can "disable" the watchdog temporarily by feeding it automatically.
There may be a better and easier way to make watchdog timeout period longer and can be disabled temporarily. I'm glad to know other methods :smileyhappy:
Charlie
Hi Charlie,
Not aware of the code involved here, but in general, you can't allow interrupts while writing to flash as they cause flash accesses (vector fetch) which will disturb the write process. The only way to have the watchdog enabled during this is to clear it just before and after the sections where no flash access is allowed. If this doesn't work you will have to disable the watchdog.
Hello,
Actually the watchdog should be periodically cleared from within the RAM based portion of the NvData function code, whilst waiting for the completion of the flash erase command. If the function does not do this, I might consider to be a bug since the erase process will take 25ms, or longer. Similarly, I would expect this function to globally disable interrupts whilst flash is inaccessible, and then restore the previous interrupt status at the completion of the flash command.
Regards,
Mac
Thanks peg and mac.
My first try was to put feed dog interrupt routing into RAM, and expected the interrupt can still happen and feed the watchdog during Flash accessing. It didn't work because of the reason presented by peg. So I had to try another way.
The good thing is, I found the exactly place where access Flash routing is waiting. The following code is generated by freescale beekit, located in file NV_FlashHAL.c.
/***********************************************************/
static bool_t NvHalExecuteFlashCmd
(
uint8_t data, /* IN: Data to be written */
void *pDestination, /* IN: Address where data has to be written */
uint8_t flashCommand, /* IN: Flash command to be executed */
uint8_t loopIndex /* IN: Initial loop index. */
)
{
/* Wait for flash to be ready for a command. */
while ( !( FSTAT & FCCF ))
{/* Do nothing for a while. */}
/* Clear all errors. */
FSTAT = FPVIOL | FACCERR;
for (;/* Do it until a break point is reached. */; )
{
/* Write data to flash. This is required by the flash controller, even */
/* for commands that don't modify data. */
*( unsigned char * ) pDestination = data;
/* Load command register with flash command. */
FCMD = flashCommand;
/* Launch the command. */
FSTAT = FCBEF;
/* Get the next byte form the logical sector buffer. */
data = maNvSectorBuffer[ ++loopIndex ];
if ( loopIndex >= sizeof( maNvSectorBuffer ))
{
/* If we are done get out */
break;
}
/* Wait for the command buffer to clear. */
while ( !( FSTAT & FCBEF ))
{/* Do nothing for a while. */}
}/* for (;; ) */
/* Wait for the command to complete. */
while ( !( FSTAT & FCCF ))
{/* Do nothing for a while. */}
if ( FSTAT & ( FPVIOL | FACCERR ))
{
/* If somethig got wrong, the set and return error. */
return FALSE; /* An error bit is set. */
}
/* We are totally done return success. */
return TRUE;
}/* NvHalExecuteFlashCmd() */
/***********************************************************/
Notice there are three while loops with "/* Do nothing for a while. */" in them. As mac said, adding "SIMRS = 0x01;" to feed dog there will keep system alive. It solves the problem.
Again, thanks for all replies!
Charlie.