/*********************************************************************************
  *Function		: uint16_t EEPROM_WriteVariable(uint16_t EepromAddress, uint16_t EepromData)
  *Description	: Writes/upadtes variable data in EEPROM.
  *Input		: EepromAddress: Variable virtual address
                  EepromData: 16 bit data to be written
  *Output		: none
  *Return		: 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
  *author		: lz
  *date			: 2015-2-1
  *Others		: none
**********************************************************************************/
uint16_t EEPROM_WriteVariable(uint16_t EepromAddress, uint16_t EepromData)
{
    uint16_t Status = 0;

    /* Unlock the Flash Program Erase controller */
    FLASH_Unlock();

    /* Write the variable virtual address and value in the EEPROM */
    Status = EEPROM_VerifyPageFullWriteVariable(EepromAddress, EepromData);

    /* In case the EEPROM active page is full */
    if (Status == PAGE_FULL)
    {
        /* Perform Page transfer */
        Status = EEPROM_PageTransfer(EepromAddress, EepromData);
    }

    /* Return last operation status */
    return Status;
}
/*********************************************************************************
  *Function		: static uint16_t EEPROM_PageTransfer(uint16_t EepromAddress, uint16_t EepromData)
  *Description	: Transfers last updated variables data from the full Page to an empty one.
  *Input		: EepromAddress: 16 bit virtual address of the variable
                  EepromData: 16 bit data to be written as variable value
  *Output		: none
  *Return		:   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
  *author		: lz
  *date			: 2015-2-1
  *Others		: none
**********************************************************************************/
static uint16_t EEPROM_PageTransfer(uint16_t EepromAddress, uint16_t EepromData)
{
    FLASH_Status FlashStatus = FLASH_COMPLETE;
    uint32_t OldPageAddress = PAGE0_BASE_ADDRESS, NewPageAddress = PAGE1_BASE_ADDRESS;
    uint16_t ValidPage = PAGE0, EepromAddressIdx = 0;
    uint16_t EepromStatus = 0, ReadStatus = 0;

    /* Get active Page for read operation */
    ValidPage = EEPROM_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 address where variable will be taken from */
        OldPageAddress = PAGE1_BASE_ADDRESS;
    }
    else if (ValidPage == PAGE0)  /* Page0 valid */
    {
        /* New page address where variable will be moved to */
        NewPageAddress = PAGE1_BASE_ADDRESS;

        /* Old page address where variable will be taken from */
        OldPageAddress = PAGE0_BASE_ADDRESS;
    }
    else
    {
        return NO_VALID_PAGE;       /* No valid Page */
    }

    /* Set the new Page status to RECEIVE_DATA status */
    FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, RECEIVE_DATA);
    /* If program operation was failed, a Flash error code is returned */
    if (FlashStatus != FLASH_COMPLETE)
    {
        return FlashStatus;
    }

    /* Write the variable passed as parameter in the new active page */
    EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddress, EepromData);
    /* If program operation was failed, a Flash error code is returned */
    if (EepromStatus != FLASH_COMPLETE)
    {
        return EepromStatus;
    }

    /* Transfer process: transfer variables from old to the new active page */
    for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++)
    {
        if (EepromAddressTab[EepromAddressIdx] != EepromAddress)  /* Check each variable except the one passed as parameter */
        {
            /* Read the other last variable updates */
            ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar);
            /* In case variable corresponding to the virtual address was found */
            if (ReadStatus != 0x1)
            {
                /* Transfer the variable to the new active page */
                EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar);
                /* If program operation was failed, a Flash error code is returned */
                if (EepromStatus != FLASH_COMPLETE)
                {
                    return EepromStatus;
                }
            }
        }
    }

    /* Erase the old Page: Set old Page status to ERASED status */
    FlashStatus = FLASH_ErasePage(OldPageAddress);
    /* If erase operation was failed, a Flash error code is returned */
    if (FlashStatus != FLASH_COMPLETE)
    {
        return FlashStatus;
    }

    /* Set new Page status to VALID_PAGE status */
    FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, VALID_PAGE);
    /* If program operation was failed, a Flash error code is returned */
    if (FlashStatus != FLASH_COMPLETE)
    {
        return FlashStatus;
    }

    /* Return last operation flash status */
    return FlashStatus;
}
/*********************************************************************************
  *Function		: uint16_t EEPROM_Init(void)
  *Description	: Restore the pages to a known good state in case of page's status corruption after a power loss.
  *Input		: none
  *Output		: none
  *Return		: none
  *author		: lz
  *date			: 2015-2-1
  *Others		: none
**********************************************************************************/
uint16_t EEPROM_Init(void)
{
    uint16_t PageStatus0 = 6, PageStatus1 = 6;
    uint16_t EepromAddressIdx = 0;
    uint16_t EepromStatus = 0, ReadStatus = 0;
    int16_t x = -1;
    uint16_t  FlashStatus;

    /* Unlock the Flash Program Erase controller */
    FLASH_Unlock();

    /* Get Page0 status */
    PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
    /* Get Page1 status */
    PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);

    /* Check for invalid header states and repair if necessary */
    switch (PageStatus0)
    {
        case ERASED:
            if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
            {
                /* Erase Page0 */
                FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
            {
                /* Erase Page0 */
                FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Mark Page1 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    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 = EEPROM_Format();
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            break;

        case RECEIVE_DATA:
            if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
            {
                /* Transfer data from Page1 to Page0 */
                for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++)
                {
                    if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == EepromAddressTab[EepromAddressIdx])
                    {
                        x = EepromAddressIdx;
                    }
                    if (EepromAddressIdx != x)
                    {
                        /* Read the last variables' updates */
                        ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar);
                        /* In case variable corresponding to the virtual address was found */
                        if (ReadStatus != 0x1)
                        {
                            /* Transfer the variable to the Page0 */
                            EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar);
                            /* If program operation was failed, a Flash error code is returned */
                            if (EepromStatus != FLASH_COMPLETE)
                            {
                                return EepromStatus;
                            }
                        }
                    }
                }
                /* Mark Page0 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Erase Page1 */
                FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
            {
                /* Erase Page1 */
                FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Mark Page0 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else /* Invalid state -> format eeprom */
            {
                /* Erase both Page0 and Page1 and set Page0 as valid page */
                FlashStatus = EEPROM_Format();
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    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 = EEPROM_Format();
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
            {
                /* Erase Page1 */
                FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else /* Page0 valid, Page1 receive */
            {
                /* Transfer data from Page0 to Page1 */
                for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++)
                {
                    if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == EepromAddressTab[EepromAddressIdx])
                    {
                        x = EepromAddressIdx;
                    }
                    if (EepromAddressIdx != x)
                    {
                        /* Read the last variables' updates */
                        ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar);
                        /* In case variable corresponding to the virtual address was found */
                        if (ReadStatus != 0x1)
                        {
                            /* Transfer the variable to the Page1 */
                            EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar);
                            /* If program operation was failed, a Flash error code is returned */
                            if (EepromStatus != FLASH_COMPLETE)
                            {
                                return EepromStatus;
                            }
                        }
                    }
                }
                /* Mark Page1 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Erase Page0 */
                FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            break;
        default:  /* Any other state -> format eeprom */
            /* Erase both Page0 and Page1 and set Page0 as valid page */
            FlashStatus = EEPROM_Format();
            /* If erase/program operation was failed, a Flash error code is returned */
            if (FlashStatus != FLASH_COMPLETE)
            {
                return FlashStatus;
            }
            break;
    }
    return FLASH_COMPLETE;
}
Beispiel #4
0
/**
 * @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
 */
static uint16_t EEPROM_Init(void)
{
    uint16_t PageStatus0 = 6, PageStatus1 = 6;
    uint16_t virtualAddress = 0;
    uint16_t EepromStatus = 0, ReadStatus = 0;
    int16_t x = -1;
    uint16_t  FlashStatus;
    uint16_t EepromDataVar = 0;

    /* Calling this is here is critical on STM32F2 Devices Else Flash Operation Fails */
    FLASH_ClearFlags();

    /* Get Page0 status */
    PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
    /* Get Page1 status */
    PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);

    /* Check for invalid header states and repair if necessary */
    switch (PageStatus0)
    {
        case ERASED:
            if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
            {
                /* Normal valid state -> nothing to do */
            }
            else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
            {
                /* Erase Page0 */
                FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Mark Page1 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    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 = EEPROM_Format();
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            break;

        case RECEIVE_DATA:
            if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
            {
                /* Transfer data from Page1 to Page0 */
                for (virtualAddress = 0; virtualAddress < EEPROM_SIZE; virtualAddress++)
                {
                    if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == virtualAddress)
                    {
                        x = virtualAddress;
                    }
                    if (virtualAddress != x)
                    {
                        /* Read the last variables' updates */
                        ReadStatus = EEPROM_ReadVariable(virtualAddress, &EepromDataVar);
                        /* In case variable corresponding to the virtual address was found */
                        if (ReadStatus != 0x1)
                        {
                            /* Transfer the variable to the Page0 */
                            EepromStatus = EEPROM_VerifyPageFullWriteVariable(virtualAddress, EepromDataVar);
                            /* If program operation was failed, a Flash error code is returned */
                            if (EepromStatus != FLASH_COMPLETE)
                            {
                                return EepromStatus;
                            }
                        }
                    }
                }
                /* Mark Page0 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Erase Page1 */
                FlashStatus = FLASH_EraseSector(PAGE1_ID, VOLTAGE_RANGE);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
            {
                /* Erase Page1 */
                FlashStatus = FLASH_EraseSector(PAGE1_ID, VOLTAGE_RANGE);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Mark Page0 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else /* Invalid state -> format eeprom */
            {
                /* Erase both Page0 and Page1 and set Page0 as valid page */
                FlashStatus = EEPROM_Format();
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            break;

        case VALID_PAGE:
            if (PageStatus1 == VALID_PAGE) /* Harmless invalid state -> pick one page and format the other */
            {
                /* Erase Page0 */
                FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE);
                /* If erase/program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
            {
                /* Normal valid state -> nothing to do */
            }
            else /* Page0 valid, Page1 receive */
            {
                /* Transfer data from Page0 to Page1 */
                for (virtualAddress = 0; virtualAddress < EEPROM_SIZE; virtualAddress++)
                {
                    if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == virtualAddress)
                    {
                        x = virtualAddress;
                    }
                    if (virtualAddress != x)
                    {
                        /* Read the last variables' updates */
                        ReadStatus = EEPROM_ReadVariable(virtualAddress, &EepromDataVar);
                        /* In case variable corresponding to the virtual address was found */
                        if (ReadStatus != 0x1)
                        {
                            /* Transfer the variable to the Page1 */
                            EepromStatus = EEPROM_VerifyPageFullWriteVariable(virtualAddress, EepromDataVar);
                            /* If program operation was failed, a Flash error code is returned */
                            if (EepromStatus != FLASH_COMPLETE)
                            {
                                return EepromStatus;
                            }
                        }
                    }
                }
                /* Mark Page1 as valid */
                FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
                /* If program operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
                /* Erase Page0 */
                FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE);
                /* If erase operation was failed, a Flash error code is returned */
                if (FlashStatus != FLASH_COMPLETE)
                {
                    return FlashStatus;
                }
            }
            break;

        default:  /* Any other state -> format eeprom */
            /* Erase both Page0 and Page1 and set Page0 as valid page */
            FlashStatus = EEPROM_Format();
            /* If erase/program operation was failed, a Flash error code is returned */
            if (FlashStatus != FLASH_COMPLETE)
            {
                return FlashStatus;
            }
            break;
    }

    return FLASH_COMPLETE;
}