EEPROM ,Worcking

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: EEPROM ,Worcking

Post by Giovanni »

If you go in the megabytes range then probably the SD card is the correct choice, alternatively some huge dedicated flash memory connected on FSMC or SPI.

Giovanni
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: EEPROM ,Worcking

Post by barthess »

If you need about 4mbytes of storage than take a look at AT45xxx or AT25xxx.
Also you can split your storage in 2 pieces: small EEPROM IC (for example 24AAxx storing valuable parameters) + large NAND/SDC (for data logs).

deadlyboy wrote:but as ulikoehler said : if you don't hate them you just haven't used them enough

I am totally agree with ulikoehler here. Probably NAND with simple ring buffer will be better.
Note ChibiOS HAL has drivers for NAND in community overlay.
ulikoehler
Posts: 71
Joined: Tue Mar 17, 2015 2:32 am
Been thanked: 3 times

Re: EEPROM ,Worcking

Post by ulikoehler »

[url]@deadlyboy:

It seems like you only need a few megabytes of data, that's not very much. You could get away with a SPI flash like this one:
http://www.spansion.com/Support/Datasheets/S25FL208K_00.pdf
It is 8 MiB and 31 €-cents on DigiKey @1pc. Doubt you can get a decent quality SD card for that.
You'll have to handle ring buffering / wear levelling / erasing by yourself, however. I think it is wort it. I don't know if there are open source ChibiOS drivers on GitHub or here on the forum for such devices - if not I'd appreciate if you could publish yours if possible.

I need to use SD cards (at least until I get the USB host working...) and ended up with ultra-expensive industrial SD cards (~100€/16GiB) that - according to our tests - have quite a good immunity to poweroffs on the block level. I would still not use FatFS though, it's IMO quite easy to introduce fatal-ish errors on filesystems that have a complex state spread across many blocks.

About length matching see section 6 in https://cache.freescale.com/files/32bit/doc/app_note/AN4215.pdf. IMO it is far less critical than RMII, though. However, ANY hardware bug related to SDIO instability, not matter how small, is your worst nightmare if you have to debug it. I can only recommend doing absolutely anything you can think of to avoid such issues.
If you don't do it right you might also have issues with EMI compliance, operation over full temperature range and similar

SPI is also somewhat critical when you use it @76MHz which is the max speed the spansion IC (see above) supports. However, you can more easily debug it using a good DSO and it has way fewer signals that need to be match. You could pay attention to length/impedance matching of SCLK relative to MOSI/MISO but in my experience for most applications it is advisable to just use a better firmware algorithm (write queues, for example) and run SPI on 10MHz or so. Then you only need to make sure SCLK and MOSI/MISO are length-matched within a centimeters or so (I'm eyeballing this, but @10Mhz it should be OK). Your best bet is to place the SPI device close to the uC.

NAND memory usually consumes more pin and is more complex to use (initialize FSMC/FMC). I'd use SPI flash if I could get away with it, but fundamentally they work the same.

There is an appnote from TI about SPI delays and related issues, especially for long distance SPI. I suggest you have a look at it to understand some of the problems that might emerge: http://www.ti.com/lit/an/slyt441/slyt441.pdf

Best regards
rew
Posts: 383
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 14 times

Re: EEPROM ,Worcking

Post by rew »

uli: He needs "2Mb, preferably 5Mb of log". That's probably megabytes, not bits. So the 1 megabyte flash chip is too small.

If you mount an SD card on your system, you suddenly can't get any devices smaller than 1000 times larger.... weird. $0.31 for 1 Mbyte, about $1 for 1Gb SD.
ulikoehler
Posts: 71
Joined: Tue Mar 17, 2015 2:32 am
Been thanked: 3 times

Re: EEPROM ,Worcking

Post by ulikoehler »

@rew: Yep, I suppose you're right about the bits/bytes thing. Here's the 0,86€ @1pc 64 Mbit part:
http://www.spansion.com/Support/Datasheets/S25FL1-K_00.pdf

The difference is: The 1$ SD won't really work reliably, in other words it has unknown failure modes. Raw flash has well-known failure modes, you just have to get your firmware right (wear levelling, page accesses etc).
deadlyboy
Posts: 27
Joined: Wed Nov 26, 2014 9:27 am

Re: EEPROM ,Working

Post by deadlyboy »

thank you guys.

i thought seriously about this and i decided to use one of AT45xxx family , maybe AT45DB32 or 64(it would be great if i find SO-8 packages) beside SD card for my next board .

the SD card will be experimenting memory for the next board, i also thought about nor and nand flashe , F-RAM , and .... but given that i saw AT45DB32 flamily works well in other projects i'm a bit more optimistic about them.

last night i was working on sd card which in mounted in my current board and it seemed work well with the STM32F4xx SDC demo , it create's a file in sd using FATFS and put some data in it , but always it halted when it wanted to Check file content here :

Code: Select all

err = f_open(&FileObject, "0:chtest.txt", FA_READ | FA_OPEN_EXISTING);


and when i put all of these code which was run in Shell to be executed in main whenever the program started, it showed weird behavior. it halted at first f_open function , and it couldn't even create a file in sd.

is it normal ? or i did something wrong(all i did was a copy and past)??
if i don't want to use FATFS is there another way to write and read raw data in sd card ? i saw these :

Code: Select all

/**
 * @brief   Writes one or more blocks.
 */
sdcWrite(&SDCD1,0,myBuffer,1)
sdcRead(&SDCD1,0,myBuffer1,1);



i used them but they don't work for writing data in SD card(in my case). do any body has Applicable example of SDC without FatFS ?
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: EEPROM ,Worcking

Post by Giovanni »

Hi,

See the SDC demo for F4 under testhal.

Giovanni
ulikoehler
Posts: 71
Joined: Tue Mar 17, 2015 2:32 am
Been thanked: 3 times

Re: EEPROM ,Worcking

Post by ulikoehler »

A few notes regarding raw SD block access:
- SD cards generally work with 512 byte blocks. With the ChibiOS API you can only write / read whole 512 byte blocks.
- Multi-block reads/writes are usually faster
- Manually pre-erasing blocks is not required. You can just overwrite them

Best regards
User avatar
Chudik
Posts: 152
Joined: Fri Jan 16, 2015 7:51 am
Has thanked: 7 times
Been thanked: 1 time

Re: EEPROM ,Worcking

Post by Chudik »

In our another project for the similar purposes of data logging we used relatively small (and not so expensive) FRAM for the temporary buffer. After filling up the buffer (512Bytes-4kBytes) it's been written to the SD card. It helps to keep log data in case of power break.

Giovanni,
Do I need any special stuff to use built-in EEPROM in my STM32L1?
ulikoehler
Posts: 71
Joined: Tue Mar 17, 2015 2:32 am
Been thanked: 3 times

Re: EEPROM ,Worcking

Post by ulikoehler »

@Chudik: In a STM32F0 project I have successfully used the ST library (from STM32F0Cube) without significant modifications. I mainly copied code from the example from STM32F0Cube. It should be the same for STM32L1.

There are a few minor pitfalls, however, e.g. you need to unlock flash write access.

Here's my init function that is called once in main() (use it as public domain):

Code: Select all

static void initializeEEPROMEmulation(void) {
    //Allow all flash operations
    FLASH_Unlock();
    //Format EEPROM if there is no valid page
    EE_Init();
    //Initialize values to 0 if no stored value is present
    uint16_t dummy; //Just a dummy, data argument to EE_ReadVariable() must be != NULL
    if(EE_ReadVariable(EEPROM_FIRST_VARIABLE, &dummy) == 1) { //Not found
        EE_WriteVariable(EEPROM_FIRST_VARIABLE, 0);
        EE_WriteVariable(EEPROM_SECOND_VARIABLE, 0);
        EE_WriteVariable(EEPROM_THIRD_VARIABLE, 0);
    }
}


Here's my address table for reference:

Code: Select all


/**
 * Virtual addresses
 * stored in the EEPROM emulation
 */
const uint16_t VirtAddVarTab[NB_OF_VAR] = {
    //Describe variables here
    0x5555,
    0x5556,
    0x5558,
};
#define EEPROM_FIRST_VARIABLE (VirtAddVarTab[0])
#define EEPROM_SECOND_VARIABLE (VirtAddVarTab[1])
#define EEPROM_THIRD_VARIABLE (VirtAddVarTab[2])


Note that you also need to modify the linker script. I use a STM32F030F4P6, with this linkerscript reserving 2 pages (pay close attention to the page size) (this is for ChibiOS 2.x):

Code: Select all

/*
    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/*
 * ST32F030F4 memory setup.
 */
__main_stack_size__     = 0x0100;
__process_stack_size__  = 0x0800;

MEMORY
{
    /* 16k flash, but 2k used for EEPROM */
    flash : org = 0x08000000, len = 14k
    ram : org = 0x20000000, len = 4k
}

__ram_start__           = ORIGIN(ram);
__ram_size__            = LENGTH(ram);
__ram_end__             = __ram_start__ + __ram_size__;

ENTRY(ResetHandler)

SECTIONS
{
    . = 0;
    _text = .;

    startup : ALIGN(16) SUBALIGN(16)
    {
        KEEP(*(vectors))
    } > flash

    constructors : ALIGN(4) SUBALIGN(4)
    {
        PROVIDE(__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE(__init_array_end = .);
    } > flash

    destructors : ALIGN(4) SUBALIGN(4)
    {
        PROVIDE(__fini_array_start = .);
        KEEP(*(.fini_array))
        KEEP(*(SORT(.fini_array.*)))
        PROVIDE(__fini_array_end = .);
    } > flash

    .text : ALIGN(16) SUBALIGN(16)
    {
        *(.text.startup.*)
        *(.text)
        *(.text.*)
        *(.rodata)
        *(.rodata.*)
        *(.glue_7t)
        *(.glue_7)
        *(.gcc*)
    } > flash

    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > flash

    .ARM.exidx : {
        PROVIDE(__exidx_start = .);
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        PROVIDE(__exidx_end = .);
     } > flash

    .eh_frame_hdr :
    {
        *(.eh_frame_hdr)
    } > flash

    .eh_frame : ONLY_IF_RO
    {
        *(.eh_frame)
    } > flash
   
    .textalign : ONLY_IF_RO
    {
        . = ALIGN(8);
    } > flash

    . = ALIGN(4);
    _etext = .;
    _textdata = _etext;

    .stacks :
    {
        . = ALIGN(8);
        __main_stack_base__ = .;
        . += __main_stack_size__;
        . = ALIGN(8);
        __main_stack_end__ = .;
        __process_stack_base__ = .;
        __main_thread_stack_base__ = .;
        . += __process_stack_size__;
        . = ALIGN(8);
        __process_stack_end__ = .;
        __main_thread_stack_end__ = .;
    } > ram

    .data :
    {
        . = ALIGN(4);
        PROVIDE(_data = .);
        *(.data)
        . = ALIGN(4);
        *(.data.*)
        . = ALIGN(4);
        *(.ramtext)
        . = ALIGN(4);
        PROVIDE(_edata = .);
    } > ram AT > flash

    .bss :
    {
        . = ALIGN(4);
        PROVIDE(_bss_start = .);
        *(.bss)
        . = ALIGN(4);
        *(.bss.*)
        . = ALIGN(4);
        *(COMMON)
        . = ALIGN(4);
        PROVIDE(_bss_end = .);
    } > ram   
}

PROVIDE(end = .);
_end            = .;

__heap_base__   = _end;
__heap_end__    = __ram_end__;


I also added stm32f0xx_flash.c + header from the Cube library in order to support FLASH_Unlock().

With the configurations listed above, this is my eeprom.h (basically the header for eeprom.c from the Cube library)

Code: Select all


/* Exported constants --------------------------------------------------------*/
/* Define the size of the sectors to be used */
#define PAGE_SIZE             ((uint32_t)0x0400)  /* Page size = 1KByte */

/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS  ((uint32_t)0x08003800) /* EEPROM emulation start address:
                                                        from sector2, after 14KByte of used
                                                        Flash memory */

/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))

#define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
#define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))

/* Used Flash pages for EEPROM emulation */
#define PAGE0                 ((uint16_t)0x0000)
#define PAGE1                 ((uint16_t)0x0001)

/* No valid page define */
#define NO_VALID_PAGE         ((uint16_t)0x00AB)

/* Page status definitions */
#define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */
#define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to receive data */
#define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing valid data */

/* Valid pages in read and write defines */
#define READ_FROM_VALID_PAGE  ((uint8_t)0x00)
#define WRITE_IN_VALID_PAGE   ((uint8_t)0x01)

/* Page full define */
#define PAGE_FULL             ((uint8_t)0x80)

/* Variables' number */
#define NB_OF_VAR             ((uint8_t)0x05)


Note that 14 kiB of flash remains usable for code, data etc. The remaining 2 kiB (= two pages) are used to store variables.

Best regards, Uli
Post Reply