| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749 |
- /*
- * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
- * Copyright (C) 2010 by Rittal GmbH & Co. KG. All rights reserved.
- * Copyright (C) 2012, 2013 Uwe Bonnes
- *
- * 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 the copyright holders nor the names of
- * 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 OWNER 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.
- *
- * For additional information see http://www.ethernut.de/
- *
- */
- #include <stdint.h>
- #include <string.h>
- #include <cfg/arch.h>
- #include <cfg/memory.h>
- #include <cfg/eeprom.h>
- #include <sys/nutdebug.h>
- #include <sys/heap.h>
- #include <dev/iap_flash.h>
- #if defined(MCU_STM32F0) || defined(MCU_STM32F1) || defined(MCU_STM32F3)
- #include <arch/cm3/stm/stm32xxxx.h>
- #else
- #warning "STM32 family has no F1/F3 compatible FLASH"
- #endif
- #if defined (STM32F030) || defined (STM32F031) || defined (STM32F051)
- #define FLASH_PAGE_SIZE 1024
- static uint32_t pagelist[2] = {0, 0};
- #elif defined (STM32F072)
- static uint32_t pagelist[2] = {0, 0};
- #define FLASH_PAGE_SIZE 2048
- #elif defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
- #define FLASH_PAGE_SIZE 1024
- static uint32_t pagelist[1] = {0};
- #elif defined (STM32F10X_MD) || defined(STM32F10X_MD_VL)
- #define FLASH_PAGE_SIZE 1024
- static uint32_t pagelist[4] = {0, 0, 0, 0};
- #elif defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) ||\
- defined (STM32F10X_CL) /* || defined(STM32F3) */
- #define FLASH_PAGE_SIZE 2048
- static uint32_t pagelist[8] = {0,0,0,0,0,0,0,0};
- #elif defined(STM32F10X_XL)
- #define FLASH_PAGE_SIZE 2048
- static uint32_t pagelist[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- #elif defined(MCU_STM32F3)
- #define FLASH_PAGE_SIZE 2048
- static uint32_t pagelist[4] = {0,0,0,0};
- #else
- #warning Unknown STM32 Type
- #endif
- #define ERASED_PATTERN_16 0xffff
- #ifndef FLASH_CONF_SIZE
- #define FLASH_CONF_SIZE FLASH_PAGE_SIZE
- #elif ((FLASH_CONF_SIZE != 256) && (FLASH_CONF_SIZE != 512) && \
- (FLASH_CONF_SIZE != 1024) && (FLASH_CONF_SIZE != 2048) && \
- (FLASH_CONF_SIZE != 4096) && (FLASH_CONF_SIZE != 8192))
- #error FLASH_CONF_SIZE has to be either FLASH_PAGE_SIZE (default), 256, 512, 1024, 2048, 4096 or 8192
- #endif
- #if !defined(RDP_KEY)
- #define RDP_KEY 0x00aa;
- #endif
- #if !defined(FLASH_KEY1)
- #define FLASH_KEY1 0x45670123L
- #endif
- #if !defined(FLASH_KEY2)
- #define FLASH_KEY2 0xCDEF89ABL
- #endif
- #if !defined(FLASH_OPTKEY1)
- #define FLASH_OPTKEY1 0x08192A3B
- #endif
- #if !defined(FLASH_OPTKEY2)
- #define FLASH_OPTKEY2 0x4C5D6E7F
- #endif
- #if !defined(FLASH_SR_WRPRTERR) && defined(FLASH_SR_WRPERR)
- #define FLASH_SR_WRPRTERR FLASH_SR_WRPERR
- #endif
- void FlashUntouch(void)
- {
- int i;
- for (i = 0; i< sizeof(pagelist); i++)
- pagelist[1] = 0;
- }
- static uint32_t FlashEnd(void)
- {
- uint16_t size;
- #if defined(MCU_STM32F3)
- size = *(__I uint16_t *) 0x1FFFF7CC;
- #else
- size = *(__I uint16_t *) 0x1FFFF7E0;
- #endif
- return FLASH_BASE - 1 + size * 1024;
- }
- /*!
- * \brief Returns the FLASH Status.
- *
- * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
- */
- static FLASH_Status FLASH_GetStatus(void)
- {
- FLASH_Status rs = FLASH_COMPLETE;
- /* Decode the Flash Status */
- if (FLASH->SR & FLASH_SR_WRPRTERR)
- rs = FLASH_ERROR_WRP;
- else if (FLASH->SR & FLASH_SR_PGERR) {
- rs = FLASH_ERROR_PG;
- FLASH->CR = 0; /* Reset STRT */
- }
- else if (FLASH->SR & FLASH_SR_BSY)
- rs = FLASH_BUSY;
- FLASH->SR = FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR;
- #if defined(STM32F10X_XL)
- /* Decode the Flash Status */
- if (FLASH->SR2 & FLASH_SR_WRPRTERR)
- rs |= FLASH_ERROR_WRP;
- else if (FLASH->SR2 & FLASH_SR_PGERR)
- rs |= FLASH_ERROR_PG;
- else if (FLASH->SR2 & FLASH_SR_BSY)
- rs |= FLASH_BUSY;
- #endif /* STM32F10X_XL */
- /* Return the Flash Status */
- return rs;
- }
- /*!
- * \brief Waits for a Flash operation to complete
- *
- * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
- * Every flash access stalls while FLASH erase/program is running
- * The erase/program process however will finish at some point
- * and may indicate failure then
- */
- static FLASH_Status FlashWaitReady(void)
- {
- FLASH_Status status;
- do
- status = FLASH_GetStatus();
- while(status == FLASH_BUSY);
- /* Return the operation status */
- return status;
- }
- /*!
- * \brief Erase FLASH Page at specified address.
- *
- * This routine is called by Stm32FlashWritePage to erase
- * before programming.
- *
- * \param page Page to erase.
- *
- * \return FLASH Status.
- *
- * Even for page erase, AR takes the memory address while
- * rm0316 ands pm0075 tell about the page as argument
- */
- static FLASH_Status FlashErasePage(uint32_t mem)
- {
- FLASH_Status rs = FLASH_COMPLETE;
- uint32_t current_page = ((uint32_t)mem - FLASH_BASE)/FLASH_PAGE_SIZE;
- uint32_t *addr = (uint32_t *)(current_page * FLASH_PAGE_SIZE);
- int i;
- for(i = 0; i < FLASH_PAGE_SIZE >> 2; i++)
- if (addr[i] != ((ERASED_PATTERN_16 << 16) | ERASED_PATTERN_16))
- break;
- if (i >= (FLASH_PAGE_SIZE >> 2))
- goto erase_done;
- /* Wait for last operation to be completed */
- rs = FlashWaitReady();
- if(rs == FLASH_COMPLETE) {
- #if defined(STM32F10X_XL)
- if ((current_page / FLASH_PAGE_SIZE) >255) {
- FLASH->CR2 = FLASH_CR_PER;
- FLASH->AR2 = mem;
- FLASH->CR2 = FLASH_CR_PER | FLASH_CR_STRT;
- rs = FlashWaitReady();
- FLASH->CR2 = 0;
- goto erase_done;
- }
- #endif
- /* if the previous operation is completed, proceed to erase the page */
- FLASH->CR = FLASH_CR_PER;
- FLASH->AR = mem;
- FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
- rs = FlashWaitReady();
- FLASH->CR = 0;
- }
- erase_done:
- if (rs != FLASH_COMPLETE)
- pagelist[current_page/32] &= ~(1 <<(current_page%32));
- else
- pagelist[current_page/32] |= (1 <<(current_page%32));
- /* Return the Erase Status */
- return rs;
- }
- /*!
- * \brief Program any data to FLASH.
- *
- * This function writes data from source address to FLASH.
- *
- * \param dst Pointer to address anywhere in FLASH. Must be word
- * aligned
- * \param src Pointer to source data. With SRC == NULL, the region
- * is checked for write protection
- * \param len Number of bytes to be written/checked. Must be even.
- *
- * \return FLASH Status: FLASH_COMPLETE or appropriate error.
- */
- static FLASH_Status FlashWrite( void* dst, void* src, size_t len,
- FLASH_ERASE_MODE mode)
- {
- FLASH_Status rs = FLASH_COMPLETE;
- uint32_t wrpr = FLASH->WRPR; /* Old write protection state */
- uint32_t page_start, page_end;
- int i;
- void *wptr = dst;
- void *rptr = src;
- uint32_t length = len;
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check boundaries */
- if ((((uint32_t)dst + len - 1) > FlashEnd()) || ((uint32_t)dst < FLASH_BASE)) {
- return FLASH_BOUNDARY;
- }
- /* Check for write protected sectors */
- page_start = ((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE;
- page_end = (((uint32_t)dst + len -1) - FLASH_BASE)/FLASH_PAGE_SIZE;
- /* Write protection happens in 4 kiByte unites. The uppermost bit in
- FLASH->WRPR handles all remaining units*/
- #if FLASH_PAGE_SIZE == 1024
- for (i = page_start>>2; i <= page_end>>2; i++)
- #else
- for (i = page_start>>1; i <= page_end>>1; i++)
- #endif
- if (((i < 31) && ((wrpr & (1<<i)) == 0)) || ((i >= 31) && (wrpr & 0x80000000) == 0))
- return FLASH_ERROR_WRP;
- if (src == NULL)
- /* Only a check for write protection was requested */
- return FLASH_COMPLETE;
- /* Unlock related banks*/
- if (((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE <256) {
- FLASH->KEYR = FLASH_KEY1;
- FLASH->KEYR = FLASH_KEY2;
- rs = FLASH->CR & FLASH_CR_LOCK;
- }
- #if defined(STM32F10X_XL)
- if (((uint32_t)dst + len - FLASH_BASE)/FLASH_PAGE_SIZE > 255) {
- FLASH->KEYR2 = FLASH_KEY1;
- FLASH->KEYR2 = FLASH_KEY2;
- rs |= FLASH->SR2;
- }
- #endif
- if (rs != FLASH_COMPLETE)
- return FLASH_LOCKED;
- while (length && (rs == FLASH_COMPLETE))
- {
- uint32_t current_page = ((uint32_t)wptr - FLASH_BASE)/FLASH_PAGE_SIZE;
- uint32_t current_length = length;
- uint32_t offset_in_page = (uint32_t)wptr % FLASH_PAGE_SIZE;
- int prepend = 0, append = 0;
- uint16_t prepend_data = 0, append_data = 0;
- if (length > FLASH_PAGE_SIZE)
- current_length = FLASH_PAGE_SIZE;
- length -= current_length;
- prepend = (offset_in_page & 1);
- if (prepend) {
- uint8_t saved_data = *(uint8_t*)wptr;
- if (saved_data != (ERASED_PATTERN_16 & 0xff))
- return FLASH_ERR_ALIGNMENT;
- prepend_data = (*(uint8_t*)( rptr)<< 8) | (*(uint8_t *)wptr);
- }
- else {
- append = (current_length &1);
- if(append) {
- uint8_t saved_data = *(uint8_t*)( wptr + current_length );
- if (saved_data != (ERASED_PATTERN_16 & 0xff))
- return FLASH_ERR_ALIGNMENT;
- append_data = *(uint8_t*)( rptr + current_length -1) | (saved_data << 8);
- }
- }
- /* Check if page needs erase*/
- if ((mode == FLASH_ERASE_ALWAYS) ||
- ((mode == FLASH_ERASE_FIRST_TOUCH) &&
- (((pagelist[current_page/32] & (1 <<(current_page%32))) == 0)))) {
- if (i < (FLASH_PAGE_SIZE>>1)) {
- rs = FlashErasePage((uint32_t)wptr);
- if (rs != FLASH_COMPLETE)
- /* Erase failed for any reason */
- goto done;
- }
- }
- /* Program the sector */
- rs = FlashWaitReady();
- if (rs != FLASH_COMPLETE)
- goto done;
- if (((uint32_t)wptr -FLASH_BASE)/FLASH_PAGE_SIZE <256)
- FLASH->CR = FLASH_CR_PG;
- #if defined(STM32F10X_XL)
- else
- FLASH->CR2 = FLASH_CR_PG;
- #endif
- if (prepend) {
- if(prepend_data != ERASED_PATTERN_16)
- *(volatile uint16_t*)((uint32_t)wptr & ~1) = prepend_data;
- current_length -= 1;
- wptr += 1;
- rptr += 1;
- }
- while (current_length > 1 && (rs == FLASH_COMPLETE)) {
- rs = FlashWaitReady();
- if(*(volatile uint16_t*)rptr != ERASED_PATTERN_16)
- *(volatile uint16_t*)wptr = *(volatile uint16_t*)rptr;
- current_length -=2;
- wptr += 2;
- rptr += 2;
- }
- if (append) {
- if(append_data != ERASED_PATTERN_16)
- *(volatile uint16_t*)(wptr) = append_data;
- current_length -= 1;
- wptr += 1;
- rptr += 1;
- }
- rs = FlashWaitReady();
- FLASH->CR = 0;
- if(rs != FLASH_COMPLETE)
- goto done;
- }
- rs = FlashWaitReady();
- /* Check the written data */
- wptr = dst;
- rptr = src;
- length = len;
- /* Align flash access to 4 Byte Boundary*/
- while (length && ((uint32_t)wptr & 3)) {
- if(*(volatile uint8_t*)wptr++ != *(uint8_t*)rptr++)
- goto cmp_err;
- length--;
- }
- /* Now compare word at a time*/
- while (length > 3) {
- if(*(volatile uint32_t*)wptr != *(uint32_t*)rptr)
- goto cmp_err;
- length -= 4;
- wptr += +4;
- rptr += +4;
- }
- /* Compare the rest */
- while (length) {
- if((*(volatile uint8_t*)wptr++) != *(uint8_t*)rptr++)
- goto cmp_err;
- length--;
- }
- goto done;
- cmp_err:
- rs = FLASH_COMPARE;
- done:
- /* Lock the FLASH again */
- FLASH->CR = FLASH_CR_LOCK;
- #if defined(STM32F10X_XL)
- FLASH->CR2 = FLASH_CR_LOCK;
- #endif
- return rs;
- }
- /*!
- * \brief Program any data to FLASH.
- *
- * This function writes data from source address to FLASH. Write to
- * configuration area, if configured, is denied.
- *
- * \param dst Pointer to address anywhere in FLASH. Must be word
- * aligned
- * \param src Pointer to source data. With SRC == NULL, the region
- * is checked for write protection
- * \param len Number of bytes to be written/checked. Must be even.
- *
- * \return FLASH Status: FLASH_COMPLETE or appropriate error.
- */
- FLASH_Status IapFlashWrite( void* dst, void* src, size_t len,
- FLASH_ERASE_MODE mode)
- {
- uint32_t iap_flash_end = FlashEnd();
- #if defined(NUT_CONFIG_STM32_IAP) && FLASH_CONF_SIZE > FLASH_PAGE_SIZE
- iap_flash_end -= FLASH_CONF_SIZE ;
- #elif defined(NUT_CONFIG_STM32_IAP)
- iap_flash_end -= FLASH_PAGE_SIZE ;
- #endif
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check top boundary */
- if ((((uint32_t)dst + len - 1) > iap_flash_end ) || ((uint32_t)dst < FLASH_BASE))
- {
- return FLASH_BOUNDARY;
- }
- return FlashWrite(dst, src, len, mode);
- }
- /*!
- * \brief Get Upper limit of Flash.
- *
- * This function writes data from source address to FLASH. Write to
- * configuration area, if configured, is denied.
- *
- * \param NONE
- * \return Last Flash Address.
- */
- uint32_t IapFlashEnd(void)
- {
- #if defined(NUT_CONFIG_STM32_IAP) && FLASH_CONF_SIZE > FLASH_PAGE_SIZE
- return FlashEnd() - FLASH_CONF_SIZE;
- #elif defined(NUT_CONFIG_STM32_IAP)
- return FlashEnd() - FLASH_PAGE_SIZE;
- #else
- return FlashEnd();
- #endif
- }
- /*!
- * \brief Try to protect/unprotect the requested flash region.
- *
- * \param dst Pointer to address anywhere in FLASH.
- * \param len Length of region in bytes.
- * \param ena 0 disables write protection anything else write-protects.
- *
- * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
- */
- FLASH_Status IapFlashWriteProtect(void *dst, size_t len, int ena)
- {
- uint32_t page_start, page_end;
- int i;
- FLASH_Status rs = FLASH_COMPLETE;
- uint32_t wrpr = FLASH->WRPR; /* Old write protection state */
- __IO uint16_t *WRP = &OB->WRP0;
- uint32_t iap_flash_end = FlashEnd();
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check boundaries */
- if ((((uint32_t)dst+len) > iap_flash_end ) || ((uint32_t)dst < FLASH_BASE))
- {
- return FLASH_BOUNDARY;
- }
- /* Wait for last operation to be completed */
- rs = FlashWaitReady();
- if(rs != FLASH_COMPLETE)
- return rs;
- /* erase option bytes */
- /* set OPTWRE by wrinting key*/
- FLASH->OPTKEYR = FLASH_KEY1;
- FLASH->OPTKEYR = FLASH_KEY2;
- FLASH->CR = FLASH_CR_OPTER;
- FLASH->CR = FLASH_CR_OPTER | FLASH_CR_STRT;
- rs = FlashWaitReady();
- if(rs != FLASH_COMPLETE)
- return rs;
- FLASH->CR = FLASH_CR_OPTPG;
- OB->RDP = RDP_KEY;
- page_start = ((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE;
- page_end = (((uint32_t)dst + len -1) - FLASH_BASE)/FLASH_PAGE_SIZE;
- rs = FlashWaitReady();
- #if FLASH_PAGE_SIZE == 1024
- for (i = page_start>>2; i <= page_end>>2; i++)
- #else
- for (i = page_start>>1; i <= page_end>>1; i++)
- #endif
- {
- if (i < 31) {
- if (ena)
- wrpr &= ~(1<<(i));
- else
- wrpr |= (1<<(i));
- }
- /* If one high page is write protected, protect all high pages*/
- else if (ena) wrpr &= ~0x80000000;
- }
- #if defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
- for(i = 0; i < 1 && rs == FLASH_COMPLETE; i++)
- #else
- for(i = 0; i < 4 && rs == FLASH_COMPLETE; i++)
- #endif
- {
- uint8_t val = (wrpr>>(8*i) && 0xff);
- uint16_t pval = ~val<<8 |val;
- if (val == 0xff)
- continue;
- rs = FlashWaitReady();
- if(rs != FLASH_COMPLETE)
- break;
- *WRP++ = pval;
- }
- rs = FlashWaitReady();
- FLASH->CR = 0;
- return rs;
- }
- /*!
- * \brief Nut/OS specific handling for parameters in FLASH.
- *
- * This function enables to read system specific parameters
- * from processors FLASH. The sectors used for storage are
- * configureable via nutconf.
- *
- * If multiple FLASH_CONF_SIZE fit into the FLASH_PAGE_SIZE,
- * implement a rolling scheme. The first FLASH_CONF_SIZE unit
- * in FLASH_PAGE_SIZE with with the uppermost word erased is
- * considered valid.
- *
- * \param pos Offset of parameter(s) in configured page(s).
- * \param data Pointer where to copy data from flash to.
- * \param len Number of bytes to be copied.
- *
- * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
- */
- FLASH_Status Stm32FlashParamRead(uint32_t pos, void *data, size_t len)
- {
- uint32_t flash_conf_sector = FlashEnd() & ~(FLASH_PAGE_SIZE - 1);
- if (FLASH_CONF_SIZE > FLASH_PAGE_SIZE)
- return FLASH_ERR_CONF_LAYOUT;
- #if defined(FLASH_CONF_SIZE) && (FLASH_CONF_SIZE << 1) <= FLASH_PAGE_SIZE
- uint8_t conf_page = 0;
- uint16_t marker = *(uint16_t*) (flash_conf_sector + ((conf_page + 1) * FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check boundaries */
- if (pos + len + sizeof(ERASED_PATTERN_16) > FLASH_CONF_SIZE)
- {
- return FLASH_CONF_OVERFLOW;
- }
- /* Find configuration page in CONF_SECTOR*/
- while ((marker != ERASED_PATTERN_16) && (conf_page < ((FLASH_PAGE_SIZE/FLASH_CONF_SIZE) - 1 ))) {
- conf_page++;
- marker = *(uint32_t*)(flash_conf_sector + ((conf_page + 1)* FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
- }
- if (marker != ERASED_PATTERN_16)
- /* no page sizes unit in CONF_SECTOR has a valid mark */
- return FLASH_ERR_CONF_LAYOUT;
- memcpy( data, (uint8_t *)((uint8_t*)flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos), len);
- #else
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check boundaries */
- if (pos + len > FLASH_PAGE_SIZE)
- {
- return FLASH_CONF_OVERFLOW;
- }
- memcpy( data, (uint8_t *)((uint8_t*)flash_conf_sector + pos), len);
- #endif
- /* Return success or fault code */
- return FLASH_COMPLETE;
- }
- /*!
- * \brief Nut/OS specific handling for parameters in FLASH.
- *
- * This function enables to store system specific parameters
- * in processors FLASH. The sectors used for storage are
- * configurable via nutconf.
- *
- * If multiple FLASH_CONF_SIZE fit into FLASH_PAGE_SIZE,
- * implement a rolling scheme. The first FLASH_CONF_SIZE unit
- * in FLASH_PAGE_SIZE with with the uppermost word erased is
- * considered valid.
- *
- * \param pos Offset of parameter(s) in configured page(s).
- * \param data Pointer to source data.
- * \param len Number of bytes to be written.
- *
- * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
- */
- FLASH_Status Stm32FlashParamWrite(unsigned int pos, void *data,
- size_t len)
- {
- FLASH_Status rs = 0;
- uint8_t *buffer;
- void* flash_conf_sector = (void*)(FlashEnd() & ~(FLASH_PAGE_SIZE - 1));
- int i;
- uint8_t *mem, *src;
- if(FLASH_CONF_SIZE > FLASH_PAGE_SIZE)
- return FLASH_ERR_CONF_LAYOUT;
- #if defined(FLASH_CONF_SIZE) && (FLASH_CONF_SIZE << 1) <= FLASH_PAGE_SIZE
- uint8_t conf_page = 0;
- uint16_t marker = *(uint16_t*) (flash_conf_sector + ((conf_page +1) * FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
- FLASH_ERASE_MODE mode;
- if (len == 0)
- return FLASH_COMPLETE;
- /* Check top boundaries */
- if (pos + len + sizeof(ERASED_PATTERN_16) > FLASH_CONF_SIZE)
- {
- return FLASH_BOUNDARY;
- }
- /* Find configuration page in CONF_SECTOR*/
- while ((marker != ERASED_PATTERN_16) && conf_page < ((FLASH_PAGE_SIZE/FLASH_CONF_SIZE) -1)) {
- conf_page++;
- marker = *(uint16_t*)(flash_conf_sector + ((conf_page + 1)* FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
- }
- if (marker != ERASED_PATTERN_16) {
- /* no page sizes unit in CONF_SECTOR has a valid mark
- * Erase Sector and write provided data to position at first sector */
- rs = FlashWrite( flash_conf_sector + pos, data, len, FLASH_ERASE_ALWAYS);
- /* Return success or fault code */
- return rs;
- }
- /* Check if target area is erased.
- * It seems no C standard function provides this functionality!
- */
- mem = (uint8_t*) (flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos);
- src = (uint8_t*) data;
- for (i = 0; i < len; i++) {
- if ((mem[i] != 0xff) && (mem[i] != src[i]))
- break;
- }
- if (i >= len) {
- /* Needed area is erased, simply write the data to the requested area*/
- rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos, data, len, FLASH_ERASE_NEVER);
- return rs;
- }
- /* Check if content needs no update. */
- if (memcmp(flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos, data, len) == 0)
- return FLASH_COMPLETE;
- /* Save configuration page in RAM and write updated data to next configuration page,
- * eventually erasing the sector wrapping to the first page
- */
- buffer = NutHeapAlloc(FLASH_CONF_SIZE);
- if (buffer == NULL)
- {
- /* Not enough memory */
- return FLASH_OUT_OF_MEMORY;
- }
- /* Get the content of the whole config page*/
- memcpy( buffer, flash_conf_sector + conf_page * FLASH_CONF_SIZE , FLASH_CONF_SIZE);
- /* Overwrite new data region*/
- memcpy (buffer + pos, data, len);
- conf_page++;
- mode = FLASH_ERASE_NEVER;
- if (conf_page < FLASH_PAGE_SIZE/FLASH_CONF_SIZE) {
- uint16_t indicator = (uint16_t)~ERASED_PATTERN_16;
- rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE - sizeof(indicator),
- &indicator, sizeof(indicator), FLASH_ERASE_NEVER);
- }
- else {
- /* All pages used, mark the sector as not yet erases to force erase*/
- FlashUntouch();
- conf_page = 0;
- mode = FLASH_ERASE_ALWAYS;
- }
- rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE , buffer, FLASH_CONF_SIZE, mode);
- #else
- /* Check top boundaries */
- if (pos + len > FLASH_PAGE_SIZE)
- {
- return FLASH_BOUNDARY;
- }
- /* Check if target area is erased.
- * It seems no C standard function provides this functionality!
- */
- mem = (uint8_t*) (flash_conf_sector + pos);
- src = (uint8_t*) data;
- for (i = 0; i < len; i++) {
- if ((mem[i] != 0xff) && (mem[i] != src[i]))
- break;
- }
- if (i >= len) {
- /* Needed area is erased, simply write the data to the requested area*/
- rs = FlashWrite( flash_conf_sector + pos, data, len, FLASH_ERASE_NEVER);
- return rs;
- }
- buffer = NutHeapAlloc(FLASH_CONF_SIZE);
- if (buffer == NULL)
- {
- /* Not enough memory */
- return FLASH_OUT_OF_MEMORY;
- }
- /* Get the content of the whole config page*/
- memcpy( buffer, flash_conf_sector , FLASH_PAGE_SIZE);
- /* Overwrite new data region*/
- memcpy (buffer + pos, data, len);
- rs = FlashWrite( flash_conf_sector, buffer, FLASH_PAGE_SIZE, FLASH_ERASE_ALWAYS);
- #endif
- NutHeapFree(buffer);
- /* Return success or fault code */
- return rs;
- }
|