cancel
Showing results for 
Search instead for 
Did you mean: 

Fast programming for STM32L496 not working

Christian Neubert
Associate II

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?

6 REPLIES 6

> *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

Christian Neubert
Associate II

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.

JFieb
Associate II

Where does ptrRead point to?

Where is your code executing from?

Christian Neubert
Associate II

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.

PWint
Associate III

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

RM0351 section 3.3.7:

Fast programming

1 Perform a mass erase of the bank to program. If not, PGSERR is set.