Kaynağa Gözat

Merge pull request #4405 from zhuyf233/master

[bsp][stm32]fix stm32h7 flash driver error
Bernard Xiong 4 yıl önce
ebeveyn
işleme
d69c411197

+ 88 - 138
bsp/stm32/libraries/HAL_Drivers/drv_flash/drv_flash_h7.c

@@ -9,6 +9,7 @@
  * 2019-3-2       jinsheng     add Macro judgment
  * 2020-1-6       duminmin     support single bank mode
  * 2020-5-17      yufanyufan77 support support H7
+ * 2021-3-3       zhuyf233     fix some bugs
  */
 
 #include "board.h"
@@ -24,110 +25,6 @@
 //#define DRV_DEBUG
 #define LOG_TAG                "drv.flash"
 #include <drv_log.h>
-#define ADDR_FLASH_SECTOR_0     ((rt_uint32_t)0x08000000) /* Base address of Sector 0, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_1     ((rt_uint32_t)0x08020000) /* Base address of Sector 1, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_2     ((rt_uint32_t)0x08040000) /* Base address of Sector 2, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_3     ((rt_uint32_t)0x08060000) /* Base address of Sector 3, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_4     ((rt_uint32_t)0x08080000) /* Base address of Sector 4, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_5     ((rt_uint32_t)0x080A0000) /* Base address of Sector 5, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_6     ((rt_uint32_t)0x080C0000) /* Base address of Sector 6, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_7     ((rt_uint32_t)0x080E0000) /* Base address of Sector 7, 128 Kbytes */
-#define ADDR_FLASH_SECTOR_8     ((rt_uint32_t)0x08100000) /* Base address of Sector 8, 128 Kbytes */
-
-#define FLASH_SECTOR_0             0U       /* Sector Number 0   */
-#define FLASH_SECTOR_1             1U       /* Sector Number 1   */
-#define FLASH_SECTOR_2             2U       /* Sector Number 2   */
-#define FLASH_SECTOR_3             3U       /* Sector Number 3   */
-#define FLASH_SECTOR_4             4U       /* Sector Number 4   */
-#define FLASH_SECTOR_5             5U       /* Sector Number 5   */
-#define FLASH_SECTOR_6             6U       /* Sector Number 6   */
-#define FLASH_SECTOR_7             7U       /* Sector Number 7   */
-/**
-  * @brief  Gets the sector of a given address
-  * @param  addr flash address
-  * @param  flash bank
-  * @param  flash sector
-  * @retval The sector of a given address
-  */
-static void GetSector(rt_uint32_t Address,uint32_t* bank,uint32_t* sector)
-{
-#if defined (FLASH_OPTCR_nDBANK)
-    FLASH_OBProgramInitTypeDef OBInit;
-    uint32_t nbank = 0;
-
-    /* get duel bank ability:nDBANK(Bit29) */
-    HAL_FLASHEx_OBGetConfig(&OBInit);
-    nbank = ((OBInit.USERConfig & 0x20000000U) >> 29);
-    /* 1:single bank mode */
-    if (1 == nbank)
-    {
-        if ((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
-        {
-            sector = FLASH_SECTOR_0;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
-        {
-            sector = FLASH_SECTOR_1;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
-        {
-            sector = FLASH_SECTOR_2;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
-        {
-            sector = FLASH_SECTOR_3;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
-        {
-            sector = FLASH_SECTOR_4;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
-        {
-            sector = FLASH_SECTOR_5;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
-        {
-            sector = FLASH_SECTOR_6;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
-        {
-            sector = FLASH_SECTOR_7;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
-        {
-            sector = FLASH_SECTOR_8;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
-        {
-            sector = FLASH_SECTOR_9;
-        }
-        else if ((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
-        {
-            sector = FLASH_SECTOR_10;
-        }
-        else
-        {
-            sector = FLASH_SECTOR_11;
-        }
-    }
-    else  /* 0:dual bank mode */
-    {
-        LOG_E("rtthread doesn't support duel bank mode yet!");
-        RT_ASSERT(0);
-    }
-#else /* no dual bank ability */
-    *sector = (Address&0xffffff)/FLASH_SIZE_GRANULARITY_128K;
-    if(*sector>7)
-    {
-        *bank = FLASH_BANK_1;
-        *sector = *sector/2;
-    }
-    else
-    {
-        *bank = FLASH_BANK_2;
-    }
-#endif
-}
 
 /**
  * Read data from flash.
@@ -137,16 +34,16 @@ static void GetSector(rt_uint32_t Address,uint32_t* bank,uint32_t* sector)
  * @param buf buffer to store read data
  * @param size read bytes size
  *
- * @return result
+ * @retval The length of bytes that have been read
  */
 int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
 {
     size_t i;
 
-    if ((addr + size) > STM32_FLASH_END_ADDRESS)
+    if ((addr + size - 1) > FLASH_END)
     {
         LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
-        return -1;
+        return -RT_ERROR;
     }
 
     for (i = 0; i < size; i++, buf++, addr++)
@@ -166,47 +63,68 @@ int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
  * @param buf the write data buffer
  * @param size write bytes size
  *
- * @return result
+ * @return The length of bytes that have been written
  */
 int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
 {
     rt_err_t result      = RT_EOK;
-    rt_uint32_t end_addr = addr + size;
-    rt_uint32_t bank = addr/ADDR_FLASH_SECTOR_8;;
+    rt_uint32_t end_addr = addr + size - 1, write_addr;
+    rt_uint32_t write_granularity = FLASH_NB_32BITWORD_IN_FLASHWORD * 4;
+    rt_uint32_t write_size = write_granularity;
+    rt_uint8_t write_buffer[32] = {0};
 
-    if ((end_addr) > STM32_FLASH_END_ADDRESS)
+    if ((end_addr) > FLASH_END)
     {
         LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
         return -RT_EINVAL;
     }
+    
+    if(addr % 32 != 0)
+    {
+        LOG_E("write addr must be 32-byte alignment");
+        return -RT_EINVAL;
+    }
 
     if (size < 1)
     {
         return -RT_EINVAL;
     }
 
-    /* Unlock the Flash to enable the flash control register access */
     HAL_FLASH_Unlock();
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR );
-
-    for (size_t i = 0; i < size/32; i++, addr+=32, buf+=32)
+    write_addr = (uint32_t)buf;
+    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR);
+    while (addr < end_addr)
     {
-        /* write data to flash */
-        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr,  (uint64_t)((uint32_t)buf)) == HAL_OK)
+        if(end_addr - addr + 1 < write_granularity)
         {
-            if (*(rt_uint8_t *)addr != *buf)
+            write_size = end_addr - addr + 1;
+            for(size_t i = 0; i < write_size; i++)
             {
-                result = -RT_ERROR;
-                break;
+                write_buffer[i] = *((uint8_t *)(write_addr + i));
             }
+            write_addr = (uint32_t)((rt_uint32_t *)write_buffer);
+        }
+        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, write_addr) == HAL_OK)
+        {
+            for(rt_uint8_t i = 0; i < write_size; i++)
+            {
+                if (*(rt_uint8_t *)(addr + i) != *(rt_uint8_t *)(write_addr + i))
+                {
+                    result = -RT_ERROR;
+                    goto __exit;
+                }
+            }
+            addr += write_granularity;
+            write_addr  += write_granularity;
         }
         else
         {
             result = -RT_ERROR;
-            break;
+            goto __exit;
         }
     }
 
+__exit:
     HAL_FLASH_Lock();
 
     if (result != RT_EOK)
@@ -230,42 +148,74 @@ int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
 int stm32_flash_erase(rt_uint32_t addr, size_t size)
 {
     rt_err_t result = RT_EOK;
-    rt_uint32_t FirstSector = 0, NbOfSectors = 0;
     rt_uint32_t SECTORError = 0;
-    rt_uint32_t bank = 0;
 
-    if ((addr + size) > STM32_FLASH_END_ADDRESS)
+    if ((addr + size - 1) > FLASH_END)
     {
         LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
         return -RT_EINVAL;
     }
 
+    rt_uint32_t addr_bank1 = 0;
+    rt_uint32_t size_bank1 = 0;
+    rt_uint32_t addr_bank2 = 0;
+    rt_uint32_t size_bank2 = 0;
+
+    if((addr + size) < FLASH_BANK2_BASE)
+    {
+        addr_bank1 = addr;
+        size_bank1 = size;
+        size_bank2 = 0;
+    }
+    else if(addr >= FLASH_BANK2_BASE)
+    {
+        size_bank1 = 0;
+        addr_bank2 = addr;
+        size_bank2 = size; 
+    }
+    else
+    {
+        addr_bank1 = addr;
+        size_bank1 = FLASH_BANK2_BASE - addr_bank1;
+        addr_bank2 = FLASH_BANK2_BASE;
+        size_bank2 = addr + size - FLASH_BANK2_BASE;
+    }
+
     /*Variable used for Erase procedure*/
     FLASH_EraseInitTypeDef EraseInitStruct;
-
     /* Unlock the Flash to enable the flash control register access */
     HAL_FLASH_Unlock();
-
-    /* Get the 1st sector to erase */
-    GetSector(addr,&bank,&FirstSector);
-    /* Get the number of sector to erase from 1st sector */
-    GetSector(addr + size,0,&NbOfSectors);
-    NbOfSectors = NbOfSectors - FirstSector + 1;
-    /* Fill EraseInit structure */
     EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
     EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;
-    EraseInitStruct.Sector        = FirstSector;
-    EraseInitStruct.NbSectors     = NbOfSectors;
-    EraseInitStruct.Banks         = bank;
+    SCB_DisableDCache();
+    
+    if(size_bank1)
+    {
+        EraseInitStruct.Sector    = (addr_bank1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE;
+        EraseInitStruct.NbSectors = (addr_bank1 + size_bank1 -1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
+        EraseInitStruct.Banks = FLASH_BANK_1;
+        if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
+        {
+            result = -RT_ERROR;
+            goto __exit;
+        }
+    }
 
-    if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
+    if(size_bank2)
     {
-        result = -RT_ERROR;
-        goto __exit;
+        EraseInitStruct.Sector    = (addr_bank2 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE;
+        EraseInitStruct.NbSectors = (addr_bank2 + size_bank2 -1 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
+        EraseInitStruct.Banks = FLASH_BANK_2;
+        if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
+        {
+            result = -RT_ERROR;
+            goto __exit;
+        }
     }
 
 __exit:
 
+    SCB_EnableDCache();
     HAL_FLASH_Lock();
 
     if (result != RT_EOK)