mirror of
https://github.com/apache/nuttx.git
synced 2026-10-24 07:18:45 +00:00
SAMV7 flash logic is complete, uncompiled, and untested
This commit is contained in:
parent
78153004ee
commit
1593cd7149
6 changed files with 779 additions and 379 deletions
|
|
@ -517,6 +517,24 @@ config SAMV7_GPIOE_IRQ
|
|||
|
||||
endif # SAMV7_GPIO_IRQ
|
||||
|
||||
menuconfig SAMV7_PROGMEM
|
||||
bool "FLASH program memory"
|
||||
---help---
|
||||
Enable support FLASH interfaces as defined in include/nuttx/progmem.h
|
||||
|
||||
if SAMV7_PROGMEM
|
||||
|
||||
config SAMV7_PROGMEM_NSECTORS
|
||||
int "Number of 128KB sectors"
|
||||
default 4
|
||||
range 1 15
|
||||
---help---
|
||||
This is the number of 128KB FLASH sectors at the end of the program
|
||||
flash memory that will be reserved for use with by the interfaces
|
||||
prototyped in include/nuttx/progmem.h
|
||||
|
||||
endif # SAMV7_PROGMEM
|
||||
|
||||
menu "SDRAM Configuration"
|
||||
depends on SAMV7_SDRAMC
|
||||
|
||||
|
|
|
|||
|
|
@ -175,3 +175,7 @@ endif
|
|||
ifeq ($(CONFIG_SAMV7_USBDEVHS),y)
|
||||
CHIP_CSRCS += sam_usbdevhs.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SAMV7_PROGMEM),y)
|
||||
CHIP_CSRCS += sam_progmem.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -78,14 +78,40 @@
|
|||
|
||||
/* EEFC Flash Command Register */
|
||||
|
||||
Start read unique identifier 0x0E STUI
|
||||
|
||||
#define FCMD_GETD (0) /* Get Flash Descriptor */
|
||||
#define FCMD_WP (1) /* Write page */
|
||||
#define FCMD_WPL (2) /* Write page and lock */
|
||||
#define FCMD_EWP (3) /* Erase page and write page */
|
||||
#define FCMD_EWPL (4) /* Erase page and write page then lock */
|
||||
#define FCMD_EA (5) /* Erase all */
|
||||
#define FCMD_EPA (7) /* Erase pages */
|
||||
#define FCMD_SLB (8) /* Set Lock Bit */
|
||||
#define FCMD_CLB (9) /* Clear Lock Bit */
|
||||
#define FCMD_GLB (10) /* Get Lock Bit */
|
||||
#define FCMD_SGPB (11) /* Set GPNVM Bit */
|
||||
#define FCMD_CGPB (12) /* Clear GPNVM Bit */
|
||||
#define FCMD_GGPB (13) /* Get GPNVM Bit */
|
||||
#define FCMD_STUI (14) /* Start Read Unique Identifier */
|
||||
#define FCMD_SPUI (15) /* Stop Read Unique Identifier */
|
||||
#define FCMD_GCALB (16) /* Get CALIB Bit */
|
||||
#define FCMD_ES (17) /* Erase Sector */
|
||||
#define FCMD_WUS (18) /* Write User Signature */
|
||||
#define FCMD_EUS (19) /* Erase User Signature */
|
||||
#define FCMD_STUS (20) /* Start Read User Signature */
|
||||
#define FCMD_SPUS (21) /* Stop Read User Signature */
|
||||
|
||||
#define EEFC_FCR_FCMD_SHIFT (0) /* Bits 0-7: Flash Command */
|
||||
#define EEFC_FCR_FCMD_MASK (0xff << EEFC_FCR_FCMD_SHIFT)
|
||||
# define EEFC_FCR_FCMD(cmd) ((uint32_t)(cmd) << EEFC_FCR_FCMD_SHIFT)
|
||||
# define EEFC_FCR_FCMD_GETD (0 << EEFC_FCR_FCMD_SHIFT) /* Get Flash Descriptor */
|
||||
# define EEFC_FCR_FCMD_WP (1 << EEFC_FCR_FCMD_SHIFT) /* Write page */
|
||||
# define EEFC_FCR_FCMD_WPL (2 << EEFC_FCR_FCMD_SHIFT) /* Write page and lock */
|
||||
# define EEFC_FCR_FCMD_EWP (3 << EEFC_FCR_FCMD_SHIFT) /* Erase page and write page */
|
||||
# define EEFC_FCR_FCMD_EWPL (4 << EEFC_FCR_FCMD_SHIFT) /* Erase page and write page then lock */
|
||||
# define EEFC_FCR_FCMD_EA (5 << EEFC_FCR_FCMD_SHIFT) /* Erase all */
|
||||
# define EEFC_FCR_FCMD_EPA (7 << EEFC_FCR_FCMD_SHIFT) /* Erase pages */
|
||||
# define EEFC_FCR_FCMD_SLB (8 << EEFC_FCR_FCMD_SHIFT) /* Set Lock Bit */
|
||||
# define EEFC_FCR_FCMD_CLB (9 << EEFC_FCR_FCMD_SHIFT) /* Clear Lock Bit */
|
||||
# define EEFC_FCR_FCMD_GLB (10 << EEFC_FCR_FCMD_SHIFT) /* Get Lock Bit */
|
||||
|
|
@ -102,7 +128,7 @@
|
|||
# define EEFC_FCR_FCMD_SPUS (21 << EEFC_FCR_FCMD_SHIFT) /* Stop Read User Signature */
|
||||
#define EEFC_FCR_FARG_SHIFT (8) /* Bits 8-23: Flash Command Argument */
|
||||
#define EEFC_FCR_FARG_MASK (0xffff << EEFC_FCR_FARG_SHIFT)
|
||||
# define EEFC_FCR_FARG(n) ((uint32_t)(n) << EEFC_FCR_FARG_SHIFT)
|
||||
# define EEFC_FCR_FARG(arg) ((uint32_t)(arg) << EEFC_FCR_FARG_SHIFT)
|
||||
#define EEFC_FCR_FKEY_SHIFT (24) /* Bits 24-31: Flash Writing Protection Key */
|
||||
#define EEFC_FCR_FKEY_MASK (0xff << EEFC_FCR_FKEY_SHIFT)
|
||||
# define EEFC_FCR_FKEY_PASSWD (0x5a << EEFC_FCR_FKEY_SHIFT)
|
||||
|
|
|
|||
|
|
@ -1,373 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/samv7/sam_flash.c
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* 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 NuttX 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 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/samv7/chip.h> /* For SAMV7_ALIGNED_FLASH_SIZE */
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "cache.h"
|
||||
|
||||
#include "sam_flash.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_CHIP_SAMV71)
|
||||
# define SAMV7_SECTOR_SHIFT (17) /* 2**17 = 128KB */
|
||||
# define SAMV7_PAGE_SHIFT (9) /* 2**9 = 512B */
|
||||
#else
|
||||
# error FLASH geometry for this SAMV7 chip not known
|
||||
#endif
|
||||
|
||||
#define SAMV7_SECTOR_SIZE (1 << SAMV7_SECTOR_SHIFT)
|
||||
#define SAMV7_SECTOR_MASK (SAMV7_SECTOR_SIZE - 1)
|
||||
#define SAMV7_PAGE_SIZE (1 << SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE_MASK (SAMV7_PAGE_SIZE - 1)
|
||||
#define SAMV7_SEC2PAGE_SHIFT (SAMV7_SECTOR_SHIFT - SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE_PER_SEC (1 << SAMV7_SEC2PAGE_SHIFT)
|
||||
|
||||
/* Free FLASH begins at the first sector after the FLASH image */
|
||||
#warning Missing logic
|
||||
#define SAMV7_FREE_FLASH_BASE To be provided
|
||||
|
||||
#define ALIGN_UP(v,m) (((v) + (m)) & ~(m))
|
||||
#define ALIGN_DOWN(v,m) ((v) & ~(m))
|
||||
#define SAMV7_ALIGNED_FLASH_BASE ALIGN_UP(SAMV7_FREE_FLASH_BASE)
|
||||
#define SAMV7_FREE_FLASH_SIZE (SAMV7_ALIGNED_FLASH_SIZE - SAMV7_ALIGNED_FLASH_BASE)
|
||||
#define SAMV7_ALIGNED_FLASH_SIZE ALIGN_DOWN(SAMV7_FREE_FLASH_SIZE)
|
||||
#define SAMV7_NSECTORS (SAMV7_ALIGNED_FLASH_SIZE >> SAMV7_SECTOR_SHIFT)
|
||||
#define SAMV7_NPAGES (SAMV7_ALIGNED_FLASH_SIZE >> SAMV7_PAGE_SHIFT)
|
||||
|
||||
#define SAMV7_WRITE_ALIGN (16)
|
||||
#define SAMV7_WRITE_ALIGN_MASK (15)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_flash_unlock(void)
|
||||
{
|
||||
#warning Missing logic
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_npages
|
||||
*
|
||||
* Description:
|
||||
* Return number of pages
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_npages(void)
|
||||
{
|
||||
return SAMV7_NPAGES;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_isuniform
|
||||
*
|
||||
* Description:
|
||||
* Is program memory uniform or page size differs?
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool up_progmem_isuniform(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_pagesize
|
||||
*
|
||||
* Description:
|
||||
* Return page size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_pagesize(size_t page)
|
||||
{
|
||||
return SAMV7_PAGE_SIZE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_getpage
|
||||
*
|
||||
* Description:
|
||||
* Address to page conversion
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - Address with or without flash offset (absolute or aligned to page0)
|
||||
*
|
||||
* Returned Value:
|
||||
* Page or negative value on error. The following errors are reported
|
||||
* (errno is not set!):
|
||||
*
|
||||
* EFAULT: On invalid address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_getpage(size_t addr)
|
||||
{
|
||||
if (addr >= SAMV7_ALIGNED_FLASH_BASE)
|
||||
{
|
||||
addr -= SAMV7_ALIGNED_FLASH_BASE;
|
||||
}
|
||||
|
||||
if (addr >= SAMV7_ALIGNED_FLASH_SIZE)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return addr >> SAMV7_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_getaddress
|
||||
*
|
||||
* Description:
|
||||
* Page to address conversion
|
||||
*
|
||||
* Input Parameters:
|
||||
* page - page index
|
||||
*
|
||||
* Returned Value:
|
||||
* Base address of given page, SIZE_MAX if page index is not valid.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_getaddress(size_t page)
|
||||
{
|
||||
if (page >= SAMV7_NPAGES)
|
||||
{
|
||||
return SAMV7_ALIGNED_FLASH_SIZE;
|
||||
}
|
||||
|
||||
return (page << SAMV7_PAGE_SHIFT) + SAMV7_ALIGNED_FLASH_BASE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_erasepage
|
||||
*
|
||||
* Description:
|
||||
* Erase selected page.
|
||||
*
|
||||
* Input Parameters:
|
||||
* page -
|
||||
*
|
||||
* Returned Value:
|
||||
* Page size or negative value on error. The following errors are reported
|
||||
* (errno is not set!):
|
||||
*
|
||||
* EFAULT: On invalid page
|
||||
* EIO: On unsuccessful erase
|
||||
* EROFS: On access to write protected area
|
||||
* EACCES: Insufficient permissions (read/write protected)
|
||||
* EPERM: If operation is not permitted due to some other constraints
|
||||
* (i.e. some internal block is not running etc.)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_erasepage(size_t page)
|
||||
{
|
||||
size_t page_address;
|
||||
|
||||
if (page >= SAMV7_NPAGES)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Erase a single page */
|
||||
|
||||
sam_flash_unlock();
|
||||
#warning Missing logic
|
||||
|
||||
/* Invalidate I- and D-Cache in this address range */
|
||||
#warning Mising logic
|
||||
|
||||
/* Verify */
|
||||
|
||||
if (up_progmem_ispageerased(page) == 0)
|
||||
{
|
||||
return SAMV7_PAGE_SIZE; /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EIO; /* Failure */
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_ispageerased
|
||||
*
|
||||
* Description:
|
||||
* Checks whether page is erased
|
||||
*
|
||||
* Input Parameters:
|
||||
* page -
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns number of bytes written or negative value on error. If it
|
||||
* returns zero then complete page is empty (erased).
|
||||
*
|
||||
* The following errors are reported (errno is not set!)
|
||||
* EFAULT: On invalid page
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_ispageerased(size_t page)
|
||||
{
|
||||
size_t addr;
|
||||
size_t bwritten;
|
||||
int count;
|
||||
|
||||
if (page >= SAMV7_NPAGES)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Invalidate D-Cache for this address range */
|
||||
|
||||
addr = up_progmem_getaddress(page);
|
||||
arch_invalidate_dcache(addr, addr + SAMV7_PAGE_SIZE);
|
||||
|
||||
/* Verify that the page is erased (i.e., all 0xff) */
|
||||
|
||||
for (count = SAMV7_PAGE_SIZE, bwritten = 0;
|
||||
count > 0;
|
||||
count--, addr++)
|
||||
{
|
||||
if (getreg8(addr) != 0xff)
|
||||
{
|
||||
bwritten++;
|
||||
}
|
||||
}
|
||||
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_write
|
||||
*
|
||||
* Description:
|
||||
* Program data at given address
|
||||
*
|
||||
* Note: this function is not limited to single page and nor it requires
|
||||
* the address be aligned inside the page boundaries.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - Address with or without flash offset (absolute or aligned to page0)
|
||||
* buf - Pointer to buffer
|
||||
* count - Number of bytes to write
|
||||
*
|
||||
* Returned Value:
|
||||
* Bytes written or negative value on error. The following errors are
|
||||
* reported (errno is not set!)
|
||||
*
|
||||
* EINVAL: If count is not aligned with the flash boundaries (i.e.
|
||||
* some MCU's require per half-word or even word access)
|
||||
* EFAULT: On invalid address
|
||||
* EIO: On unsuccessful write
|
||||
* EROFS: On access to write protected area
|
||||
* EACCES: Insufficient permissions (read/write protected)
|
||||
* EPERM: If operation is not permitted due to some other constraints
|
||||
* (i.e. some internal block is not running etc.)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||
{
|
||||
uint8_t *src = (uint8_t *)buf;
|
||||
size_t written = count;
|
||||
|
||||
/* SAMV7 requires 128-bit/16-byte aligned access */
|
||||
|
||||
if ((addr & SAMV7_WRITE_ALIGN_MASK) != 0 ||
|
||||
(count & SAMV7_WRITE_ALIGN_MASK) != 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check for valid address range */
|
||||
|
||||
if (addr >= SAMV7_ALIGNED_FLASH_BASE)
|
||||
{
|
||||
/* Convert address to an offset relative to be beginning of the
|
||||
* writable FLASH region.
|
||||
*/
|
||||
|
||||
addr -= SAMV7_ALIGNED_FLASH_BASE;
|
||||
}
|
||||
|
||||
if ((addr + count) >= SAMV7_ALIGNED_FLASH_SIZE)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Write the data to FLASH */
|
||||
|
||||
sam_flash_unlock();
|
||||
#warning Missing logic
|
||||
|
||||
for (addr += SAMV7_ALIGNED_FLASH_BASE;
|
||||
count;
|
||||
count -= SAMV7_WRITE_ALIGN, src += SAMV7_WRITE_ALIGN, addr += SAMV7_WRITE_ALIGN)
|
||||
{
|
||||
/* Write 128-bit/16-bytes block to FLASH and wait to complete */
|
||||
#warning Mising logic
|
||||
|
||||
/* Invalidate I- and D-Caches for this address range */
|
||||
#warning Mising logic
|
||||
|
||||
/* Verify */
|
||||
#warning Mising logic
|
||||
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
705
arch/arm/src/samv7/sam_progmem.c
Normal file
705
arch/arm/src/samv7/sam_progmem.c
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/samv7/sam_progmem.c
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* 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 NuttX 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 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/samv7/chip.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "cache.h"
|
||||
#include "chip/memorymap.h"
|
||||
|
||||
#include "sam_progmem.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_SAMV7_PROGMEM_NSECTORS
|
||||
# error CONFIG_SAMV7_PROGMEM_NSECTORS is not defined
|
||||
#endif
|
||||
|
||||
/* Chip dependencies */
|
||||
|
||||
#if defined(CONFIG_ARCH_CHIP_SAMV71)
|
||||
/* All sectors are 128KB and are uniform in size.
|
||||
* The only execption is sector 0 which is subdivided into two small sectors
|
||||
* of 8KB and one larger sector of 112KB.
|
||||
* The page size is 515 bytes. However, the smallest thing that can be
|
||||
* erased is four pages. We will refer to this as a "cluster".
|
||||
*/
|
||||
|
||||
# define SAMV7_SECTOR_SHIFT (17) /* 2**17 = 128KB */
|
||||
# define SAMV7_PAGE_SHIFT (9) /* 2**9 = 512B */
|
||||
# define SAMV7_CLUSTER_SHIFT (11) /* 2**13 = 8*KB = 16 pages */
|
||||
# define SAMV7_LOCK_REGION_SHIFT (11) /* 2**13 = 8*KB = 16 pages */
|
||||
#else
|
||||
# error FLASH geometry for this SAMV7 chip not known
|
||||
#endif
|
||||
|
||||
/* Start address */
|
||||
|
||||
#define SAMV7_PROGMEM_NBYTES (CONFIG_SAMV7_PROGMEM_NSECTORS << SAMV7_SECTOR_SHIFT)
|
||||
#define SAMV7_PROGMEM_END (SAM_INTFLASH_BASE + SAMV7_FLASH_SIZE)
|
||||
#define SAMV7_PROGMEM_START (SAMV7_PROGMEM_END - SAMV7_PROGMEM_NBYTES)
|
||||
|
||||
/* Sizes and masks */
|
||||
|
||||
#define SAMV7_SECTOR_SIZE (1 << SAMV7_SECTOR_SHIFT)
|
||||
#define SAMV7_SECTOR_MASK (SAMV7_SECTOR_SIZE - 1)
|
||||
|
||||
#define SAMV7_PAGE_SIZE (1 << SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE_WORDS (1 << (SAMV7_PAGE_SHIFT - 2))
|
||||
#define SAMV7_PAGE_MASK (SAMV7_PAGE_SIZE - 1)
|
||||
|
||||
#define SAMV7_CLUSTER_SIZE (1 << SAMV7_CLUSTER_SHIFT)
|
||||
#define SAMV7_CLUSTER_MASK (SAMV7_CLUSTER_SHIFT - 1)
|
||||
|
||||
/* Relationships */
|
||||
|
||||
#define SAMV7_PAGE2SEC_SHIFT (SAMV7_SECTOR_SHIFT - SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE_PER_SEC (1 << SAMV7_PAGE2SEC_SHIFT)
|
||||
|
||||
#define SAMV7_PAGE2CLUST_SHIFT (SAMV7_CLUSTER_SHIFT - SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE_PER_CLUSTER (1 << SAMV7_PAGE2CLUST_SHIFT)
|
||||
|
||||
#define SAMV7_CLUST2SECT_SHIFT (SAMV7_SECTOR_SHIFT - SAMV7_CLUSTER_SHIFT)
|
||||
#define SAMV7_CLUSTER_PER_SEC (1 << SAMV7_CLUST2SECT_SHIFT)
|
||||
|
||||
/* Conversions */
|
||||
|
||||
#define SAMV7_OFFSET2PAGE(o) ((o) >> SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_OFFSET2CLUST(o) ((o) >> SAMV7_CLUSTER_SHIFT)
|
||||
#define SAMV7_OFFSET2SECT(o) ((o) >> SAMV7_SECTOR_SHIFT)
|
||||
|
||||
#define SAMV7_PAGE2OFFSET(p) ((p) << SAMV7_PAGE_SHIFT)
|
||||
#define SAMV7_PAGE2CLUST(p) ((p) >> SAMV7_PAGE2CLUST_SHIFT)
|
||||
#define SAMV7_PAGE2SEC(p) ((p) >> SAMV7_PAGE2SEC_SHIFT)
|
||||
|
||||
#define SAMV7_CLUST2OFFSET(c) ((c) << SAMV7_CLUSTER_SHIFT)
|
||||
#define SAMV7_CLUST2PAGE(c) ((c) << SAMV7_PAGE2CLUST_SHIFT)
|
||||
#define SAMV7_CLUST2SEC(c) ((c) >> SAMV7_CLUST2SECT_SHIFT)
|
||||
|
||||
#define SAMV7_SEC2OFFSET(s) ((s) << SAMV7_SECTOR_SHIFT)
|
||||
#define SAMV7_SEC2PAGE(s) ((s) << SAMV7_PAGE2SEC_SHIFT)
|
||||
#define SAMV7_SEC2CLUST(s) ((s) << SAMV7_CLUST2SECT_SHIFT)
|
||||
|
||||
/* Lock region */
|
||||
|
||||
#define SAMV7_LOCK_REGION_SIZE (1 << SAMV7_LOCK_REGION_SHIFT)
|
||||
#define SAMV7_LOCK_REGION_MASK (SAMV7_LOCK_REGION_SIZE - 1)
|
||||
|
||||
/* Sizes of the programmable region */
|
||||
|
||||
#define SAMV7_NSECTORS (CONFIG_SAMV7_PROGMEM_NSECTORS)
|
||||
#define SAMV7_NPAGES SAMV7_SEC2PAGE(CONFIG_SAMV7_PROGMEM_NSECTORS)
|
||||
#define SAMV7_NCLUSTERS SAMV7_SEC2CLUST(CONFIG_SAMV7_PROGMEM_NSECTORS)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t g_page_buffer[SAMV7_PAGE_WORDS];
|
||||
static sem_t g_page_sem;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: page_lock
|
||||
*
|
||||
* Description:
|
||||
* Get exclusive access to the global page buffer
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void page_lock(void)
|
||||
{
|
||||
while ((ret = sem_wait(&g_page_sem)) < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
|
||||
/* sem_wait should only fail if it was awakened by a signal */
|
||||
|
||||
DEBUGASSERT(errcode == EINTR);
|
||||
if (errcode != EINTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define page_unlock() sem_post(&g_page_sem)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: efc_command
|
||||
*
|
||||
* Description:
|
||||
* Send a FLASH command
|
||||
*
|
||||
* Input Parameters:
|
||||
* cmd - The FLASH command to be sent
|
||||
* arg - The argument to accompany the command
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success; a negated errno value is returned on any
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int efc_command(uint32_t cmd, uint32_t arg)
|
||||
{
|
||||
uint32_t regval ;
|
||||
|
||||
/* Write the command to the flash command register */
|
||||
|
||||
regval = EEFC_FCR_FCMD(cmd) | EEFC_FCR_FARG(arg) | EEFC_FCR_FKEY_PASSWD;
|
||||
putreg32(regval, SAM_EEFC_FCR);
|
||||
|
||||
/* Wait for the FLASH to become ready again */
|
||||
|
||||
do
|
||||
{
|
||||
regval = getreg32(SAM_EEFC_FSR);
|
||||
}
|
||||
while ((regval & EEFC_FSR_FRDY) == 0);
|
||||
|
||||
/* Check for errors */
|
||||
|
||||
if ((regval & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)) != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: efc_lock
|
||||
*
|
||||
* Description:
|
||||
* Lock a region of FLASH
|
||||
*
|
||||
* Input Parameters:
|
||||
* page - The first page to unlock
|
||||
* npages - The number of consecutive pages to unlock
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if 0 /* Not used */
|
||||
static int efc_lock(size_t page, size_t npages)
|
||||
{
|
||||
size_t start_page;
|
||||
size_t end_page;
|
||||
size_t lockpage;
|
||||
int ret;
|
||||
|
||||
/* Align the page to the lock region */
|
||||
|
||||
end_page = start_page + npages;
|
||||
start_page = (page & SAMV7_LOCK_REGION_MASK)
|
||||
|
||||
for (lockpage = start_page;
|
||||
lockpage < end_page;
|
||||
lockpage += SAMV7_LOCK_REGION_SIZE)
|
||||
{
|
||||
ret = efc_command(FCMD_SLB, lockpage);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: efc_unlock
|
||||
*
|
||||
* Description:
|
||||
* Make sure that the FLASH is unlocked
|
||||
*
|
||||
* Input Parameters:
|
||||
* page - The first page to unlock
|
||||
* npages - The number of consecutive pages to unlock
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void efc_unlock(size_t page, size_t npages)
|
||||
{
|
||||
size_t start_page;
|
||||
size_t end_page;
|
||||
size_t lockpage;
|
||||
int ret;
|
||||
|
||||
/* Align the page to the lock region */
|
||||
|
||||
end_page = start_page + npages;
|
||||
start_page = (page & SAMV7_LOCK_REGION_MASK)
|
||||
|
||||
for (lockpage = start_page;
|
||||
lockpage < end_page;
|
||||
lockpage += SAMV7_LOCK_REGION_SIZE)
|
||||
{
|
||||
ret = efc_command(FCMD_CLB, lockpage);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_progmem_initialize
|
||||
*
|
||||
* Description:
|
||||
* Call to initialize FLASH programming memory access
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_progmem_initialize(void)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
/* Make sure that the read interrupt is disabled */
|
||||
|
||||
regval = getreg32(SAM_EEFC_FMR);
|
||||
regval &= ~EEFC_FMR_FRDY;
|
||||
putreg32(regval, SAM_EEFC_FMR);
|
||||
|
||||
/* Initialize the semaphore that manages exclusive access to the global
|
||||
* page buffer.
|
||||
*/
|
||||
|
||||
sem_init(&g_page_sem, 0, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_npages
|
||||
*
|
||||
* Description:
|
||||
* Return number of clusters in the available FLASH memory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_npages(void)
|
||||
{
|
||||
return SAMV7_NCLUSTERS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_isuniform
|
||||
*
|
||||
* Description:
|
||||
* Cluster size is uniform? Say 'yes' even though that is not strictly
|
||||
* true do to the odd organization of sector 0.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool up_progmem_isuniform(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_pagesize
|
||||
*
|
||||
* Description:
|
||||
* Return cluster size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_pagesize(size_t cluster)
|
||||
{
|
||||
return SAMV7_CLUSTER_SIZE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_getpage
|
||||
*
|
||||
* Description:
|
||||
* Address to cluster conversion
|
||||
*
|
||||
* Input Parameters:
|
||||
* address - Address with or without flash offset
|
||||
*
|
||||
* Returned Value:
|
||||
* Page or negative value on error. The following errors are reported
|
||||
* (errno is not set!):
|
||||
*
|
||||
* -EFAULT: On invalid address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_getpage(size_t address)
|
||||
{
|
||||
if (address >= SAMV7_PROGMEM_START)
|
||||
{
|
||||
address -= SAMV7_PROGMEM_START;
|
||||
}
|
||||
|
||||
if (address >= SAMV7_PROGMEM_NBYTES)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return address >> SAMV7_CLUSTER_SHIFT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_getaddress
|
||||
*
|
||||
* Description:
|
||||
* Cluster to address conversion
|
||||
*
|
||||
* Input Parameters:
|
||||
* cluster - cluster index
|
||||
*
|
||||
* Returned Value:
|
||||
* Base address of given cluster, maximum size if cluster index is not valid.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_progmem_getaddress(size_t cluster)
|
||||
{
|
||||
if (cluster >= SAMV7_NCLUSTERS)
|
||||
{
|
||||
return SAMV7_PROGMEM_NBYTES;
|
||||
}
|
||||
|
||||
return (cluster << SAMV7_CLUSTER_SHIFT) + SAMV7_PROGMEM_START;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_erasepage
|
||||
*
|
||||
* Description:
|
||||
* Erase selected cluster.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cluster - cluster index to be erased
|
||||
*
|
||||
* Returned Value:
|
||||
* Page size or negative value on error. The following errors are reported
|
||||
* (errno is not set!):
|
||||
*
|
||||
* -EFAULT: On invalid cluster
|
||||
* -EIO: On unsuccessful erase
|
||||
* -EROFS: On access to write protected area
|
||||
* -EACCES: Insufficient permissions (read/write protected)
|
||||
* -EPERM: If operation is not permitted due to some other constraints
|
||||
* (i.e. some internal block is not running etc.)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_erasepage(size_t cluster)
|
||||
{
|
||||
uintptr_t address;
|
||||
uint32_t page;
|
||||
uint32_t arg;
|
||||
|
||||
if (cluster >= SAMV7_NCLUSTERS)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Get the page number of the start of the cluster */
|
||||
|
||||
page = SAMV7_CLUST2PAGE((uint32_t)cluster);
|
||||
|
||||
/* Erase all pages in the cluster */
|
||||
|
||||
efc_unlock(page, SAMV7_PAGE_PER_CLUSTER);
|
||||
|
||||
/* Get FARG field for EPA command:
|
||||
*
|
||||
* The first page to be erased is specified in the FARG[15:2] field of
|
||||
* the EEFC_FCR register. The first page number must be modulo 4, 8,16 or
|
||||
* 32 according to the number of pages to erase at the same time.
|
||||
*
|
||||
* The 2 lowest bits of the FARG field define the number of pages to
|
||||
* be erased (FARG[1:0]).
|
||||
*/
|
||||
|
||||
#if SAMV7_CLUSTER_SIZE == 32
|
||||
arg = (page << 2) | 3; /* Not valid for small 8 KB sectors */
|
||||
#elif SAMV7_CLUSTER_SIZE == 16
|
||||
arg = (page << 2) | 2;
|
||||
#elif SAMV7_CLUSTER_SIZE == 8
|
||||
# error Cluster size of 8 not suportted
|
||||
arg = (page << 2) | 1; /* 0nly valid for small 8 KB sectors */
|
||||
#elif SAMV7_CLUSTER_SIZE == 4
|
||||
# error Cluster size of 4 not suportted
|
||||
arg = (page << 2) | 0; /* 0nly valid for small 8 KB sectors */
|
||||
#else
|
||||
# error Unsupported/undefined cluster size
|
||||
#endif
|
||||
|
||||
ret = efc_command(pEfc, FCMD_EPA, arg);
|
||||
|
||||
/* Invalidate I- and D-Cache in this address range */
|
||||
|
||||
address = SAMV7_CLUST2OFFSET((uintptr_t)cluster) + SAMV7_PROGMEM_START;
|
||||
arch_dcache_invalidate(address, address + SAMV7_CLUSTER_SIZE);
|
||||
|
||||
/* Verify */
|
||||
|
||||
if (up_progmem_ispageerased(cluster) == 0)
|
||||
{
|
||||
return SAMV7_CLUSTER_SIZE; /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EIO; /* Failure */
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_ispageerased
|
||||
*
|
||||
* Description:
|
||||
* Checks whether cluster is erased
|
||||
*
|
||||
* Input Parameters:
|
||||
* cluster - cluster to be checked
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns number of bytes erased or negative value on error. If it
|
||||
* returns zero then complete cluster is empty (erased).
|
||||
*
|
||||
* The following errors are reported (errno is not set!)
|
||||
* -EFAULT: On invalid cluster
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_ispageerased(size_t cluster)
|
||||
{
|
||||
size_t address;
|
||||
size_t nwritten;
|
||||
int nleft;
|
||||
|
||||
if (cluster >= SAMV7_NCLUSTERS)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Invalidate D-Cache for this address range */
|
||||
|
||||
address = (cluster << SAMV7_CLUSTER_SHIFT) + SAMV7_PROGMEM_START;
|
||||
arch_invalidate_dcache(address, address + SAMV7_CLUSTER_SIZE);
|
||||
|
||||
/* Verify that the cluster is erased (i.e., all 0xff) */
|
||||
|
||||
for (nleft = SAMV7_CLUSTER_SIZE, nwritten = 0;
|
||||
nleft > 0;
|
||||
nleft--, address++)
|
||||
{
|
||||
if (getreg8(address) != 0xff)
|
||||
{
|
||||
nwritten++;
|
||||
}
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_progmem_write
|
||||
*
|
||||
* Description:
|
||||
* Program data at given address
|
||||
*
|
||||
* Input Parameters:
|
||||
* address - Address with or without flash offset
|
||||
* buffer - Pointer to buffer
|
||||
* buflen - Number of bytes to write
|
||||
*
|
||||
* Returned Value:
|
||||
* Bytes written or negative value on error. The following errors are
|
||||
* reported (errno is not set!)
|
||||
*
|
||||
* EINVAL: If buflen is not aligned with the flash boundaries (i.e.
|
||||
* some MCU's require per half-word or even word access)
|
||||
* EFAULT: On invalid address
|
||||
* EIO: On unsuccessful write
|
||||
* EROFS: On access to write protected area
|
||||
* EACCES: Insufficient permissions (read/write protected)
|
||||
* EPERM: If operation is not permitted due to some other constraints
|
||||
* (i.e. some internal block is not running etc.)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_progmem_write(size_t address, const void *buffer, size_t buflen)
|
||||
{
|
||||
FAR uint32_t *dest;
|
||||
FAR const uint32_t *src;
|
||||
size_t written;
|
||||
size_t xfrsize;
|
||||
size_t offset;
|
||||
size_t page;
|
||||
|
||||
/* Convert the address into a FLASH offset, if necessary */
|
||||
|
||||
offset = address;
|
||||
if (address >= SAMV7_PROGMEM_START)
|
||||
{
|
||||
/* Convert address to an offset relative to be beginning of the
|
||||
* writable FLASH region.
|
||||
*/
|
||||
|
||||
offset -= SAMV7_PROGMEM_START;
|
||||
}
|
||||
|
||||
/* Check for valid address range */
|
||||
|
||||
if ((offset + buflen) >= SAMV7_PROGMEM_NBYTES)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Get the page number corresponding to the flash offset and the byte
|
||||
* offset into the page.
|
||||
*/
|
||||
|
||||
page = offset >> SAMV7_PAGE_SHIFT;
|
||||
offset &= SAMV7_PAGE_MASK;
|
||||
|
||||
/* Get exclusive access to the global page buffer */
|
||||
|
||||
page_lock();
|
||||
|
||||
/* Make sure that the FLASH is unlocked */
|
||||
|
||||
efc_unlock(page, SAMV7_SECTOR_SHIFT(buflen));
|
||||
|
||||
/* Loop until all of the data has been written */
|
||||
|
||||
dest = (FAR uint32_t *)address;
|
||||
written = 0;
|
||||
|
||||
while (buflen > 0)
|
||||
{
|
||||
/* How much can we write into this page? */
|
||||
|
||||
xfrsize = min((size_t)SAMV7_PAGE_SIZE - offset, buflen) ;
|
||||
|
||||
/* Do we need to use the intermediate buffer? */
|
||||
|
||||
if (offset == 0 && xfsize == SAMV7_PAGE_SIZE)
|
||||
{
|
||||
/* No, we can take the data directly from the user buffer */
|
||||
|
||||
src = (FAR const uint32_t *)buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, copy data into global page buffer */
|
||||
|
||||
memcpy(g_page_buffer, dest, offset);
|
||||
memcpy((uint8_t *)g_page_buffer + offset, buffer, xfrsize);
|
||||
memcpy((uint8_t *)g_page_buffer + offset + xfrsize,
|
||||
(const uint8_t *)dest + offset + xfrsize,
|
||||
SAMV7_PAGE_SIZE - offset - xfrsize);
|
||||
|
||||
src = g_page_buffer;
|
||||
}
|
||||
|
||||
/* Write the page */
|
||||
|
||||
for (i = 0; i < (SAMV7_PAGE_SIZE / sizeof(uint32_t)); i++)
|
||||
{
|
||||
*dest++ = *src++;
|
||||
ARM_DMB();
|
||||
}
|
||||
|
||||
/* Flush the data cache to memory */
|
||||
|
||||
arch_clean_dcache(address, address + SAMV7_PAGE_SIZE);
|
||||
|
||||
/* Send the write command */
|
||||
|
||||
ret = efc_command(FCMD_WP, page);
|
||||
if (ret >= 0)
|
||||
{
|
||||
written += wrsize;
|
||||
}
|
||||
|
||||
/* Adjust pointers and counts for the next time through the loop */
|
||||
|
||||
address += wrsize;
|
||||
dest = (FAR uint32_t *)address;
|
||||
buffer = (FAR void *)((uintptr_t)buffer + wrsize);
|
||||
buflen -= wrsize;
|
||||
page++;
|
||||
}
|
||||
|
||||
page_unlock();
|
||||
return written;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/samv7/sam_flash.c
|
||||
* arch/arm/src/samv7/sam_progmem.c
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_SAMV7_SAM_FLASH_H
|
||||
#define __ARCH_ARM_SRC_SAMV7_SAM_FLASH_H
|
||||
#ifndef __ARCH_ARM_SRC_SAMV7_SAM_PROGMEM_H
|
||||
#define __ARCH_ARM_SRC_SAMV7_SAM_PROGMEM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
|
@ -42,9 +42,29 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "up_arch.h"
|
||||
#include "chip/sam_eefc.h"
|
||||
|
||||
#include <nuttx/progmem.h>
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_SAMV7_SAM_FLASH_H */
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_progmem_initialize
|
||||
*
|
||||
* Description:
|
||||
* Call to initialize FLASH programming memory access
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_progmem_initialize(void);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_SAMV7_SAM_PROGMEM_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue