From 09f70c462de80ad1492838cc2bc08912a7e118b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 22 Mar 2017 10:56:37 -0700 Subject: [PATCH] stm32: Make up_progmem thread safe Writing to a flash sector while starting the erase of other sector have a undefined behavior so lets add a semaphore and syncronize access to Flash registers. But for the semaphore to work it needs to be initialized so each board needs call stm32_flash_initialize() on initialization, so to avoid runtime problems it is only using semaphore and making it thread safe if initialized, after all boards starts to call stm32_flash_initialize() we can remove the boolean and the check. --- arch/arm/src/stm32/chip/stm32_flash.h | 1 + arch/arm/src/stm32/stm32_flash.c | 70 ++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/stm32/chip/stm32_flash.h b/arch/arm/src/stm32/chip/stm32_flash.h index 32eeaf90dd8..16c67a933e5 100644 --- a/arch/arm/src/stm32/chip/stm32_flash.h +++ b/arch/arm/src/stm32/chip/stm32_flash.h @@ -392,6 +392,7 @@ * Public Functions ************************************************************************************/ +void stm32_flash_initialize(void); void stm32_flash_lock(void); void stm32_flash_unlock(void); diff --git a/arch/arm/src/stm32/stm32_flash.c b/arch/arm/src/stm32/stm32_flash.c index 9ac38a19a13..7f0b53ee607 100644 --- a/arch/arm/src/stm32/stm32_flash.c +++ b/arch/arm/src/stm32/stm32_flash.c @@ -47,7 +47,9 @@ #include #include + #include +#include #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,36 @@ void stm32_flash_unlock(void) } } -void stm32_flash_lock(void) +static void flash_lock(void) { modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK); } +/************************************************************************************ + * 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 +278,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 +289,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 +308,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 +370,19 @@ 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(); modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG); @@ -351,17 +404,20 @@ 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); + sem_unlock(); return written; }