Squashed commit of the following:
Author: Juha Niskanen <juha.niskanen@haltian.com> Date: Mon Feb 19 15:03:17 2018 -0600 drivers/mtd: mtd_config.c: Add still more error handling (to detect bad underlying flash implementations) drivers/mtd: mtd_config.c: Remove MTD_ERASE that was erasing data block instead of erase block. This is a partial revert of 4f18b4. Reported-by: Pascal Speck <iktek01@yahoo.com> arch/arm/src/stm32l4: stm32l4_flash: change flash programming to use page buffer for unaligned writes.
This commit is contained in:
parent
bd81664b31
commit
8572837d9e
@ -67,7 +67,7 @@
|
|||||||
/* All sectors are 128KB and are uniform in size.
|
/* All sectors are 128KB and are uniform in size.
|
||||||
* The only execption is sector 0 which is subdivided into two small sectors
|
* The only execption is sector 0 which is subdivided into two small sectors
|
||||||
* of 8KB and one larger sector of 112KB.
|
* of 8KB and one larger sector of 112KB.
|
||||||
* The page size is 515 bytes. However, the smallest thing that can be
|
* The page size is 512 bytes. However, the smallest thing that can be
|
||||||
* erased is four pages. We will refer to this as a "cluster".
|
* erased is four pages. We will refer to this as a "cluster".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -577,7 +577,7 @@ ssize_t up_progmem_ispageerased(size_t cluster)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush and invalidate nvalidate D-Cache for this address range */
|
/* Flush and invalidate D-Cache for this address range */
|
||||||
|
|
||||||
address = (cluster << SAMV7_CLUSTER_SHIFT) + SAMV7_PROGMEM_START;
|
address = (cluster << SAMV7_CLUSTER_SHIFT) + SAMV7_PROGMEM_START;
|
||||||
arch_flush_dcache(address, address + SAMV7_CLUSTER_SIZE);
|
arch_flush_dcache(address, address + SAMV7_CLUSTER_SIZE);
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "stm32l4_rcc.h"
|
#include "stm32l4_rcc.h"
|
||||||
#include "stm32l4_waste.h"
|
#include "stm32l4_waste.h"
|
||||||
@ -75,26 +76,37 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#define FLASH_KEY1 0x45670123
|
#define FLASH_KEY1 0x45670123
|
||||||
#define FLASH_KEY2 0xCDEF89AB
|
#define FLASH_KEY2 0xCDEF89AB
|
||||||
|
|
||||||
#define OPTBYTES_KEY1 0x08192A3B
|
#define OPTBYTES_KEY1 0x08192A3B
|
||||||
#define OPTBYTES_KEY2 0x4C5D6E7F
|
#define OPTBYTES_KEY2 0x4C5D6E7F
|
||||||
|
|
||||||
|
#define FLASH_PAGE_SIZE STM32L4_FLASH_PAGESIZE
|
||||||
|
#define FLASH_PAGE_WORDS (FLASH_PAGE_SIZE / 4)
|
||||||
|
#define FLASH_PAGE_MASK (FLASH_PAGE_SIZE - 1)
|
||||||
|
#define FLASH_PAGE_SHIFT (11) /* 2**11 = 2048B */
|
||||||
|
#define FLASH_BYTE2PAGE(o) ((o) >> FLASH_PAGE_SHIFT)
|
||||||
|
|
||||||
#define FLASH_CR_PAGE_ERASE FLASH_CR_PER
|
#define FLASH_CR_PAGE_ERASE FLASH_CR_PER
|
||||||
#define FLASH_SR_WRITE_PROTECTION_ERROR FLASH_SR_WRPERR
|
#define FLASH_SR_WRITE_PROTECTION_ERROR FLASH_SR_WRPERR
|
||||||
|
|
||||||
/* All errors for Standard Programming, not for other operations. */
|
/* All errors for Standard Programming, not for other operations. */
|
||||||
|
|
||||||
#define FLASH_SR_ALLERRS (FLASH_SR_PGSERR | FLASH_SR_SIZERR | \
|
#define FLASH_SR_ALLERRS (FLASH_SR_PGSERR | FLASH_SR_SIZERR | \
|
||||||
FLASH_SR_PGAERR | FLASH_SR_WRPERR | \
|
FLASH_SR_PGAERR | FLASH_SR_WRPERR | \
|
||||||
FLASH_SR_PROGERR)
|
FLASH_SR_PROGERR)
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static sem_t g_sem = SEM_INITIALIZER(1);
|
static sem_t g_sem = SEM_INITIALIZER(1);
|
||||||
|
static uint32_t g_page_buffer[FLASH_PAGE_WORDS];
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -167,6 +179,22 @@ static inline void flash_optbytes_lock(void)
|
|||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void flash_erase(size_t page)
|
||||||
|
{
|
||||||
|
finfo("erase page %u\n", page);
|
||||||
|
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_PAGE_ERASE);
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PNB_MASK, FLASH_CR_PNB(page));
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_START);
|
||||||
|
|
||||||
|
while (getreg32(STM32L4_FLASH_SR) & FLASH_SR_BSY)
|
||||||
|
{
|
||||||
|
up_waste();
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PAGE_ERASE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@ -290,22 +318,12 @@ ssize_t up_progmem_erasepage(size_t page)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Erase single page */
|
||||||
|
|
||||||
sem_lock();
|
sem_lock();
|
||||||
|
|
||||||
/* Get flash ready and begin erasing single page. */
|
|
||||||
|
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
|
|
||||||
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_PAGE_ERASE);
|
flash_erase(page);
|
||||||
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PNB_MASK, FLASH_CR_PNB(page));
|
|
||||||
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_START);
|
|
||||||
|
|
||||||
while (getreg32(STM32L4_FLASH_SR) & FLASH_SR_BSY)
|
|
||||||
{
|
|
||||||
up_waste();
|
|
||||||
}
|
|
||||||
|
|
||||||
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PAGE_ERASE, 0);
|
|
||||||
|
|
||||||
flash_lock();
|
flash_lock();
|
||||||
sem_unlock();
|
sem_unlock();
|
||||||
@ -347,90 +365,133 @@ ssize_t up_progmem_ispageerased(size_t page)
|
|||||||
return bwritten;
|
return bwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
uint32_t *word = (uint32_t *)buf;
|
uint32_t *dest;
|
||||||
size_t written = count;
|
const uint32_t *src;
|
||||||
|
size_t written;
|
||||||
|
size_t xfrsize;
|
||||||
|
size_t offset;
|
||||||
|
size_t page;
|
||||||
|
int i;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
/* STM32L4 requires double-word access and alignment. */
|
|
||||||
|
|
||||||
if (addr & 7)
|
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* But we can complete single-word writes by writing the
|
|
||||||
* erase value 0xffffffff as second word ourselves, so
|
|
||||||
* allow odd number of words here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (count & 3)
|
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for valid address range. */
|
/* Check for valid address range. */
|
||||||
|
|
||||||
|
offset = addr;
|
||||||
if (addr >= STM32L4_FLASH_BASE)
|
if (addr >= STM32L4_FLASH_BASE)
|
||||||
{
|
{
|
||||||
addr -= STM32L4_FLASH_BASE;
|
offset -= STM32L4_FLASH_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((addr + count) > STM32L4_FLASH_SIZE)
|
if (offset + buflen > STM32L4_FLASH_SIZE)
|
||||||
{
|
{
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the page number corresponding to the flash offset and the byte
|
||||||
|
* offset into the page. Align write destination to page boundary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
page = FLASH_BYTE2PAGE((uint32_t)offset);
|
||||||
|
offset &= FLASH_PAGE_MASK;
|
||||||
|
|
||||||
|
dest = (uint32_t *)((uint8_t *)addr - offset);
|
||||||
|
written = 0;
|
||||||
|
|
||||||
sem_lock();
|
sem_lock();
|
||||||
|
|
||||||
/* Get flash ready and begin flashing. */
|
/* Get flash ready and begin flashing. */
|
||||||
|
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
|
|
||||||
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_PG);
|
/* Loop until all of the data has been written */
|
||||||
|
|
||||||
for (addr += STM32L4_FLASH_BASE; count; count -= 8, word += 2, addr += 8)
|
while (buflen > 0)
|
||||||
{
|
{
|
||||||
uint32_t second_word;
|
/* How much can we write into this page? */
|
||||||
|
|
||||||
/* Write first word. */
|
xfrsize = MIN((size_t)FLASH_PAGE_SIZE - offset, buflen);
|
||||||
|
|
||||||
putreg32(*word, addr);
|
/* Do we need to use the intermediate buffer? */
|
||||||
|
|
||||||
/* Write second word and wait to complete. */
|
if (offset == 0 && xfrsize == FLASH_PAGE_SIZE)
|
||||||
|
|
||||||
second_word = (count == 4) ? 0xffffffff : *(word + 1);
|
|
||||||
putreg32(second_word, (addr + 4));
|
|
||||||
|
|
||||||
while (getreg32(STM32L4_FLASH_SR) & FLASH_SR_BSY)
|
|
||||||
{
|
{
|
||||||
up_waste();
|
/* No, we can take the data directly from the user buffer */
|
||||||
|
|
||||||
|
src = (const uint32_t *)buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Yes, copy data into global page buffer */
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
memcpy(g_page_buffer, dest, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((uint8_t *)g_page_buffer + offset, buf, xfrsize);
|
||||||
|
|
||||||
|
if (offset + xfrsize < FLASH_PAGE_SIZE)
|
||||||
|
{
|
||||||
|
memcpy((uint8_t *)g_page_buffer + offset + xfrsize,
|
||||||
|
(const uint8_t *)dest + offset + xfrsize,
|
||||||
|
FLASH_PAGE_SIZE - offset - xfrsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
src = g_page_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify */
|
/* Erase the page. Unlike most flash chips, STM32L4 is unable to
|
||||||
|
* write back existing data read from page without erase.
|
||||||
|
*/
|
||||||
|
|
||||||
if (getreg32(STM32L4_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR)
|
flash_erase(page);
|
||||||
|
|
||||||
|
/* Write the page. Must be with double-words. */
|
||||||
|
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_PG);
|
||||||
|
|
||||||
|
for (i = 0; i < FLASH_PAGE_WORDS; i += 2)
|
||||||
{
|
{
|
||||||
ret = -EROFS;
|
*dest++ = *src++;
|
||||||
goto out;
|
*dest++ = *src++;
|
||||||
|
|
||||||
|
while (getreg32(STM32L4_FLASH_SR) & FLASH_SR_BSY)
|
||||||
|
{
|
||||||
|
up_waste();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify */
|
||||||
|
|
||||||
|
if (getreg32(STM32L4_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR)
|
||||||
|
{
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
|
||||||
|
ret = -EROFS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getreg32(dest-1) != *(src-1) || getreg32(dest-2) != *(src-2))
|
||||||
|
{
|
||||||
|
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getreg32(addr) != *word || getreg32((addr + 4)) != second_word)
|
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
|
||||||
{
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 4)
|
/* Adjust pointers and counts for the next time through the loop */
|
||||||
{
|
|
||||||
break;
|
written += xfrsize;
|
||||||
}
|
addr += xfrsize;
|
||||||
|
dest = (uint32_t *)addr;
|
||||||
|
buf = (void *)((uintptr_t)buf + xfrsize);
|
||||||
|
buflen -= xfrsize;
|
||||||
|
page++;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
|
|
||||||
|
|
||||||
/* If there was an error, clear all error flags in status
|
/* If there was an error, clear all error flags in status
|
||||||
* register (rc_w1 register so do this by writing the
|
* register (rc_w1 register so do this by writing the
|
||||||
* error bits).
|
* error bits).
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/mtd_config.c
|
* drivers/mtd/mtd_config.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014, 2017-2018 Gregory Nutt. All rights reserved.
|
||||||
* Copyright (C) 2013 Ken Pettit. All rights reserved.
|
* Copyright (C) 2013 Ken Pettit. All rights reserved.
|
||||||
* Author: Ken Pettit <pettitkd@gmail.com>
|
* Author: Ken Pettit <pettitkd@gmail.com>
|
||||||
* With Updates from Gregory Nutt <gnutt@nuttx.org>
|
* With Updates from Gregory Nutt <gnutt@nuttx.org>
|
||||||
@ -153,8 +153,8 @@ static const struct file_operations mtdconfig_fops =
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int mtdconfig_readbytes(FAR struct mtdconfig_struct_s *dev, int offset,
|
static int mtdconfig_readbytes(FAR struct mtdconfig_struct_s *dev, int offset,
|
||||||
FAR uint8_t *pdata, int readlen)
|
FAR uint8_t *pdata, int readlen)
|
||||||
{
|
{
|
||||||
off_t bytestoread = readlen;
|
off_t bytestoread = readlen;
|
||||||
off_t bytesthisblock, firstbyte;
|
off_t bytesthisblock, firstbyte;
|
||||||
@ -250,8 +250,8 @@ errout:
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int mtdconfig_writebytes(FAR struct mtdconfig_struct_s *dev, int offset,
|
static int mtdconfig_writebytes(FAR struct mtdconfig_struct_s *dev, int offset,
|
||||||
FAR const uint8_t *pdata, int writelen)
|
FAR const uint8_t *pdata, int writelen)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
@ -286,17 +286,6 @@ static int mtdconfig_writebytes(FAR struct mtdconfig_struct_s *dev, int offset,
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now erase the block */
|
|
||||||
|
|
||||||
ret = MTD_ERASE(dev->mtd, block, 1);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
/* Error erasing the block */
|
|
||||||
|
|
||||||
ret = -EIO;
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = offset - block * dev->blocksize;
|
index = offset - block * dev->blocksize;
|
||||||
bytes_this_block = dev->blocksize - index;
|
bytes_this_block = dev->blocksize - index;
|
||||||
if (bytes_this_block > writelen)
|
if (bytes_this_block > writelen)
|
||||||
@ -563,11 +552,11 @@ read_next:
|
|||||||
* block is available in the partition.
|
* block is available in the partition.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* offset to the next available entry (after consolidation)..
|
* Offset to the next available entry (after consolidation).
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
||||||
{
|
{
|
||||||
FAR uint8_t *pBuf;
|
FAR uint8_t *pBuf;
|
||||||
FAR struct mtdconfig_header_s *phdr;
|
FAR struct mtdconfig_header_s *phdr;
|
||||||
@ -601,7 +590,6 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
{
|
{
|
||||||
/* Error doing block read */
|
/* Error doing block read */
|
||||||
|
|
||||||
dst_offset = 0;
|
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,7 +600,6 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
{
|
{
|
||||||
/* Error erasing the block */
|
/* Error erasing the block */
|
||||||
|
|
||||||
dst_offset = 0;
|
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,17 +610,25 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
sig[0] = 'C';
|
sig[0] = 'C';
|
||||||
sig[1] = 'D';
|
sig[1] = 'D';
|
||||||
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
||||||
mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
|
||||||
|
ret = mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
||||||
|
if (ret != sizeof(sig))
|
||||||
|
{
|
||||||
|
/* Cannot write even the signature. */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy active items back to the MTD device */
|
/* Copy active items back to the MTD device. */
|
||||||
|
|
||||||
while (src_offset < dev->erasesize)
|
while (src_offset < dev->erasesize)
|
||||||
{
|
{
|
||||||
phdr = (FAR struct mtdconfig_header_s *) &pBuf[src_offset];
|
phdr = (FAR struct mtdconfig_header_s *) &pBuf[src_offset];
|
||||||
if (phdr->id == MTD_ERASED_ID)
|
if (phdr->id == MTD_ERASED_ID)
|
||||||
{
|
{
|
||||||
/* No more data in this erase block */
|
/* No more data in this erase block. */
|
||||||
|
|
||||||
src_offset = dev->erasesize;
|
src_offset = dev->erasesize;
|
||||||
continue;
|
continue;
|
||||||
@ -650,7 +645,7 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
if (bytes_left_in_block < sizeof(*phdr) + phdr->len)
|
if (bytes_left_in_block < sizeof(*phdr) + phdr->len)
|
||||||
{
|
{
|
||||||
/* Item won't fit in the destination block. Move to
|
/* Item won't fit in the destination block. Move to
|
||||||
* the next block
|
* the next block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dst_block++;
|
dst_block++;
|
||||||
@ -663,19 +658,29 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
DEBUGASSERT(dst_block != dev->neraseblocks);
|
DEBUGASSERT(dst_block != dev->neraseblocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now Write the item to the current dst_offset location */
|
/* Now write the item to the current dst_offset location. */
|
||||||
|
|
||||||
ret = mtdconfig_writebytes(dev, dst_offset, (uint8_t *) phdr,
|
ret = mtdconfig_writebytes(dev, dst_offset, (uint8_t *) phdr,
|
||||||
sizeof(hdr));
|
sizeof(hdr));
|
||||||
if (ret < 0)
|
if (ret != sizeof(hdr))
|
||||||
{
|
{
|
||||||
dst_offset = 0;
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst_offset += sizeof(hdr);
|
dst_offset += sizeof(hdr);
|
||||||
ret = mtdconfig_writebytes(dev, dst_offset, &pBuf[src_offset
|
ret = mtdconfig_writebytes(dev, dst_offset,
|
||||||
+ sizeof(hdr)], phdr->len);
|
&pBuf[src_offset + sizeof(hdr)], phdr->len);
|
||||||
|
if (ret != phdr->len)
|
||||||
|
{
|
||||||
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
dst_offset += phdr->len;
|
dst_offset += phdr->len;
|
||||||
|
|
||||||
/* Test if enough space in dst block for another header */
|
/* Test if enough space in dst block for another header */
|
||||||
@ -705,9 +710,13 @@ static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
src_offset = CONFIGDATA_BLOCK_HDR_SIZE;
|
src_offset = CONFIGDATA_BLOCK_HDR_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
errout:
|
|
||||||
kmm_free(pBuf);
|
kmm_free(pBuf);
|
||||||
return dst_offset;
|
return dst_offset;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
kmm_free(pBuf);
|
||||||
|
ferr("ERROR: fail ram consolidate: %d\n", ret);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -720,7 +729,7 @@ errout:
|
|||||||
* partition as it goes.
|
* partition as it goes.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* offset to the next available entry (after consolidation)..
|
* Offset to the next available entry (after consolidation).
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@ -781,9 +790,17 @@ static off_t mtdconfig_consolidate(FAR struct mtdconfig_struct_s *dev)
|
|||||||
sig[0] = 'C';
|
sig[0] = 'C';
|
||||||
sig[1] = 'D';
|
sig[1] = 'D';
|
||||||
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
||||||
mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
|
||||||
|
|
||||||
/* Now consolidate entries */
|
ret = mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
||||||
|
if (ret != sizeof(sig))
|
||||||
|
{
|
||||||
|
/* Cannot write even the signature. */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now consolidate entries. */
|
||||||
|
|
||||||
src_block = 1;
|
src_block = 1;
|
||||||
dst_block = 0;
|
dst_block = 0;
|
||||||
@ -800,6 +817,7 @@ retry_relocate:
|
|||||||
{
|
{
|
||||||
/* I/O Error! */
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,7 +858,15 @@ retry_relocate:
|
|||||||
|
|
||||||
/* Copy this entry to the destination */
|
/* Copy this entry to the destination */
|
||||||
|
|
||||||
mtdconfig_writebytes(dev, dst_offset, (uint8_t *) &hdr, sizeof(hdr));
|
ret = mtdconfig_writebytes(dev, dst_offset, (uint8_t *) &hdr, sizeof(hdr));
|
||||||
|
if (ret != sizeof(hdr))
|
||||||
|
{
|
||||||
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
src_offset += sizeof(hdr);
|
src_offset += sizeof(hdr);
|
||||||
dst_offset += sizeof(hdr);
|
dst_offset += sizeof(hdr);
|
||||||
|
|
||||||
@ -856,8 +882,23 @@ retry_relocate:
|
|||||||
|
|
||||||
/* Move the data. */
|
/* Move the data. */
|
||||||
|
|
||||||
mtdconfig_readbytes(dev, src_offset, pBuf, bytes);
|
ret = mtdconfig_readbytes(dev, src_offset, pBuf, bytes);
|
||||||
mtdconfig_writebytes(dev, dst_offset, pBuf, bytes);
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mtdconfig_writebytes(dev, dst_offset, pBuf, bytes);
|
||||||
|
if (ret != bytes)
|
||||||
|
{
|
||||||
|
/* I/O Error! */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Update control variables */
|
/* Update control variables */
|
||||||
|
|
||||||
@ -916,10 +957,15 @@ retry_relocate:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmm_free(pBuf);
|
||||||
|
return dst_offset;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
kmm_free(pBuf);
|
kmm_free(pBuf);
|
||||||
|
ferr("ERROR: fail consolidate: %d\n", ret);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MTD_CONFIG_RAM_CONSOLIDATE */
|
#endif /* CONFIG_MTD_CONFIG_RAM_CONSOLIDATE */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1108,7 +1154,15 @@ retry:
|
|||||||
sig[0] = 'C';
|
sig[0] = 'C';
|
||||||
sig[1] = 'D';
|
sig[1] = 'D';
|
||||||
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
sig[2] = CONFIGDATA_FORMAT_VERSION;
|
||||||
mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
|
||||||
|
ret = mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
|
||||||
|
if (ret != sizeof(sig))
|
||||||
|
{
|
||||||
|
/* Cannot write even the signature. */
|
||||||
|
|
||||||
|
ret = -EIO;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now go try to read the signature again (as verification) */
|
/* Now go try to read the signature again (as verification) */
|
||||||
|
|
||||||
@ -1147,6 +1201,7 @@ retry:
|
|||||||
/* Now find a new entry for this config data */
|
/* Now find a new entry for this config data */
|
||||||
|
|
||||||
retrycount = 0;
|
retrycount = 0;
|
||||||
|
|
||||||
retry_find:
|
retry_find:
|
||||||
offset = mtdconfig_findfirstentry(dev, &hdr);
|
offset = mtdconfig_findfirstentry(dev, &hdr);
|
||||||
if (offset > 0 && hdr.id == MTD_ERASED_ID)
|
if (offset > 0 && hdr.id == MTD_ERASED_ID)
|
||||||
@ -1226,7 +1281,7 @@ retry_find:
|
|||||||
hdr.flags = MTD_ERASED_FLAGS;
|
hdr.flags = MTD_ERASED_FLAGS;
|
||||||
|
|
||||||
ret = mtdconfig_writebytes(dev, offset, (uint8_t *)&hdr, sizeof(hdr));
|
ret = mtdconfig_writebytes(dev, offset, (uint8_t *)&hdr, sizeof(hdr));
|
||||||
if (ret < 0)
|
if (ret != sizeof(hdr))
|
||||||
{
|
{
|
||||||
/* Cannot write even header! */
|
/* Cannot write even header! */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user