Merged in zehortigoza/nuttx/flash (pull request #289)

STM32 Flash fixes

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Jose Souza 2017-03-22 21:38:47 +00:00 committed by Gregory Nutt
commit 6710e58a32
3 changed files with 95 additions and 8 deletions

View File

@ -2633,6 +2633,12 @@ config STM32_FLASH_PREFETCH
on F1 parts). Some early revisions of F4 parts do not support FLASH pre-fetch
properly and enabling this option may interfere with ADC accuracy.
config STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW
bool "Enable the workaround to fix flash data cache corruption when reading from one flash bank while writing on other flash bank"
default n
---help---
See your STM32 errata to check if your STM32 is affected by this problem.
choice
prompt "JTAG Configuration"
default STM32_JTAG_DISABLE

View File

@ -328,10 +328,11 @@
# define FLASH_CR_SER (1 << 1) /* Bit 1: Sector Erase */
# define FLASH_CR_MER (1 << 2) /* Bit 2: Mass Erase sectors 0..11 */
# define FLASH_CR_SNB_SHIFT (3) /* Bits 3-6: Sector number */
# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT)
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429)
# define FLASH_CR_SNB_MASK (31 << FLASH_CR_SNB_SHIFT)
# define FLASH_CR_SNB(n) (((n % 12) << FLASH_CR_SNB_SHIFT) | ((n / 12) << 7)) /* Sector n, n=0..23 */
#else
# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT)
# define FLASH_CR_SNB(n) ((n) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..11 */
#endif
# define FLASH_CR_PSIZE_SHIFT (8) /* Bits 8-9: Program size */
@ -391,6 +392,7 @@
* Public Functions
************************************************************************************/
void stm32_flash_initialize(void);
void stm32_flash_lock(void);
void stm32_flash_unlock(void);

View File

@ -47,7 +47,9 @@
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <errno.h>
#include <stdbool.h>
#include "stm32_flash.h"
#include "stm32_rcc.h"
@ -84,10 +86,30 @@
* Private Functions
************************************************************************************/
/************************************************************************************
* Public Functions
************************************************************************************/
void stm32_flash_unlock(void)
static sem_t g_sem;
/*
* After all SMT32 boards starts calling stm32_flash_initialize() this can
* be removed.
*/
static bool g_initialized = false;
static void sem_lock(void)
{
if (g_initialized)
{
sem_wait(&g_sem);
}
}
static void sem_unlock(void)
{
if (g_initialized)
{
sem_post(&g_sem);
}
}
static void flash_unlock(void)
{
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
{
@ -103,11 +125,50 @@ void stm32_flash_unlock(void)
}
}
void stm32_flash_lock(void)
static void flash_lock(void)
{
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK);
}
static void data_cache_disable(void)
{
modifyreg32(STM32_FLASH_ACR, FLASH_ACR_DCEN, 0);
}
static void data_cache_enable(void)
{
/* reset data cache */
modifyreg32(STM32_FLASH_ACR, 0, FLASH_ACR_DCRST);
/* enable data cache */
modifyreg32(STM32_FLASH_ACR, 0, FLASH_ACR_DCEN);
}
/************************************************************************************
* Public Functions
************************************************************************************/
void stm32_flash_initialize(void)
{
g_initialized = true;
/*
* Initialize the semaphore that manages exclusive access flash registers
*/
sem_init(&g_sem, 0, 1);
}
void stm32_flash_unlock(void)
{
sem_lock();
flash_unlock();
sem_unlock();
}
void stm32_flash_lock(void)
{
sem_lock();
flash_lock();
sem_unlock();
}
#if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX)
@ -231,6 +292,8 @@ ssize_t up_progmem_erasepage(size_t page)
return -EFAULT;
}
sem_lock();
#if !defined(CONFIG_STM32_STM32F40XX)
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
{
@ -240,7 +303,7 @@ ssize_t up_progmem_erasepage(size_t page)
/* Get flash ready and begin erasing single page */
stm32_flash_unlock();
flash_unlock();
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PAGE_ERASE);
@ -259,6 +322,7 @@ ssize_t up_progmem_erasepage(size_t page)
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
modifyreg32(STM32_FLASH_CR, FLASH_CR_PAGE_ERASE, 0);
sem_unlock();
/* Verify */
if (up_progmem_ispageerased(page) == 0)
@ -320,16 +384,23 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
return -EFAULT;
}
sem_lock();
#if !defined(CONFIG_STM32_STM32F40XX)
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
{
sem_unlock();
return -EPERM;
}
#endif
/* Get flash ready and begin flashing */
stm32_flash_unlock();
flash_unlock();
#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
data_cache_disable();
#endif
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
@ -351,17 +422,25 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR)
{
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
sem_unlock();
return -EROFS;
}
if (getreg16(addr) != *hword)
{
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
sem_unlock();
return -EIO;
}
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
data_cache_enable();
#endif
sem_unlock();
return written;
}