arch/arm/src/stm32f7/stm32_flash.c: Add flash block mapping support for progmem.

This commit is contained in:
Valmantas Paliksa 2019-04-12 08:43:16 -06:00 committed by Gregory Nutt
parent c574e71c89
commit 29164c5706
3 changed files with 132 additions and 58 deletions

View File

@ -1118,6 +1118,27 @@ config STM32F7_FLASH_ART_ACCELERATOR
Enable if code and/or read-only data is accessed through ITCM bus instead of
AXIM bus.
config STM32F7_PROGMEM
bool "Flash progmem support"
default n
---help---
Add progmem support, start block and end block options are provided to
obtain an uniform flash memory mapping.
if STM32F7_PROGMEM
config STM32F7_PROGMEM_STARTBLOCK
int "First mapped progmem block"
default 0
range 0 64
config STM32F7_PROGMEM_LASTBLOCK
int "Last mapped progmem block"
default -1
range -1 64
endif # STM32F7_PROGMEM
menu "STM32 Peripheral Support"
# These "hidden" settings determine is a peripheral option is available for the

View File

@ -104,10 +104,16 @@ endif
CHIP_ASRCS =
CHIP_CSRCS = stm32_allocateheap.c stm32_exti_gpio.c stm32_gpio.c
CHIP_CSRCS += stm32_irq.c stm32_lowputc.c stm32_rcc.c stm32_serial.c
CHIP_CSRCS += stm32_start.c stm32_capture.c stm32_flash.c
CHIP_CSRCS += stm32_start.c stm32_capture.c stm32_uid.c
ifneq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += stm32_timerisr.c
else
CHIP_CSRCS += stm32_tickless.c
endif
ifeq ($(CONFIG_STM32F7_PROGMEM),y)
CHIP_CSRCS += stm32_flash.c
endif
ifeq ($(CONFIG_BUILD_PROTECTED),y)

View File

@ -73,20 +73,33 @@
#define FLASH_OPTKEY2 0x4c5d6e7f
#define FLASH_ERASEDVALUE 0xff
#if CONFIG_STM32F7_PROGMEM_STARTBLOCK < 0 || \
CONFIG_STM32F7_PROGMEM_STARTBLOCK >= STM32_FLASH_NPAGES
# error "Invalid CONFIG_STM32F7_PROGMEM_STARTBLOCK"
#endif
#if CONFIG_STM32F7_PROGMEM_LASTBLOCK < 0
# undef CONFIG_STM32F7_PROGMEM_LASTBLOCK
# define CONFIG_STM32F7_PROGMEM_LASTBLOCK (STM32_FLASH_NPAGES-1)
#endif
#define PROGMEM_NBLOCKS \
(CONFIG_STM32F7_PROGMEM_LASTBLOCK - CONFIG_STM32F7_PROGMEM_STARTBLOCK + 1)
#define PAGESIZE 256
/****************************************************************************
* Private Data
****************************************************************************/
static sem_t g_sem = SEM_INITIALIZER(1);
static const size_t page_sizes[STM32_FLASH_NPAGES] = STM32_FLASH_SIZES;
/****************************************************************************
* Private Functions
****************************************************************************/
static void up_waste(void)
{
}
static void sem_lock(void)
{
int ret;
@ -115,7 +128,6 @@ static void flash_unlock(void)
{
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
{
up_waste();
}
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
@ -132,6 +144,39 @@ static void flash_lock(void)
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK);
}
static uint32_t flash_size(void)
{
static uint32_t size;
int i;
if (size == 0)
{
for (i = 0; i < PROGMEM_NBLOCKS; i++)
{
size += page_sizes[CONFIG_STM32F7_PROGMEM_STARTBLOCK + i];
}
}
return size;
}
static uint32_t flash_base(void)
{
static uint32_t base;
int i;
if (base == 0)
{
base = STM32_FLASH_BASE;
for (i = 0; i < CONFIG_STM32F7_PROGMEM_STARTBLOCK; i++)
{
base += page_sizes[i];
}
}
return base;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -158,27 +203,29 @@ void stm32_flash_lock(void)
*
****************************************************************************/
int stm32_flash_writeprotect(size_t page, bool enabled)
int stm32_flash_writeprotect(size_t block, bool enabled)
{
uint32_t reg;
uint32_t val;
if (page >= STM32_FLASH_NPAGES)
if (block >= PROGMEM_NBLOCKS)
{
return -EFAULT;
}
block = block + CONFIG_STM32F7_PROGMEM_STARTBLOCK;
/* Select the register that contains the bit to be changed */
if (page < 12)
if (block < 12)
{
reg = STM32_FLASH_OPTCR;
}
#if defined(CONFIG_STM32_FLASH_CONFIG_I)
#if defined(CONFIG_STM32F7_FLASH_CONFIG_I)
else
{
reg = STM32_FLASH_OPTCR1;
page -= 12;
block -= 12;
}
#else
else
@ -195,11 +242,11 @@ int stm32_flash_writeprotect(size_t page, bool enabled)
if (enabled)
{
val &= ~(1 << (16 + page));
val &= ~(1 << (16 + block));
}
else
{
val |= (1 << (16 + page));
val |= (1 << (16 + block));
}
/* Unlock options */
@ -219,7 +266,6 @@ int stm32_flash_writeprotect(size_t page, bool enabled)
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
{
up_waste();
}
/* Re-lock options */
@ -230,75 +276,57 @@ int stm32_flash_writeprotect(size_t page, bool enabled)
size_t up_progmem_pagesize(size_t page)
{
static const size_t page_sizes[STM32_FLASH_NPAGES] = STM32_FLASH_SIZES;
if (page >= sizeof(page_sizes) / sizeof(*page_sizes))
{
return 0;
}
else
{
return page_sizes[page];
}
return PAGESIZE;
}
ssize_t up_progmem_getpage(size_t addr)
{
size_t page_end = 0;
size_t i;
if (addr >= STM32_FLASH_BASE)
if (addr >= flash_base())
{
addr -= STM32_FLASH_BASE;
addr -= flash_base();
}
if (addr >= STM32_FLASH_SIZE)
if (addr >= 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;
return addr / PAGESIZE;
}
size_t up_progmem_getaddress(size_t page)
{
size_t base_address = STM32_FLASH_BASE;
size_t i;
size_t base_address = flash_base();
if (page >= STM32_FLASH_NPAGES)
if (page >= flash_size() / PAGESIZE)
{
return SIZE_MAX;
}
for (i = 0; i < page; ++i)
{
base_address += up_progmem_pagesize(i);
}
base_address += PAGESIZE * page;
return base_address;
}
size_t up_progmem_neraseblocks(void)
{
return STM32_FLASH_NPAGES;
return PROGMEM_NBLOCKS;
}
bool up_progmem_isuniform(void)
{
#ifdef STM32_FLASH_PAGESIZE
size_t size = up_progmem_pagesize(0);
int i;
for (i = 1; i < PROGMEM_NBLOCKS; i++)
{
if (up_progmem_pagesize(i) != size)
{
return false;
}
}
return true;
#else
return false;
#endif
}
ssize_t up_progmem_ispageerased(size_t page)
@ -307,7 +335,7 @@ ssize_t up_progmem_ispageerased(size_t page)
size_t count;
size_t bwritten = 0;
if (page >= STM32_FLASH_NPAGES)
if (page >= flash_size() / PAGESIZE)
{
return -EFAULT;
}
@ -328,7 +356,7 @@ ssize_t up_progmem_ispageerased(size_t page)
ssize_t up_progmem_eraseblock(size_t block)
{
if (block >= STM32_FLASH_NPAGES)
if (block >= PROGMEM_NBLOCKS)
{
return -EFAULT;
}
@ -340,10 +368,13 @@ ssize_t up_progmem_eraseblock(size_t block)
flash_unlock();
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_SER);
modifyreg32(STM32_FLASH_CR, FLASH_CR_SNB_MASK, FLASH_CR_SNB(block));
modifyreg32(STM32_FLASH_CR, FLASH_CR_SNB_MASK,
FLASH_CR_SNB((block + CONFIG_STM32F7_PROGMEM_STARTBLOCK)));
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
{
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_SER, 0);
sem_unlock();
@ -360,6 +391,20 @@ ssize_t up_progmem_eraseblock(size_t block)
}
}
size_t up_progmem_erasesize(size_t block)
{
block = block + CONFIG_STM32F7_PROGMEM_STARTBLOCK;
if (block >= sizeof(page_sizes) / sizeof(*page_sizes))
{
return 0;
}
else
{
return page_sizes[block];
}
}
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
{
uint8_t *byte = (uint8_t *)buf;
@ -371,7 +416,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
if (addr >= STM32_FLASH_BASE &&
addr + count <= STM32_FLASH_BASE + STM32_FLASH_SIZE)
{
flash_base = STM32_FLASH_BASE;
flash_base = up_progmem_getaddress(0);
}
else if (addr >= STM32_OPT_BASE &&
addr + count <= STM32_OPT_BASE + STM32_OPT_SIZE)
@ -410,7 +455,9 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
ARM_DSB();
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
{
}
/* Verify */