2019-02-14 11:07 PM
I wanted to use the flash fast programming, but it does not work. If I use the normal flash programming it is working as indended.
The procedure is that I unlock the flash, erase a 2KB page and then want to fast program that page with this code:
// wait for FLASH to be ready
Board_Flash_WaitForNotBusy();
Board_Flash_ResetErrorAndStatusFlags();
// disable interrupts
__disable_irq();
// enable Fast programming
FLASH->CR = FLASH_CR_FSTPG | FLASH_CR_EOPIE | FLASH_CR_ERRIE;
// program
for(int i = 0; i < (FLASH_FAST_PROGRAM_PAGE_SIZE / sizeof(uint64_t)); i++, ptrWrite++, ptrRead++)
{
*ptrWrite = *ptrRead;
}
// wait for finishing
Board_Flash_WaitForNotBusy();
Board_Flash_WaitForProgrammingFinished();
// disable Fast programming
FLASH->CR = 0;
Board_Flash_ResetErrorAndStatusFlags();
// enable interrupts
__enable_irq();
If I debug this code it happens that after writing the first 64bit that the FLASH->SR register has the value 0x2A2.
What am I doing wrong?
2019-02-15 04:58 AM
> *ptrWrite = *ptrRead;
Are these volatile uint64_t*? Look at the disasm, how are they implemented, whether this results in consecutively written words, i.e. the address increasing monotonically (I assume you don't attempt to write across row boundaries.
JW
2019-02-20 01:15 AM
I changed the code so that really 2 32bit values are written, but after the first 32bit value was written I get an error. I even disabled the data cache, but this does not help either.
FLASH->SR has the value 0x82, meaning PGSERR and OPERR are set.
FLASH->CR has the value 43040000, meaning FSTPG is set.
This does not make sense!? I´m afraid I´m doing something wrong which is not so clear by reading the manual.
2019-06-06 05:19 PM
Where does ptrRead point to?
Where is your code executing from?
2019-08-01 10:28 PM
The function does run from RAM as I want to write to the flash and ptrRead points to a 64bit aligned buffer where the data is.
As the normal function which only writes 64bit at once is working and this is the only difference to this function I don´t know what is wrong.
This is the function source code:
RAMFUNC
static
void
Board_Flash_FastProgramPage(uint64_t* addrWrite,
const uint64_t* addrRead)
{
// check if programming is necessary
if(Board_FlashCheckForBlanksOnly((uint32_t*)addrRead, FLASH_FAST_PROGRAM_PAGE_SIZE / sizeof(uint32_t)) == true)
{
return;
}
// wait for FLASH to be ready
Board_Flash_WaitForNotBusy();
Board_Flash_ResetErrorAndStatusFlags();
// disable interrupts
__disable_irq();
// disable data cache
FLASH->ACR &= ~FLASH_ACR_DCEN;
// enable Fast programming
FLASH->CR = FLASH_CR_FSTPG | FLASH_CR_EOPIE | FLASH_CR_ERRIE/* | FLASH_CR_PG*/;
// program
for(int i = 0; i < (FLASH_FAST_PROGRAM_PAGE_SIZE / sizeof(uint64_t)); i++, addrWrite++, addrRead++)
{
volatile uint32_t* ptrWrite = (volatile uint32_t*)addrWrite;
volatile uint32_t* ptrRead = (volatile uint32_t*)addrRead;
*ptrWrite = *ptrRead;
ptrWrite++;
ptrRead++;
MEMORY_BARRIER();
*ptrWrite = *ptrRead;
MEMORY_BARRIER();
}
// wait for finishing
Board_Flash_WaitForNotBusy();
Board_Flash_WaitForProgrammingFinished();
// disable Fast programming
FLASH->CR = 0;
Board_Flash_ResetErrorAndStatusFlags();
// enable data cache
FLASH->ACR |= FLASH_ACR_DCRST;
FLASH->ACR &= ~FLASH_ACR_DCRST;
FLASH->ACR |= FLASH_ACR_DCEN;
// enable interrupts
__enable_irq();
}
RAMFUNC is a define for telling GCC that this functions needs to be in RAM.
MEMORY_BARRIER is a macro which tells GCC that all memory needs to be read and written after this point.
This is the function which only writes 64bit at once:
RAMFUNC
static
void
Board_Flash_ProgramQWord(uint64_t* addrWrite,
const uint64_t* addrRead)
{
volatile uint64_t* ptrWrite = addrWrite;
volatile const uint64_t* ptrRead = addrRead;
// check if programming is necessary
if(Board_FlashCheckForBlanksOnly((uint32_t*)ptrRead, 2) == true)
{
return;
}
// wait for FLASH to be ready
Board_Flash_WaitForNotBusy();
Board_Flash_ResetErrorAndStatusFlags();
// disable interrupts
__disable_irq();
// enable programming
FLASH->CR = FLASH_CR_PG | FLASH_CR_EOPIE | FLASH_CR_ERRIE;
// program
*ptrWrite = *ptrRead;
// wait for finishing
Board_Flash_WaitForNotBusy();
Board_Flash_WaitForProgrammingFinished();
// disable programming
FLASH->CR = 0;
Board_Flash_ResetErrorAndStatusFlags();
// enable interrupts
__enable_irq();
}
This function is working without problems.
2020-05-08 02:01 AM
Hi Christian,
Did you ever receive a solution to your problem?
I've also written a flash-programming function and tried to use the fast programming, but it does not work.
My FSTPG bit is set in the CR, and I can confirm it with the debugger, but as soon as I write to flash, the sequence error bit, PGSERR is set. The documentation states that PGSERR is set when you write to flash without PG or FSTPG set. So I agree with you, it does not make sense, and fast programming does not seem to work as documented.
Regards,
Pieter
2020-05-30 06:27 AM
RM0351 section 3.3.7:
Fast programming
1 Perform a mass erase of the bank to program. If not, PGSERR is set.