flash/nor/tcl: Distinguish between sectors and blocks in status messages
[fw/openocd] / src / flash / nor / stm32l4x.c
index 6bdb51d60329b60cdcf38c169e22a7a9b09857f6..4fb7e039aa627c7fa82bc2d6b91dc9217d0bc1fa 100644 (file)
@@ -13,8 +13,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.                                        *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 
 /* STM32L4xxx series for reference.
  *
- * RM0351
- * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf
+ * RM0351 (STM32L4x5/STM32L4x6)
+ * http://www.st.com/resource/en/reference_manual/dm00083560.pdf
  *
- * STM32L476RG Datasheet (for erase timing)
- * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf
+ * RM0394 (STM32L43x/44x/45x/46x)
+ * http://www.st.com/resource/en/reference_manual/dm00151940.pdf
  *
+ * STM32L476RG Datasheet (for erase timing)
+ * http://www.st.com/resource/en/datasheet/stm32l476rg.pdf
  *
- * The device has normally two banks, but on 512 and 256 kiB devices an
- * option byte is available to map all sectors to the first bank.
+ * The RM0351 devices have normally two banks, but on 512 and 256 kiB devices
+ * an option byte is available to map all sectors to the first bank.
  * Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices
  * handlers do!
  *
+ * RM0394 devices have a single bank only.
+ *
  */
 
 /* Erase time can be as high as 25ms, 10x this and assume it's toast... */
@@ -184,6 +187,8 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
 
        /* Clear but report errors */
        if (status & FLASH_ERROR) {
+               if (retval == ERROR_OK)
+                       retval = ERROR_FAIL;
                /* If this operation fails, we ignore it and report the original
                 * retval
                 */
@@ -458,32 +463,23 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
-       /* See contrib/loaders/flash/stm32l4x.S for source and
-        * hints how to generate the data!
-        */
-
        static const uint8_t stm32l4_flash_write_code[] = {
-               0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x22, 0xd0, 0x47, 0x68,
-               0xb8, 0xeb, 0x07, 0x06, 0x07, 0x2e, 0xf5, 0xd3, 0xdf, 0xf8, 0x3c, 0x60,
-               0x66, 0x61, 0x57, 0xf8, 0x04, 0x6b, 0x42, 0xf8, 0x04, 0x6b, 0x57, 0xf8,
-               0x04, 0x6b, 0x42, 0xf8, 0x04, 0x6b, 0xbf, 0xf3, 0x4f, 0x8f, 0x26, 0x69,
-               0x16, 0xf4, 0x80, 0x3f, 0xfb, 0xd1, 0x16, 0xf0, 0xfa, 0x0f, 0x07, 0xd1,
-               0x8f, 0x42, 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
-               0x13, 0xb1, 0xd9, 0xe7, 0x00, 0x21, 0x41, 0x60, 0x30, 0x46, 0x00, 0xbe,
-               0x01, 0x00, 0x00, 0x00
+#include "../../../contrib/loaders/flash/stm32/stm32l4x.inc"
        };
 
        if (target_alloc_working_area(target, sizeof(stm32l4_flash_write_code),
                        &write_algorithm) != ERROR_OK) {
                LOG_WARNING("no working area available, can't do block memory writes");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       };
+       }
 
        retval = target_write_buffer(target, write_algorithm->address,
                        sizeof(stm32l4_flash_write_code),
                        stm32l4_flash_write_code);
-       if (retval != ERROR_OK)
+       if (retval != ERROR_OK) {
+               target_free_working_area(target, write_algorithm);
                return retval;
+       }
 
        /* memory buffer */
        while (target_alloc_working_area_try(target, buffer_size, &source) !=
@@ -497,7 +493,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
                        LOG_WARNING("no large enough working area available, can't do block memory writes");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-       };
+       }
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
        armv7m_info.core_mode = ARM_MODE_THREAD;
@@ -600,6 +596,7 @@ static int stm32l4_probe(struct flash_bank *bank)
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        int i;
        uint16_t flash_size_in_kb = 0xffff;
+       uint16_t max_flash_size_in_kb;
        uint32_t device_id;
        uint32_t options;
        uint32_t base_address = 0x08000000;
@@ -614,7 +611,15 @@ static int stm32l4_probe(struct flash_bank *bank)
 
        /* set max flash size depending on family */
        switch (device_id & 0xfff) {
+       case 0x461:
        case 0x415:
+               max_flash_size_in_kb = 1024;
+               break;
+       case 0x462:
+               max_flash_size_in_kb = 512;
+               break;
+       case 0x435:
+               max_flash_size_in_kb = 256;
                break;
        default:
                LOG_WARNING("Cannot identify target as a STM32L4 family.");
@@ -624,17 +629,31 @@ static int stm32l4_probe(struct flash_bank *bank)
        /* get flash size from target. */
        retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb);
 
+       /* failed reading flash size or flash size invalid (early silicon),
+        * default to max target family */
+       if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
+               LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
+                       max_flash_size_in_kb);
+               flash_size_in_kb = max_flash_size_in_kb;
+       }
+
+       LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
+
+       /* did we assign flash size? */
+       assert(flash_size_in_kb != 0xffff);
+
        /* get options to for DUAL BANK. */
        retval = target_read_u32(target, STM32_FLASH_OPTR, &options);
 
+       if (retval != ERROR_OK)
+               return retval;
+
        /* only devices with < 1024 kiB may be set to single bank dual banks */
        if ((flash_size_in_kb == 1024) || !(options & OPT_DUALBANK))
                stm32l4_info->option_bytes.bank_b_start = 256;
        else
                stm32l4_info->option_bytes.bank_b_start = flash_size_in_kb << 9;
 
-       LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
-
        /* did we assign flash size? */
        assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
 
@@ -686,7 +705,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
        if (retval != ERROR_OK)
                return retval;
 
-       uint16_t device_id = dbgmcu_idcode & 0xffff;
+       uint16_t device_id = dbgmcu_idcode & 0xfff;
        uint8_t rev_id = dbgmcu_idcode >> 28;
        uint8_t rev_minor = 0;
        int i;
@@ -701,8 +720,20 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
        const char *device_str;
 
        switch (device_id) {
-       case 0x6415:
-               device_str = "STM32L4xx";
+       case 0x461:
+               device_str = "STM32L496/4A6";
+               break;
+
+       case 0x415:
+               device_str = "STM32L475/476/486";
+               break;
+
+       case 0x462:
+               device_str = "STM32L45x/46x";
+               break;
+
+       case 0x435:
+               device_str = "STM32L43x/44x";
                break;
 
        default:
@@ -915,4 +946,5 @@ struct flash_driver stm32l4x_flash = {
        .erase_check = default_flash_blank_check,
        .protect_check = stm32l4_protect_check,
        .info = get_stm32l4_info,
+       .free_driver_priv = default_flash_free_driver_priv,
 };