mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 23:40:19 +08:00
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:
@@ -67,11 +67,16 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#define FLASH_KEY1 0x45670123
|
#define FLASH_KEY1 0x45670123
|
||||||
#define FLASH_KEY2 0xcdef89ab
|
#define FLASH_KEY2 0xcdef89ab
|
||||||
#define FLASH_OPTKEY1 0x08192a3b
|
#define FLASH_OPTKEY1 0x08192a3b
|
||||||
#define FLASH_OPTKEY2 0x4c5d6e7f
|
#define FLASH_OPTKEY2 0x4c5d6e7f
|
||||||
#define FLASH_ERASEDVALUE 0xff
|
#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
|
* Private Data
|
||||||
@@ -107,25 +112,25 @@ static inline void sem_unlock(void)
|
|||||||
nxsem_post(&g_sem);
|
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();
|
up_waste();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
|
if ((getreg32(base + STM32_FLASH_CR_OFFSET) & FLASH_CR_LOCK) != 0)
|
||||||
{
|
{
|
||||||
/* Unlock sequence */
|
/* Unlock sequence */
|
||||||
|
|
||||||
putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
|
putreg32(FLASH_KEY1, base + STM32_FLASH_KEYR_OFFSET);
|
||||||
putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
|
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)
|
void stm32_flash_unlock(void)
|
||||||
{
|
{
|
||||||
sem_lock();
|
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();
|
sem_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stm32_flash_lock(void)
|
void stm32_flash_lock(void)
|
||||||
{
|
{
|
||||||
sem_lock();
|
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();
|
sem_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +233,7 @@ ssize_t up_progmem_ispageerased(size_t page)
|
|||||||
|
|
||||||
ssize_t up_progmem_erasepage(size_t page)
|
ssize_t up_progmem_erasepage(size_t page)
|
||||||
{
|
{
|
||||||
|
uintptr_t base;
|
||||||
size_t page_address;
|
size_t page_address;
|
||||||
|
|
||||||
if (page >= STM32_FLASH_NPAGES)
|
if (page >= STM32_FLASH_NPAGES)
|
||||||
@@ -229,9 +241,24 @@ ssize_t up_progmem_erasepage(size_t page)
|
|||||||
return -EFAULT;
|
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();
|
sem_lock();
|
||||||
|
|
||||||
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
|
if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
|
||||||
{
|
{
|
||||||
sem_unlock();
|
sem_unlock();
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@@ -239,20 +266,23 @@ ssize_t up_progmem_erasepage(size_t page)
|
|||||||
|
|
||||||
/* Get flash ready and begin erasing single 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 */
|
/* Must be valid - page index checked above */
|
||||||
|
|
||||||
page_address = up_progmem_getaddress(page);
|
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();
|
sem_unlock();
|
||||||
|
|
||||||
/* Verify */
|
/* 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)
|
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
uintptr_t base;
|
||||||
uint16_t *hword = (uint16_t *)buf;
|
uint16_t *hword = (uint16_t *)buf;
|
||||||
size_t written = count;
|
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 */
|
/* STM32 requires half-word access */
|
||||||
|
|
||||||
if (count & 1)
|
if (count & 1)
|
||||||
@@ -293,7 +339,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
|||||||
|
|
||||||
sem_lock();
|
sem_lock();
|
||||||
|
|
||||||
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
|
if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
|
||||||
{
|
{
|
||||||
sem_unlock();
|
sem_unlock();
|
||||||
return -EPERM;
|
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 */
|
/* 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)
|
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);
|
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 */
|
/* 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();
|
sem_unlock();
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getreg16(addr) != *hword)
|
if (getreg16(addr) != *hword)
|
||||||
{
|
{
|
||||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
|
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
|
||||||
sem_unlock();
|
sem_unlock();
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
|
modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
|
||||||
|
|
||||||
sem_unlock();
|
sem_unlock();
|
||||||
return written;
|
return written;
|
||||||
|
|||||||
Reference in New Issue
Block a user