diff --git a/arch/arm/src/stm32/chip/stm32_flash.h b/arch/arm/src/stm32/chip/stm32_flash.h index 3a4e97bd1a..06e33386a4 100644 --- a/arch/arm/src/stm32/chip/stm32_flash.h +++ b/arch/arm/src/stm32/chip/stm32_flash.h @@ -72,11 +72,15 @@ #elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) # define STM32_FLASH_NPAGES 8 -# define STM32_FLASH_PAGESIZE (128*1024) - /* XXX this is wrong for 427, and not really right for 40x due to mixed page sizes */ +/* STM32F4 has mixed page size */ +# undef STM32_FLASH_PAGESIZE +/* TODO: add proper sizes for each chip in the family - maybe in chip.h? */ +# define STM32_FLASH_SIZE (8 * 128 * 1024) #endif -#define STM32_FLASH_SIZE (STM32_FLASH_NPAGES * STM32_FLASH_PAGESIZE) +#ifdef STM32_FLASH_PAGESIZE +# define STM32_FLASH_SIZE (STM32_FLASH_NPAGES * STM32_FLASH_PAGESIZE) +#endif /* def STM32_FLASH_PAGESIZE */ /* Register Offsets *****************************************************************/ @@ -204,6 +208,7 @@ # define FLASH_CR_PSIZE_X16 (1 << FLASH_CR_PSIZE_SHIFT) /* 01 program x16 */ # define FLASH_CR_PSIZE_X32 (2 << FLASH_CR_PSIZE_SHIFT) /* 10 program x32 */ # define FLASH_CR_PSIZE_X64 (3 << FLASH_CR_PSIZE_SHIFT) /* 11 program x64 */ +# define FLASH_CR_STRT (1 << 16) /* Bit 16: Start Erase */ # define FLASH_CR_EOPIE (1 << 24) /* Bit 24: End of operation interrupt enable */ # define FLASH_CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */ # define FLASH_CR_LOCK (1 << 31) /* Bit 31: Lock */ diff --git a/arch/arm/src/stm32/stm32_flash.c b/arch/arm/src/stm32/stm32_flash.c index f725fb7f7d..d9e09da064 100644 --- a/arch/arm/src/stm32/stm32_flash.c +++ b/arch/arm/src/stm32/stm32_flash.c @@ -57,7 +57,7 @@ /* Only for the STM32F10xx family for now */ -#ifdef CONFIG_STM32_STM32F10XX +#if defined(CONFIG_STM32_STM32F10XX) || defined (CONFIG_STM32_STM32F40XX) /************************************************************************************ * Pre-processor Definitions @@ -66,6 +66,14 @@ #define FLASH_KEY1 0x45670123 #define FLASH_KEY2 0xCDEF89AB +#if defined(CONFIG_STM32_STM32F10XX) +#define FLASH_CR_PAGE_ERASE FLASH_CR_PER +#define FLASH_SR_WRITE_PROTECTION_ERROR FLASH_SR_WRPRT_ERR +#elif defined(CONFIG_STM32_STM32F40XX) +#define FLASH_CR_PAGE_ERASE FLASH_CR_SER +#define FLASH_SR_WRITE_PROTECTION_ERROR FLASH_SR_WRPERR +#endif + /************************************************************************************ * Private Functions ************************************************************************************/ @@ -88,29 +96,21 @@ void stm32_flash_unlock(void) void stm32_flash_lock(void) { - modifyreg16(STM32_FLASH_CR, 0, FLASH_CR_LOCK); + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK); } /************************************************************************************ * Public Functions ************************************************************************************/ -uint16_t up_progmem_npages(void) -{ - return STM32_FLASH_NPAGES; -} +#ifdef CONFIG_STM32_STM32F10XX -bool up_progmem_isuniform(void) -{ - return true; -} - -uint16_t up_progmem_pagesize(uint16_t page) +size_t up_progmem_pagesize(size_t page) { return STM32_FLASH_PAGESIZE; } -int up_progmem_getpage(uint32_t addr) +ssize_t up_progmem_getpage(size_t addr) { if (addr >= STM32_FLASH_BASE) { @@ -125,10 +125,110 @@ int up_progmem_getpage(uint32_t addr) return addr / STM32_FLASH_PAGESIZE; } -int up_progmem_erasepage(uint16_t page) +size_t up_progmem_getaddress(size_t page) { - uint32_t addr; - uint16_t count; + if (page >= STM32_FLASH_NPAGES) + { + return SIZE_MAX; + } + + return page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE; +} + +#endif /* def CONFIG_STM32_STM32F10XX */ + +#ifdef CONFIG_STM32_STM32F40XX + +size_t up_progmem_pagesize(size_t page) +{ + static const size_t page_sizes[STM32_FLASH_NPAGES] = + { + 16 * 1024, + 16 * 1024, + 16 * 1024, + 16 * 1024, + 64 * 1024, + 128 * 1024, + 128 * 1024, + 128 * 1024, + }; + + if (page >= sizeof(page_sizes) / sizeof(*page_sizes)) + { + return 0; + } + else + { + return page_sizes[page]; + } +} + +ssize_t up_progmem_getpage(size_t addr) +{ + size_t page_end = 0; + size_t i; + + if (addr >= STM32_FLASH_BASE) + { + addr -= STM32_FLASH_BASE; + } + + if (addr >= STM32_FLASH_SIZE) + { + return -EFAULT; + } + + for (i = 0; i < STM32_FLASH_NPAGES; ++i) + { + page_end += up_progmem_pagesize(i); + if (page_end > addr) + { + return i; + } + } + + return -EFAULT; +} + +size_t up_progmem_getaddress(size_t page) +{ + size_t base_address = STM32_FLASH_BASE; + size_t i; + + if (page >= STM32_FLASH_NPAGES) + { + return SIZE_MAX; + } + + for (i = 0; i < page; ++i) + { + base_address += up_progmem_pagesize(i); + } + + return base_address; +} + +#endif /* def CONFIG_STM32_STM32F40XX */ + +size_t up_progmem_npages(void) +{ + return STM32_FLASH_NPAGES; +} + +bool up_progmem_isuniform(void) +{ +#ifdef STM32_FLASH_PAGESIZE + return true; +#else + return false; +#endif /* def STM32_FLASH_PAGESIZE */ +} + +ssize_t up_progmem_erasepage(size_t page) +{ +#ifdef CONFIG_STM32_STM32F10XX + size_t page_address; +#endif /* def CONFIG_STM32_STM32F10XX */ if (page >= STM32_FLASH_NPAGES) { @@ -144,33 +244,38 @@ int up_progmem_erasepage(uint16_t page) stm32_flash_unlock(); - modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER); - putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR); + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PAGE_ERASE); + +#if defined(CONFIG_STM32_STM32F10XX) + /* must be valid - page index checked above */ + page_address = up_progmem_getaddress(page); + putreg32(page_address, STM32_FLASH_AR); +#elif defined(CONFIG_STM32_STM32F40XX) + modifyreg32(STM32_FLASH_CR, FLASH_CR_SNB_MASK, FLASH_CR_SNB(page)); +#endif + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT); while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); - modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0); + modifyreg32(STM32_FLASH_CR, FLASH_CR_PAGE_ERASE, 0); /* Verify */ - - for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; - count; count-=4, addr += 4) + if (up_progmem_ispageerased(page) == 0) { - if (getreg32(addr) != 0xffffffff) - { - return -EIO; - } + return up_progmem_pagesize(page); /* success */ + } + else + { + return -EIO; /* failure */ } - - return STM32_FLASH_PAGESIZE; } -int up_progmem_ispageerased(uint16_t page) +ssize_t up_progmem_ispageerased(size_t page) { - uint32_t addr; - uint16_t count; - uint16_t bwritten = 0; + size_t addr; + size_t count; + size_t bwritten = 0; if (page >= STM32_FLASH_NPAGES) { @@ -179,7 +284,7 @@ int up_progmem_ispageerased(uint16_t page) /* Verify */ - for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; + for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page); count; count--, addr++) { if (getreg8(addr) != 0xff) @@ -191,7 +296,7 @@ int up_progmem_ispageerased(uint16_t page) return bwritten; } -int up_progmem_write(uint32_t addr, const void *buf, size_t count) +ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) { uint16_t *hword = (uint16_t *)buf; size_t written = count; @@ -226,6 +331,11 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG); +#if defined(CONFIG_STM32_STM32F40XX) + /* TODO: implement up_progmem_write() to support other sizes than 16-bits */ + modifyreg32(STM32_FLASH_CR, FLASH_CR_PSIZE_MASK, FLASH_CR_PSIZE_X16); +#endif + for (addr += STM32_FLASH_BASE; count; count-=2, hword++, addr+=2) { /* Write half-word and wait to complete */ @@ -236,7 +346,7 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) /* Verify */ - if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRPRT_ERR) + if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR) { modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); return -EROFS; @@ -253,4 +363,4 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) return written; } -#endif /* CONFIG_STM32_STM32F10XX */ +#endif /* defined(CONFIG_STM32_STM32F10XX) || defined (CONFIG_STM32_STM32F40XX) */ diff --git a/configs/vsn/src/sif.c b/configs/vsn/src/sif.c index ed7f805a89..d9e859cc78 100644 --- a/configs/vsn/src/sif.c +++ b/configs/vsn/src/sif.c @@ -566,8 +566,8 @@ int sif_main(int argc, char *argv[]) clock_settime(CLOCK_REALTIME, &t_set); } else if (!strcmp(argv[1], "free")) { - uint16_t page = 0, stpage = 0xFFFF; - int status; + size_t page = 0, stpage = 0xFFFF; + ssize_t status; do { status = up_progmem_ispageerased(page++); @@ -586,13 +586,13 @@ int sif_main(int argc, char *argv[]) return 0; } else if (!strcmp(argv[1], "erase") && argc == 3) { - int page = atoi(argv[2]); + size_t page = atoi(argv[2]); printf("Erase result: %d\n", up_progmem_erasepage(page)); return 0; } else if (!strcmp(argv[1], "flash") && argc == 3) { - uint16_t page = atoi(argv[2]); - uint32_t addr = page * up_progmem_pagesize(page); + size_t page = atoi(argv[2]); + size_t addr = page * up_progmem_pagesize(page); printf("Write result: %d (writing to address %xh)\n", up_progmem_write(addr, "Test", 4), addr); diff --git a/include/nuttx/progmem.h b/include/nuttx/progmem.h index 46dd1db619..7f5d13f89c 100644 --- a/include/nuttx/progmem.h +++ b/include/nuttx/progmem.h @@ -43,7 +43,6 @@ #include #include -#include #include /**************************************************************************** @@ -70,7 +69,7 @@ extern "C" { * ****************************************************************************/ -uint16_t up_progmem_npages(void); +size_t up_progmem_npages(void); /**************************************************************************** * Name: up_progmem_isuniform @@ -90,7 +89,7 @@ bool up_progmem_isuniform(void); * ****************************************************************************/ -uint16_t up_progmem_pagesize(uint16_t page); +size_t up_progmem_pagesize(size_t page); /**************************************************************************** * Name: up_progmem_getpage @@ -109,7 +108,23 @@ uint16_t up_progmem_pagesize(uint16_t page); * ****************************************************************************/ -int up_progmem_getpage(uint32_t addr); +ssize_t up_progmem_getpage(size_t addr); + +/**************************************************************************** + * 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); /**************************************************************************** * Name: up_progmem_erasepage @@ -133,7 +148,7 @@ int up_progmem_getpage(uint32_t addr); * ****************************************************************************/ -int up_progmem_erasepage(uint16_t page); +ssize_t up_progmem_erasepage(size_t page); /**************************************************************************** * Name: up_progmem_ispageerased @@ -153,7 +168,7 @@ int up_progmem_erasepage(uint16_t page); * ****************************************************************************/ -int up_progmem_ispageerased(uint16_t page); +ssize_t up_progmem_ispageerased(size_t page); /**************************************************************************** * Name: up_progmem_write @@ -184,7 +199,7 @@ int up_progmem_ispageerased(uint16_t page); * ****************************************************************************/ -int up_progmem_write(uint32_t addr, const void *buf, size_t count); +ssize_t up_progmem_write(size_t addr, const void *buf, size_t count); /* TODO: Define the following functions and their options: * - up_progmem_protect()