My problem occurs immediately after erasing a bock of the flash. This is a tough problem - it usually works, but sometimes locks up. I have done some searching, not found this elsewhere. I've been through the applicable parts that I can find in the STM manual, but no help. The closest is their comments:
Any attempt to read the Flash memory on STM32F4xx while it is being written or erased, causes the bus to stall. Read operations are processed correctly once the program operation has completed. This means that code or data fetches cannot be performed while a write/erase operation is ongoing.
The FLASH_CR register is not accessible in write mode when the BSY bit in the FLASH_SR register is set. Any attempt to write to it with the BSY bit set will cause the AHB bus to stall until the BSY bit is cleared.
I am a slow learner, not quite sure what they are saying here. It probably makes more sense in the original German. Does anyone know of any tech notes dealing specifically with these issues?
Moving right along, here is the function:
FLASH_Status FLASH_EraseSector(uint16_t FLASH_Sector) { FLASH_Status status = FLASH_COMPLETE; if((FLASH_Sector != FLASH_Sector_10)&&(FLASH_Sector != FLASH_Sector_11)) // sectors 10 & 11 only { status = FLASH_ERROR_WRP; // set fault message return status; // exit without any damage } status = FLASH_WaitForLastOperation(); // Wait for last operation to be completed gblDbgReg[1]=50; if(status == FLASH_COMPLETE) { /* if the previous operation is completed, proceed to erase the sector */ FLASH->CR &= CR_PSIZE_MASK; // the device voltage range is 2.7V to 3.6V, FLASH->CR |= FLASH_PSIZE_WORD; // the operation is by word (32-bit) FLASH->CR &= SECTOR_MASK; // clear out sector control bits FLASH->CR |= FLASH_CR_SER | FLASH_Sector;// set for sector erase and sector number gblDbgReg[1]=51; FLASH->CR |= FLASH_CR_STRT; // start erasing... // wait for about a second.... gblDbgReg[1]=52; status = FLASH_WaitForLastOperation(); // Wait for last operation to be completed gblDbgReg[1]=53; FLASH->CR &= (~FLASH_CR_SER); // turn off sector erase FLASH->CR &= SECTOR_MASK; // clear out the sector number } gblDbgReg[1]=54; return status; // Return the Erase Status }
Usually, this works great. The lines with "gblDbgReg[1] assignments are non-functional, but allow me to see this going through its paces on the logic analyzer. It does exactly what I expect.
Other times, it hangs up. There is no recognized pattern. For a while yesterday, it was perhaps one time out of three on average. When these occurred, I observed the following: - gblDbgReg[1] had a value of 53 - the program hung up until the watchdog reset the whole program - I was able to catch it in the locked up state a couple times, in an interrupt handler that I do not think was ever called. I am assuming that the program jumped to an inappropriate place withing this function. - It was never found in a FLASH_WaitForLastOperation() hangup
I have tried disabling / enabling interrupts, no change I have tried salting with a few more FLASH_WaitForLastOperation() after commands were sent, no change
I rebuilt the entire program, and now I am no longer seeing a hangup. I have gone through dozens of attempts with no observed errors. What happened?
My point was more that you are setting the entire register back to 0 EXCEPT for the Sector number (twice).
My bad; did not furnish all the information to you. Here it is:
#define CR_PSIZE_MASK ((uint32_t)0xFFFFFCFF) #define SECTOR_MASK ((uint32_t)0xFFFFFF07)
so these clear the bits.
The issue went away for awhile, then reappeared a couple times yesterday. In those instances, the crash occurred just prior to erasing. In all of these instances, the execution stops, until the watchdog resets the whole works.
This happens so infrequently that it is difficult to locate cause. There may be some relationship with an ISR. If anyone has had some experience with flash erasing, I would sure appreciate additional suggestions.