flash: handle zero when reading stm32 flash size reg
[openocd.git] / src / flash / nor / stm32lx.c
index 58a2a80b02edb8a1010ee21342b7a41e94ded778..27a446de19b4522f5494ab8e54fa3ed00f591099 100644 (file)
@@ -409,6 +409,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
        }
 
        bytes_written = 128 * halfpages_number;
+       address += bytes_written;
 
        retval = stm32lx_unlock_program_memory(bank);
        if (retval != ERROR_OK)
@@ -461,9 +462,8 @@ static int stm32lx_probe(struct flash_bank *bank)
        struct target *target = bank->target;
        struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
        int i;
-       uint16_t flash_size;
+       uint16_t flash_size_in_kb;
        uint32_t device_id;
-       uint32_t reg32;
 
        stm32lx_info->probed = 0;
 
@@ -474,78 +474,35 @@ static int stm32lx_probe(struct flash_bank *bank)
 
        LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
 
-       if ((device_id & 0xfff) != 0x416) {
-               LOG_WARNING("Cannot identify target as a STM32L family.");
-               return ERROR_FAIL;
+       /* get flash size from target. */
+       retval = target_read_u16(target, F_SIZE, &flash_size_in_kb);
+       if (retval != ERROR_OK) {
+               LOG_WARNING("failed reading flash size, default to max target family");
+               /* failed reading flash size, default to max target family */
+               flash_size_in_kb = 0xffff;
        }
 
-       /* Read the RDP byte and check if it is 0xAA */
-       uint8_t rdp;
-       retval = target_read_u32(target, FLASH_OBR, &reg32);
-       if (retval != ERROR_OK)
-               return retval;
-       rdp = reg32 & 0xFF;
-       if (rdp != 0xAA) {
-               /*
-                * Unlocking the option byte is done by unlocking the PECR, then
-                * by writing the 2 option byte keys to OPTKEYR
-                */
-
-               /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */
-               retval = target_write_u32(target, FLASH_PEKEYR, PEKEY1);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = target_write_u32(target, FLASH_PEKEYR, PEKEY2);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* Make sure it worked */
-               retval = target_read_u32(target, FLASH_PECR, &reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (reg32 & FLASH_PECR__PELOCK)
-                       return ERROR_FLASH_OPERATION_FAILED;
+       /* some variants read 0 for flash size register
+        * use a max flash size as a default */
+       if (flash_size_in_kb == 0)
+               flash_size_in_kb = 0xffff;
 
-               retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY1);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY2);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = target_read_u32(target, FLASH_PECR, &reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (reg32 & FLASH_PECR__OPTLOCK) {
-                       LOG_ERROR("OPTLOCK is not cleared");
-                       return ERROR_FLASH_OPERATION_FAILED;
+       if ((device_id & 0xfff) == 0x416) {
+               /* check for early silicon */
+               if (flash_size_in_kb == 0xffff) {
+                       /* number of sectors may be incorrrect on early silicon */
+                       LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
+                       flash_size_in_kb = 128;
                }
-
-               /* Then, write RDP to 0x00 to set level 1 */
-               reg32 = ((~0xAA) << 16) | (0xAA);
-               retval = target_write_u32(target, OB_RDP, reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */
-               reg32 = FLASH_PECR__OBL_LAUNCH;
-               retval = target_write_u32(target, FLASH_PECR, reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       /* get flash size from target. */
-       retval = target_read_u16(target, F_SIZE, &flash_size);
-       if (retval != ERROR_OK)
-               return retval;
-
-       /* check for valid flash size */
-       if (flash_size == 0xffff) {
-               /* number of sectors incorrect on revA */
-               LOG_ERROR("STM32 flash size failed, probe inaccurate");
+       } else if ((device_id & 0xfff) == 0x436) {
+               /* check for early silicon */
+               if (flash_size_in_kb == 0xffff) {
+                       /* number of sectors may be incorrrect on early silicon */
+                       LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 384k flash");
+                       flash_size_in_kb = 384;
+               }
+       } else {
+               LOG_WARNING("Cannot identify target as a STM32L family.");
                return ERROR_FAIL;
        }
 
@@ -553,8 +510,8 @@ static int stm32lx_probe(struct flash_bank *bank)
         * 16 pages for a protection area */
 
        /* calculate numbers of sectors (4kB per sector) */
-       int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE;
-       LOG_INFO("flash size = %dkbytes", flash_size);
+       int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE;
+       LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
 
        if (bank->sectors) {
                free(bank->sectors);
@@ -562,7 +519,7 @@ static int stm32lx_probe(struct flash_bank *bank)
        }
 
        bank->base = FLASH_BANK0_ADDRESS;
-       bank->size = flash_size * 1024;
+       bank->size = flash_size_in_kb * 1024;
        bank->num_sectors = num_sectors;
        bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
        if (bank->sectors == NULL) {
@@ -668,6 +625,37 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
                        case 0x1008:
                                snprintf(buf, buf_size, "Y");
                                break;
+
+                       case 0x1018:
+                               snprintf(buf, buf_size, "X");
+                               break;
+
+                       case 0x1038:
+                               snprintf(buf, buf_size, "W");
+                               break;
+
+                       case 0x1078:
+                               snprintf(buf, buf_size, "V");
+                               break;
+
+                       default:
+                               snprintf(buf, buf_size, "unknown");
+                               break;
+               }
+       } else if ((device_id & 0xfff) == 0x436) {
+               printed = snprintf(buf, buf_size, "stm32lx (HD) - Rev: ");
+               buf += printed;
+               buf_size -= printed;
+
+               switch (device_id >> 16) {
+                       case 0x1000:
+                               snprintf(buf, buf_size, "A");
+                               break;
+
+                       case 0x1008:
+                               snprintf(buf, buf_size, "Z");
+                               break;
+
                        default:
                                snprintf(buf, buf_size, "unknown");
                                break;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)