This is an automated email from the ASF dual-hosted git repository.

utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 5e5dee8  Fix some issues with the L1/L0 flash driver
5e5dee8 is described below

commit 5e5dee8148123bd9b592311bd1271ab245833eab
Author: Fabio Utzig <[email protected]>
AuthorDate: Thu Jul 26 15:19:44 2018 -0300

    Fix some issues with the L1/L0 flash driver
    
    - Fix alignment;
    - Disable write protection just while erasing/writing instead of always
      leaving the flash unlocked. Since the watchdog was left on in Mynewt
      when asking for an upgrade, and not initialized on MCUBoot, the tickle
      in this driver was causing an invalid write to the flash, that was
      unprotected, as well as a restart failing verification of the swapped
      image. A related watchdog issue is being submitted to MCUBoot;
    - Other small refactorings applied to ease merging L4/L1/L0 into one
      single configurable flash driver.
---
 hw/mcu/stm/stm32l1xx/src/hal_flash.c | 47 ++++++++++++++++++++++++++++--------
 hw/mcu/stm/stm32l1xx/syscfg.yml      |  2 +-
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/hw/mcu/stm/stm32l1xx/src/hal_flash.c 
b/hw/mcu/stm/stm32l1xx/src/hal_flash.c
index a4803b4..4a4dfc6 100644
--- a/hw/mcu/stm/stm32l1xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32l1xx/src/hal_flash.c
@@ -18,6 +18,7 @@
  */
 
 #include <string.h>
+#include <syscfg/syscfg.h>
 #include "stm32l1xx_hal_def.h"
 #include "stm32l1xx_hal_flash.h"
 #include "stm32l1xx_hal_flash_ex.h"
@@ -50,7 +51,7 @@ const struct hal_flash stm32l1_flash_dev = {
     .hf_base_addr = 0x08000000,
     .hf_size = _FLASH_SIZE,
     .hf_sector_cnt = _FLASH_SIZE / _FLASH_SECTOR_SIZE,
-    .hf_align = 8,
+    .hf_align = MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE),
 };
 
 static int
@@ -65,31 +66,55 @@ static int
 stm32l1_flash_write(const struct hal_flash *dev, uint32_t address,
         const void *src, uint32_t num_bytes)
 {
-    const uint32_t *sptr;
+    uint32_t val;
     uint32_t i;
     int rc;
+    uint8_t align;
     uint32_t num_words;
 
     if (!num_bytes) {
         return -1;
     }
 
+    align = dev->hf_align;
+
+#if MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 1
+    num_words = num_bytes;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 2
+    num_words = ((num_bytes - 1) >> 1) + 1;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 4
+    num_words = ((num_bytes - 1) >> 2) + 1;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 8
+    num_words = ((num_bytes - 1) >> 3) + 1;
+#else
+    #error "Unsupported MCU_FLASH_MIN_WRITE_SIZE"
+#endif
+
     /* Clear status of previous operation. */
     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_MASK);
 
-    sptr = (const uint32_t *)src;
-    num_words = ((num_bytes - 1) / 4) + 1;
     for (i = 0; i < num_words; i++) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAMDATA_WORD, address, sptr[i]);
+        if (num_bytes < align) {
+            memcpy(&val, &((uint8_t *)src)[i * align], num_bytes);
+            /* NOTE: 0 is the erased value for L1 */
+            memset((uint32_t *)&val + num_bytes, 0, align - num_bytes);
+        } else {
+            memcpy(&val, &((uint8_t *)src)[i * align], align);
+        }
+
+        HAL_FLASH_Unlock();
+        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAMDATA_WORD, address, val);
+        HAL_FLASH_Lock();
         if (rc != HAL_OK) {
             return rc;
         }
-        address += 4;
+
+        address += align;
+        num_bytes -= align;
 
         /*
-         * Long writes take excessive time, and stall the idle
-         * thread, so tickling the watchdog here to avoid resetting
-         * during writes...
+         * Long writes take excessive time, and stall the idle thread,
+         * so tickling the watchdog here to avoid reset...
          */
         if (!(i % 32)) {
             hal_watchdog_tickle();
@@ -117,7 +142,10 @@ stm32l1_flash_erase_sector(const struct hal_flash *dev, 
uint32_t sector_address)
         eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
         eraseinit.PageAddress = sector_address;
         eraseinit.NbPages = _FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE;
+
+        HAL_FLASH_Unlock();
         rc = HAL_FLASHEx_Erase(&eraseinit, &PageError);
+        HAL_FLASH_Lock();
         if (rc == HAL_OK) {
             return 0;
         }
@@ -138,7 +166,6 @@ stm32l1_flash_sector_info(const struct hal_flash *dev, int 
idx,
 static int
 stm32l1_flash_init(const struct hal_flash *dev)
 {
-    HAL_FLASH_Unlock();
     /* TODO: enable ACC64 + prefetch */
     return 0;
 }
diff --git a/hw/mcu/stm/stm32l1xx/syscfg.yml b/hw/mcu/stm/stm32l1xx/syscfg.yml
index fcdbb26..c7ce10c 100644
--- a/hw/mcu/stm/stm32l1xx/syscfg.yml
+++ b/hw/mcu/stm/stm32l1xx/syscfg.yml
@@ -27,7 +27,7 @@ syscfg.defs:
         description: >
             Specifies the required alignment for internal flash writes.
             Used internally by the newt tool.
-        value: 8
+        value: 4
 
     MCU_STM32L1:
         description: MCUs are of STM32L1xx family

Reply via email to