SAMV7 FLASH driver now at least compiles

This commit is contained in:
Gregory Nutt
2015-11-12 12:26:53 -06:00
parent 1593cd7149
commit 4ecf9b5bec
2 changed files with 55 additions and 37 deletions
-2
View File
@@ -78,8 +78,6 @@
/* EEFC Flash Command Register */ /* EEFC Flash Command Register */
Start read unique identifier 0x0E STUI
#define FCMD_GETD (0) /* Get Flash Descriptor */ #define FCMD_GETD (0) /* Get Flash Descriptor */
#define FCMD_WP (1) /* Write page */ #define FCMD_WP (1) /* Write page */
#define FCMD_WPL (2) /* Write page and lock */ #define FCMD_WPL (2) /* Write page and lock */
+55 -35
View File
@@ -39,6 +39,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <string.h>
#include <semaphore.h> #include <semaphore.h>
#include <errno.h> #include <errno.h>
@@ -47,7 +48,7 @@
#include "up_arch.h" #include "up_arch.h"
#include "cache.h" #include "cache.h"
#include "chip/memorymap.h" #include "chip/sam_memorymap.h"
#include "sam_progmem.h" #include "sam_progmem.h"
@@ -72,8 +73,8 @@
# define SAMV7_SECTOR_SHIFT (17) /* 2**17 = 128KB */ # define SAMV7_SECTOR_SHIFT (17) /* 2**17 = 128KB */
# define SAMV7_PAGE_SHIFT (9) /* 2**9 = 512B */ # define SAMV7_PAGE_SHIFT (9) /* 2**9 = 512B */
# define SAMV7_CLUSTER_SHIFT (11) /* 2**13 = 8*KB = 16 pages */ # define SAMV7_CLUSTER_SHIFT (13) /* 2**13 = 8*KB = 16 pages */
# define SAMV7_LOCK_REGION_SHIFT (11) /* 2**13 = 8*KB = 16 pages */ # define SAMV7_LOCK_REGION_SHIFT (13) /* 2**13 = 8*KB = 16 pages */
#else #else
# error FLASH geometry for this SAMV7 chip not known # error FLASH geometry for this SAMV7 chip not known
#endif #endif
@@ -109,19 +110,19 @@
/* Conversions */ /* Conversions */
#define SAMV7_OFFSET2PAGE(o) ((o) >> SAMV7_PAGE_SHIFT) #define SAMV7_BYTE2PAGE(o) ((o) >> SAMV7_PAGE_SHIFT)
#define SAMV7_OFFSET2CLUST(o) ((o) >> SAMV7_CLUSTER_SHIFT) #define SAMV7_BYTE2CLUST(o) ((o) >> SAMV7_CLUSTER_SHIFT)
#define SAMV7_OFFSET2SECT(o) ((o) >> SAMV7_SECTOR_SHIFT) #define SAMV7_BYTE2SECT(o) ((o) >> SAMV7_SECTOR_SHIFT)
#define SAMV7_PAGE2OFFSET(p) ((p) << SAMV7_PAGE_SHIFT) #define SAMV7_PAGE2BYTE(p) ((p) << SAMV7_PAGE_SHIFT)
#define SAMV7_PAGE2CLUST(p) ((p) >> SAMV7_PAGE2CLUST_SHIFT) #define SAMV7_PAGE2CLUST(p) ((p) >> SAMV7_PAGE2CLUST_SHIFT)
#define SAMV7_PAGE2SEC(p) ((p) >> SAMV7_PAGE2SEC_SHIFT) #define SAMV7_PAGE2SEC(p) ((p) >> SAMV7_PAGE2SEC_SHIFT)
#define SAMV7_CLUST2OFFSET(c) ((c) << SAMV7_CLUSTER_SHIFT) #define SAMV7_CLUST2BYTE(c) ((c) << SAMV7_CLUSTER_SHIFT)
#define SAMV7_CLUST2PAGE(c) ((c) << SAMV7_PAGE2CLUST_SHIFT) #define SAMV7_CLUST2PAGE(c) ((c) << SAMV7_PAGE2CLUST_SHIFT)
#define SAMV7_CLUST2SEC(c) ((c) >> SAMV7_CLUST2SECT_SHIFT) #define SAMV7_CLUST2SEC(c) ((c) >> SAMV7_CLUST2SECT_SHIFT)
#define SAMV7_SEC2OFFSET(s) ((s) << SAMV7_SECTOR_SHIFT) #define SAMV7_SEC2BYTE(s) ((s) << SAMV7_SECTOR_SHIFT)
#define SAMV7_SEC2PAGE(s) ((s) << SAMV7_PAGE2SEC_SHIFT) #define SAMV7_SEC2PAGE(s) ((s) << SAMV7_PAGE2SEC_SHIFT)
#define SAMV7_SEC2CLUST(s) ((s) << SAMV7_CLUST2SECT_SHIFT) #define SAMV7_SEC2CLUST(s) ((s) << SAMV7_CLUST2SECT_SHIFT)
@@ -136,6 +137,16 @@
#define SAMV7_NPAGES SAMV7_SEC2PAGE(CONFIG_SAMV7_PROGMEM_NSECTORS) #define SAMV7_NPAGES SAMV7_SEC2PAGE(CONFIG_SAMV7_PROGMEM_NSECTORS)
#define SAMV7_NCLUSTERS SAMV7_SEC2CLUST(CONFIG_SAMV7_PROGMEM_NSECTORS) #define SAMV7_NCLUSTERS SAMV7_SEC2CLUST(CONFIG_SAMV7_PROGMEM_NSECTORS)
/* Misc stuff */
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@@ -163,14 +174,14 @@ static sem_t g_page_sem;
static void page_lock(void) static void page_lock(void)
{ {
while ((ret = sem_wait(&g_page_sem)) < 0) while (sem_wait(&g_page_sem) < 0)
{ {
int errcode = errno; int errcode = errno;
/* sem_wait should only fail if it was awakened by a signal */ /* sem_wait should only fail if it was awakened by a signal */
DEBUGASSERT(errcode == EINTR); DEBUGASSERT(errcode == EINTR);
if (errcode != EINTER) if (errcode != EINTR)
{ {
break; break;
} }
@@ -197,7 +208,7 @@ static void page_lock(void)
static int efc_command(uint32_t cmd, uint32_t arg) static int efc_command(uint32_t cmd, uint32_t arg)
{ {
uint32_t regval ; uint32_t regval;
/* Write the command to the flash command register */ /* Write the command to the flash command register */
@@ -249,8 +260,8 @@ static int efc_lock(size_t page, size_t npages)
/* Align the page to the lock region */ /* Align the page to the lock region */
end_page = start_page + npages; end_page = page + npages;
start_page = (page & SAMV7_LOCK_REGION_MASK) start_page = page & SAMV7_LOCK_REGION_MASK;
for (lockpage = start_page; for (lockpage = start_page;
lockpage < end_page; lockpage < end_page;
@@ -262,7 +273,8 @@ static int efc_lock(size_t page, size_t npages)
return ret; return ret;
} }
} }
}
return OK;
} }
#endif #endif
@@ -281,7 +293,7 @@ static int efc_lock(size_t page, size_t npages)
* *
****************************************************************************/ ****************************************************************************/
static void efc_unlock(size_t page, size_t npages) static int efc_unlock(size_t page, size_t npages)
{ {
size_t start_page; size_t start_page;
size_t end_page; size_t end_page;
@@ -290,8 +302,8 @@ static void efc_unlock(size_t page, size_t npages)
/* Align the page to the lock region */ /* Align the page to the lock region */
end_page = start_page + npages; end_page = page + npages;
start_page = (page & SAMV7_LOCK_REGION_MASK) start_page = page & SAMV7_LOCK_REGION_MASK;
for (lockpage = start_page; for (lockpage = start_page;
lockpage < end_page; lockpage < end_page;
@@ -303,7 +315,8 @@ static void efc_unlock(size_t page, size_t npages)
return ret; return ret;
} }
} }
}
return OK;
} }
/**************************************************************************** /****************************************************************************
@@ -464,6 +477,7 @@ ssize_t up_progmem_erasepage(size_t cluster)
uintptr_t address; uintptr_t address;
uint32_t page; uint32_t page;
uint32_t arg; uint32_t arg;
int ret;
if (cluster >= SAMV7_NCLUSTERS) if (cluster >= SAMV7_NCLUSTERS)
{ {
@@ -476,7 +490,7 @@ ssize_t up_progmem_erasepage(size_t cluster)
/* Erase all pages in the cluster */ /* Erase all pages in the cluster */
efc_unlock(page, SAMV7_PAGE_PER_CLUSTER); (void)efc_unlock(page, SAMV7_PAGE_PER_CLUSTER);
/* Get FARG field for EPA command: /* Get FARG field for EPA command:
* *
@@ -488,26 +502,30 @@ ssize_t up_progmem_erasepage(size_t cluster)
* be erased (FARG[1:0]). * be erased (FARG[1:0]).
*/ */
#if SAMV7_CLUSTER_SIZE == 32 #if SAMV7_PAGE_PER_CLUSTER == 32
arg = (page << 2) | 3; /* Not valid for small 8 KB sectors */ arg = (page << 2) | 3; /* Not valid for small 8 KB sectors */
#elif SAMV7_CLUSTER_SIZE == 16 #elif SAMV7_PAGE_PER_CLUSTER == 16
arg = (page << 2) | 2; arg = (page << 2) | 2;
#elif SAMV7_CLUSTER_SIZE == 8 #elif SAMV7_PAGE_PER_CLUSTER == 8
# error Cluster size of 8 not suportted # error Cluster size of 8 not suportted
arg = (page << 2) | 1; /* 0nly valid for small 8 KB sectors */ arg = (page << 2) | 1; /* 0nly valid for small 8 KB sectors */
#elif SAMV7_CLUSTER_SIZE == 4 #elif SAMV7_PAGE_PER_CLUSTER == 4
# error Cluster size of 4 not suportted # error Cluster size of 4 not suportted
arg = (page << 2) | 0; /* 0nly valid for small 8 KB sectors */ arg = (page << 2) | 0; /* 0nly valid for small 8 KB sectors */
#else #else
# error Unsupported/undefined cluster size # error Unsupported/undefined pages-per-cluster size
#endif #endif
ret = efc_command(pEfc, FCMD_EPA, arg); ret = efc_command(FCMD_EPA, arg);
if (ret < 0)
{
return ret;
}
/* Invalidate I- and D-Cache in this address range */ /* Invalidate I- and D-Cache in this address range */
address = SAMV7_CLUST2OFFSET((uintptr_t)cluster) + SAMV7_PROGMEM_START; address = SAMV7_CLUST2BYTE((uintptr_t)cluster) + SAMV7_PROGMEM_START;
arch_dcache_invalidate(address, address + SAMV7_CLUSTER_SIZE); arch_invalidate_dcache(address, address + SAMV7_CLUSTER_SIZE);
/* Verify */ /* Verify */
@@ -604,6 +622,8 @@ ssize_t up_progmem_write(size_t address, const void *buffer, size_t buflen)
size_t xfrsize; size_t xfrsize;
size_t offset; size_t offset;
size_t page; size_t page;
size_t i;
int ret;
/* Convert the address into a FLASH offset, if necessary */ /* Convert the address into a FLASH offset, if necessary */
@@ -637,7 +657,7 @@ ssize_t up_progmem_write(size_t address, const void *buffer, size_t buflen)
/* Make sure that the FLASH is unlocked */ /* Make sure that the FLASH is unlocked */
efc_unlock(page, SAMV7_SECTOR_SHIFT(buflen)); (void)efc_unlock(page, SAMV7_BYTE2PAGE(buflen + SAMV7_PAGE_MASK));
/* Loop until all of the data has been written */ /* Loop until all of the data has been written */
@@ -648,11 +668,11 @@ ssize_t up_progmem_write(size_t address, const void *buffer, size_t buflen)
{ {
/* How much can we write into this page? */ /* How much can we write into this page? */
xfrsize = min((size_t)SAMV7_PAGE_SIZE - offset, buflen) ; xfrsize = MIN((size_t)SAMV7_PAGE_SIZE - offset, buflen) ;
/* Do we need to use the intermediate buffer? */ /* Do we need to use the intermediate buffer? */
if (offset == 0 && xfsize == SAMV7_PAGE_SIZE) if (offset == 0 && xfrsize == SAMV7_PAGE_SIZE)
{ {
/* No, we can take the data directly from the user buffer */ /* No, we can take the data directly from the user buffer */
@@ -688,15 +708,15 @@ ssize_t up_progmem_write(size_t address, const void *buffer, size_t buflen)
ret = efc_command(FCMD_WP, page); ret = efc_command(FCMD_WP, page);
if (ret >= 0) if (ret >= 0)
{ {
written += wrsize; written += xfrsize;
} }
/* Adjust pointers and counts for the next time through the loop */ /* Adjust pointers and counts for the next time through the loop */
address += wrsize; address += xfrsize;
dest = (FAR uint32_t *)address; dest = (FAR uint32_t *)address;
buffer = (FAR void *)((uintptr_t)buffer + wrsize); buffer = (FAR void *)((uintptr_t)buffer + xfrsize);
buflen -= wrsize; buflen -= xfrsize;
page++; page++;
} }