Skip to main content
varga
Associate
March 23, 2018
Question

FLASH FastProgram allways return PGAERR ...

  • March 23, 2018
  • 5 replies
  • 5768 views
Posted on March 23, 2018 at 16:34

Device STM32L452RE on my HW board with 3V3 Vdd ...

This code is placed in RAM ...

//--- Program

__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);

//--- FLASH_Program_Fast

uint8_t

ID;

uint32_t

DstAddr = (FLASH_BASE + Addr) & 0xFFFFFFF8;

SET_BIT(FLASH->

CR

, FLASH_CR_FSTPG);

//--- Program the double word of the row

for

(ID = 0; ID < (32 * 2); ID++)

{

*(

uint32_t

*)(DstAddr) = 0xAABBCCDD;

DstAddr += 4;

}

// Wait for last operation to be completed

while

(READ_BIT(FLASH->

SR

, FLASH_FLAG_BSY)) {};

if

(READ_BIT(FLASH->

SR

, FLASH_FLAG_PGAERR)) LED_BO_Set(

LED_BO_ORANGE

, 1);

Where is error?

#stm32l4-fastprogram
This topic has been closed for replies.

5 replies

Tesla DeLorean
Guru
March 23, 2018
Posted on March 23, 2018 at 18:19

What address are you writing?

Is the memory erased first?

The mask aligns to 64-bits

You write 64 32-bit words, 256 bytes, 2048-bits

uint8_t variables are not efficient

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
varga
vargaAuthor
Associate
April 3, 2018
Posted on April 03, 2018 at 15:33

1. FLASH_BASE = 0x08000000, Addr = 0x00040000

2. Yes, page erased (

Checked via STM32 ST-LINK Utility v4.1.0.0)

Andreas Bolsch
Lead III
April 13, 2018
Posted on April 13, 2018 at 12:57

2. Yes, page erased (

Checked via STM32 ST-LINK Utility v4.1.0.0)

Did you do only a *PAGE* erase? The RM explicitly says that a bank *MASS* erase ist required:

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

...

PGSERR is set if one of the following conditions occurs:

...

In the fast programming sequence: the Mass erase is not performed before setting

FSTPG bit.
Dave Jones
Associate III
April 10, 2018
Posted on April 10, 2018 at 06:48

I'm having this same problem, with this same processor. I'm not running it out of RAM, like the OP.

I successfully wrote a page erase function, following the steps in the reference manual. It works fine with no errors. I also wrote a program double word function, which also works fine with no errors. But when I tried to write a program row function, the PGAERR bit is set, as well as the PGSERR and FASTERR bits (both of which say they will be set if the PGAERR bit is set). The PGAERR says on row programming it will be set if the function changes page during the writing of the 64 words. But that is not happening in my code. 

I am starting the write at address 0x08010800. That is the page that I first erase (page #33). And the address I start at is not only a double word boundary, and a row boundary, it is also a page boundary. So there's no way that writing to the first 64 words of a page should cause an error defined as 'changing page'.

After a few hours of trying various things in my own code, I tried using the HAL function HAL_FLASH_Program(), which is the polling version of their FLASH memory writing functions. I gave it that same address, set the 'TypeProgram' to FLASH_TYPEPROGRAM_FAST_AND_LAST (which means program one row and then stop). I  created a uint64_t array full of zeros and passed that to the function (that's what they use for the data in). I tested the function on return and it failed the return check for HAL_OK. And checking the page in the debugger shows none of it got set to zeros.

So my function (several variations of it) failed, and so did the HAL function to do a row program.

I checked the errata sheet and the only issue with FLASH is that the OPTVERR bit is incorrectly set in this part. I did add the code earlier in my program to clear that bit, as suggested in the errata. It made no difference.

So, if anybody out there has a board with an STM32L452 on it that is able to do a row program, please let us know how you did it.

Dave Jones
Associate III
April 10, 2018
Posted on April 10, 2018 at 22:07

And I tried this with optimization disabled (easier debugging) and with it optimized for speed. No difference.

There's no reference manual for the L4x2 parts (like there are for L4x1, L4x5, and L4x6), so I'm using the one for the L43x, L44x, L45x, and L46x.

So if anybody has gotten an L4 part to work with row programming ('FASTPG'), I'd love to hear which part and what steps you used. And if you came across the same error and found a solution.

Tesla DeLorean
Guru
April 11, 2018
Posted on April 11, 2018 at 07:54

That seems like the right RM for the L452, it specifically calls it out.

Will check the box at the office, none to hand here.

The DEV_ID should be 0x0462

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Dave Jones
Associate III
April 12, 2018
Posted on April 12, 2018 at 22:45

One thing I came across today was a comment in a thread talking about the row programming function not executing from RAM because even though HAL defines the function as being in section .RamFunc, there is in fact no section with that name defined in the linker script. I didn't pay attention last night to verify in the debugger if the function was actually running from RAM. I added that section to my linker script (in the initialized RAM area), and verified while debugging that my row write function is in fact executing from RAM. Still doesn't work though.

To try and dig deeper into what is happening I created an array in RAM, and before each of the word writes in my function I read the FLASH->CR and FLASH->SR registers and stuck them into the array. Then I stop the debugger near the end of the function and look at the contents of that array.

What I found is that throughout the loop the CR didn't change (as would be expected), and that the FSTPG bit is set and LOCK is clear, and no other unexpected bits are set wrong.

Before the first word is written, the SR register is clear. No bits set. After the first word is written the PGSERR bit is set, all other bits are clear. After the second word is written the PGSERR, FASTERR, and PGAERR bits are all set (the rest are clear). That remains the same for the rest of the loop and afterwards when I reach the breakpoint at the end of the function.

The ref manual says that PGSERR is set if a write access to flash is performed without PG or FSTPG set. (but FSTPG is set, according to the CR register reading in my array). PGSERR can also be set if PROGERR, SIZERR, PGAERR, MISSERR, or FASTERR are set. But after that first word write, only the PGSERR bit is set. Those others are all clear.

After writing the second word, PGSERR, FASTERR, and PGAERR bits are all set. FASTERR says it is set during a fast write if PGAERR, SIZERR, WRPERR, or MISSERR are set. Of those, only the PGAERR is set. So at that point I have to assume that FASTERR and PGSERR are both set because PGAERR is set. (though that still doesn't explain why PGSERR was set by itself after the first word write).

PGAERR says it is set if there is a change of page during Fast programming. But that isn't happening. The first word write is going to 0x8010800, which is the start of a page. Subsequent writes are to words continuing from that point. The pointer used to point at the flash location is defined as __IO uint32_t *, and the debugger is showing it pointing to the next word after the first row (64 words) when the function is done. So the pointer starts out pointing at 0x8010800 and after the loop it is pointing at 0x8010900.

So I do not see how by the time of the second word write the hardware believes that the write was attempted at a different page. Or understand why PGSERR is set by itself after the first word write.

VC.8
Visitor II
December 19, 2018

See DataSheet..

from STM32L475:

time for prog dw = 0.08169ms

time for prog row = 32*dw = 2.61ms (1.91ms for fast programming)

You really still need fast programming?!! It's LESS THEN half-page(64byte) programming on STM32L0!

jr_it
Associate II
April 1, 2020

Any solution on this? I have the exact same issue for STM32G474.

Code is executing entirely from RAM. It seems there's something essential missing for fast programming.