EEPROM emulation (STM algorithm described in the application notes: AN4061, AN3969, AN2594, AN3390, AN4056) with added multipage possibility. For Nucleo-F030 and others boards with similar microcontrolers.

Dependencies:   mbed

Description in AN4061 from STM.

Changed (compared with the original code AN4061):

  • possibility of a larger size of emulated EEPROM (using multiple Flash pages)
  • dummy variables prevent overwrite code in Flash by algorithm of EEPROM emulation



Macro PAGE_NB_PVP (in eeprom.h) defines the size of the virtual page. Eg. For F030 where Flash page are 1kB value 4 gives 4kB.

Size 4kB virtual page gives you the ability to use max. approx. 1k of 16-bit variables.

Files at this revision

API Documentation at this revision

Comitter:
mega64
Date:
Sat Sep 24 00:52:55 2016 +0000
Commit message:
Added possibility to increase size of virtual pages of emulation

Changed in this revision

eeprom/eeprom.cpp Show annotated file Show diff for this revision Revisions of this file
eeprom/eeprom.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2eda09ff61d0 eeprom/eeprom.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eeprom/eeprom.cpp	Sat Sep 24 00:52:55 2016 +0000
@@ -0,0 +1,746 @@
+/**
+  ******************************************************************************
+  * @file    EEPROM_Emulation/src/eeprom.c 
+  * @author  MCD Application Team
+  * @version V1.6.0
+  * @date    27-May-2016
+  * @brief   This file provides all the EEPROM emulation firmware functions.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/** @addtogroup EEPROM_Emulation
+  * @{
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "eeprom.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+/* Dummy variables to protect eeprom pages if code size is bigger than 32kb, needed in Mbed online compiler to avoid conflict with linker (N.S.)  */
+const uint8_t Eeprom_area0[PAGE_SIZE] __attribute__((at(PAGE0_BASE_ADDRESS),used))={ [0 ... (PAGE_SIZE-1)] = 0xFF };
+const uint8_t Eeprom_area1[PAGE_SIZE] __attribute__((at(PAGE1_BASE_ADDRESS),used))={ [0 ... (PAGE_SIZE-1)] = 0xFF };
+
+
+/* Global variable used to store variable value in read sequence */
+uint16_t DataVar = 0;
+
+/* Virtual address defined by the user: 0xFFFF value is prohibited */
+extern uint16_t VirtAddVarTab[NB_OF_VAR];
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+static HAL_StatusTypeDef EE_Format(void);
+static uint16_t EE_FindValidPage(uint8_t Operation);
+static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
+static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
+static uint16_t EE_VerifyPageFullyErased(uint32_t Address);
+
+/**
+  * @brief  Restore the pages to a known good state in case of page's status
+  *   corruption after a power loss.
+  * @param  None.
+  * @retval - Flash error code: on write Flash error
+  *         - FLASH_COMPLETE: on success
+  */
+uint16_t EE_Init(void)
+{
+  uint16_t pagestatus0 = 6, pagestatus1 = 6;
+  uint16_t varidx = 0;
+  uint16_t eepromstatus = 0, readstatus = 0;
+  int16_t x = -1;
+  HAL_StatusTypeDef  flashstatus;
+  uint32_t page_error = 0;
+  FLASH_EraseInitTypeDef s_eraseinit;
+
+
+  /* Get Page0 status */
+  pagestatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
+  /* Get Page1 status */
+  pagestatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
+
+  /* Fill EraseInit structure*/
+  s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+  s_eraseinit.PageAddress = PAGE0_BASE_ADDRESS;
+  s_eraseinit.NbPages     = PAGE_NB_PVP;
+  
+  /* Check for invalid header states and repair if necessary */
+  switch (pagestatus0)
+  {
+    case ERASED:
+      if (pagestatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
+      {
+          /* Erase Page0 */
+        if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
+        {
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+      }
+      else if (pagestatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
+      {
+        /* Erase Page0 */
+        if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
+        { 
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+        /* Mark Page1 as valid */
+        flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);
+        /* If program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+      }
+      else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
+      {
+        /* Erase both Page0 and Page1 and set Page0 as valid page */
+        flashstatus = EE_Format();
+        /* If erase/program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+      }
+      break;
+
+    case RECEIVE_DATA:
+      if (pagestatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
+      {
+        /* Transfer data from Page1 to Page0 */
+        for (varidx = 0; varidx < NB_OF_VAR; varidx++)
+        {
+          if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[varidx])
+          {
+            x = varidx;
+          }
+          if (varidx != x)
+          {
+            /* Read the last variables' updates */
+            readstatus = EE_ReadVariable(VirtAddVarTab[varidx], &DataVar);
+            /* In case variable corresponding to the virtual address was found */
+            if (readstatus != 0x1)
+            {
+              /* Transfer the variable to the Page0 */
+              eepromstatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[varidx], DataVar);
+              /* If program operation was failed, a Flash error code is returned */
+              if (eepromstatus != HAL_OK)
+              {
+                return eepromstatus;
+              }
+            }
+          }
+        }
+        /* Mark Page0 as valid */
+        flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
+        /* If program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+        s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+        s_eraseinit.PageAddress = PAGE1_BASE_ADDRESS;
+        s_eraseinit.NbPages     = PAGE_NB_PVP;
+        /* Erase Page1 */
+        if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
+        { 
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+      }
+      else if (pagestatus1 == ERASED) /* Page0 receive, Page1 erased */
+      {
+        s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+        s_eraseinit.PageAddress = PAGE1_BASE_ADDRESS;
+        s_eraseinit.NbPages     = PAGE_NB_PVP;
+        /* Erase Page1 */
+        if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
+        { 
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+        /* Mark Page0 as valid */
+        flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
+        /* If program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+      }
+      else /* Invalid state -> format eeprom */
+      {
+        /* Erase both Page0 and Page1 and set Page0 as valid page */
+        flashstatus = EE_Format();
+        /* If erase/program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+      }
+      break;
+
+    case VALID_PAGE:
+      if (pagestatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
+      {
+        /* Erase both Page0 and Page1 and set Page0 as valid page */
+        flashstatus = EE_Format();
+        /* If erase/program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+      }
+      else if (pagestatus1 == ERASED) /* Page0 valid, Page1 erased */
+      {
+        s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+        s_eraseinit.PageAddress = PAGE1_BASE_ADDRESS;
+        s_eraseinit.NbPages     = PAGE_NB_PVP;
+        /* Erase Page1 */
+        if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
+        { 
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+      }
+      else /* Page0 valid, Page1 receive */
+      {
+        /* Transfer data from Page0 to Page1 */
+        for (varidx = 0; varidx < NB_OF_VAR; varidx++)
+        {
+          if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[varidx])
+          {
+            x = varidx;
+          }
+          if (varidx != x)
+          {
+            /* Read the last variables' updates */
+            readstatus = EE_ReadVariable(VirtAddVarTab[varidx], &DataVar);
+            /* In case variable corresponding to the virtual address was found */
+            if (readstatus != 0x1)
+            {
+              /* Transfer the variable to the Page1 */
+              eepromstatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[varidx], DataVar);
+              /* If program operation was failed, a Flash error code is returned */
+              if (eepromstatus != HAL_OK)
+              {
+                return eepromstatus;
+              }
+            }
+          }
+        }
+        /* Mark Page1 as valid */
+        flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);        
+        /* If program operation was failed, a Flash error code is returned */
+        if (flashstatus != HAL_OK)
+        {
+          return flashstatus;
+        }
+        s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+        s_eraseinit.PageAddress = PAGE0_BASE_ADDRESS;
+        s_eraseinit.NbPages     = PAGE_NB_PVP;
+        /* Erase Page0 */
+        if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
+        { 
+          flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+          /* If erase operation was failed, a Flash error code is returned */
+          if (flashstatus != HAL_OK)
+          {
+            return flashstatus;
+          }
+        }
+      }
+      break;
+
+    default:  /* Any other state -> format eeprom */
+      /* Erase both Page0 and Page1 and set Page0 as valid page */
+      flashstatus = EE_Format();
+      /* If erase/program operation was failed, a Flash error code is returned */
+      if (flashstatus != HAL_OK)
+      {
+        return flashstatus;
+      }
+      break;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Verify if specified page is fully erased.
+  * @param  Address: page address
+  *   This parameter can be one of the following values:
+  *     @arg PAGE0_BASE_ADDRESS: Page0 base address
+  *     @arg PAGE1_BASE_ADDRESS: Page1 base address
+  * @retval page fully erased status:
+  *           - 0: if Page not erased
+  *           - 1: if Page erased
+  */
+uint16_t EE_VerifyPageFullyErased(uint32_t Address)
+{
+  uint32_t readstatus = 1;
+  uint16_t addressvalue = 0x5555;
+  uint32_t end_address;
+  
+  if (PAGE0_BASE_ADDRESS==Address)
+  {
+    end_address = PAGE0_END_ADDRESS;
+  }
+  else
+  {
+    end_address = PAGE1_END_ADDRESS;
+  };
+  
+    
+  /* Check each active page address starting from end */
+  while (Address <= end_address)
+  {
+    /* Get the current location content to be compared with virtual address */
+    addressvalue = (*(__IO uint16_t*)Address);
+
+    /* Compare the read address with the virtual address */
+    if (addressvalue != ERASED)
+    {
+      
+      /* In case variable value is read, reset readstatus flag */
+      readstatus = 0;
+
+      break;
+    }
+    /* Next address location */
+    Address = Address + 4;
+  }
+  
+  /* Return readstatus value: (0: Page not erased, 1: Page erased) */
+  return readstatus;
+}
+
+/**
+  * @brief  Returns the last stored variable data, if found, which correspond to
+  *   the passed virtual address
+  * @param  VirtAddress: Variable virtual address
+  * @param  Data: Global variable contains the read variable value
+  * @retval Success or error status:
+  *           - 0: if variable was found
+  *           - 1: if the variable was not found
+  *           - NO_VALID_PAGE: if no valid page was found.
+  */
+uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
+{
+  uint16_t validpage = PAGE0;
+  uint16_t addressvalue = 0x5555, readstatus = 1;
+  uint32_t address = EEPROM_START_ADDRESS, PageStartAddress = EEPROM_START_ADDRESS;
+
+  /* Get active Page for read operation */
+  validpage = EE_FindValidPage(READ_FROM_VALID_PAGE);
+
+  /* Check if there is no valid page */
+  if (validpage == NO_VALID_PAGE)
+  {
+    return  NO_VALID_PAGE;
+  }
+
+  /* Get the valid Page start Address */
+  PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(validpage * PAGE_SIZE));
+
+  /* Get the valid Page end Address */
+  address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + validpage) * PAGE_SIZE));
+
+  /* Check each active page address starting from end */
+  while (address > (PageStartAddress + 2))
+  {
+    /* Get the current location content to be compared with virtual address */
+    addressvalue = (*(__IO uint16_t*)address);
+
+    /* Compare the read address with the virtual address */
+    if (addressvalue == VirtAddress)
+    {
+      /* Get content of Address-2 which is variable value */
+      *Data = (*(__IO uint16_t*)(address - 2));
+
+      /* In case variable value is read, reset readstatus flag */
+      readstatus = 0;
+
+      break;
+    }
+    else
+    {
+      /* Next address location */
+      address = address - 4;
+    }
+  }
+
+  /* Return readstatus value: (0: variable exist, 1: variable doesn't exist) */
+  return readstatus;
+}
+
+/**
+  * @brief  Writes/upadtes variable data in EEPROM.
+  * @param  VirtAddress: Variable virtual address
+  * @param  Data: 16 bit data to be written
+  * @retval Success or error status:
+  *           - FLASH_COMPLETE: on success
+  *           - PAGE_FULL: if valid page is full
+  *           - NO_VALID_PAGE: if no valid page was found
+  *           - Flash error code: on write Flash error
+  */
+uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
+{
+  uint16_t Status = 0;
+
+  /* Write the variable virtual address and value in the EEPROM */
+  Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
+
+  /* In case the EEPROM active page is full */
+  if (Status == PAGE_FULL)
+  {
+    /* Perform Page transfer */
+    Status = EE_PageTransfer(VirtAddress, Data);
+  }
+
+  /* Return last operation status */
+  return Status;
+}
+
+/**
+  * @brief  Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE
+  * @param  None
+  * @retval Status of the last operation (Flash write or erase) done during
+  *         EEPROM formating
+  */
+static HAL_StatusTypeDef EE_Format(void)
+{
+  HAL_StatusTypeDef flashstatus = HAL_OK;
+  uint32_t page_error = 0;
+  FLASH_EraseInitTypeDef s_eraseinit;
+
+  s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+  s_eraseinit.PageAddress = PAGE0_BASE_ADDRESS;
+  s_eraseinit.NbPages     = PAGE_NB_PVP;
+  /* Erase Page0 */
+  if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
+  {
+    flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error); 
+    /* If erase operation was failed, a Flash error code is returned */
+    if (flashstatus != HAL_OK)
+    {
+      return flashstatus;
+    }
+  }
+  /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
+  flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); 
+  /* If program operation was failed, a Flash error code is returned */
+  if (flashstatus != HAL_OK)
+  {
+    return flashstatus;
+  }
+
+  s_eraseinit.PageAddress = PAGE1_BASE_ADDRESS;
+  /* Erase Page1 */
+  if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
+  {  
+    flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error); 
+    /* If erase operation was failed, a Flash error code is returned */
+    if (flashstatus != HAL_OK)
+    {
+      return flashstatus;
+    }
+  }
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  Find valid Page for write or read operation
+  * @param  Operation: operation to achieve on the valid page.
+  *   This parameter can be one of the following values:
+  *     @arg READ_FROM_VALID_PAGE: read operation from valid page
+  *     @arg WRITE_IN_VALID_PAGE: write operation from valid page
+  * @retval Valid page number (PAGE or PAGE1) or NO_VALID_PAGE in case
+  *   of no valid page was found
+  */
+static uint16_t EE_FindValidPage(uint8_t Operation)
+{
+  uint16_t pagestatus0 = 6, pagestatus1 = 6;
+
+  /* Get Page0 actual status */
+  pagestatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
+
+  /* Get Page1 actual status */
+  pagestatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
+
+  /* Write or read operation */
+  switch (Operation)
+  {
+    case WRITE_IN_VALID_PAGE:   /* ---- Write operation ---- */
+      if (pagestatus1 == VALID_PAGE)
+      {
+        /* Page0 receiving data */
+        if (pagestatus0 == RECEIVE_DATA)
+        {
+          return PAGE0;         /* Page0 valid */
+        }
+        else
+        {
+          return PAGE1;         /* Page1 valid */
+        }
+      }
+      else if (pagestatus0 == VALID_PAGE)
+      {
+        /* Page1 receiving data */
+        if (pagestatus1 == RECEIVE_DATA)
+        {
+          return PAGE1;         /* Page1 valid */
+        }
+        else
+        {
+          return PAGE0;         /* Page0 valid */
+        }
+      }
+      else
+      {
+        return NO_VALID_PAGE;   /* No valid Page */
+      }
+
+    case READ_FROM_VALID_PAGE:  /* ---- Read operation ---- */
+      if (pagestatus0 == VALID_PAGE)
+      {
+        return PAGE0;           /* Page0 valid */
+      }
+      else if (pagestatus1 == VALID_PAGE)
+      {
+        return PAGE1;           /* Page1 valid */
+      }
+      else
+      {
+        return NO_VALID_PAGE ;  /* No valid Page */
+      }
+
+    default:
+      return PAGE0;             /* Page0 valid */
+  }
+}
+
+/**
+  * @brief  Verify if active page is full and Writes variable in EEPROM.
+  * @param  VirtAddress: 16 bit virtual address of the variable
+  * @param  Data: 16 bit data to be written as variable value
+  * @retval Success or error status:
+  *           - FLASH_COMPLETE: on success
+  *           - PAGE_FULL: if valid page is full
+  *           - NO_VALID_PAGE: if no valid page was found
+  *           - Flash error code: on write Flash error
+  */
+static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data)
+{
+  HAL_StatusTypeDef flashstatus = HAL_OK;
+  uint16_t validpage = PAGE0;
+  uint32_t address = EEPROM_START_ADDRESS, pageendaddress = EEPROM_START_ADDRESS+PAGE_SIZE;
+
+  /* Get valid Page for write operation */
+  validpage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
+  
+  /* Check if there is no valid page */
+  if (validpage == NO_VALID_PAGE)
+  {
+    return  NO_VALID_PAGE;
+  }
+
+  /* Get the valid Page start address */
+  address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(validpage * PAGE_SIZE));
+
+  /* Get the valid Page end address */
+  pageendaddress = (uint32_t)((EEPROM_START_ADDRESS - 1) + (uint32_t)((validpage + 1) * PAGE_SIZE));
+
+  /* Check each active page address starting from begining */
+  while (address < pageendaddress)
+  {
+    /* Verify if address and address+2 contents are 0xFFFFFFFF */
+    if ((*(__IO uint32_t*)address) == 0xFFFFFFFF)
+    {
+      /* Set variable data */
+      flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, Data);       
+      /* If program operation was failed, a Flash error code is returned */
+      if (flashstatus != HAL_OK)
+      {
+        return flashstatus;
+      }
+      /* Set variable virtual address */
+      flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address + 2, VirtAddress);       
+      /* Return program operation status */
+      return flashstatus;
+    }
+    else
+    {
+      /* Next address location */
+      address = address + 4;
+    }
+  }
+
+  /* Return PAGE_FULL in case the valid page is full */
+  return PAGE_FULL;
+}
+
+/**
+  * @brief  Transfers last updated variables data from the full Page to
+  *   an empty one.
+  * @param  VirtAddress: 16 bit virtual address of the variable
+  * @param  Data: 16 bit data to be written as variable value
+  * @retval Success or error status:
+  *           - FLASH_COMPLETE: on success
+  *           - PAGE_FULL: if valid page is full
+  *           - NO_VALID_PAGE: if no valid page was found
+  *           - Flash error code: on write Flash error
+  */
+static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
+{
+  HAL_StatusTypeDef flashstatus = HAL_OK;
+  uint32_t newpageaddress = EEPROM_START_ADDRESS;
+  uint32_t oldpageid = 0;
+  uint16_t validpage = PAGE0, varidx = 0;
+  uint16_t eepromstatus = 0, readstatus = 0;
+  uint32_t page_error = 0;
+  FLASH_EraseInitTypeDef s_eraseinit;
+
+  /* Get active Page for read operation */
+  validpage = EE_FindValidPage(READ_FROM_VALID_PAGE);
+
+  if (validpage == PAGE1)       /* Page1 valid */
+  {
+    /* New page address where variable will be moved to */
+    newpageaddress = PAGE0_BASE_ADDRESS;
+
+    /* Old page ID where variable will be taken from */
+    oldpageid = PAGE1_BASE_ADDRESS;
+  }
+  else if (validpage == PAGE0)  /* Page0 valid */
+  {
+    /* New page address  where variable will be moved to */
+    newpageaddress = PAGE1_BASE_ADDRESS;
+
+    /* Old page ID where variable will be taken from */
+    oldpageid = PAGE0_BASE_ADDRESS;
+  }
+  else
+  {
+    return NO_VALID_PAGE;       /* No valid Page */
+  }
+
+  /* Set the new Page status to RECEIVE_DATA status */
+  flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, newpageaddress, RECEIVE_DATA);  
+  /* If program operation was failed, a Flash error code is returned */
+  if (flashstatus != HAL_OK)
+  {
+    return flashstatus;
+  }
+  
+  /* Write the variable passed as parameter in the new active page */
+  eepromstatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
+  /* If program operation was failed, a Flash error code is returned */
+  if (eepromstatus != HAL_OK)
+  {
+    return eepromstatus;
+  }
+
+  /* Transfer process: transfer variables from old to the new active page */
+  for (varidx = 0; varidx < NB_OF_VAR; varidx++)
+  {
+    if (VirtAddVarTab[varidx] != VirtAddress)  /* Check each variable except the one passed as parameter */
+    {
+      /* Read the other last variable updates */
+      readstatus = EE_ReadVariable(VirtAddVarTab[varidx], &DataVar);
+      /* In case variable corresponding to the virtual address was found */
+      if (readstatus != 0x1)
+      {
+        /* Transfer the variable to the new active page */
+        eepromstatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[varidx], DataVar);
+        /* If program operation was failed, a Flash error code is returned */
+        if (eepromstatus != HAL_OK)
+        {
+          return eepromstatus;
+        }
+      }
+    }
+  }
+
+  s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+  s_eraseinit.PageAddress = oldpageid;
+  s_eraseinit.NbPages     = PAGE_NB_PVP;
+  
+  /* Erase the old Page: Set old Page status to ERASED status */
+  flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);  
+  /* If erase operation was failed, a Flash error code is returned */
+  if (flashstatus != HAL_OK)
+  {
+    return flashstatus;
+  }
+
+  /* Set new Page status to VALID_PAGE status */
+  flashstatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, newpageaddress, VALID_PAGE);   
+  /* If program operation was failed, a Flash error code is returned */
+  if (flashstatus != HAL_OK)
+  {
+    return flashstatus;
+  }
+  
+  
+
+  /* Return last operation flash status */
+  return flashstatus;
+}
+
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r 2eda09ff61d0 eeprom/eeprom.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eeprom/eeprom.h	Sat Sep 24 00:52:55 2016 +0000
@@ -0,0 +1,162 @@
+/**
+  ******************************************************************************
+  * @file    EEPROM_Emulation/inc/eeprom.h 
+  * @author  MCD Application Team
+  * @version V1.6.0
+  * @date    27-May-2016
+  * @brief   This file contains all the functions prototypes for the EEPROM 
+  *          emulation firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __EEPROM_H
+#define __EEPROM_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f0xx_hal.h"
+
+/* Exported constants --------------------------------------------------------*/
+
+/* Base address of the Flash sectors STM32F030R8 */ 
+#define ADDR_FLASH_PAGE_0     ((uint32_t)0x08000000) /* Base @ of Page 0, 1 Kbyte */
+#define ADDR_FLASH_PAGE_1     ((uint32_t)0x08000400) /* Base @ of Page 1, 1 Kbyte */
+#define ADDR_FLASH_PAGE_2     ((uint32_t)0x08000800) /* Base @ of Page 2, 1 Kbyte */
+#define ADDR_FLASH_PAGE_3     ((uint32_t)0x08000C00) /* Base @ of Page 3, 1 Kbyte */
+#define ADDR_FLASH_PAGE_4     ((uint32_t)0x08001000) /* Base @ of Page 4, 1 Kbyte */
+#define ADDR_FLASH_PAGE_5     ((uint32_t)0x08001400) /* Base @ of Page 5, 1 Kbyte */
+#define ADDR_FLASH_PAGE_6     ((uint32_t)0x08001800) /* Base @ of Page 6, 1 Kbyte */
+#define ADDR_FLASH_PAGE_7     ((uint32_t)0x08001C00) /* Base @ of Page 7, 1 Kbyte */
+#define ADDR_FLASH_PAGE_8     ((uint32_t)0x08002000) /* Base @ of Page 8, 1 Kbyte */
+#define ADDR_FLASH_PAGE_9     ((uint32_t)0x08002400) /* Base @ of Page 9, 1 Kbyte */
+#define ADDR_FLASH_PAGE_10    ((uint32_t)0x08002800) /* Base @ of Page 10, 1 Kbyte */
+#define ADDR_FLASH_PAGE_11    ((uint32_t)0x08002C00) /* Base @ of Page 11, 1 Kbyte */
+#define ADDR_FLASH_PAGE_12    ((uint32_t)0x08003000) /* Base @ of Page 12, 1 Kbyte */
+#define ADDR_FLASH_PAGE_13    ((uint32_t)0x08003400) /* Base @ of Page 13, 1 Kbyte */
+#define ADDR_FLASH_PAGE_14    ((uint32_t)0x08003800) /* Base @ of Page 14, 1 Kbyte */
+#define ADDR_FLASH_PAGE_15    ((uint32_t)0x08003C00) /* Base @ of Page 15, 1 Kbyte */
+#define ADDR_FLASH_PAGE_16    ((uint32_t)0x08004000) /* Base @ of Page 16, 1 Kbyte */
+#define ADDR_FLASH_PAGE_17    ((uint32_t)0x08004400) /* Base @ of Page 17, 1 Kbyte */
+#define ADDR_FLASH_PAGE_18    ((uint32_t)0x08004800) /* Base @ of Page 18, 1 Kbyte */
+#define ADDR_FLASH_PAGE_19    ((uint32_t)0x08004C00) /* Base @ of Page 19, 1 Kbyte */
+#define ADDR_FLASH_PAGE_20    ((uint32_t)0x08005000) /* Base @ of Page 20, 1 Kbyte */
+#define ADDR_FLASH_PAGE_21    ((uint32_t)0x08005400) /* Base @ of Page 21, 1 Kbyte */
+#define ADDR_FLASH_PAGE_22    ((uint32_t)0x08005800) /* Base @ of Page 22, 1 Kbyte */
+#define ADDR_FLASH_PAGE_23    ((uint32_t)0x08005C00) /* Base @ of Page 23, 1 Kbyte */
+#define ADDR_FLASH_PAGE_24    ((uint32_t)0x08006000) /* Base @ of Page 24, 1 Kbyte */
+#define ADDR_FLASH_PAGE_25    ((uint32_t)0x08006400) /* Base @ of Page 25, 1 Kbyte */
+#define ADDR_FLASH_PAGE_26    ((uint32_t)0x08006800) /* Base @ of Page 26, 1 Kbyte */
+#define ADDR_FLASH_PAGE_27    ((uint32_t)0x08006C00) /* Base @ of Page 27, 1 Kbyte */
+#define ADDR_FLASH_PAGE_28    ((uint32_t)0x08007000) /* Base @ of Page 28, 1 Kbyte */
+#define ADDR_FLASH_PAGE_29    ((uint32_t)0x08007400) /* Base @ of Page 29, 1 Kbyte */
+#define ADDR_FLASH_PAGE_30    ((uint32_t)0x08007800) /* Base @ of Page 30, 1 Kbyte */
+#define ADDR_FLASH_PAGE_31    ((uint32_t)0x08007C00) /* Base @ of Page 31, 1 Kbyte */
+#define ADDR_FLASH_PAGE_32    ((uint32_t)0x08008000) /* Base @ of Page 32, 1 Kbyte */
+#define ADDR_FLASH_PAGE_33    ((uint32_t)0x08008400) /* Base @ of Page 33, 1 Kbyte */
+#define ADDR_FLASH_PAGE_34    ((uint32_t)0x08008800) /* Base @ of Page 34, 1 Kbyte */
+#define ADDR_FLASH_PAGE_35    ((uint32_t)0x08008C00) /* Base @ of Page 35, 1 Kbyte */
+#define ADDR_FLASH_PAGE_36    ((uint32_t)0x08009000) /* Base @ of Page 36, 1 Kbyte */
+#define ADDR_FLASH_PAGE_37    ((uint32_t)0x08009400) /* Base @ of Page 37, 1 Kbyte */
+#define ADDR_FLASH_PAGE_38    ((uint32_t)0x08009800) /* Base @ of Page 38, 1 Kbyte */
+#define ADDR_FLASH_PAGE_39    ((uint32_t)0x08009C00) /* Base @ of Page 39, 1 Kbyte */
+#define ADDR_FLASH_PAGE_40    ((uint32_t)0x0800A000) /* Base @ of Page 40, 1 Kbyte */
+#define ADDR_FLASH_PAGE_41    ((uint32_t)0x0800A400) /* Base @ of Page 41, 1 Kbyte */
+#define ADDR_FLASH_PAGE_42    ((uint32_t)0x0800A800) /* Base @ of Page 42, 1 Kbyte */
+#define ADDR_FLASH_PAGE_43    ((uint32_t)0x0800AC00) /* Base @ of Page 43, 1 Kbyte */
+#define ADDR_FLASH_PAGE_44    ((uint32_t)0x0800B000) /* Base @ of Page 44, 1 Kbyte */
+#define ADDR_FLASH_PAGE_45    ((uint32_t)0x0800B400) /* Base @ of Page 45, 1 Kbyte */
+#define ADDR_FLASH_PAGE_46    ((uint32_t)0x0800B800) /* Base @ of Page 46, 1 Kbyte */
+#define ADDR_FLASH_PAGE_47    ((uint32_t)0x0800BC00) /* Base @ of Page 47, 1 Kbyte */
+#define ADDR_FLASH_PAGE_48    ((uint32_t)0x0800C000) /* Base @ of Page 48, 1 Kbyte */
+#define ADDR_FLASH_PAGE_49    ((uint32_t)0x0800C400) /* Base @ of Page 49, 1 Kbyte */
+#define ADDR_FLASH_PAGE_50    ((uint32_t)0x0800C800) /* Base @ of Page 50, 1 Kbyte */
+#define ADDR_FLASH_PAGE_51    ((uint32_t)0x0800CC00) /* Base @ of Page 51, 1 Kbyte */
+#define ADDR_FLASH_PAGE_52    ((uint32_t)0x0800D000) /* Base @ of Page 52, 1 Kbyte */
+#define ADDR_FLASH_PAGE_53    ((uint32_t)0x0800D400) /* Base @ of Page 53, 1 Kbyte */
+#define ADDR_FLASH_PAGE_54    ((uint32_t)0x0800D800) /* Base @ of Page 54, 1 Kbyte */
+#define ADDR_FLASH_PAGE_55    ((uint32_t)0x0800DC00) /* Base @ of Page 55, 1 Kbyte */
+#define ADDR_FLASH_PAGE_56    ((uint32_t)0x0800E000) /* Base @ of Page 56, 1 Kbyte */
+#define ADDR_FLASH_PAGE_57    ((uint32_t)0x0800E400) /* Base @ of Page 57, 1 Kbyte */
+#define ADDR_FLASH_PAGE_58    ((uint32_t)0x0800E800) /* Base @ of Page 58, 1 Kbyte */
+#define ADDR_FLASH_PAGE_59    ((uint32_t)0x0800EC00) /* Base @ of Page 59, 1 Kbyte */
+#define ADDR_FLASH_PAGE_60    ((uint32_t)0x0800F000) /* Base @ of Page 60, 1 Kbyte */
+#define ADDR_FLASH_PAGE_61    ((uint32_t)0x0800F400) /* Base @ of Page 61, 1 Kbyte */
+#define ADDR_FLASH_PAGE_62    ((uint32_t)0x0800F800) /* Base @ of Page 62, 1 Kbyte */
+#define ADDR_FLASH_PAGE_63    ((uint32_t)0x0800FC00) /* Base @ of Page 63, 1 Kbyte */
+
+
+/* Define the number of physical pages per virtual page of algorithm*/
+#define PAGE_NB_PVP ((uint32_t) 4)
+
+/* Define the size of the sectors to be used */
+#define PAGE_SIZE               ((uint32_t)FLASH_PAGE_SIZE * PAGE_NB_PVP)  /* Page size */
+
+/* EEPROM start address in Flash */
+#define EEPROM_START_ADDRESS  ((uint32_t)ADDR_FLASH_PAGE_16) /* EEPROM emulation start address */
+
+/* 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)(ADDR_FLASH_PAGE_48))
+#define PAGE1_END_ADDRESS     ((uint32_t)(ADDR_FLASH_PAGE_48 + PAGE_SIZE - 1))
+
+/* Used Flash pages for EEPROM emulation */
+#define PAGE0                 ((uint16_t)0x0000)
+#define PAGE1                 ((uint16_t)((PAGE1_BASE_ADDRESS-PAGE0_BASE_ADDRESS)/PAGE_SIZE)) /* Virtual page nb between PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/
+
+/* No valid page define */
+#define NO_VALID_PAGE         ((uint16_t)0xFFFF)
+
+/* 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)0x03)
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+uint16_t EE_Init(void);
+uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
+uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
+
+#endif /* __EEPROM_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r 2eda09ff61d0 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Sep 24 00:52:55 2016 +0000
@@ -0,0 +1,110 @@
+
+#include "mbed.h"
+#include "eeprom.h"
+#include <ctype.h>
+
+
+
+uint16_t n = 0;
+/* Virtual address defined by the user: 0xFFFF value is prohibited */
+uint16_t VirtAddVarTab[NB_OF_VAR] = {0x5555, 0x6666, 0x7777};
+uint16_t VarDataTab[] = {0, 0, 0};
+
+
+
+int main()
+{
+    
+    
+
+    /* Unlock the Flash Program Erase controller */
+    HAL_FLASH_Unlock();
+
+    EE_Init();
+    
+
+    printf("EEPROM emulation test\n\n");
+    printf("\n\rType one of the following commands and press space or enter");
+    printf("\n\r READ - read all variables\n\r WRITE1 <n> - write first variable\n\r WRITE2 <n> - write second variable\n\r WRITE3 <n> - write third variable");
+    printf("\n\rwhere <n> is uint16_t value (0-65535)");
+    printf("\n\r");
+
+
+    char command[20];
+    char arg[10];
+            int i;
+
+    while(1) {
+        scanf("%s", command);
+    i=0;    
+    while(command[i])
+   {
+      command[i]=toupper(command[i]);
+      i++;
+   }
+       
+
+        if (strcmp("READ", command)==0) {
+            for (i=0; i<3; i++) {
+                EE_ReadVariable(VirtAddVarTab[i], &VarDataTab[i]);
+            };
+            printf("\nvar1=%6u,  var2=%6u,  var3=%6u",VarDataTab[0],VarDataTab[1],VarDataTab[2]);
+        }
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("WRITE1", command)==0) {
+            scanf("%s", arg);
+            printf("\nok");
+            n=atoi(arg);
+            EE_WriteVariable(VirtAddVarTab[0], n);
+        }
+////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("WRITE2", command)==0) {
+            scanf("%s", arg);
+            printf("\nok");
+            n=atoi(arg);
+            EE_WriteVariable(VirtAddVarTab[1], n);
+        }
+////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("WRITE3", command)==0) {
+            scanf("%s", arg);
+            printf("\nok");
+            n=atoi(arg);
+            EE_WriteVariable(VirtAddVarTab[2], n);
+        }
+////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("T1", command)==0) {
+            // multiple write test. After test var1 = 1000
+            printf("\nok");
+            for (n=0;n<1001;n++)
+            {
+            EE_WriteVariable(VirtAddVarTab[0], n);
+            };
+        }
+////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("T2", command)==0) {
+            // multiple write test. After test var2 = 1001
+            printf("\nok");
+            for (n=0;n<1002;n++)
+            {
+            EE_WriteVariable(VirtAddVarTab[1], n);
+            };
+        }
+////////////////////////////////////////////////////////////////////////////////////
+        else if (strcmp("T3", command)==0) {
+            // multiple write test. After test var3 = 1002
+            printf("\nok");
+            for (n=0;n<1003;n++)
+            {
+            EE_WriteVariable(VirtAddVarTab[2], n);
+            };
+        }
+////////////////////////////////////////////////////////////////////////////////////
+
+        else perror("\nThere is no command matching. Try again");
+
+        command[0] = arg[0] = 0;
+        printf("\n\r");
+    }
+
+
+}
diff -r 000000000000 -r 2eda09ff61d0 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Sep 24 00:52:55 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/f9eeca106725
\ No newline at end of file