Author Topic: EEPROM emulation – STM32F4 flash vs external flash chip  (Read 6688 times)

0 Members and 1 Guest are viewing this topic.

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: EEPROM emulation – STM32F4 flash vs external flash chip
« Reply #25 on: December 18, 2020, 09:03:28 am »
ECC often can not be disabled, and often is not even exposed to the user (except in strange limitations of programming ).

But after checking the datasheet it appears  this device does not have ECC. In fact the reference manual is explicit on this: "Successive write operations are possible without the need of an erase operation when changing bits from ‘1’ to ‘0’. Writing ‘1’ requires a Flash memory erase operation."

So how exactly did the flash controller complain? STMs are very verbose with their error codes on flash operations.

Oh, wait you have 407. I was looking in the manual for the original device. Ok, the same exact text is present in the 407 RM.

A excellent question, I don't actually know right now as I'm waiting for feedback from the architect of the Forth system (mecrisp-Stellaris) I use.

I grepped the Mecrisp-Stellaris source and it seems the error came from the Forth Kernel, not the F407 Flash_SR register which has the following Bitfields for flash issues.

: Flash_SR_EOP ( -- x addr ) 5 bit Flash_SR ; \ Flash_SR_EOP, End of operation
: Flash_SR_WRPRT ( -- x addr ) 4 bit Flash_SR ; \ Flash_SR_WRPRT, Write protection error
: Flash_SR_PGERR ( -- x addr ) 2 bit Flash_SR ; \ Flash_SR_PGERR, Programming error
: Flash_SR_BSY ( -- x addr ) 0 bit Flash_SR ; \ Flash_SR_BSY, Busy

I expected that the Flash_SR_PGERR was the issue but I can't see it being raised ( or any of the others) or find it in the source, but then the source is mostly in German and not exactly CMSIS-SVD compliant, so I'll have to wait for advice from the architect.

The architect pointed out that his assembly code had protection against altering flash and once this code was removed everything worked as expected from the User Manual.

Code: [Select]
Sector 11  0x080E 0000 - 0x080F FFFF  = 128 Kbytes
Code: [Select]
11 eraseflashsector Erase sector 11
 ok.
read_$F0000 000000FF  ok.
flash_0xAA->$F0000  ok.
read_$F0000 000000AA  ok.
flash_0x00->$F0000  ok.
read_$F0000 00000000  ok.
 

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: EEPROM emulation – STM32F4 flash vs external flash chip
« Reply #26 on: December 18, 2020, 09:16:19 am »
I want to store few KB of settings/presets, due to 128KB external flash block size I was hoping to store presets in MCU (STM32F407) flash. My idea is to use predefined memory amount per preset (for example 1KB) and define first byte on it as its ID for indentification while reading presets. If preset gets updated MCU finds new emty space, writes new preset there and sets old preset 1st byte to 0x00 to indicate that it's no longer valid.

Summary:

Yes, this can be done, a single flash location can have the data reflashed with "0"'s, (but not "1"'s).

Minimum erasure size is the sector involved. My test used Sector 11.
NOTE: the MCU (STM32F407) does not have ECC flash.

Code: [Select]
Sector 11  0x080E 0000 - 0x080F FFFF  = 128 Kbytes
11 eraseflashsector Erase sector 11  ok.


Data from a STM32F407 Discovery Board running Mecrisp-Stellaris Forth showing the above.

Code: [Select]
read_$F0000 000000FF  ok.

flash_0xAA->$F0000  ok.

read_$F0000 000000AA  ok.

flash_0x00->$F0000  ok.

read_$F0000 00000000  ok.




 
« Last Edit: December 18, 2020, 09:18:36 am by techman-001 »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11299
  • Country: us
    • Personal site
Re: EEPROM emulation – STM32F4 flash vs external flash chip
« Reply #27 on: December 18, 2020, 09:19:56 am »
The only danger here with one sector is that power may go away while you are erasing and you will lose your settings. You need at least two sectors for reliable operation.
Alex
 

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: EEPROM emulation – STM32F4 flash vs external flash chip
« Reply #28 on: December 18, 2020, 10:14:19 am »
The only danger here with one sector is that power may go away while you are erasing and you will lose your settings. You need at least two sectors for reliable operation.

If a hobbyist is willing to forgo that professional level of data security, a 64KB logger could be built using the second "hidden" flash block in a "blue-pill" with the STM32F103C8 MCU found in most units.
That would leave 64KB for the main program, which is tons for C and Forth.
 

Online S. Petrukhin

  • Super Contributor
  • ***
  • Posts: 1199
  • Country: ru
Re: EEPROM emulation – STM32F4 flash vs external flash chip
« Reply #29 on: December 20, 2020, 03:21:39 am »
The logic of flash is that it can't accept data using MOV (like eeprom), it accepts data as AND. I.e. you can write 0 to each bit of flash, but you can't write 1. To write 1, you need to erase the entire sector at the same time - erased flash contains 1 in all bits.

When I often needed to write just one byte, it seemed unnecessary to supplement the eeprom, often erase flash-a hole will be wiped. I organized a chain of data cells. The first byte was a signature with the values: FFh-cell is free, 0Fh-cell contains current data, 00h-cell is canceled. So by finding a cell with the signature 0Fh, I could find the actual data. To write new actual data, I wrote the signature 00h to the current cell, and the signature 0Fh to the next one. When the sector ended, I erased it and used a new circle.

Code: [Select]
const
    cEmptyFlashCell = 0xFF;
    cActualFlashCell = 0x0F;
    cCanceledFlashCell = 0x00;
    cEmptyFlashValue = 0;

type
    tFlashCell = record
       Singnatute : byte;
       Value : byte;
   end;

const
   cLowFlashData = 1;
   cHighFlashData = cSectorSize div SizeOf(tFlashCell);

type
   tFlashData = array[cLowFlashData..cHighFlashData] of tFlashCell;

var
   FlashData : tFlashData absolute cFlashEnd-cFlashSectorSize;

funtion GetFlashCurrPos:dword;
var i: dword;
begin
   i:=cLowFlashData;
   while (i<=cHighFlashData) and (FlashData[i].Signature<>cActualFlashCell ) do Inc(i);
   if i>cHighFlashData then i:=cLowFlashData;
   Result:=i;
end;

function GetFromFlashValue:byte;
var t: dword;
begin
   t:=GetFlashCurPos;
   if FlashData[t].Signature=cEmptyFlashCell then begin
      Result:=cEmptyFlashValue;
   and else begin
      Result:=FlashData[t].Value;
   end;
end;

procedure SetToFlashValue(aValue:byte);
var t: dword;
begin
    t:=GetFlashCurPos;
    if t=cHighFlashData then begin
       EraseFlashSector;
       t:=cLowFlashData;
    end else begin
       if FlashData[t].Signature<>cEmptyFlashCell then begin
          SaveToFlash(t,cCanceledFlashCell,0);
          Inc(t);
       end;
    end;
    SaveToFlash(t,cActualFlashCell,aValue);
end;

« Last Edit: December 20, 2020, 03:34:21 am by S. Petrukhin »
And sorry for my English.
 
The following users thanked this post: Davor


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf