Implemente support for STM32 F1 banked FLASH

Squashed commit of the following:

    arch/arm/src/stm32/stm32f10xxf30xx_flash.c:  Re-implemented Dmitriy Linikov's change to support multi-banked FLASH on the STM32 F1 parts AFTER separating the FLASH support by architecture and implementing more standard base+offset register addressing.  Now the change goes in rather cleanly.
    arch/arm/src/stm32/stm32f10xxf30xx_flash.c:  Use base + offset address to simplify implementation of dual bank flash.
This commit is contained in:
Gregory Nutt 2018-06-05 12:50:55 -06:00
parent fb07bd7e27
commit 6fd4caf00f

View File

@ -67,11 +67,16 @@
* Pre-processor Definitions
************************************************************************************/
#define FLASH_KEY1 0x45670123
#define FLASH_KEY2 0xcdef89ab
#define FLASH_OPTKEY1 0x08192a3b
#define FLASH_OPTKEY2 0x4c5d6e7f
#define FLASH_ERASEDVALUE 0xff
#define FLASH_KEY1 0x45670123
#define FLASH_KEY2 0xcdef89ab
#define FLASH_OPTKEY1 0x08192a3b
#define FLASH_OPTKEY2 0x4c5d6e7f
#define FLASH_ERASEDVALUE 0xff
#if !defined(STM32_FLASH_DUAL_BANK)
# define STM32_FLASH_BANK0_NPAGES STM32_FLASH_NPAGES
# define STM32_FLASH_BANK0_BASE STM32_FLASH_BASE
#endif
/************************************************************************************
* Private Data
@ -107,25 +112,25 @@ static inline void sem_unlock(void)
nxsem_post(&g_sem);
}
static void flash_unlock(void)
static void flash_unlock(uintptr_t base)
{
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
{
up_waste();
}
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
if ((getreg32(base + STM32_FLASH_CR_OFFSET) & FLASH_CR_LOCK) != 0)
{
/* Unlock sequence */
putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
putreg32(FLASH_KEY1, base + STM32_FLASH_KEYR_OFFSET);
putreg32(FLASH_KEY2, base + STM32_FLASH_KEYR_OFFSET);
}
}
static void flash_lock(void)
static void flash_lock(uintptr_t base)
{
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK);
modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_LOCK);
}
/************************************************************************************
@ -135,14 +140,20 @@ static void flash_lock(void)
void stm32_flash_unlock(void)
{
sem_lock();
flash_unlock();
flash_unlock(STM32_FLASH_BANK0_BASE);
#if defined(STM32_FLASH_DUAL_BANK)
flash_unlock(STM32_FLASH_BANK1_BASE);
#endif
sem_unlock();
}
void stm32_flash_lock(void)
{
sem_lock();
flash_lock();
flash_lock(STM32_FLASH_BANK0_BASE);
#if defined(STM32_FLASH_DUAL_BANK)
flash_lock(STM32_FLASH_BANK1_BASE);
#endif
sem_unlock();
}
@ -222,6 +233,7 @@ ssize_t up_progmem_ispageerased(size_t page)
ssize_t up_progmem_erasepage(size_t page)
{
uintptr_t base;
size_t page_address;
if (page >= STM32_FLASH_NPAGES)
@ -229,9 +241,24 @@ ssize_t up_progmem_erasepage(size_t page)
return -EFAULT;
}
#if defined(STM32_FLASH_DUAL_BANK)
/* Handle paged FLASH */
if (page >= STM32_FLASH_BANK0_NPAGES)
{
base = STM32_FLASH_BANK1_BASE;
}
else
{
base = STM32_FLASH_BANK0_BASE;
}
#else
base = STM32_FLASH_BANK0_BASE;
#endif
sem_lock();
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
{
sem_unlock();
return -EPERM;
@ -239,20 +266,23 @@ ssize_t up_progmem_erasepage(size_t page)
/* Get flash ready and begin erasing single page */
flash_unlock();
flash_unlock(base);
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER);
modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_PER);
/* Must be valid - page index checked above */
page_address = up_progmem_getaddress(page);
putreg32(page_address, STM32_FLASH_AR);
putreg32(page_address, base + STM32_FLASH_AR_OFFSET);
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_STRT);
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
{
up_waste();
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0);
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PER, 0);
sem_unlock();
/* Verify */
@ -269,9 +299,25 @@ ssize_t up_progmem_erasepage(size_t page)
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
{
uintptr_t base;
uint16_t *hword = (uint16_t *)buf;
size_t written = count;
#if defined(STM32_FLASH_DUAL_BANK)
/* Handle paged FLASH */
if (page >= STM32_FLASH_BANK0_NPAGES)
{
base = STM32_FLASH_BANK1_BASE;
}
else
{
base = STM32_FLASH_BANK0_BASE;
}
#else
base = STM32_FLASH_BANK0_BASE;
#endif
/* STM32 requires half-word access */
if (count & 1)
@ -293,7 +339,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
sem_lock();
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
{
sem_unlock();
return -EPERM;
@ -301,9 +347,9 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
/* Get flash ready and begin flashing */
flash_unlock();
flash_unlock(base);
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_PG);
for (addr += STM32_FLASH_BASE; count; count -= 2, hword++, addr += 2)
{
@ -311,26 +357,29 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
putreg16(*hword, addr);
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
{
up_waste();
}
/* Verify */
if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRPRT_ERR)
if ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_WRPRT_ERR) != 0)
{
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
sem_unlock();
return -EROFS;
}
if (getreg16(addr) != *hword)
{
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
sem_unlock();
return -EIO;
}
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
sem_unlock();
return written;