[En-Nut-Discussion] IAP Api proposal, was: Re: nvmem problems with STM32F103

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Fri Jul 19 11:35:11 CEST 2013


>>>>> "Ole" == Ole Reinhardt <ole.reinhardt at embedded-it.de> writes:

    Ole> Hi Achim,
    Achim> Hi all, I´ve problems using the internal flash memory for storing
    Achim> some variables in STM32F103. When I call NutNvMemSave the systems
    Achim> hangs up in IntDefaultHandler.  (FLASH CONF SECTOR = 0x1F800 in
    Achim> nutconf)
    >>
    Achim> Has anybody already used this function with STM32?  I´ve used the
    Achim> same function formerly with AT91SAM7X without any problems.
    >>
    >> Achim,
    >>
    >> are you sure there _is_ flash at 0x1F800 for your device? What device
    >> are you using and what configuration file?

    Ole> I got a patch from Daniel Rosenthal and applied it to the trunk. It
    Ole> should enable the NVMEM functionality for the internal flash of the
    Ole> STM32F1xx.

    Ole> Could you please test it again? But please check the
    Ole> FLASH_CONF_SECTOR to point to the last available flash sector).

I have code for nvmem with flash on F1/3/ and  F2/4 and on EEPROM L1 in
private trunk. The code automatically reserves FLASH_CONF_SIZE when
configured at the end of flash when working with flash. No need to configure
the config location, only eventually the size/

It uses an In-Application-Programming API I would propose for EN-Nut and I
have implemented for F1/3, L1 and F2/4/

The API requires the application code to have as minimal knowledge of
the actual flash layout as possible, so application code is as portable as
possible. It consists of

* uint32_t IapFlashEnd(void);
to return the end of Flash, excluding eventual configured configuration space.

* FLASH_Status IapFlashWriteProtect(void *dst, size_t len, int ena);
to change write protection of the specified range, extending the
range to physical units of flash the architecture can protect.

* FLASH_Status  IapFlashWrite( void* dst, void* src, size_t len,
  FLASH_ERASE_MODE mode);
to write the provided space with the provided data. If src == NULL, only a
  check for write protection is done. Configuration space is excluded in the
  exported API.
** FLASH_ERASE_MODE may be
- FLASH_ERASE_ALWAYS where the minimal physical flash unit including the
  requested area is _always_ erased before writing
- FLASH_ERASE_NEVER where no erase is done before writing. Writing will
  succeed if flash was erased before, for many architecture if the pattern
  written is the complement of the erased flash pattern and may also
  fail when not working on erased memory. User has to know what he does and
  must check return value.
- FLASH_ERASE_FIRST_TOUCH where NUTOS keeps track of the sectors it has
  erased. If a write request to the pysical flash unit is requested, erase
  is done and the sector erased. Later write requests will not erase.
  Writing a single 32-bit word at a 32-bit boundary should always succeed on
  erased flash, writing smaller units off the boundary may or may not
  succeed, depending on implementation and architecture. E.g. F2/4 allows Byte
  write for the flash, and L1 has small 256 byte pages where we can load the
  old page content and only substitute the new data. So Byte write is
  possible. On F1/3, only 16-bit write at 16-bit boundary is possible and
  sectors are quite large with 2048 byte, so byte write will fail.

* void FlashUntouch(void)
will zero out the list of already erased physical flash units.

Why do we need FLASH_ERASE_FIRST_TOUCH?
E.g. STM32F4 has flash sector sizes of 128 kiByte. For In-appplication
programming it will nearly be impossible to provide a 128 kiByte RAM buffer to
assemble a full sector before writing. With FLASH_ERASE_FIRST_TOUCH we can
write smaller chunks.

FLASH_ERASE_NEVER I use to mark flash config pages in the 128kiByte sectors
of the F2/4 invalid by writing 0 to top of the page. A config page of 128
kiByte again would require a 128 kiByte RAM buffer when erase is needed, so
dividing the sector into config pages only needs resonable sized RAM buffer
and allows some wear leveling by copying the old page to the next page on
content cange and invalidating the old page. Read searches for the first
valid page and reads from there.

Ole, you already have some IAP routines for NXP. Would you consider
exporting above API?

I have appended the header for the proposed API.

Bye
-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
#ifndef _INCLUDE_IAP_FLASH_H
#define _INCLUDE__IAP_FLASH_H
#include <cfg/memory.h>

typedef enum
{
    FLASH_ERASE_ALWAYS      = 0,   /*!< Always erase whole memory block before writing */
    FLASH_ERASE_FIRST_TOUCH = 1,   /*!< Only erase whole memory block with first write to that block*/
    FLASH_ERASE_NEVER       = 2,   /*!< Write without erasing */
} FLASH_ERASE_MODE;

/*!
 * brief FLASH status returns of any operation.
 */
typedef enum
{
    FLASH_BUSY          =  1,   /*!< Flash operation pending */
    FLASH_COMPLETE      =  0,   /*!< Flash operation successfull completed */
    FLASH_ERROR_PG      = -1,   /*!< Flash programming failed */
    FLASH_ERROR_WRP     = -2,   /*!< Flash write protected */
    FLASH_LOCKED        = -3,   /*!< FLASH is locked, unlocking failed */
    FLASH_TIMEOUT       = -4,   /*!< Flash operation timed out */
    FLASH_BOUNDARY      = -5,   /*!< Flash write crosses page/sector border */
    FLASH_COMPARE       = -6,   /*!< FLASH compare mismatch */
    FLASH_OUT_OF_MEMORY = -7,   /*!< Intermediate buffer allocation failed*/
    FLASH_ERR_CONF_LAYOUT = -8,   /*!< CONF_PAGE has unexpected layout*/
    FLASH_ERR_ALIGNMENT   = -9,   /*!< Unaligned Flash access*/
    FLASH_NOT_IMPLEMENTED = -10,   /*!< Not implemented*/
} FLASH_Status;

#if defined(IAP_FLASH)
extern FLASH_Status  IapFlashWrite( void* dst, void* src, size_t len, FLASH_ERASE_MODE mode);
extern FLASH_Status IapFlashWriteProtect(void *dst, size_t len, int ena);
extern uint32_t IapFlashEnd(void);
extern void FlashUntouch(void);
#else
FLASH_Status  IapFlashWrite( void* dst, void* src, size_t len, FLASH_ERASE_MODE mode)
{
    return FLASH_NOT_IMPLEMENTED;
}
FLASH_Status  IapFlashWriteProtect(void *dst, size_t len, int ena)
{
    return FLASH_NOT_IMPLEMENTED;
}
uint32_t IapFlashEnd(void)
{
    return 0;
}
void FlashUntouch(void){};
#endif
#endif


More information about the En-Nut-Discussion mailing list